5
votes

Scenario: One of our scripts uses boto3 kms api to PUT and GET SSM parameters with KMS encryption and decryption. SSM param put works perfectly fine and parameters are added (with decryption as true) with secure string in the EC2 SSM param store. The issue we are facing is when trying to GET SSM param values with decryption as true. The corresponding lambda code that runs this script throws following error when trying to run following boto3 script (on running get_ssm_parameters_by_path):

       session = boto3.Session()
       ssm_client = session.client('ssm', 'us-east-1')
       ssm_parameters = []
       response = ssm_client.get_parameters_by_path(
         Path=self.ssm_parameter_path,
         Recursive=True,
         WithDecryption=True
       )

ERROR: An error occurred (AccessDeniedException) when calling the GetParametersByPath operation: The ciphertext refers to a customer master key that does not exist, does not exist in this region, or you are not allowed to access. (Service: AWSKMS; Status Code: 400; Error Code: AccessDeniedException; Request ID: eaaxx-7ae7-11e8-97xx5e-b9exxxxxxx410): ClientError

I went through different AWS docs on working with KMS encryption and decryption and updated my policy document as below but no luck so far. The role that the lambda uses has following policy access in place:

{
"Sid": "AllowSSMAccess",
"Effect": "Allow",
"Action": ["kms:Encrypt", "kms:Decrypt", "kms:ReEncrypt*", "kms:GenerateDataKey*", "kms:DescribeKey"],
"Resource": "arn:aws:kms:us-east-1:AWS_ACCOUNT_NUMBER:key/<aws/ssm default key id>",
"Condition": {
    "StringEquals": {
        "kms:ViaService": "ssm.us-east-1.amazonaws.com",
        "kms:CallerAccount": "AWS_ACCOUNT_NUMBER"
    }
  }
}, 
{
"Sid": "AllowKeyMetadata",
"Effect": "Allow",
"Action": ["kms:Describe*", "kms:Get*", "kms:List*"],
"Resource": "arn:aws:kms:us-east-1:AWS_ACCOUNT_NUMBER:key/<aws/ssm default key id>"
},  
{
  "Sid": "KeyAccess",
  "Effect": "Allow",
  "Action": [
    "kms:Describe*",
    "kms:Enable*",
    "kms:List*",
    "kms:Get*",
"kms:TagResource"
  ],
  "Resource": "arn:aws:kms:us-east-1:AWS_ACCOUNT_NUMBER:key/<aws/ssm default key id>"
}

Where AWS_ACCOUNT_NUMBER is my AWS account number and kms key id is default "aws/ssm" key to encrypt and decrypt SSM param. The key does exists in the account. The region we are giving is "us-east-1" so thats okay to0. The last part of error says "or you dont have access".

I can see that the parameter is available in EC2 SSM param store and properly decrypted with the KEY ID I am using to decrypt.

What other policy access or addition we need to perform in order to run "get_parameters_by_path" run successfully.

2
Ever figure out what it was?BWStearns
no luck yet. I am on a different task and will come back this to reanalyze everything one more time.Vishal

2 Answers

9
votes

You have to define the below policy to access parameter store key.

{
   "Sid": "getParameter",
    "Effect": "Allow",
    "Action": [
        "ssm:GetParameters"
    ],
    "Resource": "arn:aws:ssm:<region>:<AWS_ACCOUNT_NUMBER>:parameter/<Parameter_Store_Key_Name>"
},
{
    "Sid": "decryptKey",
    "Effect": "Allow",
    "Action": [
        "kms:Decrypt"
    ],
    "Resource": "arn:aws:kms:<region>:<AWS_ACCOUNT_NUMBER>:key/<aws/ssm_Key_Id>"
}

ssm:GetParameters will allow us to access Parameter_Store_Key_Name. Refer the https://docs.aws.amazon.com/kms/latest/developerguide/services-parameter-store.html.

1
votes

So, at least for us the solution was in IAM. Down at the bottom of the list there's a section called Encryption Keys. You need to add the relevant user or role to the relevant key. This error is a pain since it only directly refers to SSM so it's misleading as to where the solution is.

Some more info: https://docs.aws.amazon.com/kms/latest/developerguide/key-policies.html#key-policy-default-allow-users