m90
m90

Reputation: 11822

How do I grant a rotation Lambda access to AWS Secrets Manager

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?

Upvotes: 19

Views: 17731

Answers (4)

Sushil Kumar
Sushil Kumar

Reputation: 1529

I got this resolved by adding following aws_lambda_permission resource

resource "aws_lambda_permission" "example_permission" {
  statement_id  = "AllowSecretsManagerToInvokeFunction"
  action        = "lambda:InvokeFunction"
  function_name = module.moduleName.aws_lambda_function.lambda_handler
  principal     = "secretsmanager.amazonaws.com"
}

Upvotes: 2

Secrets...
Secrets...

Reputation: 151

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

Upvotes: 15

Martin Löper
Martin Löper

Reputation: 6649

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

Upvotes: 14

DominikHelps
DominikHelps

Reputation: 1021

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. Policy builder

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

Upvotes: -2

Related Questions