I'd like to have a secret that can be access by all lambdas with different roles in an AWS account. One option would be to attach a policy that allows access to the secret to all the lambdas, but given that we have large number of lambdas, I was wondering if I could do the reverse with resource permissions with in secrets manager.
I've attached the following policy to the secret.
{
"Version" : "2012-10-17",
"Statement" : [ {
"Effect" : "Allow",
"Principal" : {
"Service" : "lambda.amazonaws.com"
},
"Action" : "secretsmanager:GetSecretValue",
"Resource" : "arn:aws:secretsmanager:us-east-1:{AWS_ACCOUNT_ID}:secret:dummy-secret-46DfjO",
"Condition" : {
"StringEquals" : {
"aws:sourceAccount" : "{AWS_ACCOUNT_ID}"
}
}
} ]
}
I'd expect the following policy to allow reads from all the lambdas that is in the AWS_ACCOUT_ID, but I am still getting following error:
ERROR | Error while trying to read an API Key from Secrets Manager: Secrets Manager read error: AccessDeniedException: User: arn:aws:sts::AWS_ACCOUNT_ID:assumed-role/dummy-role-name is not authorized to perform: secretsmanager:GetSecretValue on resource: arn:aws:secretsmanager:us-east-1:AWS_ACCOUNT_ID:secret:dummy-secret-46DfjO because no identity-based policy allows the secretsmanager:GetSecretValue action
What am I missing here?
Lambda functions leverage an IAM execution role (dummy-role-name
). This implies that when the permissions are evaluated against the resource-based policy of the secret, there is no service principal (lambda.amazonaws.com
), but instead there is an assumed-role session principal.
As outlined in the documentation, the syntax for this principal is:
"Principal": { "AWS": "arn:aws:sts::AWS-account-ID:assumed-role/role-name/role-session-name" }
where the role-session-name
corresponds to the name of the lambda function.
So your resource-based policy would be:
{
"Version" : "2012-10-17",
"Statement" : [ {
"Effect" : "Allow",
"Principal": {
"AWS": "arn:aws:sts::AWS_ACCOUNT_ID:assumed-role/dummy-role-name/role-session-name"
},
"Action" : "secretsmanager:GetSecretValue",
"Resource" : "arn:aws:secretsmanager:us-east-1:{AWS_ACCOUNT_ID}:secret:dummy-secret-46DfjO"
} ]
}
since you mentioned that you would like multiple lambdas to be able to read from this secret, you would have to change the policy to allow the secret retrieval from the other lambda functions.
Alternatively, you could ditch the resource-based policy entirely and leverage an identity-based policy. This would require you to modify the dummy-role-name
role to include a policy that allows the secretsmanager:GetSecretValue
action.
This might be a better solution if you have many lambda functions, since you could have each lambda function have its own role with its own finegrained permissions. This would be easier than having to manage a single resource-based policy for all of the lambdas.
You can read more about the differences between identity-based and resource-based policies here: https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_identity-vs-resource.html