I have defined an S3 bucket in my serverless.yml file as follows:
resources:
Resources:
nameOfS3Bucket:
Type: AWS::S3::Bucket
Properties:
BucketName: ${self:custom.stage}-name-of-s3-bucket
AccessControl: Private
What I would like to do now is to reference the arn of the bucket in an IAM role which is also defined as a resource e.g.
resources:
Resources:
# s3 bucket definition removed for brevity
iamRoleName:
Type: AWS::IAM::Role
Properties:
RoleName: ${self:custom.stage}-iam-role-name
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
Service:
- lambda.amazonaws.com
Action: sts:AssumeRole
Policies:
- PolicyName: ${self:custom.stage}-iam-role-policy
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action: "s3:PutObject"
Resource: *** Need the ARN of the s3 bucket here***
Is there a way to do this?
In my experience, the intrinsic functions in cloudformation work fine inside serverless.yml, but not the yaml short form.
i.e. use Fn::GetAtt over !GetAtt
As long as you use the full syntax for yaml, it should work.
Try this (untested)
resources:
Resources:
nameOfS3Bucket:
Type: AWS::S3::Bucket
Properties:
BucketName: ${self:custom.stage}-name-of-s3-bucket
AccessControl: Private
iamRoleName:
Type: AWS::IAM::Role
Properties:
RoleName: ${self:custom.stage}-iam-role-name
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
Service:
- lambda.amazonaws.com
Action: sts:AssumeRole
Policies:
- PolicyName: ${self:custom.stage}-iam-role-policy
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action: "s3:PutObject"
Resource:
"Fn::GetAtt": [ nameOfS3Bucket, Arn ]
Related
Trying to get CodeBuild to push notifications to an SNS topic (bound to a Lambda), via a CloudWatch Events Rule.
Cloudformation template (see below) deploys fine.
CodeBuild process works fine (have tested).
SNS topic and bound Lambda work fine - I can push a message to the topic via AWS CLI and see Lambda dump that message to Cloudwatch logs.
The Cloudwatch Event Rule seems to be configured fine - I can see it in the cosole, it looks well formed, seems to be bound to SNS topic.
In addition I have been careful to give the Event Rule a role with permissions to sns:Publish, and also defined an AWS::SNS::TopicPolicy for the SNS topic -
Unable to successfully set up SNS on CodeBuild project through CFT but works manually
But still nothing - CodeBuild successfully completes but I don't receive any notifications.
Any thoughts as to what might be wrong ?
TIA :)
---
AWSTemplateFormatVersion: '2010-09-09'
Parameters:
AppName:
Type: String
StagingBucket:
Type: String
RepoOwner:
Type: String
RepoName:
Type: String
RepoBranch:
Type: String
RepoPAT:
Type: String
CodeBuildBuildSpec:
Type: String
CodeBuildType:
Type: String
Default: LINUX_CONTAINER
CodeBuildComputeType:
Type: String
Default: BUILD_GENERAL1_SMALL
CodeBuildImage:
Type: String
Default: aws/codebuild/standard:4.0
LambdaHandler:
Type: String
Default: "index.handler"
LambdaMemory:
Type: Number
Default: 128
LambdaTimeout:
Type: Number
Default: 30
LambdaRuntime:
Type: String
Default: python3.8
Resources:
CodeBuildProject:
DependsOn:
- CodeBuildSourceCredential
Properties:
Environment:
ComputeType:
Ref: CodeBuildComputeType
Image:
Ref: CodeBuildImage
Type:
Ref: CodeBuildType
Name:
Ref: AppName
ServiceRole:
Fn::GetAtt:
- CodeBuildRole
- Arn
Source:
Location:
Fn::Sub:
- "https://github.com/${repo_owner}/${repo_name}.git"
- repo_owner:
Ref: RepoOwner
repo_name:
Ref: RepoName
Type: GITHUB
BuildSpec:
Fn::Sub:
- "${build_spec}"
- build_spec:
Ref: CodeBuildBuildSpec
Artifacts:
Type: S3
Location:
Ref: StagingBucket
SourceVersion:
Ref: RepoBranch
Triggers:
Webhook: true
FilterGroups:
- - Type: EVENT
Pattern: PUSH
ExcludeMatchedPattern: false
- Type: HEAD_REF
Pattern: "refs/tags/.*"
ExcludeMatchedPattern: false
Type: AWS::CodeBuild::Project
CodeBuildSourceCredential:
Type: AWS::CodeBuild::SourceCredential
Properties:
Token:
Ref: RepoPAT
ServerType: GITHUB
AuthType: PERSONAL_ACCESS_TOKEN
CodeBuildRole:
Properties:
AssumeRolePolicyDocument:
Statement:
- Action: sts:AssumeRole
Effect: Allow
Principal:
Service: codebuild.amazonaws.com
Version: '2012-10-17'
ManagedPolicyArns:
- arn:aws:iam::aws:policy/AdministratorAccess
Path: /
Type: AWS::IAM::Role
CodeBuildNotificationFunction:
Properties:
Code:
ZipFile: "def handler(event, context):\n print (event)"
Handler:
Ref: LambdaHandler
MemorySize:
Ref: LambdaMemory
Role:
Fn::GetAtt:
- CodeBuildNotificationFunctionRole
- Arn
Runtime:
Ref: LambdaRuntime
Timeout:
Ref: LambdaTimeout
Type: AWS::Lambda::Function
CodeBuildNotificationFunctionRole:
Properties:
AssumeRolePolicyDocument:
Statement:
- Action: sts:AssumeRole
Effect: Allow
Principal:
Service: lambda.amazonaws.com
Version: '2012-10-17'
Policies:
- PolicyDocument:
Statement:
- Action:
- logs:CreateLogGroup
- logs:CreateLogStream
- logs:PutLogEvents
Effect: Allow
Resource: '*'
Version: '2012-10-17'
PolicyName: code-build-notification-role-policy
Type: AWS::IAM::Role
CodeBuildNotificationTopic:
Properties:
Subscription:
- Protocol: lambda
Endpoint:
Fn::GetAtt:
- CodeBuildNotificationFunction
- Arn
Type: AWS::SNS::Topic
CodeBuildNotificationTopicPolicy:
Properties:
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
Service: "events.amazonaws.com"
Action:
- "sns:Publish"
Resource:
Ref: CodeBuildNotificationTopic
Topics:
- Ref: CodeBuildNotificationTopic
Type: AWS::SNS::TopicPolicy
CodeBuildNotificationLambdaInvokePermission:
Properties:
Action: "lambda:InvokeFunction"
FunctionName:
Ref: CodeBuildNotificationFunction
Principal: "sns.amazonaws.com"
SourceArn:
Ref: CodeBuildNotificationTopic
Type: AWS::Lambda::Permission
SampleNotificationRule:
Type: AWS::Events::Rule
Properties:
EventPattern:
Fn::Sub:
- '{"source": ["aws.codebuild"], "detail-type": ["Codebuild Build Phase Change"], "detail": {"completed-phase": ["SUBMITTED", "PROVISIONING", "DOWNLOAD_SOURCE", "INSTALL", "PRE_BUILD", "BUILD", "POST_BUILD", "UPLOAD_ARTIFACTS", "FINALIZING"], "completed-phase-status": ["TIMED_OUT", "STOPPED", "FAILED", "SUCCEEDED", "FAULT", "CLIENT_ERROR"], "project-name": ["${project_name}"]}}'
- project_name:
Ref: CodeBuildProject
State: ENABLED
RoleArn:
Fn::GetAtt:
- SampleNotificationRuleRole
- Arn
Targets:
- Arn:
Ref: CodeBuildNotificationTopic
Id: sample-notification
SampleNotificationRuleRole:
Properties:
AssumeRolePolicyDocument:
Statement:
- Action: sts:AssumeRole
Effect: Allow
Principal:
Service: events.amazonaws.com
Version: '2012-10-17'
Policies:
- PolicyDocument:
Statement:
- Action:
- "sns:Publish"
Effect: Allow
Resource: '*'
Version: '2012-10-17'
PolicyName: sample-notification-rule-role-policy
Type: AWS::IAM::Role
Fixed - AWS::Events::Rule target was missing an InputTransformer block like so
Targets:
- Arn:
Ref: CodeBuildNotificationTopic
Id: sample-notification
InputTransformer:
InputPathsMap:
build-id: "$.detail.build-id"
project-name: "$.detail.project-name"
completed-phase: "$.detail.completed-phase"
completed-phase-status: "$.detail.completed-phase-status"
InputTemplate: |
"Build '<build-id>' for build project '<project-name>' has completed the build phase of '<completed-phase>' with a status of '<completed-phase-status>'."
I am creating an S3 bucket in a SAM template and would like to give it public read access. This is what I came up with so far:
ProductBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: !Sub ${ProductBucketName}${Stage}
ProductBucketPolicy:
Type: AWS::S3::BucketPolicy
Properties:
Bucket: !Ref ProductBucket
PolicyDocument:
Id: PublicReadPolicy
Version: 2012-10-17
Statement:
- Sid: PublicReadForGetBucketObjects
Effect: Allow
Principal: '*'
Action: 's3:GetObject'
Resource: !Join
- ''
- - 'arn:aws:s3:::'
- !Ref ProductBucket
This fails with a malformed exception.
Your template is fine except the line that says - - 'arn:aws:s3:::' where its malformed. Just a suggestion that you can use Fn::Sub over Fn::Join when delimiter is an empty string.
AWSTemplateFormatVersion: "2010-09-09"
Parameters:
ProductBucketName:
Type: String
Resources:
ProductBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: !Sub ${ProductBucketName}-${AWS::StackName}
ProductBucketPolicy:
Type: AWS::S3::BucketPolicy
Properties:
Bucket: !Ref ProductBucket
PolicyDocument:
Id: PublicReadPolicy
Version: 2012-10-17
Statement:
- Sid: PublicReadForGetBucketObjects
Effect: Allow
Principal: '*'
Action: 's3:GetObject'
Resource: !Sub arn:aws:s3:::${ProductBucket}/*
Hope this help you move forward.
I found the AWS documentation's yaml example to look a bit funny, but I followed it and gave my CF stack IAM s3:PutBucketPolicy permissions, and it worked. Below is my SAM.
ExampleBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: !Sub <bucket-name>
ExampleBucketPolicy:
Type: AWS::S3::BucketPolicy
Properties:
Bucket:
Ref: "ExampleBucket"
PolicyDocument:
Statement:
- Action:
- "s3:GetObject"
Effect: "Allow"
Resource:
Fn::Join:
- ""
- - "arn:aws:s3:::"
- Ref: "ExampleBucket"
- "/*"
Principal: "*"
Here is the AWS documentation page you've probably already consulted: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-s3-policy.html.
I am creating a cloudformation stack where the templates creates Cloud trail and then S3 bucket and pushes all logs to S3 bucket.
I have tried creating Cloud trail,s3 bucket and tried attaching the s3 Bucket Policy to the bucket
Parameters:
loggroupname:
Type: String
trailname:
Type: String
s3bucketname:
Type: String
Resources:
createloggroup:
Type: AWS::Logs::LogGroup
Properties:
LogGroupName: !Sub ${loggroupname}
creates3bucket:
Type: AWS::S3::Bucket
Properties:
BucketName: !Sub ${s3bucketname}
s3bucketpolicy:
Type: AWS::S3::BucketPolicy
Properties:
Bucket: !Sub ${s3bucketname}
PolicyDocument:
Version: '2012-10-17'
Statement:
- Sid: 'AWSCloudTrailAclCheck20150319'
Effect: 'Allow'
Principal:
Service: 'cloudtrail.amazonaws.com'
Action: 's3:GetBucketAcl'
Resource:
!Sub 'arn:aws:s3:::${s3bucketname}'
PolicyDocument:
Version: '2012-10-17'
Statement:
- Sid: AWSCloudTrailWrite20150319
Effect: 'Allow'
Principal:
Service: 'cloudtrail.amazonaws.com'
Action: 's3:PutObject'
Resource:
!Sub 'arn:aws:s3:::${s3bucketname}/AWSLogs/${AWS::AccountId}/*'
Condition:
StringsEquals:
s3:x-amz-acl: 'bucket-owner-full-control'
myvpctrail:
DependsOn:
- s3bucketpolicy
Type: AWS::CloudTrail::Trail
Properties:
IsLogging: true
IsMultiRegionTrail: true
IncludeGlobalServiceEvents: true
S3BucketName: !Ref creates3bucket
Invalid Condition type : StringsEquals (Service: Amazon S3; Status Code: 400; Error Code: MalformedPolicy; Request ID: F7439B111E82A3FA; S3 Extended Request ID: IGU1L7BB77WcrhPtmydd5j6viQdMK0vqA3Qo4RTS209FAvjT3q6wBIsyabdt5B7pBFvdr2MT+sM=)
Simple typo.
It's StringEquals not StringsEquals.
Source: https://docs.aws.amazon.com/AmazonS3/latest/dev/amazon-s3-policy-keys.html
I need some help writing the cloud formation that would get triggered by S3 put, from reading the documentation I see that you need NotificationConfiguration with event and function specified in bucket definition, but I keep getting the error " Unable to validate the following destination configurations" and it craps out and rollback the update. Can someone take a look at my CF script and identify what I am doing wrong, I think the issue could be in either NotificationConfiguration or rLambdaInvokePermission, but I am not sure which much appreciated!
here's my yaml:
Resources:
rAppBucketS3Policy:
Type: AWS::S3::BucketPolicy
Properties:
Bucket: !Ref rS3bucket
PolicyDocument:
Statement:
# SSL access enforced
- Sid: EnforceSecureTransport
Action: s3:*
Effect: Deny
Principal: '*'
Resource: !Join ["",[ "arn:aws:s3:::", Ref: rS3bucket, '/*' ] ]
Condition:
Bool:
aws:SecureTransport: 'false'
- Sid: EnforceEncryptionOnPut
Effect: Deny
Principal: '*'
Action: s3:PutObject
Resource: !Join ["",[ "arn:aws:s3:::", Ref: rS3bucket, '/*' ] ]
Condition:
StringNotEquals:
s3:x-amz-server-side-encryption: AES256
rLambdaInvokePermission:
#DependsOn: "int1-draps-us-east-1"
Type: AWS::Lambda::Permission
Properties:
FunctionName: us-east-1-upload
#FunctionName: !GetAtt rUploadLambda.Arn
Action: lambda:InvokeFunction
Principal: s3.amazonaws.com
SourceArn: !GetAtt rS3bucket.Arn
rS3bucket:
Type: AWS::S3::Bucket
Properties:
AccessControl: Private
BucketName: !Sub ${pAWSAccountLC}-${pParentVPCLC}-${pAppNameLC}-${AWS::Region}
CorsConfiguration:
CorsRules:
- AllowedHeaders: [ChecksumValue, CheckDate]
AllowedMethods: [GET, PUT, POST, DELETE]
ExposedHeaders: [ChecksumValue, CheckDate]
AllowedOrigins: ['*']
LifecycleConfiguration:
Rules:
- Id: Transition1day
Status: Enabled
Transitions:
- TransitionInDays: !Ref pS3GLACIERTransitionPeriod
StorageClass: GLACIER
**NotificationConfiguration:
LambdaConfigurations:
-
Event: "s3:ObjectCreated:*"
Function:
Fn::ImportValue:
Fn::Sub: "us-east-1-upload-rUploadLambda"**
I'm trying to make a reusable CloudFormation template and would like to do some kind of conditional where if the Environment parameter is "test" (or any other environment other than "prod"), then send SES emails to only gmail accounts (i.e., corporate accounts), but for "prod", send SES emails anywhere. Would I have to do two different roles and have conditions on each one? Or is there a way to do this inside of just the one role below? Thanks for any help!
Parameters:
Environment:
Description: Environment, which can be "test", "stage", "prod", etc.
Type: String
Resources:
Role:
Type: AWS::IAM::Role
Properties:
RoleName: myRole
Path: /
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
-
Effect: "Allow"
Principal:
Service:
- "ecs.amazonaws.com"
Action:
- "sts:AssumeRole"
Policies:
-
PolicyName: "ses-policy"
PolicyDocument:
Version: "2012-10-17"
Statement:
-
Effect: "Allow"
Action:
- "ses:SendEmail"
- "ses:SendRawEmail"
Resource: "*"
Condition:
"ForAllValues:StringLike":
"ses:Recipients":
- "*#gmail.com"
Conditions are perfectly suited for adding this sort of conditional logic to CloudFormation Resource Properties. In your example, you could use the Fn::If Intrinsic Function to include the existing Policy Condition (not to be confused with the CloudFormation Condition!) if the environment is not prod, and AWS::NoValue otherwise (removing the Policy Condition entirely when environment is prod):
Parameters:
Environment:
Description: Environment, which can be "test", "stage", "prod", etc.
Type: String
AllowedValues: [test, stage, prod]
Conditions:
IsProdEnvironment: !Equals [ !Ref Environment, prod ]
Resources:
Role:
Type: AWS::IAM::Role
Properties:
RoleName: myRole
Path: /
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
-
Effect: "Allow"
Principal:
Service:
- "ecs.amazonaws.com"
Action:
- "sts:AssumeRole"
Policies:
-
PolicyName: "ses-policy"
PolicyDocument:
Version: "2012-10-17"
Statement:
-
Effect: "Allow"
Action:
- "ses:SendEmail"
- "ses:SendRawEmail"
Resource: "*"
Condition: !If
- IsProdEnvironment
- !Ref AWS::NoValue
- "ForAllValues:StringLike":
"ses:Recipients":
- "*#gmail.com"