Specify resources allowed to call a function in its AWS SAM Function template - aws-lambda

TL; DR: How should I edit the template below so that it can be triggered by a user pool trigger?
I try to crate a CloudFormation template for a Lambda function defining both the services the function can call and be called from. It should be run with a Cognito User Pool trigger.
To do that, I've defined a resource in template of type AWS::Serverless::Function briefly as follows. Watch out the Policies section:
Resources:
MyFunctionResource:
Type: AWS::Serverless::Function
Properties:
FunctionName: MyFunctionName
CodeUri: ./
Handler: "lambda_function.lambda_handler"
MemorySize: 128
Runtime: python3.7
Timeout: 3
Policies:
- Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- "cognito-idp:*"
- "logs:*"
...
Resource: "*"
- Version: "2012-10-17"
Statement:
- Effect: Allow
Action: "lambda:InvokeFunction"
Principal:
Service: cognito-idp.amazonaws.com
Resource: !Sub "arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:MyFunctionName"
The second policy I have inserted for restricting the resources can call my function fails during the stack creation:
Policy document should not specify a principal. (Service: AmazonIdentityManagement; Status Code: 400; Error Code: MalformedPolicyDocument; Request ID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)
When I remove that policy with principal, the access to the function through the user pool trigger is denied.

I figured out that the permissions should be created as a separate resource with type AWS::Lambda::Permission which can take the function name or arn it will be attached to.
Thus, the following logic creates the function with permissions (a.k.a. Function Policy) successfully:
Resources:
MyFunctionResource:
Type: AWS::Serverless::Function
Properties:
FunctionName: MyFunctionName
CodeUri: ./
Handler: "lambda_function.lambda_handler"
MemorySize: 128
Runtime: python3.7
Timeout: 3
Policies:
- Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- "cognito-idp:*"
- "logs:*"
...
Resource: "*"
## Remove this section
# - Version: "2012-10-17"
# Statement:
# - Effect: Allow
# Action: "lambda:InvokeFunction"
# Principal:
# Service: cognito-idp.amazonaws.com
# Resource: !Sub "arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:MyFunctionName"
## Add this instead
MyFunctionPermissions:
Type: AWS::Lambda::Permission
Properties:
Action: "lambda:InvokeFunction"
FunctionName: !GetAtt MyFunctionResource.Arn
Principal: "cognito-idp.amazonaws.com"
SourceArn: !Sub "arn:aws:cognito-idp:${AWS::Region}:${AWS::AccountId}:userpool/*"

Related

How to add desired policy to lambda with cloudformation & SAM

I want to make a lambda function that has access to dynamoDB and other lambda functions.
However, I don't know how to make an appropriate YAML template for SAM to give appropriate permissions.
Especially, I don't understand the confusing 3 entries including definitions
of the permissions (AWS::IAM::Role, AWS::Serverless::Function, AWS::Lambda::Permission). Which entry should I use to add the necessary permissions?
Here is my YAML below. But the created my_lambda_role does not have AWSLambdaRole policy and policy for dynamoDB. As a result, the lambda fails to access to dynamoDB. Please tell me how to fix it.
MyLambdaRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service: lambda.amazonaws.com
Action: sts:AssumeRole
ManagedPolicyArns:
- arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
- arn:aws:iam::aws:policy/service-role/AWSLambdaRole
RoleName: my_lambda_role
OnConnectFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: onconnect/
Handler: index.lambda_handler
MemorySize: 256
Role: !GetAtt MyLambdaRole.Arn
Runtime: python3.6
Environment:
Variables:
TABLE_NAME: !Ref TableName
Policies:
- DynamoDBCrudPolicy:
TableName: !Ref TableName
- Statement:
- Effect: Allow
Action:
- 'execute-api:ManageConnections'
Resource:
- 'arn:aws:execute-api:*:*:*/#connections/*'
OnConnectPermission:
Type: AWS::Lambda::Permission
DependsOn:
- MyAPI
Properties:
Action: lambda:InvokeFunction
FunctionName: !Ref OnConnectFunction
Principal: apigateway.amazonaws.com
You can add the missing policies. Depending on what you want, but if you want full access, then you can add AmazonDynamoDBFullAccess:
ManagedPolicyArns:
- arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
- arn:aws:iam::aws:policy/service-role/AWSLambdaRole
- arn:aws:iam::aws:policy/AmazonDynamoDBFullAccess

Invalid template resource property 'Policies'

Can you please help with what is wrong here?
when I am trying to run this following cloud formation stack getting error. I am trying to create the lambda function with the sns role using cloud formation Invalid template resource property 'Policies'
AWSTemplateFormatVersion: '2010-09-09'
Description: VPC function.
Resources:
Function:
Type: AWS::Lambda::Function
Properties:
Handler: index.handler
Code:
S3Bucket: teste-artifact-bucket
S3Key: function.zip
Runtime: python3.6
Timeout: 5
TracingConfig:
Mode: Active
LambdaExecutionRole:
Description: Creating service role in IAM for AWS Lambda
Type: AWS::IAM::Role
Properties:
RoleName:
Fn::Sub: ${ProjectId}-execution
AssumeRolePolicyDocument:
Statement:
- Effect: Allow
Principal:
Service:
- lambda.amazonaws.com
Action: sts:AssumeRole
Path: /
Policies:
PolicyName: Lamda addtional access
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- sns:Subscribe
- sns:Publish
- sns:CreateTopic
- logs:PutLogEvents
- logs:CreateLogStream
- logs:CreateLogGroup
Resource: '*'
ManagedPolicyArns:
- !Sub 'arn:${AWS::Partition}:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole'
LambdaFunctionLogGroup:
Type: AWS::Logs::LogGroup
Properties:
LogGroupName: !Sub '/aws/lambda/${ProjectId}'
RetentionInDays: 60
Policies code block isn't indented far enough

Can i add a codecommit trigger to my lambda function via CloudFormation

Im writing a lambda function that i want to be triggered by somebody updating the master branch of a repo. The repo already exists on the account.
Is there a way in cloudformation that i can add the trigger to the lambda function? I guess at a snip i could cretae some cloudwatch rule to trigger the lambda, but would rather keep it all inside the lambda.
Thanks
R
If you are using AWS serverless transform then you can self contain it within the lambda. Although the transform generates the cloudwatch rule and the lambda permission, so it's basically the same you mentioned.
nevertheless here's an example to do what you want
AWSTemplateFormatVersion: "2010-09-09"
Transform: AWS::Serverless-2016-10-31
Description: Pipeline which triggers lambda for codecommit changes
Parameters:
BranchName:
Default: master
Description: The GIT branch
Type: String
RepositoryName:
Description: The GIT repository
Type: String
StackOwner:
Description: The stack owner
Type: String
Resources:
BasicLambdaRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
Effect: Allow
Principal:
Service: lambda.amazonaws.com
Action: sts:AssumeRole
Path: "/"
Policies:
- PolicyName: root
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action: logs:*
Resource: arn:aws:logs:*:*:*
- Effect: Allow
Action: '*'
Resource: '*'
PipelineTriggerFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: src/trigger
Handler: codetrigger.handler
MemorySize: 256
Role: !GetAtt BasicLambdaRole.Arn
Runtime: python3.6
Timeout: 900
Environment:
Variables:
TestVariable: "TestValue"
Events:
CodeCommitPushEvent:
Type: CloudWatchEvent
Properties:
Pattern:
source:
- aws.codecommit
resources:
- !Sub 'arn:aws:codecommit:${AWS::Region}:${AWS::AccountId}:${RepositoryName}'
detail:
event:
- referenceCreated
- referenceUpdated
repositoryName:
- !Ref RepositoryName
referenceName:
- !Ref BranchName
Tags:
'owner': !Ref StackOwner
'task': !Ref RepositoryName
Obviously, specify the lambda role better and not give all permissions as provided in the example.

Setting Access Role for Event Stream Created Via CloudFormation

I'm trying to add a dynamodb stream with the following template.yml
MyFunc:
Type: AWS::Serverless::Function
Properties:
CodeUri: ./myfunc
Handler: main
Runtime: go1.x
Events:
MyStream:
Type: DynamoDB
Properties:
Stream: !GetAtt MyTable.StreamArn
BatchSize: 1
StartingPosition: LATEST
Role:
Fn::ImportValue:
!Join ['-', [!Ref 'ProjectId', !Ref 'AWS::Region', 'LambdaTrustRole']]
However, I'm getting the following error during the deploy stage:
Please ensure the role can perform the GetRecords, GetShardIterator, DescribeStream, and ListStreams Actions on your stream in IAM.
Attempt 1
So I tried fixing the problem by adding the following policies to my IAM, CodeStarWorker-myproject-CloudFormation:
"dynamodb:GetRecords",
"dynamodb:GetShardIterator",
"dynamodb:DescribeStream",
"dynamodb:ListStreams",
That didn't work, still giving me the same error
Attempt 2
Tried using policies stead of role in template.yml
MyFunc:
Type: AWS::Serverless::Function
Properties:
CodeUri: ./myfunc
Handler: main
Runtime: go1.x
Events:
MyStream:
Type: DynamoDB
Properties:
Stream: !GetAtt MyTable.StreamArn
BatchSize: 1
StartingPosition: LATEST
Policies:
- IAMFullAccess
- AWSLambdaFullAccess
But it gave me the following error
API: iam:CreateRole User: arn:aws:sts::xxx:assumed-role/CodeStarWorker-xxx-CloudFormation/AWSCloudFormation is not authorized to perform: iam:CreateRole on resource: arn:aws:iam::xxx:role/awscodestar-xxx-lambda-MyFuncRole-1BO7G545IR5IC
Attempt 3
Specifying a role in template.yml
LambdaRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow #allow lambda to assume this role
Principal:
Service:
- lambda.amazonaws.com
Action:
- sts:AssumeRole
Path: "/"
Policies:
- PolicyName: LambdaRolePolicy
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow # allow to write logs to cloudwatch
Action:
- logs:CreateLogGroup
- logs:CreateLogStream
- logs:PutLogEvents
Resource: arn:aws:logs:*:*:*
- Effect: Allow # allow lambda to read from the event stream
Action:
- dynamodb:DescribeStream
- dynamodb:GetRecords
- dynamodb:GetShardIterator
- dynamodb:ListStreams
Resource: "*"
And assign it to MyFunc
Role:
Fn::GetAtt: [ LambdaRole , Arn ]
However, it's also giving me the same error indicating that I'm not authorized to perform iam:CreateRole
Any help?
iam:CreateRole - you would need this action to create a role. The user that you use to run the Cloudformation template would need to include the "CreateRole" action.

How do I assign function level IamRoleStatements in Serverless Framework?

I want to assign different permissions for different functions listed in my serverless.yml
functions:
hello:
handler: handler.hello
crawl-distributor:
handler: CrawlDistributor.handler
product-scanner:
handler: ProductScanner.handler
iamRoleStatements:
- Effect: Allow
Action:
- dynamodb:*
- lambda:*
Resource: "*"
This doesn't seem to work. When I add the iamRoleStatements at the provider level, it works, but ends up applying the permissions to all the functions.
provider:
name: aws
runtime: nodejs4.3
stage: api
region: us-east-1
profile: dev
iamRoleStatements:
- Effect: Allow
Action:
- dynamodb:*
- lambda:*
Resource: "*"
From docs, you need to create the function role under resources and reference this new role inside your function.
Example:
service: my-test
provider:
name: aws
runtime: nodejs4.3
stage: api
region: us-east-1
profile: dev
functions:
hello:
handler: handler.hello
crawl-distributor:
handler: CrawlDistributor.handler
product-scanner:
role: myDynamoRole
handler: ProductScanner.handler
resources:
Resources:
myDynamoRole:
Type: AWS::IAM::Role
Properties:
RoleName: myDynamoRole
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service:
- lambda.amazonaws.com
Action: sts:AssumeRole
Policies:
- PolicyName: myPolicyName
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- dynamodb:*
- lambda:*
Resource: "*"
Using the module serverless-iam-roles-per-function, you can write iamRoleStatements: under the name of each function like the questioner Hexy wrote.
functions:
hello:
handler: handler.hello
crawl-distributor:
handler: CrawlDistributor.handler
product-scanner:
handler: ProductScanner.handler
iamRoleStatements:
- Effect: Allow
Action:
- dynamodb:*
- lambda:*
Resource: "*"
Document of serverless framework
https://www.serverless.com/plugins/serverless-iam-roles-per-function

Resources