I like how a role + inline policy is created when I deploy my template:
Resources:
MyFUnction:
Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction
Properties:
Description: Enter description of what this specific Lambda does
CodeUri: hello_world/build/
Handler: app.lambda_handler
Runtime: python2.7
Environment: # More info about Env Vars: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#environment-object
Variables:
PARAM1: VALUE
Policies:
# Using AWSLambdaExecute automatically creates a role named: <StackName>Role-<UUID>
- AWSLambdaExecute
# This policy is assigned as an Inline policy to the role
- Version: '2012-10-17' # Policy Document
Statement:
Effect: Allow
Action: ......
Now can I ref the role that is dynamically created and add an Output: for it in the SAM template?
The resulting role that SAM creates for you is just the name of your function with "Role" added to the end. You can use this information to get the Role or properties of it using normal CloudFormation functions.
For example, if you wanted to access the role ARN of MyFunction, you would use !GetAtt MyFunctionRole.Arn in your SAM YAML template. The same principle should apply for !Ref and other functions.
I was able to test a solution to this, in the SAM template.yaml you can add an Output as you would in CloudFormation for the Logical ID that is created automatically for you as part of the Transform when using Properties such as Policies for AWS::Serverless::Function
The Logical ID of the resulting IAM Role is <Function Logical ID>Role, I used the below:
Outputs:
LambdaRole:
Value:
Fn::GetAtt:
- "LambdaFunctionRole"
- "Arn"
Description: "Lambda IAM Role"
Related
I need create a way for execute especific lambdas for specific IAM users, then i am doing:
I am creating a Usergroup in cloudformation:
Resources:
XXXGroup:
Type: AWS::IAM::Group
And after I am creating a policy and add the policy to my UserGroup
UsersXPolicies:
Type: AWS::IAM::Policy
Properties:
Groups:
- !Ref XXXGroup
PolicyDocument:
Version: "2012-10-17"
Statement:
-
Effect: "Allow"
Action:
- "lambda:*"
Resource:
- !Sub arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:MyFunction
- !Sub arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:MyFunction2
PolicyName: xxx-access-policy
I try first only with "lambda:InvokeFunction" but it not works, then I try with lambda:* but it not works
After I am creating a user:
XXUser:
Type: AWS::IAM::User
Properties:
UserName: xxx.user
LoginProfile:
Password: l98GaTc9xzT9
PasswordResetRequired: true
Path: /
And finally i am adding the user to my usergroup:
USerAdditionX:
Type: AWS::IAM::UserToGroupAddition
Properties:
GroupName: !Ref XXXGroup
Users:
- !Ref XXUser
But after login with my new user i am getting the following error when i go to lambda service:
User: arn:aws:iam::xxxxxxxxx:user/xx.user is not authorized to perform: lambda:GetAccountSettings on resource: * because no identity-based policy allows the lambda:GetAccountSettings action
Access to specific lambdas from my new user
The problem is that lambda get its permission from a role.Policies are attached to role.
You need to attach your policies to a role and then attach a role to lambda.
Please read about lambda execution role over here
You can't limit the visibility for the list of all the Lambda Functions (there is also the same "problem" on EC2 Instances and S3 Buckets permissions policy), so your user cannot interact with the Lambda because the policy that you provided have the condition on the specific resource, but he need the full read-only capability even to see the function.
You should add at least an Allow statement on lambda:ListFunctions and lambda:GetAccountSettings for Resource "*" (so on every Lambda of your account), as stated here.
You could also, as documented here, add the standard AWSLambda_ReadOnlyAccess policy to your group.
I have created a CFN template for rotating secret of RDS. It consist of a AWS HostedLambda which calls for an autogenerated Role. I want to attach another policy to that role.
rRotationLambdaDecryptPolicy:
Type: AWS::IAM::ManagedPolicy
DependsOn: rSecretRotationScheduleHostedRotationLambda
Properties:
Description: "Providing access to HostedLambda for decrypting KMS"
ManagedPolicyName: CustomedHostedLambdaKmsUserRolePolicy
PolicyDocument:
Version: '2012-10-17'
Statement:
- Sid: AllowLambdaDecryptKMS
Effect: Allow
Action:
- kms:Decrypt
- kms:CreateGrant
Resource:
- !Sub arn:aws:kms:*:${AWS::AccountId}:key/*
Condition:
ForAnyValue:StringLike:
kms:ResourceAliases: alias/SecretsManager_KMSKey
Roles: <friendly rolename>
Problem is i know the Lambda friendly name and its Arn. Need to find the rolename linked to this lambda so that i can attach the above policy to it(Add its friendly name to Roles).
tried attaching this below
Roles:
Fn::Join:
- ""
- - '"'
- Fn::GetAtt:
- !Sub 'arn:aws:lambda::${AWS::AccountId}:function:SecretsManager-research-creds-rotation-lambda'
- Role
- '"'
P.S.- cant use importvalue here, because the nested stack has been created by AWS and its output doesn't consist of export.
Lambda used:-
rSecretRotationSchedule:
Type: AWS::SecretsManager::RotationSchedule
Properties:
SecretId:<SecretId>
HostedRotationLambda:
KmsKeyArn: <KmsKeyArn>
MasterSecretArn: <MasterSecretArn>
MasterSecretKmsKeyArn: <MasterSecretKmsKeyArn>
RotationType: PostgreSQLMultiUser
RotationLambdaName: SecretsManager-research-creds-rotation-lambda
VpcSecurityGroupIds: <VpcSecurityGroupIds>
VpcSubnetIds: <VpcSubnetIds>
RotationRules:
AutomaticallyAfterDays: 60
Below is the link from which i took reference for template:-
https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-secretsmanager-rotationschedule.html
Most likely you can't do this with plain CFN. You would have to develop a custom resource. This would be in the form of a new lambda function which would use AWS SDK to query attributes of your primary lambda function. Once the custom resource finds the role name it would return it to your stack for further use.
I'm stuck in a weird issue. I have created an AWS S3 bucket using following cloud formation template:-
AWSTemplateFormatVersion: '2010-09-09'
Metadata:
License: Unlicensed
Description: >
This template creates a global unique S3 bucket in a specific region which is unique.
The bucket name is formed by the environment, account id and region
Parameters:
# https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/parameters-section-structure.html
Environment:
Description: This paramenter will accept the environment details from the user
Type: String
Default: sbx
AllowedValues:
- sbx
- dev
- qa
- e2e
- prod
ConstraintDescription: Invalid environment. Please select one of the given environments only
Resources:
# https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-s3-bucket.html
MyS3Bucket:
Type: AWS::S3::Bucket
DeletionPolicy: Retain
Properties:
BucketName: !Sub 'global-bucket-${Environment}-${AWS::Region}-${AWS::AccountId}' # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/pseudo-parameter-reference.html
AccessControl: Private
LoggingConfiguration:
DestinationBucketName: !Ref 'LoggingBucket'
LogFilePrefix: 'access-logs'
Tags:
- Key: name
Value: globalbucket
- Key: department
Value: engineering
LoggingBucket:
Type: AWS::S3::Bucket
DeletionPolicy: Retain
Properties:
BucketName: !Sub 'global-loggings-${Environment}-${AWS::Region}-${AWS::AccountId}'
AccessControl: LogDeliveryWrite
Outputs:
GlobalS3Bucket:
Description: A private S3 bucket with deletion policy as retain and logging configuration
Value: !Ref MyS3Bucket
Export:
Name: global-bucket
If you note in the template above then I'm exporting this S3 bucket in the Outputs section by the name called global-bucket.
Now, my intention is to refer to this existing bucket going forward in my AWS account whenever any new resource like Lambda, etc wants an S3 bucket. Here is an example using AWS SAM (Serverless Application Model), I'm trying to create an AWS Lambda and trying to refer to this existing S3 bucket using property !ImportValue and the export name as global-bucket as shown below:-
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
hellolambda
Sample SAM Template for hellolambda
# More info about Globals: https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst
Globals:
Function:
Timeout: 3
Resources:
HelloWorldFunction:
Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction
Properties:
CodeUri: hello-world/
Handler: app.lambdaHandler
Runtime: nodejs12.x
Events:
HelloLambdaEvent:
Type: S3
Properties:
Bucket: !Ref SrcBucket
Events: s3:ObjectCreated:*
SrcBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: !ImportValue global-bucket
Now, the problem is when I execute the command like sam build and then sam deploy --guided and select the same region (where my previous CloudFormation stack output is present) then I get the following error:-
global-bucket-sbx-ap-southeast-1-088853283839 already exists in stack arn:aws:cloudformation:ap-southeast-1:088853283839:stack/my-s3-global-bucket/aabd20e0-f57d-11ea-80bf-06f1487f6a64
The screenshot below:-
The problem is AWS CloudFormation is trying to create the S3 bucket rather than referring to the existing one.
But, if I try to update this SAM template like and then execute sam deploy, I get the following error:-
Waiting for changeset to be created..
Error: Failed to create changeset for the stack: my-lambda-stack, ex: Waiter ChangeSetCreateComplete failed: Waiter encountered a terminal failure state Status: FAILED. Reason: Transform AWS::Serverless-2016-10-31 failed with: Invalid Serverless Application Specification document. Number of errors found: 1. Resource with id [HelloWorldFunction] is invalid. Event with id [HelloLambdaEvent] is invalid. S3 events must reference an S3 bucket in the same template.
I'm blocked by both ends. I would really appreciate it if someone can assist to guide me writing the SAM template correctly in my Lambda so that I can refer the existing bucket properly instead of creating the new one.
Thank you
Any items listed under the Resources section refer to the resources the stack is responsible for maintaining.
When you list SrcBucket you are asking for CloudFormation to create a new S3 bucket with the name being the value of !ImportValue global-bucket which is the name of an S3 bucket you have already created.
Assuming that this is the bucket name you can simply reference it in your template as shown below.
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
hellolambda
Sample SAM Template for hellolambda
# More info about Globals: https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst
Globals:
Function:
Timeout: 3
Resources:
HelloWorldFunction:
Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction
Properties:
CodeUri: hello-world/
Handler: app.lambdaHandler
Runtime: nodejs12.x
Events:
HelloLambdaEvent:
Type: S3
Properties:
Bucket: !ImportValue global-bucket
Events: s3:ObjectCreated:*
I'm trying to use an existing IAM role in a CFN template that is already being used by other services.
The Resource definition looks like this:
MyInstanceProfile:
Type: "AWS::IAM::InstanceProfile"
Properties:
Path: "/"
Roles: ["Capras999"]
And I'm referencing it like this:
LambdaFunction:
Type: AWS::Lambda::Function
Properties:
Role: !Ref MyInstanceProfile
However I get this error:
1 validation error detected: Value 'capras-cluster-Prsr-DL-with-params-MyInstanceProfile-1R68JNUXU0SAA' at 'role' failed to satisfy constraint: Member must satisfy regular expression pattern: arn:(aws[a-zA-Z-]*)?:iam::\d{12}:role/?[a-zA-Z_0-9+=,.#\-_/]+ (Service: AWSLambdaInternal; Status Code: 400; Error Code: ValidationException; Request ID: 5f75a56d-8ce4-473e-924e-626a5d3aab0a)
What am I doing wrong? Please help me.
For lambda function you need role not instance-profile.
The solution was to copy and paste an existing role's ARN into the template. Other possibility is to pass it in using a parameter.
p.s.
Generally, you need to define AWS::IAM::Role with a thrust policy for lambda. For example:
LambdaExecutionRole:
Type: AWS::IAM::Role
Properties:
RoleName: my-lambda-execution-role
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal: {'Service': ['lambda.amazonaws.com']}
Action: ['sts:AssumeRole']
ManagedPolicyArns:
- arn:aws:iam::aws:policy/AWSLambdaExecute
Then for your function you would do:
LambdaFunction:
Type: AWS::Lambda::Function
Properties:
Role: !GetAtt LambdaExecutionRole.Arn
You are specifying the instance name as the value, this parameter should instead be the Arn of the IAM role in question.
From your question you're trying to attach an instance profile to your Lambda, these are for EC2 instances only. Instead you want the Arn of the role itself.
From the console you can get the Arn for IAM role Capras999.
If you're using an existing role make sure to update your AssumeRolePolicy to also include lambda.amazonaws.com (and lambdaedge.amazonaws.com if using it for Lambda#Edge).
In my AWS project, I use the serverless framework to deploy lambda function and IAM roles.
So I created 6 lambda functions, all using the same IAM Role below:
functions:
auto-delete-identity:
handler: src/auto-delete-identity.handler
role: arn:aws:iam::123456789012:role/lambdaIAMRole
name: auto-delete-identity
auto-move-to-user-group:
handler: src/auto-move-to-user-group.handler
role: arn:aws:iam::123456789012:role/lambdaIAMRole
name: auto-move-to-user-group
auto-validate-user-creation:
handler: src/auto-validate-user-creation.handler
role: arn:aws:iam::123456789012:role/lambdaIAMRole
name: auto-validate-user-creation
auto-validation-user-email-modification:
handler: src/auto-validation-user-email-modification.handler
role: arn:aws:iam::123456789012:role/lambdaIAMRole
name: auto-validation-user-email-modification
hello-demo:
handler: src/hello-demo.handler
role: arn:aws:iam::123456789012:role/lambdaIAMRole
name: hello-demo
reset-user-password:
handler: src/reset-user-password.handler
role: arn:aws:iam::123456789012:role/lambdaIAMRole
name: reset-user-password
resources:
Resources:
lambdaIAMRole:
Type: "AWS::IAM::Role"
Properties:
RoleName: lambdaIAMRole
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Action:
- "sts:AssumeRole"
Effect: "Allow"
Principal:
Service:
- "lambda.amazonaws.com"
Policies:
- PolicyDocument:
Version: "2012-10-17"
Statement:
- Action:
- "logs:CreateLogGroup"
- "logs:CreateLogStream"
- "logs:PutLogEvents"
Effect: "Allow"
Resource:
- !Sub "arn:aws:logs:eu-central-1:123456789012:log-group:/aws/lambda/*:*"
PolicyName: "myLambdaPolicy"
When I deploy using the serverless deploy command, I sometimes got the following error:
An error occurred: HelloDashdemoLambdaFunction - The role defined for the function cannot be assumed by Lambda. (Service: AWSLambdaInternal; Status Code: 400; Error Code: InvalidParameterValueException; Request ID: 4099072a-809d-4f1c-b83e-7f4f5dd5170b).
It looks like a random bug, since it doesn’t occurs everytime. Also, when it occurs, it doesn’t always occurs on the same function.
Did I do something wrong? How can I fix that?
Thanks for your help.
I think that the problem is that in your Lambda function declarations, you're referring to the IAM role as role: arn:aws:iam::123456789012:role/lambdaIAMRole. This is an absolute ARN and is how you would indicate an IAM role (or other resource) that was created and managed outside of your serverless.yml template.
In your case, the quickest fix is to simply replace role: arn:aws:iam::123456789012:role/lambdaIAMRole with role: lambdaIAMRole. The latter refers to an AWS resource declared inside the template.
An even better fix, assuming that all of your Lambda functions will have the same role, is to remove your lambdaIAMRole declaration entirely and then remove all role: arn:aws:iam::123456789012:role/lambdaIAMRole properties from the Lambda functions. The role declaration adds nothing over the default IAM role that the Serverless Framework will implicitly generate for you and assign to the Lambda functions. This is one of the things that makes the framework valuable - it provides good defaults to save you the time and effort. Examples here.