28

I'm getting an error in my Lambda function, which calls SSM:

AccessDeniedException: User: arn:aws:sts::redacted:assumed-role/LambdaBackend_master_lambda/SpikeLambda is not authorized to perform: ssm:GetParameter on resource: arn:aws:ssm:eu-west-1:redacted:parameter/default/key/api

However, I'm pretty sure I configured this correctly:

Role, with AssumeRole for Lambda (although we know that works from the error message).

λ aws iam get-role --role-name LambdaBackend_master_lambda
{
    "Role": {
        "AssumeRolePolicyDocument": {
            "Version": "2012-10-17",
            "Statement": [
                {
                    "Action": "sts:AssumeRole",
                    "Effect": "Allow",
                    "Principal": {
                        "Service": "lambda.amazonaws.com"
                    }
                }
            ]
        },
        "RoleId": "redacted",
        "CreateDate": "2017-06-23T20:49:37Z",
        "RoleName": "LambdaBackend_master_lambda",
        "Path": "/",
        "Arn": "arn:aws:iam::redacted:role/LambdaBackend_master_lambda"
    }
}

And my policy:

λ aws iam list-role-policies --role-name LambdaBackend_master_lambda
{
    "PolicyNames": [
        "ssm_read"
    ]
}
λ aws iam get-role-policy --role-name LambdaBackend_master_lambda --policy-name ssm_read
{
    "RoleName": "LambdaBackend_master_lambda",
    "PolicyDocument": {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Action": [
                    "ssm:DescribeParameters"
                ],
                "Resource": "*",
                "Effect": "Allow"
            },
            {
                "Action": [
                    "ssm:GetParameters"
                ],
                "Resource": "arn:aws:ssm:eu-west-1:redacted:parameter/*",
                "Effect": "Allow"
            }
        ]
    },
    "PolicyName": "ssm_read"
}

I've run it through the policy simulator and it seems to be fine!

AWS IAM policy sim

Oli
  • 582
  • 1
  • 6
  • 18
  • 2
    Seems like a bug in how ssm:GetParameters is validated. When I use `boto3.client('ssm').get_parameter()`, the lambda permissions work as expected, but I get the permissions error you mention when using `boto3.client('ssm').get_parameters()`. – skeller88 Dec 23 '17 at 21:29
  • You need to follow the steps mentioned here to allow the lambda execution role to make read calls to SSM service: https://stackoverflow.com/a/76893668/12326605 – Arpit Jain Aug 13 '23 at 16:52

7 Answers7

45

Played around with this today and got the following, dropping the s from ssm:GetParameters and using ssm:GetParameter seems to work when using the GetParameter action. ie AWS_PROFILE=pstore aws ssm get-parameter --name param_name. This weirded me out a bit because I cannot find this at all in the iam action docs here. However it does seem to work, and ssm is still a bit under documented. Amazon has updated and moved it's docs. The new docs incude both ssm:GetParameters and ssm:GetParameter.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": [
                "ssm:DescribeParameters"
            ],
            "Resource": "*",
            "Effect": "Allow"
        },
        {
            "Action": [
                "ssm:GetParameter"
            ],
            "Resource": "arn:aws:ssm:eu-west-1:redacted:parameter/*",
            "Effect": "Allow"
        }
    ]
}
jeffrey
  • 965
  • 14
  • 25
  • 2
    Under documented, but still better documented than some of the software I use! Thanks! – Oli Jun 28 '17 at 11:43
  • Attaching this policy to the role that runs the Lambda solved it for me. – jmng Sep 20 '18 at 14:39
  • 4
    I had `Action: ["ssm:GetParametersByPath", "ssm:GetParameters", "ssm:GetParameter"]` and it was failing. After removing the first two and leaving only `"ssm:GetParameter"` I got it working – Blueriver Feb 27 '20 at 18:28
8

In my case (I used AWS SDK for Go V2), I needed both ssm:GetParametersByPath and ssm:GetParameter to make it work.

Ali
  • 18,665
  • 21
  • 103
  • 138
2

Ran into the same error today. The following Java code caused it when encrypted = false and paramName referred to an unencrypted parameter

    GetParameterRequest request = new GetParameterRequest()
        .withName(paramName)
        .withWithDecryption(encrypted);
    GetParameterResult resultPacket = ssmClient.getParameter(request);

The fix was to create the unencrypted parameter request without setting the WithDecryption flag - GetParameterRequest request = new GetParameterRequest().withName(paramName);

Ross Kerr
  • 123
  • 1
  • 6
1

It really depends on the command you use in your Lambda.

If you use boto3.client('ssm').get_parameters(Names=[param1, param2]), then you need "Action": ["ssm:GetParameters"],

or alternatively when you use boto3.client('ssm').get_parameter(Name=param), you would need "Action": ["ssm:GetParameter"]

Abbas Hosseini
  • 651
  • 6
  • 10
1

regarding the confusion ssm:GetParameter and ssm:GetParameters. I attached the policy AmazonEC2RoleforSSM to some user and ran into the same problem, "not authorized to perform: ssm:GetParameter" because this Policy only has ssm:GetParameters. AWS had a deprecation warning attached to that policy and recommended to use AmazonSSMManagedInstanceCore instead, which has both Actions ssm:GetParameters and ssm:GetParameter. Which then worked fine.

0

In my case, I was using s3:GetObject and s3:ListBucket. To fix the error I had to add the bucket twice in resources and append to one of them a *. For example:

{
  "Statement" : [
    {
      "Effect" : "Allow",
      "Action" : [
        "s3:GetObject",
        "s3:ListBucket",
      ],
      "Resource" : [
        "arn:aws:s3:::mybucket/*",
        "arn:aws:s3:::mybucket",
      ]
    },
  ]
}
HereHere
  • 734
  • 1
  • 7
  • 24
0

For me I had the path wrong (I was missing the leading / on the path name when making the request - it seems obvious but it's easy to miss and worth double checking if you're experiencing this issue.

❌ Wrong

        var getParameterResponse = await _ssm.GetParameterAsync(new GetParameterRequest
        {
            Name = "my-component-namespace/my-parameter",
            WithDecryption = true
        });

✅ Correct

        var getParameterResponse = await _ssm.GetParameterAsync(new GetParameterRequest
        {
            Name = "/my-component-namespace/my-parameter",
            WithDecryption = true
        });
Tom
  • 2,321
  • 2
  • 18
  • 29