问题
Using the serverless framework, I am trying to build a Lambda function that periodically rotates a secret stored in AWS Secrets Manager.
I am having trouble configuring the roles needed for the Secret Manager to execute the Lambda. In my serverless.yml
I have defined the following resources:
resources:
Resources:
RotateKeysRole:
Type: AWS::IAM::Role
Properties:
RoleName: rotate-keys-role
ManagedPolicyArns:
- arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service:
- lambda.amazonaws.com
- secretsmanager.amazonaws.com
Action: sts:AssumeRole
and attach this role to the rotation Lambda like this:
functions:
rotateKeys:
handler: lambdas.rotate_keys.handler
role: RotateKeysRole
Yet, when I try to set up Secrets Manager to use this Lambda for rotating secrets I will get the following error message:
Secrets Manager cannot invoke the specified Lambda function. Ensure that the function policy grants access to the principal secretsmanager.amazonaws.com
which puzzles me as this principal is specified. Inspecting the role in the IAM console did not reveal anything that seemed wrong to me.
How do I correctly configure the role setup in this scenario?
回答1:
The procedure of setting up permissions for a lambda function which rotates AWS Secrets Manager secrets is explained in the docs. [1]
To put it in a nutshell, you need two steps:
- Add a trust policy to the lambda function. This can be achieved using the CloudFormation resource AWS::Lambda::Permission in the serverless.yml file. However, it is a little bit tricky to set this up, because you need to depend on the function being created. That is why the DependsOn is necessary and its value must be structured as follows:
<function-name-with-first-letter-uppercase>LambdaFunction
. - Add statements for the lambda function to call the AWS Secrets Manager API to update the secret. In the following example, I added these statements (for the Single user rotation case - see docs [1]) to the customer managed policy called rotateKeysPolicy.
Note: The function name is referenced in the DependsOn attribute. It is also referenced in the condition StringEquals and the attribute FunctionName as: arn:aws:lambda:${self:custom.region}:${self:custom.accountId}:function:${self:service}-${self:provider.stage}-rotateKeys
. Keep in mind to change them if you change your function name.
Here is how the serverless.yml file should look like:
service:
name: <your-service-name>
provider:
name: aws
region: '<your-region>'
custom:
region: ${self:provider.region}
accountId: <your-account-id>
resources:
Resources:
FunctionRole:
Type: AWS::IAM::Role
Properties:
RoleName: basic-function-role
ManagedPolicyArns:
- arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
Policies:
- PolicyName: rotateKeysPolicy
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- secretsmanager:DescribeSecret
- secretsmanager:GetSecretValue
- secretsmanager:PutSecretValue
- secretsmanager:UpdateSecretVersionStage
Resource: '*'
Condition:
StringEquals:
'secretsmanager:resource/AllowRotationLambdaArn': "arn:aws:lambda:${self:custom.region}:${self:custom.accountId}:function:${self:service}-${self:provider.stage}-rotateKeys"
- Effect: Allow
Action:
- secretsmanager:GetRandomPassword
Resource: '*'
- Effect: Allow
Action:
- ec2:CreateNetworkInterface
- ec2:DeleteNetworkInterface
- ec2:DescribeNetworkInterfaces
Resource: '*'
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service:
- lambda.amazonaws.com
Action: sts:AssumeRole
LambdaInvokePermission:
Type: AWS::Lambda::Permission
DependsOn: RotateKeysLambdaFunction
Properties:
FunctionName: "arn:aws:lambda:${self:custom.region}:${self:custom.accountId}:function:${self:service}-${self:provider.stage}-rotateKeys"
Action: lambda:InvokeFunction
Principal: 'secretsmanager.amazonaws.com'
functions:
rotateKeys:
handler: lambdas.rotate_keys.handler
role: FunctionRole
You have to replace <your-service-name>
, <your-region>
, <your-account-id>
and upload your rotation code using e.g. the package -> include
attributes.
Note: There are templates for the lambda function which update the secrets. [2][3]
Please also keep in mind to configure your VPC correctly for the lambda function being able to access the AWS Secrets Manager service over the network. [4]
References
[1] https://docs.aws.amazon.com/secretsmanager/latest/userguide/rotating-secrets-required-permissions.html
[2] https://docs.aws.amazon.com/secretsmanager/latest/userguide/rotating-secrets-create-generic-template.html
[3] https://github.com/aws-samples/aws-secrets-manager-rotation-lambdas
[4] https://docs.aws.amazon.com/secretsmanager/latest/userguide/rotation-network-rqmts.html
回答2:
I had the same issue today. I ran this and it worked for me: aws lambda add-permission --function-name ARN_of_lambda_function --principal secretsmanager.amazonaws.com --action lambda:InvokeFunction --statement-id SecretsManagerAccess
https://docs.aws.amazon.com/secretsmanager/latest/userguide/troubleshoot_rotation.html
回答3:
Your policy is incorrect. The service is secretsmanager but the action you defined is sts:AssumeRole which is from AWS Security Token Service.
A full access policy would be:
Effect: "Allow"
Action: "secretsmanager:*"
Resource: "*"
But you should limit the actions and the Resource the lambda can use. For this you can use the policy builder which can be found in IAM->Policies.
After creating a policy in the editor you can click on the JSON Tab and see the format. Then you need to adapt it to your serverless yaml format.
I hope I can help you!
Dominik
来源:https://stackoverflow.com/questions/57118962/how-do-i-grant-a-rotation-lambda-access-to-aws-secrets-manager