x-s3

Create or use existing S3 buckets to use for your applications

Properties

For the properties, go to to AWS CFN S3 Definition

MacroParameters

Some use-cases require special adjustments. This is what this section is for.

NameSeparator

Default is - which separates the different parts of the bucket that you might have automatically added via the other MacroParameters

As shown below, the separator between the bucket name and AWS::AccountId or AWS::Region is -. This parameter allows you to define something else.

Note

I would recommend not more than 2 characters separator.

Warning

The separator must allow for DNS compliance [a-z0-9.-]

ExpandRegionToBucket

When definining the BucketName in properties, if wanted to, for uniqueness or readability, you can append to that string the region id (which is DNS compliant) to the bucket name.

Properties:
  BucketName: abcd-01
Settings:
  ExpandRegionToBucket: True

Results into

!Sub abcd-01-${AWS::Region}

ExpandAccountIdToBucket

Similar to ExpandRegionToBucket, it will append the account ID (additional or instead of).

Properties:
  BucketName: abcd-01
Settings:
  ExpandRegionToBucket: True

Results into

!Sub 'abcd-01-${AWS::AccountId}'

Hint

If you set both ExpandAccountIdToBucket and ExpandRegionToBucket, you end up with

!Sub 'abcd-01-${AWS::Region}-${AWS::AccountId}'

Services

As for all other resource types, you can define the type of access you want based to the S3 buckets. However, for buckets, this means distinguish the bucket and the objects resource.

permissions example
x-s3:
  bucketA:
    Properties: {}
    Settings: {}
    Services:
      - name: service-01
        access:
          objects: RW
          bucket: ListOnly

Lookup

Lookup is currently implemented for S3 buckets!

Hint

For S3, if the S3 bucket has a default KMS key encryption, the services will automatically be granted KMS default EncryptDecrypt permissions in order to allow using the KMS key for objects manipulation.

IAM Permissions

For S3 buckets, the access types is expecting a object with objects and bucket to distinguish permissions for each. If you indicate a string, the default permissions (bucket: ListOnly and objects: RW) will be applied.

Full access types policies definitions
{
    "objects": {
        "CRUD": {
            "Action": [
                "s3:GetObject",
                "s3:DeleteObject",
                "s3:PutObject",
                "s3:GetObjectTagging",
                "s3:GetObjectVersionTagging",
                "s3:PutObjectTagging",
                "s3:PutObjectVersionTagging",
                "s3:DeleteObjectTagging",
                "s3:DeleteObjectVersionTagging",
                "s3:AbortMultipartUpload",
                "s3:PutObjectAcl"
            ],
            "Effect": "Allow"
        },
        "RW": {
            "Action": [
                "s3:GetObject*",
                "s3:PutObject*"
            ],
            "Effect": "Allow"
        },
        "StrictRW": {
            "Action": [
                "s3:GetObject",
                "s3:PutObject"
            ],
            "Effect": "Allow"
        },
        "StrictRWDelete": {
            "Action": [
                "s3:GetObject",
                "s3:PutObject",
                "s3:DeleteObject"
            ],
            "Effect": "Allow"
        },
        "RWDelete": {
            "Action": [
                "s3:GetObject*",
                "s3:PutObject*",
                "s3:DeleteObject*"
            ],
            "Effect": "Allow"
        },
        "ReadOnly": {
            "Action": [
                "s3:GetObject*"
            ],
            "Effect": "Allow"
        },
        "StrictReadOnly": {
            "Action": [
                "s3:GetObject"
            ],
            "Effect": "Allow"
        },
        "WriteOnly": {
            "Action": [
                "s3:PutObject*"
            ],
            "Effect": "Allow"
        },
        "StrictWriteOnly": {
            "Action": [
                "s3:PutObject"
            ],
            "Effect": "Allow"
        }
    },
    "bucket": {
        "ListOnly": {
            "Effect": "Allow",
            "Action": [
                "s3:ListBucket",
                "s3:GetBucketLocation",
                "s3:GetBucketPublicAccessBlock"
            ]
        },
        "PowerUser": {
            "Effect": "Allow",
            "Action": [
                "s3:ListBucket",
                "s3:GetBucket*",
                "s3:SetBucket*"
            ]
        }
    }
}

Examples

Create new S3 buckets
version: "3.8"

x-s3:
  bucket-01:
    Properties:
      BucketName: bucket-01
      AccessControl: BucketOwnerFullControl
      ObjectLockEnabled: True
      PublicAccessBlockConfiguration:
          BlockPublicAcls: True
          BlockPublicPolicy: True
          IgnorePublicAcls: True
          RestrictPublicBuckets: False
      AccelerateConfiguration:
        AccelerationStatus: Suspended
      BucketEncryption:
        ServerSideEncryptionConfiguration:
          - ServerSideEncryptionByDefault:
              SSEAlgorithm: "aws:kms"
              KMSMasterKeyID: "aws/s3"
      VersioningConfiguration:
        Status: "Enabled"
    MacroParameters:
      ExpandRegionToBucket: True
      ExpandAccountIdToBucket: True
    Settings:
      EnvNames:
        - bucket01
        - BUCKET_ABCD-01
    Services:
      - name: app03
        access: RWObjects
  bucket-03:
    Properties:
      BucketName: bucket-03
      AccessControl: BucketOwnerFullControl
      ObjectLockEnabled: True
      PublicAccessBlockConfiguration:
          BlockPublicAcls: True
          BlockPublicPolicy: True
          IgnorePublicAcls: True
          RestrictPublicBuckets: False
      AccelerateConfiguration:
        AccelerationStatus: Suspended
      BucketEncryption:
        ServerSideEncryptionConfiguration:
          - ServerSideEncryptionByDefault:
              SSEAlgorithm: AES256
      VersioningConfiguration:
        Status: "Enabled"

    Settings:
      ExpandRegionToBucket: True
      ExpandAccountIdToBucket: False
      EnvNames:
        - bucket01
        - BUCKET_ABCD-01
    Services:
      - name: app03
        access: RWObjects
  bucket-02:
    Properties: {}
    Settings:
      ExpandRegionToBucket: False
      ExpandAccountIdToBucket: False
      EnableEncryption: AES256
      EnableAcceleration: True
      EnvNames:
        - bucket01
        - BUCKET_ABCD-01
    Services:
      - name: app03
        access:
          bucket: ListOnly
          objects: RW

  bucket-04:
    Properties:
      BucketName: bucket-04
    Settings:
      NameSeparator: "."
      ExpandRegionToBucket: False
      ExpandAccountIdToBucket: False
      EnableEncryption: AES256
      EnableAcceleration: True
      EnvNames:
        - bucket01
        - BUCKET_ABCD-01
    Services:
      - name: app03
        access:
          bucket: ListOnly
          objects: RW
Lookup and use only existing buckets
version: "3.8"

x-s3:
  bucket-07:
    Lookup:
      Tags:
        - aws:cloudformation:logical-id: ArtifactsBucket
        - aws:cloudformation:stack-name: pipeline-shared-buckets
    Services:
      - name: app03
        access:
          bucket: PowerUser
          objects: RW

  bucket-08:
    Settings:
      EnvNames:
        - BUCKET03
    Lookup:
      Name: sacrificial-lamb
      Tags:
        - composex: "True"
    Services:
      - name: app03
        access:
          bucket: PowerUser
          objects: RW
Create new bucket with AWS CFN properties
version: "3.8"

x-s3:
  bucket-01:
    Properties:
      BucketName: bucket-01
      AccessControl: BucketOwnerFullControl
      AccelerateConfiguration:
        AccelerationStatus: Suspended
      ObjectLockEnabled: True
      PublicAccessBlockConfiguration:
        BlockPublicAcls: True
        BlockPublicPolicy: True
        IgnorePublicAcls: True
        RestrictPublicBuckets: False
      BucketEncryption:
        ServerSideEncryptionConfiguration:
          - ServerSideEncryptionByDefault:
              SSEAlgorithm: "aws:kms"
              KMSMasterKeyID: "aws/s3"
      VersioningConfiguration:
        Status: "Enabled"
      MetricsConfigurations:
        - Id: EntireBucket
      LifecycleConfiguration:
        Rules:
          - Id: GlacierRule
            Prefix: glacier
            Status: Enabled
            ExpirationInDays: '365'
            Transitions:
              - TransitionInDays: '1'
                StorageClass: GLACIER
      CorsConfiguration:
        CorsRules:
          - AllowedHeaders:
              - '*'
            AllowedMethods:
              - GET
            AllowedOrigins:
              - '*'
            ExposedHeaders:
              - Date
            Id: myCORSRuleId1
            MaxAge: '3600'
          - AllowedHeaders:
              - x-amz-*
            AllowedMethods:
              - DELETE
            AllowedOrigins:
              - 'http://www.example.com'
              - 'http://www.example.net'
            ExposedHeaders:
              - Connection
              - Server
              - Date
            Id: myCORSRuleId2
            MaxAge: '1800'
      WebsiteConfiguration:
        IndexDocument: index.html
        ErrorDocument: error.html
        RoutingRules:
          - RoutingRuleCondition:
              HttpErrorCodeReturnedEquals: '404'
              KeyPrefixEquals: out1/
            RedirectRule:
              HostName: ec2-11-22-333-44.compute-1.amazonaws.com
              ReplaceKeyPrefixWith: report-404/
      NotificationConfiguration:
        TopicConfigurations:
          - Topic: 'arn:aws:sns:us-east-1:123456789012:TestTopic'
            Event: 's3:ReducedRedundancyLostObject'
    MacroParameters:
      ExpandRegionToBucket: True
      ExpandAccountIdToBucket: True
    Settings:
      EnvNames:
        - bucket01
        - BUCKET_ABCD-01
    Services:
      - name: app03
        access: RWObjects