hafiz

Access Control

Hafiz provides multiple layers of access control to secure your data.

Authentication

AWS Signature V4

All requests must be signed using AWS Signature Version 4:

# AWS CLI handles this automatically
aws --endpoint-url http://localhost:9000 s3 ls

# Or set credentials
export AWS_ACCESS_KEY_ID=your-access-key
export AWS_SECRET_ACCESS_KEY=your-secret-key

LDAP Integration

Connect to enterprise directory services:

# Configure LDAP
HAFIZ_LDAP_ENABLED=true
HAFIZ_LDAP_URL=ldap://ldap.example.com:389
HAFIZ_LDAP_BASE_DN=dc=example,dc=com

Bucket Policies

IAM-style policies for fine-grained access control.

Policy Structure

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowPublicRead",
      "Effect": "Allow",
      "Principal": "*",
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::my-bucket/*"
    }
  ]
}

Apply Policy

aws --endpoint-url http://localhost:9000 s3api put-bucket-policy \
    --bucket my-bucket \
    --policy file://policy.json

Common Policy Examples

Public Read Access

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": "*",
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::public-bucket/*"
    }
  ]
}

Restrict by IP

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": "*",
      "Action": "s3:*",
      "Resource": "arn:aws:s3:::my-bucket/*",
      "Condition": {
        "IpAddress": {
          "aws:SourceIp": "192.168.1.0/24"
        }
      }
    }
  ]
}

Read-Only User

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {"AWS": "arn:aws:iam::user/readonly"},
      "Action": [
        "s3:GetObject",
        "s3:ListBucket"
      ],
      "Resource": [
        "arn:aws:s3:::my-bucket",
        "arn:aws:s3:::my-bucket/*"
      ]
    }
  ]
}

Supported Actions

Action Description
s3:GetObject Download objects
s3:PutObject Upload objects
s3:DeleteObject Delete objects
s3:ListBucket List bucket contents
s3:GetBucketPolicy Read bucket policy
s3:PutBucketPolicy Write bucket policy
s3:* All actions

Condition Keys

Key Description
aws:SourceIp Client IP address
aws:CurrentTime Current time
aws:SecureTransport HTTPS required
s3:prefix Object key prefix
s3:max-keys Maximum list results

User Management

Hafiz provides comprehensive IAM-style user management with bucket-level access control.

Creating Users

# Create a basic user
curl -X POST http://localhost:9000/admin/users \
    -H "Authorization: Basic $(echo -n 'hafizadmin:secret' | base64)" \
    -H "Content-Type: application/json" \
    -d '{
      "name": "alice",
      "email": "alice@example.com",
      "description": "Development team member"
    }'

Response:

{
  "name": "alice",
  "access_key": "AKIAXXXXXXXXXXXXXXXX",
  "secret_key": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
  "email": "alice@example.com",
  "description": "Development team member",
  "created_at": "2024-01-15T10:00:00Z",
  "bucket_access": []
}

IAM-Style Bucket Access

Assign users to specific buckets with granular permissions:

Permission Allows
read GetObject, ListBucket, HeadObject
write PutObject, DeleteObject
readwrite All read and write operations
none No access (explicit deny)

Create User with Bucket Access

curl -X POST http://localhost:9000/admin/users \
    -H "Authorization: Basic $(echo -n 'hafizadmin:secret' | base64)" \
    -H "Content-Type: application/json" \
    -d '{
      "name": "app-service",
      "description": "Application service account",
      "bucket_access": [
        {"bucket": "production-data", "permission": "readwrite"},
        {"bucket": "logs", "permission": "write"},
        {"bucket": "config", "permission": "read"}
      ]
    }'

Update User Bucket Access

curl -X PUT http://localhost:9000/admin/users/AKIAXXXXXXXXXXXXXXXX/buckets \
    -H "Authorization: Basic $(echo -n 'hafizadmin:secret' | base64)" \
    -H "Content-Type: application/json" \
    -d '{
      "bucket_access": [
        {"bucket": "production-data", "permission": "read"},
        {"bucket": "backups", "permission": "readwrite"}
      ]
    }'

List Users

curl http://localhost:9000/admin/users \
    -H "Authorization: Basic $(echo -n 'hafizadmin:secret' | base64)"

Response:

{
  "users": [
    {
      "name": "alice",
      "access_key": "AKIAXXXXXXXXXXXXXXXX",
      "email": "alice@example.com",
      "description": "Development team member",
      "enabled": true,
      "created_at": "2024-01-15T10:00:00Z",
      "bucket_access": [
        {"bucket": "dev-bucket", "permission": "readwrite"}
      ],
      "is_admin": false
    }
  ],
  "total": 1
}

Get Specific User

curl http://localhost:9000/admin/users/AKIAXXXXXXXXXXXXXXXX \
    -H "Authorization: Basic $(echo -n 'hafizadmin:secret' | base64)"

Enable/Disable Users

# Disable user (revoke all access)
curl -X POST http://localhost:9000/admin/users/AKIAXXXXXXXXXXXXXXXX/disable \
    -H "Authorization: Basic $(echo -n 'hafizadmin:secret' | base64)"

# Enable user
curl -X POST http://localhost:9000/admin/users/AKIAXXXXXXXXXXXXXXXX/enable \
    -H "Authorization: Basic $(echo -n 'hafizadmin:secret' | base64)"

Rotate Credentials

curl -X POST http://localhost:9000/admin/users/AKIAXXXXXXXXXXXXXXXX/keys \
    -H "Authorization: Basic $(echo -n 'hafizadmin:secret' | base64)"

Response:

{
  "access_key": "AKIANEWKEYXXXXXXXXX",
  "secret_key": "newxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
  "created_at": "2024-01-15T12:00:00Z"
}

Delete User

curl -X DELETE http://localhost:9000/admin/users/AKIAXXXXXXXXXXXXXXXX \
    -H "Authorization: Basic $(echo -n 'hafizadmin:secret' | base64)"

Use Case Examples

Read-Only Backup User

curl -X POST http://localhost:9000/admin/users \
    -H "Authorization: Basic $(echo -n 'hafizadmin:secret' | base64)" \
    -H "Content-Type: application/json" \
    -d '{
      "name": "backup-reader",
      "description": "Backup service - read only access to all backups",
      "bucket_access": [
        {"bucket": "daily-backups", "permission": "read"},
        {"bucket": "weekly-backups", "permission": "read"},
        {"bucket": "monthly-backups", "permission": "read"}
      ]
    }'

Application Service Account

curl -X POST http://localhost:9000/admin/users \
    -H "Authorization: Basic $(echo -n 'hafizadmin:secret' | base64)" \
    -H "Content-Type: application/json" \
    -d '{
      "name": "webapp-service",
      "description": "Web application service account",
      "bucket_access": [
        {"bucket": "user-uploads", "permission": "readwrite"},
        {"bucket": "static-assets", "permission": "read"},
        {"bucket": "temp-files", "permission": "write"}
      ]
    }'

Replication Service User

curl -X POST http://localhost:9000/admin/users \
    -H "Authorization: Basic $(echo -n 'hafizadmin:secret' | base64)" \
    -H "Content-Type: application/json" \
    -d '{
      "name": "replication-service",
      "description": "Internal replication service for DR site",
      "bucket_access": [
        {"bucket": "production-data", "permission": "write"}
      ]
    }'

Public Bucket Access

Hafiz supports making buckets publicly accessible through bucket policies.

Enabling Public Access

To make a bucket publicly readable:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "PublicRead",
      "Effect": "Allow",
      "Principal": "*",
      "Action": ["s3:GetObject", "s3:ListBucket"],
      "Resource": [
        "arn:hafiz:s3:::my-public-bucket",
        "arn:hafiz:s3:::my-public-bucket/*"
      ]
    }
  ]
}

Web File Browser

Hafiz includes a built-in web file browser for non-technical users:

Access public buckets via: http://your-server:9000/browse/bucket-name

Presigned URLs

Generate time-limited URLs for temporary access without sharing credentials.

Generate Presigned Download URL

# Via Admin API
curl -X GET "http://localhost:9000/api/v1/presigned/download/my-bucket/file.pdf?expires_in=3600" \
    -H "Authorization: Bearer $TOKEN"

# Via AWS CLI
aws --endpoint-url http://localhost:9000 s3 presign s3://my-bucket/file.pdf --expires-in 3600

Generate Presigned Upload URL

# Via Admin API
curl -X GET "http://localhost:9000/api/v1/presigned/upload/my-bucket/uploads/file.pdf?expires_in=3600" \
    -H "Authorization: Bearer $TOKEN"

Presigned URL Response

{
  "url": "http://localhost:9000/my-bucket/file.pdf?X-Amz-Algorithm=AWS4-HMAC-SHA256&...",
  "expires_at": "2024-01-15T12:00:00Z",
  "bucket": "my-bucket",
  "key": "file.pdf"
}

Best Practices

  1. Principle of least privilege - Grant only necessary permissions
  2. Use bucket policies - Prefer policies over public access
  3. Enable TLS - Always use HTTPS in production
  4. Rotate credentials - Regular key rotation
  5. Audit access - Enable access logging
  6. Use presigned URLs - For temporary file sharing instead of making buckets public
  7. Set short expiry times - Keep presigned URL validity to minimum needed