Skip to main content

S3 with Encryption

This example shows how to back up RabbitMQ messages to S3 with server-side encryption and IAM roles instead of static credentials.

Server-Side Encryption Options

AWS S3 supports three types of server-side encryption:

TypeKey ManagementConfig
SSE-S3AWS-managed keysDefault on most buckets
SSE-KMSAWS KMS customer-managed keyRequires KMS key ARN
SSE-CCustomer-provided keyKey sent with each request

rabbitmq-backup uses the object_store crate, which works with SSE-S3 and SSE-KMS transparently when configured at the bucket level.

Step 1: Enable Default Encryption on the Bucket

SSE-S3 (AES-256)

aws s3api put-bucket-encryption \
--bucket rabbitmq-backups-encrypted \
--server-side-encryption-configuration '{
"Rules": [
{
"ApplyServerSideEncryptionByDefault": {
"SSEAlgorithm": "AES256"
},
"BucketKeyEnabled": true
}
]
}'

SSE-KMS (Customer Managed Key)

# Create a KMS key
KMS_KEY_ID=$(aws kms create-key \
--description "RabbitMQ backup encryption key" \
--query 'KeyMetadata.KeyId' --output text)

# Create an alias for easy reference
aws kms create-alias \
--alias-name alias/rabbitmq-backup \
--target-key-id $KMS_KEY_ID

# Enable SSE-KMS on the bucket
aws s3api put-bucket-encryption \
--bucket rabbitmq-backups-encrypted \
--server-side-encryption-configuration "{
\"Rules\": [
{
\"ApplyServerSideEncryptionByDefault\": {
\"SSEAlgorithm\": \"aws:kms\",
\"KMSMasterKeyID\": \"$KMS_KEY_ID\"
},
\"BucketKeyEnabled\": true
}
]
}"

Step 2: Create an IAM Policy

The IAM policy must include KMS permissions when using SSE-KMS:

rabbitmq-backup-policy-encrypted.json
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "S3Access",
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:GetObject",
"s3:DeleteObject",
"s3:ListBucket",
"s3:GetBucketLocation"
],
"Resource": [
"arn:aws:s3:::rabbitmq-backups-encrypted",
"arn:aws:s3:::rabbitmq-backups-encrypted/*"
]
},
{
"Sid": "KMSAccess",
"Effect": "Allow",
"Action": [
"kms:Decrypt",
"kms:GenerateDataKey",
"kms:DescribeKey"
],
"Resource": "arn:aws:kms:us-east-1:123456789012:key/YOUR-KMS-KEY-ID"
}
]
}
aws iam create-policy \
--policy-name RabbitMQBackupEncryptedPolicy \
--policy-document file://rabbitmq-backup-policy-encrypted.json

Step 3: Use IAM Roles (No Static Credentials)

EC2 Instance Profile

Attach the policy to an IAM role used by the EC2 instance:

# Create the role
aws iam create-role \
--role-name rabbitmq-backup-role \
--assume-role-policy-document '{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": { "Service": "ec2.amazonaws.com" },
"Action": "sts:AssumeRole"
}]
}'

# Attach the policy
aws iam attach-role-policy \
--role-name rabbitmq-backup-role \
--policy-arn arn:aws:iam::123456789012:policy/RabbitMQBackupEncryptedPolicy

# Create instance profile and attach role
aws iam create-instance-profile --instance-profile-name rabbitmq-backup
aws iam add-role-to-instance-profile \
--instance-profile-name rabbitmq-backup \
--role-name rabbitmq-backup-role

EKS (IRSA)

serviceaccount.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: rabbitmq-backup
namespace: rabbitmq-backup
annotations:
eks.amazonaws.com/role-arn: arn:aws:iam::123456789012:role/rabbitmq-backup-role

Step 4: Configure rabbitmq-backup

With IAM roles, no credentials are needed in the config:

backup-s3-encrypted.yaml
mode: backup
backup_id: "encrypted-backup-001"

source:
amqp_url: "amqp://backup_user:${RABBITMQ_PASSWORD}@rabbitmq.example.com:5672/%2f"
management_url: "http://rabbitmq.example.com:15672"
management_username: backup_user
management_password: "${RABBITMQ_PASSWORD}"
queues:
include:
- "*"

storage:
backend: s3
bucket: rabbitmq-backups-encrypted
region: us-east-1
prefix: prod/
# No access_key or secret_key -- uses IAM role

backup:
compression: zstd
compression_level: 3
prefetch_count: 100
max_concurrent_queues: 4
include_definitions: true
stop_at_current_depth: true

offset_storage:
backend: sqlite
db_path: ./offsets.db
s3_key: state/offsets.db
sync_interval_secs: 30

metrics:
enabled: true
port: 8080

Step 5: Run the Backup

rabbitmq-backup backup --config backup-s3-encrypted.yaml

Step 6: Verify Encryption

Check that objects are encrypted:

aws s3api head-object \
--bucket rabbitmq-backups-encrypted \
--key prod/encrypted-backup-001/manifest.json \
--query 'ServerSideEncryption'

Expected output for SSE-S3:

"AES256"

Expected output for SSE-KMS:

"aws:kms"

Step 7: Restore from Encrypted Backup

The restore configuration is identical -- S3 handles decryption transparently:

restore-s3-encrypted.yaml
mode: restore
backup_id: "encrypted-backup-001"

target:
amqp_url: "amqp://admin:${RABBITMQ_PASSWORD}@rabbitmq.example.com:5672/%2f"
management_url: "http://rabbitmq.example.com:15672"
management_username: admin
management_password: "${RABBITMQ_PASSWORD}"

storage:
backend: s3
bucket: rabbitmq-backups-encrypted
region: us-east-1
prefix: prod/

restore:
restore_definitions: true
publish_mode: exchange
publisher_confirms: true
rabbitmq-backup restore --config restore-s3-encrypted.yaml

Additional Security: Bucket Policy

Deny unencrypted uploads to the bucket:

bucket-policy.json
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DenyUnencryptedUploads",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:PutObject",
"Resource": "arn:aws:s3:::rabbitmq-backups-encrypted/*",
"Condition": {
"StringNotEquals": {
"s3:x-amz-server-side-encryption": ["AES256", "aws:kms"]
}
}
},
{
"Sid": "DenyInsecureTransport",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::rabbitmq-backups-encrypted",
"arn:aws:s3:::rabbitmq-backups-encrypted/*"
],
"Condition": {
"Bool": { "aws:SecureTransport": "false" }
}
}
]
}
aws s3api put-bucket-policy \
--bucket rabbitmq-backups-encrypted \
--policy file://bucket-policy.json

Checklist

  • Bucket created with default encryption enabled
  • IAM policy includes S3 and KMS permissions
  • IAM role attached (instance profile, IRSA, or static credentials)
  • No credentials in config file (using IAM role)
  • Bucket policy denies unencrypted uploads
  • Bucket policy enforces HTTPS
  • Backup runs successfully
  • Objects verified as encrypted via head-object