Search code examples
amazon-web-servicesaws-lambdaaws-secrets-manager

How can I restrict a secret to be accessed only by a certain lambda function?


I have the following use case: I have stored a secret on the Secret Store Manager and I want to make available the value of that secret only for a lambda. The resource based policy of the secret looks like:


{
 "Version" : "2012-10-17",
 "Statement" : [ {
   "Effect" : "Deny",
   "NotPrincipal" : {
     "AWS" : "arn:aws:iam::8999990:role/service-role/test-get-secret-role-68hr4lv6"
   },
   "Action" : [
       "secretsmanager:DescribeSecret",
       "secretsmanager:GetRandomPassword",
       "secretsmanager:GetResourcePolicy",
       "secretsmanager:GetSecretValue",
       "secretsmanager:ListSecrets",
       "secretsmanager:ListSecretVersionIds"
       ],
   "Resource" : "arn:aws:secretsmanager:eu-west-1:99999889:secret:test-test-LLCii9"
 } ]
}

But for the lambda is still not allowed to access the secret, seeing as I also added the permissions for SecretManager on the lambda execution role. Is there another approach for this?

Updated:

{
  "Version" : "2012-10-17",
  "Statement" : [ {
    "Effect" : "Deny",
    "NotPrincipal" : {
      "AWS" : [ "arn:aws:iam::254386565891:role/service-role/test-get-secret-role-68hr4lv6", "arn:aws:sts::254386565891:assumed-role/test-get-secret-role-68hr4lv6/test-get-secret", "arn:aws:sts::254386565891:root" ]
    },
    "Action" : [ "secretsmanager:CancelRotateSecret", "secretsmanager:DeleteSecret", "secretsmanager:GetRandomPassword", "secretsmanager:GetSecretValue", "secretsmanager:ListSecrets", "secretsmanager:ListSecretVersionIds", "secretsmanager:PutSecretValue", "secretsmanager:RemoveRegionsFromReplication", "secretsmanager:ReplicateSecretToRegions", "secretsmanager:RestoreSecret", "secretsmanager:RotateSecret", "secretsmanager:StopReplicationToReplica", "secretsmanager:TagResource", "secretsmanager:UntagResource", "secretsmanager:UpdateSecret", "secretsmanager:UpdateSecretVersionStage" ],
    "Resource" : "arn:aws:secretsmanager:eu-west-1:254386565891:secret:test1-LLCii9"
  }, {
    "Effect" : "Allow",
    "Principal" : {
      "AWS" : [ "arn:aws:iam::254386565891:role/service-role/test-get-secret-role-68hr4lv6"]
    },
    "Action" : "secretsmanager:GetSecretValue",
    "Resource" : "arn:aws:secretsmanager:eu-west-1:254386565891:secret:test1-LLCii9"
  } ]
}

Solution

  • You need to add an explicit Allow statement to the resource policy of the secret to allow the Lambda role to access it.

    Currently you have omitted your test-get-secret-role from the Deny-statement, but you also have to specify what should happen (=Allow) when test-get-secret-role tries to access the resource. You can read more about combining Deny and Not Principal here.

    Update:

    Another, simpler, way to create a policy that only allows one Lambda GetSecretValue-access to a Secret is the following:

    {
      "Version" : "2012-10-17",
      "Statement" : [ {
        "Effect" : "Allow",
        "Principal" : {
          "AWS" : [ "/*lambda role Arn*/"]
        },
        "Action" : "secretsmanager:GetSecretValue",
        "Resource" : "/*secret arn*/"
      }, {
        "Effect" : "Deny",
        "Principal" : "*",
        "Action" : "secretsmanager:GetSecretValue",
        "Resource" : "/*secret arn*/",
        "Condition": {"ArnNotLike": {"aws:PrincipalArn": "/*lambda role arn*/"}}
    
      }]
    }