Creating a AWS WorkMail Lambda invoke permission in CloudFormation - amazon-web-services

When I create a Lambda::Permission resource in Cloudformation I have an issue with validating the principal. Currently I have it set to use the !Sub function and that's not a valid principal according to CloudFormation. Does any one have any experience with creating a workmail invoke permission?
AWSTemplateFormatVersion: 2010-09-09
Resources:
WorkmailInvokePermission:
Type: 'AWS::Lambda::Permission'
Properties:
Action: 'lambda:InvokeFunction'
FunctionName: arn:aws:<region>:<function_arn>
Principal: !Sub workmail.${AWS::Region}.amazonaws.com
Outputs: {}

I figured it out, it was a pretty simple, the problem was I was in a region where Workmail wasn't actually available so it ended up creating an error.

Related

Update logGroup retention for existing logs in CloudWatch using CloudFormationTemplate

I'm trying to update the logs retention of existing log groups created by my Lambda functions in CloudWatch using the CloudFormationTemplate in YAML.
In order to do that, I set
LambdaCWRetentionPermissionsPolicy:
Type: AWS::IAM::ManagedPolicy
Properties:
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- "logs:PutRetentionPolicy"
Resource:
- !Sub "arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/*"
LambdaCWRetentionPolicy:
Type: AWS::Logs::LogGroup
Properties:
LogGroupName: !Sub "/aws/lambda/*"
RetentionInDays: 14
But it does not seem to work, because it seems to try to create new log groups and they already exist. Is there a way that I can update the retention of already existing logs from CloudFormationTemplate in YAML?
CloudFormation has the function of importing existing resources. After importing, you can update the retention with the CloudFormation stack.
Bringing existing resources into CloudFormation management - AWS CloudFormation
If you created an AWS resource outside of AWS CloudFormation management, you can bring this existing resource into AWS CloudFormation management using resource import.

Serverless Lambda Resource Based Policy - All Principles

I am trying to define in the serverless YAML file with a resource based policy that ** allows any rule from EventBridge ** to invoke the function; this is due to in my application, EventBridge rules are dynamically generated.
In the AWS's console, it does not allow create a Lambda permission's EventBridge with wildcard.
The following was my attempt but it did not generate any resource policy when deployed:
provider:
resourcePolicy: ${self:custom.resourcePolicies.test}
... other things
custom:
resourcePolicies:
test:
- Effect: Allow
Principal: "*"
Action: lambda:InvokeFunction
... other things
Guidance appreciated.
I found an answer in this post by henhal on serverless forums.
Basically you have to create new resource of AWS::Lambda::Permission type.
resources:
Resources:
InvokeGenerateReportLambda:
Type: AWS::Lambda::Permission
Properties:
Action: lambda:invokeFunction
FunctionName: ${env:LAMBDA_FUNCTION_ARN}
Principal: events.amazonaws.com
SourceArn: ${env:RULE_ARN} #can include wildcards

How to add a resource based policy to a lambda using AWS SAM

I want to create a deployment script for some lambda functions using AWS SAM. Two of those functions will be deployed into one account(account A) but will be triggered by an s3 bucket object creation event in a second account(account B). From what I know the only way to do this is by using adding a resource based policy to my lambda. But I don't know how to do that in AWS SAM. My current yaml file looks like this.
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
deploy-test-s3-triggered-lambda
Parameters:
AppBucketName:
Type: String
Description: "REQUIRED: Unique S3 bucket name to use for the app."
Resources:
S3TriggeredLambda:
Type: AWS::Serverless::Function
Properties:
Role: arn:aws:iam::************:role/lambda-s3-role
Handler: src/handlers/s3-triggered-lambda.invokeAPI
CodeUri: src/handlers/s3-triggered-lambda.js.zip
Runtime: nodejs10.x
MemorySize: 128
Timeout: 60
Policies:
S3ReadPolicy:
BucketName: !Ref AppBucketName
Events:
S3NewObjectEvent:
Type: S3
Properties:
Bucket: !Ref AppBucket
Events: s3:ObjectCreated:*
AppBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: !Ref AppBucketName
What do I need to add to this yaml file in order to tie a resource based policy that allows for cross account access to my lambda function?
This can be done achieved with the help of AWS::Lambda::Permission using aws_cdk.aws_lambda.CfnPermission.
For example, to allow your lambda to be called from a role in another account, add the following to your CDK:
from aws_cdk import aws_lambda
aws_lambda.CfnPermission(
scope,
"CrossAccountInvocationPermission",
action="lambda:InvokeFunction",
function_name="FunctionName",
principal="arn:aws:iam::111111111111:role/rolename",
)
If your bucket and your Lambda function exist in separate accounts I don't know if it's possible to modify both of them from SAM / a single CloudFormation template.
Don't think cross account s3 event is possible with SAM, may need to go back to CFN.

AWS SAM Template: Issue mapping S3 events to Lambda

I've followed the AWS SAM documentation for hands-on learning experience and have reached this particular section: https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-property-function-s3.html
Above page in the documentation explains how to map the S3 events to any resource and I've done something similar on my local machine. My local template below.
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Resources:
CreateThumbnail:
Type: AWS::Serverless::Function
Properties:
CodeUri: hello_world/
Handler: app.lambda_handler
Runtime: python3.6
Timeout: 60
Policies: AWSLambdaExecute
Events:
CreateThumbnailEvent:
Type: S3
Properties:
Bucket: !Ref testBucket
Events: s3:ObjectCreated:*
testBucket:
Type: AWS::S3::Bucket
Now, when I build and deploy above SAM template, while a new S3 bucket is getting created, the 'object creation' event is not mapped to the Lambda function created. PSB screenshot.
I haven't found any articles or blogs on this error (probably, I'm doing a silly mistake here)
Please help.
Thanks.
I realized that for some reason, the AWS Lambda console is not showing the trigger event but the mapping is successful. I've also validated by uploading sample image to the bucket which triggered the lambda.
The event mapping can be seen in the properties section of the S3 bucket created.
S3 test bucket created -> Properties -> Events
You can add a AWS::Lambda::Permission to your Resources as described in this AWS SAM Github issue
LambdaInvokePermission:
Type: 'AWS::Lambda::Permission'
Properties:
FunctionName: !GetAtt MyFunction.Arn
Action: 'lambda:InvokeFunction'
Principal: 's3.amazonaws.com'
SourceAccount: !Sub ${AWS::AccountId}
SourceArn: !GetAtt MyBucket.Arn
First create bucket where you plan to save packaged code
aws s3 mb s3://youtbucketname
After sam build
go for
sam package --template-file template.yaml --s3-bucket <yourbucketname>

Give Lambda Invoke permission to ApiGateway with one deployment

I wrote resources in my serverless.yml like below:
resources:
Resources:
RestApi :
Type : AWS::ApiGateway::RestApi
Properties :
Body : ${file(./swagger.yaml)}
LoginApiToInvokeLambda:
Type: AWS::Lambda::Permission
Properties:
FunctionName: login
Action: lambda:InvokeFunction
Principal: apigateway.amazonaws.com
When I sls deploy, below error occured:
An error occurred: LoginApiToInvokeLambda - Function not found: arn:aws:lambda:ap-northeast-1:xxxxxxxxxxxx:function:api-dev-login (Service: AWSLambda; Status Code: 404; Error Code: ResourceNotFoundException
In the initial deployment, I thought that permissions were set before creating lambda functions. Therefore, I commented out LoginApiToInvokeLambda in my serverless.yml. I sls deploy again, it succeeded. But ApiGateway does not have permission to invoke lambda. After that I restored the commented out part, and sls deploy. Finally I was able to give ApiGateway the permission of Lambda invoke.
Is there a way to accomplish this at the same time?
You can use DependsOn functionality of CloudFormation in the resources section.
resources:
Resources:
# ...
LoginApiToInvokeLambda:
Type: AWS::Lambda::Permission
DependsOn: LoginLambdaFunction
Properties:
FunctionName: login
Action: lambda:InvokeFunction
Principal: apigateway.amazonaws.com
I've assumed your lambda function key is login which gets translated to LoginLambdaFunction. If not, check the serverless documentation on how the resources get named.
In short serverless translates your configuration to a CloudFormation template, and the resources section allows you to customise what gets generated, which is why you can use DependsOn to solve your issue.