IAM Configuration
Configure users, groups, and policies for S3 authentication and authorization.
Overview
ZapFS implements AWS-compatible IAM for S3 authentication and authorization. The Manager cluster serves as the central authority for all IAM state, with metadata services syncing credentials in real-time via gRPC streaming.
Configuration File
IAM is configured via TOML. Create or edit iam.toml:
# iam.toml - ZapFS IAM Configuration [iam] # Cache settings cache_max_items = 1000000 cache_ttl = "5m" # Optional: Enable STS for temporary credentials enable_sts = false sts_default_duration = "1h" sts_max_duration = "12h"
Defining Users
Users are defined with access keys for S3 authentication. Generate secure keys for production:
# Generate secure keys openssl rand -hex 10 # access key (20 chars) openssl rand -hex 20 # secret key (40 chars)
[[iam.users]] name = "admin" access_key = "AKIAADMINKEY00001" secret_key = "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLE1" account_id = "000000000001" display_name = "Admin User" email = "[email protected]" disabled = false policies = ["FullAccess"] [[iam.users]] name = "developer" access_key = "AKIADEVKEY0000002" secret_key = "devSecretKey1234567890123456789012345678" account_id = "000000000002" policies = ["ReadOnly"] groups = ["developers"]
Defining Groups
Groups let you organize users and attach policies to multiple users at once:
[[iam.groups]] name = "developers" policies = ["DevBucketAccess"] [[iam.groups]] name = "admins" policies = ["FullAccess"]
Defining Policies
Policies use AWS IAM policy format. ZapFS supports actions, resources, and conditions:
Full Access Policy
[[iam.policies]]
name = "FullAccess"
document = '''
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "FullAccess",
"Effect": "Allow",
"Action": "s3:*",
"Resource": "*"
}
]
}
'''Read-Only Policy
[[iam.policies]]
name = "ReadOnly"
document = '''
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "ReadOnlyAccess",
"Effect": "Allow",
"Action": ["s3:Get*", "s3:List*", "s3:Head*"],
"Resource": "*"
}
]
}
'''Bucket-Restricted Policy
[[iam.policies]]
name = "DevBucketAccess"
document = '''
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DevBucketFullAccess",
"Effect": "Allow",
"Action": "s3:*",
"Resource": ["arn:aws:s3:::dev-*", "arn:aws:s3:::dev-*/*"]
},
{
"Sid": "DenyProductionAccess",
"Effect": "Deny",
"Action": "s3:*",
"Resource": ["arn:aws:s3:::prod-*", "arn:aws:s3:::prod-*/*"]
}
]
}
'''Supported S3 Actions
| Action | Description |
|---|---|
| s3:* | All S3 operations |
| s3:GetObject | Download objects |
| s3:PutObject | Upload objects |
| s3:DeleteObject | Delete objects |
| s3:ListBucket | List bucket contents |
| s3:CreateBucket | Create buckets |
| s3:DeleteBucket | Delete buckets |
| s3:GetBucketLocation | Get bucket region |
| s3:HeadObject | Get object metadata |
Admin API
Manage IAM dynamically via the Manager's Admin HTTP API (default port 8060):
| Method | Endpoint | Description |
|---|---|---|
| POST | /v1/iam/users | Create user |
| GET | /v1/iam/users | List users |
| DELETE | /v1/iam/users/:name | Delete user |
| POST | /v1/iam/users/:name/keys | Create access key |
| DELETE | /v1/iam/users/:name/keys/:keyId | Delete access key |
| POST | /v1/iam/groups | Create group |
| POST | /v1/iam/groups/:name/members | Add user to group |
| POST | /v1/iam/policies | Create policy |
| POST | /v1/iam/users/:name/policies | Attach policy to user |
Example: Create a User
curl -X POST http://localhost:8060/v1/iam/users \
-H "Content-Type: application/json" \
-d '{
"name": "newuser",
"display_name": "New User",
"email": "[email protected]"
}'
# Response:
{
"name": "newuser",
"access_key": "AKIA...",
"secret_key": "..."
}Security Best Practices
- Generate unique, random access keys and secrets for each user
- Use groups to organize permissions instead of per-user policies
- Apply least-privilege: only grant permissions users need
- Use explicit Deny statements to block sensitive resources
- Rotate credentials regularly and disable unused accounts
- Set ZAPFS_IAM_MASTER_KEY for encryption at rest
Master Key Configuration
Secrets are encrypted at rest using AES-256-GCM. Set the master key:
# Generate a 32-byte master key
openssl rand -base64 32
# Set in environment (all services need the same key)
export ZAPFS_IAM_MASTER_KEY="your-base64-encoded-key"
# Or in Docker Compose
environment:
ZAPFS_IAM_MASTER_KEY: ${ZAPFS_IAM_MASTER_KEY}