aws / serverless-application-model

The AWS Serverless Application Model (AWS SAM) transform is a AWS CloudFormation macro that transforms SAM templates into CloudFormation templates.
https://aws.amazon.com/serverless/sam
Apache License 2.0
9.36k stars 2.39k forks source link

Handle ParameterName value with or without '/' when creaing generating SSMParameterReadPolicy policy #1112

Closed whimzyLive closed 1 year ago

whimzyLive commented 5 years ago

Description: When using SSMParameterReadPolicy policy template with ParameterName !Ref..ed to SSM resource SSMParameterReadPolicy will generate incorrect arn mapping. For example:

  MyCredParameter:
    Type: AWS::SSM::Parameter
    Properties:
      Name: /prefix/environment/applications/mycred
      Type: String
      Value: !Sub |
        {
          "accessKeyId": "<Your accessKeyId>",
          "accessKeySecret": "<Your accessKeySecret>"
        }

  MyFunction:
    Type: AWS::Serverless::Function
    Properties:
      Handler: file-name.js
      Runtime: nodejs8.10
      CodeUri: dir
      Policies:
        - SSMParameterReadPolicy:
            ParameterName: !Ref MyCredParameter
      Events:
        SomeEvent:
          Type: SNS
          Properties:
            Topic: !Ref MyTopic
      Environment:
        Variables:
          MY_CRED: !Ref MyCredParameter

Here I am creating SSM resource and lambda function that will use this SSM parameter, as well as I am using SAM policy templates to allow MyFunction to allow read access to MyCredParameter.

This will deploy successfully, However, when Lambda tries to get value from SSM params with name process.env.MY_CRED, it will fail.

After some debugging I found out that, My lambda function role had permission to call arn:aws:ssm:my-region:000000000:parameter//prefix/environment/applications/mycred SSM parameter instead of arn:aws:ssm:my-region:000000000:parameter/prefix/environment/applications/mycred. Notice that extra '/' after parameter in first arn.

Observed result: This was because SAM policy templates uses ParameterName as is to create arn without doing any sort of validation.

{
"SSMParameterReadPolicy": {
      "Description": "Gives access to a parameter to load secrets in this account. If not using default key, KMSDecryptPolicy will also be needed.",
      "Parameters": {
        "ParameterName": {
          "Description":"The name of the secret stored in SSM in your account."
        }
      },
      "Definition": {
        "Statement": [
          {
            "Effect": "Allow",
            "Action": [
              "ssm:DescribeParameters"
            ],
            "Resource": "*"
          },
          {
            "Effect": "Allow",
            "Action": [
              "ssm:GetParameters",
              "ssm:GetParameter",
              "ssm:GetParametersByPath"
            ],
            "Resource": {
              "Fn::Sub": [
                "arn:${AWS::Partition}:ssm:${AWS::Region}:${AWS::AccountId}:parameter/${parameterName}",
                {
                  "parameterName": {
                    "Ref": "ParameterName"
                  }
                }
              ]
            }
          }
        ]
      }
    },
}

Expected result: It would be nice to have this ParameterName validated and add or remove / based on validation. Or accept ParameterName with / and do not add / while creating policy, since all SSM parameter name must start with / to be a valid SSM Name.

davidlee-ca commented 4 years ago

This is still an outstanding issue. I'm interested in getting this resolved -- or possibly, require the leading slash to be consistent with AWS CLI syntax.

shogo82148 commented 3 years ago

I have same problem. Any updates?

winderslide008 commented 3 years ago

+1

JJSphar commented 2 years ago

How are others working around this?

I have an SSM path coming from a template parameter with a type of AWS::SSM::Parameter::Name, which validates that the input is a valid SSM parameter which exists at deploy-time. Due to SSM naming rules, this means that the input must begin with a "/". So, we run into the same problem.

Is there an intrinsic CloudFormation function that can check for / grab a substring? If not, would fixing this (at the SAM level) require a separate policy template altogether?

More broadly, there's plenty of services having ARNs that follow the pattern of service:${region}:${account}:resource/${resource_name}. But I'm not aware of any (besides SSM) that will return you a leading / as part of the name, then refuse to accept resource/${resource_name} in the ARN. But that's not something SAM can fix.

aaythapa commented 1 year ago

Closing this, it will be released over the coming weeks