Storage (S3)
S3 buckets with full feature parity — versioning, encryption, lifecycle rules, CORS, event notifications, static website hosting, Object Lock, and more.
API Group:
aws.konfig.io/v1alpha1
S3Bucket # ✅ Working
Creates and manages an S3 bucket with comprehensive configuration. All sub-configurations (versioning, encryption, lifecycle, CORS, notifications, website, Object Lock, logging) are applied idempotently on every reconcile.
Spec
| Field | Type | Required | Description |
|---|---|---|---|
| bucketName | string | ✅ | Globally unique bucket name. Immutable after creation. |
| region | string | AWS region for the bucket. Required for non-us-east-1 regions. Immutable. | |
| versioning | bool | Enable S3 versioning. | |
| serverSideEncryption.sseAlgorithm | string | AES256 or aws:kms. | |
| serverSideEncryption.kmsKeyId | string | KMS key ID or ARN (for aws:kms algorithm). | |
| blockPublicAccess.blockPublicAcls | bool | Block public ACLs. | |
| blockPublicAccess.blockPublicPolicy | bool | Block public bucket policies. | |
| blockPublicAccess.ignorePublicAcls | bool | Ignore public ACLs. | |
| blockPublicAccess.restrictPublicBuckets | bool | Restrict public bucket access. | |
| lifecycleRules | []LifecycleRule | Object lifecycle rules. | |
| lifecycleRules[].id | string | Unique rule ID. | |
| lifecycleRules[].status | string | Enabled or Disabled. | |
| lifecycleRules[].prefix | string | Object key prefix filter. | |
| lifecycleRules[].expirationDays | int32 | Days after object creation to expire. | |
| lifecycleRules[].expirationDate | string | Specific date for expiration (RFC3339). | |
| lifecycleRules[].noncurrentVersionExpirationDays | int32 | Days after a version becomes non-current to expire it. | |
| lifecycleRules[].transitions | []Transition | Storage class transitions. Each: days or date, storageClass. | |
| lifecycleRules[].noncurrentVersionTransitions | []NoncurrentTransition | Noncurrent version transitions. Each: noncurrentDays, storageClass. | |
| lifecycleRules[].abortIncompleteMultipartUploadDays | int32 | Days after initiation to abort incomplete multipart uploads. | |
| corsRules | []CORSRule | CORS configuration rules. | |
| corsRules[].id | string | Optional rule ID. | |
| corsRules[].allowedHeaders | []string | Allowed request headers. | |
| corsRules[].allowedMethods | []string | Allowed HTTP methods (GET, PUT, POST, DELETE, HEAD). | |
| corsRules[].allowedOrigins | []string | Allowed origin domains. | |
| corsRules[].exposeHeaders | []string | Response headers to expose to browsers. | |
| corsRules[].maxAgeSeconds | int32 | Browser preflight cache duration in seconds. | |
| notificationConfig.lambdaFunctionConfigurations | []LambdaNotification | Lambda function event notifications. Each: id, lambdaFunctionARN, events ([]string), filterPrefix, filterSuffix. | |
| notificationConfig.queueConfigurations | []QueueNotification | SQS queue event notifications. Same fields with queueArn. | |
| notificationConfig.topicConfigurations | []TopicNotification | SNS topic event notifications. Same fields with topicArn. | |
| notificationConfig.eventBridgeEnabled | bool | Send all events to EventBridge. | |
| websiteConfig.indexDocument | string | Index document filename (e.g. index.html). | |
| websiteConfig.errorDocument | string | Error document filename (e.g. error.html). | |
| websiteConfig.redirectAllTo.hostName | string | Redirect all requests to this hostname. | |
| websiteConfig.redirectAllTo.protocol | string | Protocol for redirect: http or https. | |
| websiteConfig.routingRules | string | JSON routing rules for conditional redirects. | |
| accelerateStatus | string | Enabled or Suspended. Transfer Acceleration. | |
| objectLockConfig.objectLockEnabled | string | Enabled. Immutable once set at bucket creation. | |
| objectLockConfig.rule.defaultRetention.mode | string | GOVERNANCE or COMPLIANCE. | |
| objectLockConfig.rule.defaultRetention.days | int32 | Retention period in days. | |
| objectLockConfig.rule.defaultRetention.years | int32 | Retention period in years (mutually exclusive with days). | |
| loggingConfig.targetBucket | string | Destination bucket name for server access logs. | |
| loggingConfig.targetPrefix | string | Key prefix for log objects. | |
| tags | map[string]string | AWS tags applied to the bucket. |
Status
| Field | Description |
|---|---|
| arn | The ARN of the bucket (e.g. arn:aws:s3:::my-bucket). |
| domainName | The bucket's regional domain name (e.g. my-bucket.s3.us-east-1.amazonaws.com). |
| websiteEndpoint | Static website hosting endpoint (if websiteConfig is configured). |
| conditions | Standard Kubernetes conditions. |
| observedGeneration | Last reconciled generation. |
| lastSyncTime | RFC3339 timestamp of last sync. |
Example — Basic with Encryption
yaml
apiVersion: aws.konfig.io/v1alpha1
kind: S3Bucket
metadata:
name: prod-app-data
namespace: storage
spec:
bucketName: my-company-prod-app-data
region: us-east-1
versioning: true
serverSideEncryption:
sseAlgorithm: aws:kms
kmsKeyId: arn:aws:kms:us-east-1:123456789012:key/mrk-abc123
blockPublicAccess:
blockPublicAcls: true
blockPublicPolicy: true
ignorePublicAcls: true
restrictPublicBuckets: true
loggingConfig:
targetBucket: my-company-access-logs
targetPrefix: prod-app-data/
tags:
env: prod
team: platform
Example — Full-Featured with Lifecycle and Notifications
yaml
apiVersion: aws.konfig.io/v1alpha1
kind: S3Bucket
metadata:
name: prod-media-bucket
namespace: storage
spec:
bucketName: my-company-prod-media
region: us-east-1
versioning: true
serverSideEncryption:
sseAlgorithm: AES256
blockPublicAccess:
blockPublicAcls: true
blockPublicPolicy: true
ignorePublicAcls: true
restrictPublicBuckets: true
lifecycleRules:
- id: transition-to-ia
status: Enabled
prefix: uploads/
transitions:
- days: 30
storageClass: STANDARD_IA
- days: 90
storageClass: GLACIER
noncurrentVersionTransitions:
- noncurrentDays: 30
storageClass: STANDARD_IA
noncurrentVersionExpirationDays: 90
abortIncompleteMultipartUploadDays: 7
notificationConfig:
queueConfigurations:
- id: new-upload-notify
queueArn: arn:aws:sqs:us-east-1:123456789012:media-processing-queue
events:
- s3:ObjectCreated:*
filterPrefix: uploads/
eventBridgeEnabled: true
tags:
env: prod
team: media
Example — Static Website with CORS
yaml
apiVersion: aws.konfig.io/v1alpha1
kind: S3Bucket
metadata:
name: prod-static-site
namespace: storage
spec:
bucketName: my-company-www
region: us-east-1
versioning: false
serverSideEncryption:
sseAlgorithm: AES256
websiteConfig:
indexDocument: index.html
errorDocument: 404.html
corsRules:
- id: allow-cdn
allowedMethods:
- GET
- HEAD
allowedOrigins:
- https://www.example.com
- https://app.example.com
allowedHeaders:
- "*"
exposeHeaders:
- ETag
maxAgeSeconds: 3600
tags:
env: prod
purpose: static-website
Notes
- Bucket names are globally unique across all AWS accounts and regions.
- The
regionfield is required for any region other thanus-east-1. It is immutable after creation. - All sub-configurations (versioning, encryption, lifecycle, CORS, notifications, website, logging) are applied idempotently — each has its own AWS API call and is reconciled independently.
objectLockConfig.objectLockEnabledcan only be set at bucket creation time and cannot be changed afterward.
Deletion
Blocked if bucket not empty. S3 does not allow deletion of non-empty buckets. Empty the bucket (delete all objects and versions) before deleting the CR. For versioned buckets, all versions and delete markers must be removed.
S3BucketPolicy # ✅ Working
Attaches a resource-based IAM policy to an S3 bucket. The controller waits for the referenced S3Bucket CR to be Ready before creating the policy.
Spec
| Field | Type | Required | Description |
|---|---|---|---|
| bucketRef.name | string | ✅ | Name of the S3Bucket CR in the same namespace. |
| bucketRef.bucketName | string | Direct bucket name (alternative to bucketRef.name). | |
| policyDocument | string | ✅ | JSON IAM policy document for the bucket resource policy. |
Status
| Field | Description |
|---|---|
| conditions | Standard Kubernetes conditions. |
| observedGeneration | Last reconciled generation. |
| lastSyncTime | RFC3339 timestamp of last sync. |
Example — HTTPS-Only Policy
yaml
apiVersion: aws.konfig.io/v1alpha1
kind: S3BucketPolicy
metadata:
name: prod-app-data-https-only
namespace: storage
spec:
bucketRef:
name: prod-app-data
policyDocument: |
{
"Version": "2012-10-17",
"Statement": [{
"Sid": "DenyHTTP",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::my-company-prod-app-data",
"arn:aws:s3:::my-company-prod-app-data/*"
],
"Condition": {
"Bool": { "aws:SecureTransport": "false" }
}
}]
}
Example — Cross-Account Read Access
yaml
apiVersion: aws.konfig.io/v1alpha1
kind: S3BucketPolicy
metadata:
name: prod-app-data-cross-account
namespace: storage
spec:
bucketRef:
name: prod-app-data
policyDocument: |
{
"Version": "2012-10-17",
"Statement": [{
"Sid": "AllowCrossAccountRead",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::987654321012:role/analytics-role"
},
"Action": ["s3:GetObject", "s3:ListBucket"],
"Resource": [
"arn:aws:s3:::my-company-prod-app-data",
"arn:aws:s3:::my-company-prod-app-data/*"
]
}]
}
Notes
- The controller waits for the
S3BucketCR to be Ready before applying the policy. - ARNs in the policy document must be specified manually — the operator does not automatically resolve CR references within the JSON.
- Policy changes replace the entire bucket policy (no delta merge).
Deletion
Immediate. The bucket policy is deleted. The bucket itself is not affected.