- Newest
- Most votes
- Most comments
Hi,
I'd suggest you a solution with another level of indirection. I use this solution often:
- Add an SSM Parameter to your template: https://docs.aws.amazon.com/fr_fr/AWSCloudFormation/latest/UserGuide/aws-resource-ssm-parameter.html
- Apply the condition to the
Valuefield of the Parameter to either choose the existing bucket or create the new one - Use !GetAtt on Value
!GetAtt <logicalNameOfYourParameter>.Valuewherever you need to use the bucket name
Best,
Didier
To conditionally create or link an existing S3 bucket in a CloudFormation template based on a parameter, you can use a combination of Parameters, Conditions, and Resources sections. Here's how you can approach this:
-
Define a parameter: In the Parameters section, define a parameter called 'CreateBucket' of type String with allowed values 'true' and 'false'.
-
Create a condition: In the Conditions section, create a condition that evaluates whether to create a new bucket:
Conditions: ShouldCreateBucket: !Equals [!Ref CreateBucket, 'true']
- Define the S3 bucket resource: In the Resources section, define the S3 bucket with a condition:
Resources: MyS3Bucket: Type: AWS::S3::Bucket Condition: ShouldCreateBucket Properties: # Add your bucket properties here
-
For referencing an existing bucket: Create a parameter for the existing bucket name and use it when CreateBucket is 'false'.
-
Use the !If function to reference the correct bucket: When applying the bucket policy or referencing the bucket elsewhere in your template, use the !If function to choose between the newly created bucket and the existing one:
BucketPolicy: Type: AWS::S3::BucketPolicy Properties: Bucket: !If - ShouldCreateBucket - !Ref MyS3Bucket - !Ref ExistingBucketName # Rest of your policy definition
Regarding your specific issues:
- The error "Every Condition member must be a string" typically occurs when you're trying to use a condition directly in a resource's Condition property. Instead, use the condition in the resource definition itself, as shown above.
- For referencing the ARN of the bucket, you can use the !GetAtt function for the new bucket and construct the ARN for the existing bucket:
BucketArn: !If - ShouldCreateBucket - !GetAtt MyS3Bucket.Arn - !Sub 'arn:aws:s3:::${ExistingBucketName}'
As for your question about reusing existing resources, CloudFormation doesn't automatically check for existing resources with the same name. However, you can use a custom resource with a Lambda function to check if a resource exists and return its details if it does. This way, you can either create a new resource or use an existing one based on the Lambda function's response.
Remember to set appropriate DeletionPolicy and UpdateReplacePolicy attributes on your resources to control their lifecycle during stack updates and deletions.
Sources
AWS::S3::Bucket - AWS CloudFormation
CloudFormation template Resources syntax - AWS CloudFormation
CloudFormation template Conditions syntax - AWS CloudFormation
answered 2 years ago
CloudFormation isn't meant to be used this way. It is a declarative language, intended to declare the desired target state of your resources, rather than being a procedural programming language that would inspect the state of resources outside the CFN stack and take different actions depending on the results of the checks.
The specific thing you're asking about you can technically accomplish by doing mostly what you're doing already: conditionally create the bucket depending on your parameter value, and when it isn't created, reference the name of the bucket in the Bucket propery of the AWS::S3::BucketPolicy resource, rather than trying to create an AWS::S3::Bucket resource for a bucket that exists already.
However, this isn't a good use of CloudFormation. For example, if a bucket policy already exists and contains other statements besides your preferred TLS restriction, setting a new bucket policy with CFN will either fail or overwrite the existing policy. It won't add the TLS restriction statement to an existing bucket policy. Also, even if setting the bucket policy succeeds but someone manually modifies the bucket policy later, the CFN stack will go into a drifted state and may behave unpredictably if ever updated.
The proper way to use CloudFormation would be to have it manage all the resources you configure via it. If you have previously created buckets and bucket policies manually via the console, for example, you should import each one into a CFN stack and make all the configuration changes there. If you want to keep some S3 buckets managed manually, you should modify or replace the bucket policies via the CLI or console, without going through CloudFormation.

Is it possible only with cloudformation template. It will only check if the resource is exist or not if its exist it will map it into cloudformation otherwise it will create that resource.?