The aws SAM local documentation states that SAM Local will invoke functions with my locally configured IAM credentials.
I want to test a cloudformation template that consists of a Lambda function and a role attached to this function that grants access to delete the content of ONE SPECIFIC s3 bucket. The bucket name is both a template parameter, and an argument to the lambda function. (Not sure it matters, but I don't use the serverless transformations in the CFN template.)
I avoid testing this function with my admin profile, since a typo in the bucket name will delete all contents of the wrong bucket.
What is the suggested workflow to test such a function?
What I'm currently doing:
Create a temporary IAM user/group
attach the policy to be tested to this group
export the access environment variables before calling sam local invoke
Is there a quicker way to do this?
Invoke Lambda with DryRun
Invoke the function with Dryrun to request AWS Lambda to not execute the function but do some verification, such as if the caller is authorized to invoke the function and if the inputs are valid.
aws lambda invoke --function-name <name> --invocation-type DryRun
Creating ChangeSets for Cloudformation: Change Sets = Dry Run Mode
Create a changeset with "create-change-set" and review the changes in the Console UI or CLI and then apply the changes using execute changes using the CLI or UI.
Create Changeset:
aws cloudformation create-change-set --stack-name example --template-body file://templates/instance_and_route53.yml --parameters file://parameters/instance_and_route53.json --change-set-name changeset-1
Execute Changeset
aws cloudformation execute-change-set --stack-name example --change-set-name changeset-1
Related
I want to create a lambda function which can create cloudformation stack in another Aws account and taking template from S3 bucket in
source account.
AWS CloudFormation can only be run from the AWS Account where resources will be deployed.
Therefore, the AWS Lambda function in Account-A would need to:
Call AssumeRole() on an IAM Role in Account-B, which will provide temporary credentials for Account-B
Use those temporary credentials to call CreateStack() to create the CloudFormation stack in Account-B
The template file used to create the stack can be passed as part of the CreateStack() call, or it can be referenced via an AmazonS3 URL. If the template is coming from Account-A, then the S3 bucket would need to make that object accessible to Account-B (eg via Bucket Policy or ACL).
Ref: https://docs.aws.amazon.com/IAM/latest/UserGuide/tutorial_cross-account-with-roles.html
In the AWS Lambda management console you can have test events associated with a function.
Is it possible to configure the test events when deploying the Lambda function using the AWS CDK such that the test events are ready to use when someone later views the function in the management console?
That is not possible at the moment as CloudFormation itself does not support this (see this answer). You can, as mentioned in the linked post, use a CloudFormation CustomResource to prepare the invocation.
Another option is to create a output that prepares a cli command with payload. So that you can just copy past the generated call aws lambda invoke --function-name {PopulateFromCDK} --payload '{"key": "value"}'
I want to have a cloud formation template to list all lambda functions for a particular region. I don't need to write a lambda code using list-function and call it inside my CFT.
I tried incorporating CLI command inside CFT but it didn't work
There is no way to directly add a aws cli command in a cloudformation template. Either you will have to create a EC2 instance and then run the CLI command in the user data or create a lambda backed custom resource to do it.
Both will complicate the simple CLI command.
aws lambda list-functions --region eu-west-1
CFN is just an orchestration tool. It cannot compute on itself.
Instead we can use a simple lambda python script and invoke the same in the CFT
import boto3
#Create an lambda client
client = boto3.client(
"lambda"
)
response = client.list_functions(
MasterRegion='string',
FunctionVersion='ALL',
Marker='string',
MaxItems=123
)
print(response)
I have a Lambda .jar that I build from a Jenkins box in an AWS account ("Account_Bld"). Once built, I copy the .jar over to an S3 bucket in a different AWS account ("Account_Dst"), and I attempt to update the Lambda in Account_Dst based on the newly copied .jar in S3.
I'm using this command as part of my deploy script, which is a slight modification of another version that works when everything is located in the same account:
aws lambda update-function-code --function-name arn:aws:lambda:us-east-1:{Account_Dst_Id}:function:{lambda_function_name} --zip-file fileb://{jar_file_relative_path} --region us-east-1
Not surprisingly, I get this error:
An error occurred (AccessDeniedException) when calling the UpdateFunctionCode operation: User: arn:aws:sts::{Account_Bld_Id}:assumed-role/{jenkins_ec2_role}/{jenkins_ec2_instance_id} is not authorized to perform: lambda:UpdateFunctionCode on resource: arn:aws:lambda:us-east-1:{Account_Dst_Id}:function:{lambda_function_name}
I have given jenkins_ec2_role rights to update the Lambda in the other account, but it makes sense that I would need to reciprocate those rights somewhere in Account_Dst -- assuming there is a simple solution to this problem.
Now, possible resolutions. I could assume a role in Account_Dst that has the correct rights and update the Lambda, but that's more setup hassle than it is worth to me right now. I've seen some Google suggestions that I could use CodePipeline, but obviously I'm using Jenkins, so that doesn't seem like a good solution, either.
So, the question is, is there an easy solution here that I am missing?
This is now possible. A Lambda resource based policy can be configured to allow a principal from another account to perform actions e.g. lambda:UpdateFunctionCode or lambda:Invoke.
In case of UpdateFunctionCode, the documentation states:
FunctionName
The name of the Lambda function.
Name formats
Function name – my-function.
Function ARN – arn:aws:lambda:us-west-2:123456789012:function:my-function.
Partial ARN – 123456789012:function:my-function.
...
Source: https://docs.aws.amazon.com/lambda/latest/dg/API_UpdateFunctionCode.html
The Lambda Function permission in account 222222222222 must be configured to allow the principal from account 111111111111 to update the function code:
aws lambda add-permission --function-name my-function --statement-id xaccount --action lambda:UpdateFunctionCode --principal 111111111111 --output out.txt
Source:
https://docs.aws.amazon.com/lambda/latest/dg/access-control-resource-based.html#permissions-resource-xaccountinvoke
Then the function code in account 222222222222 can be updated from account 111111111111:
aws lambda update-function-code --function-name arn:aws:lambda:us-west-2:222222222222:function:my-function --zip-file fileb://soure.zip
Granting permissions in Account_Bld to access Account_Dst is not sufficient to gain access to another account. This is good, because you wouldn't want people granting themselves access to other people's accounts.
The destination account needs to accept the incoming request. The method varies by service. For example, Amazon S3 can create a Bucket Policy to permit access from other accounts, as can Amazon SQS.
However, there is no such concept in Lambda to configure incoming requests from other accounts. There is simply nowhere that can be configured to allow update-function-code from another account.
Therefore, you will need to do as you suggested:
Create an IAM User or IAM Role in Account_Dst
Use the credentials from the Account_Dst IAM User (simplest) or use the existing Account_Bld credentials to assume the Role in Account_Dst (a few more lines of code)
Call update-function-code using those credentials
I have two versions of an AWS Lambda function. I wanted to attach it to two stages of API Gateway, dev and prod.
I created two aliases, dev and prod, for the two versions of the Lambda function. I created a stage variable called fname and provided the values dev and prod against them in the appropriate stages.
Against the Lambda function to be called in the Resources section, I provided the function name as stageTester:${stageVariables.fname} where stageTester is the name of my function.
It prompted me to attach permissions using AWS CLI. I ran the following command:
aws lambda add-permission --function-name arn:aws:lambda:ap-south-1:xxxxxxx:function:stageTester:dev --source-arn 'arn:aws:execute-api:ap-south-1:zzzzzz:aaaaaa/*/GET/stageTester' --principal apigateway.amazonaws.com --statement-id cxbxcx9bx5-68df-4x9d-96xd-9exb497xa934 --action lambda:InvokeFunction --profile lambdaUser --region ap-south-1
...and a similar one for prod. I expected that this would attach the permissions appropriately.
I completed the deployment and tried to invoke the API. However, I encountered Internal Server Error every time. In the Lambda function screen, against the trigger, I see the following error
The API with ID aaaaaa does not include a resource with path /stageTester
having an integration
arn:aws:lambda:ap-south-1:xxxxxxx:function:stageTester:dev on the GET
method
Can someone help me with this issue?