Serverless-application-model: !Sub & !Ref functions inside AWS::Serverless::Function Policies

Created on 31 Aug 2017  路  8Comments  路  Source: aws/serverless-application-model

The !Sub or !Ref functions don't seem to work in when used inside the AWS::Serverless::Function Policies property.

In the following cases I am trying to use the AWS::AccountId pseudo parameter within the policies property.

Case 1:
Set Policies value to a single string

  lambda:
    Type: AWS::Serverless::Function
    Properties:
      ...
      Policies: !Sub arn:aws:iam::${AWS::AccountId}:policy/my-policy
      ...

Case 2:
Set Policies value to an array of strings

  lambda:
    Type: AWS::Serverless::Function
    Properties:
      ...
      Policies: 
        - !Sub arn:aws:iam::${AWS::AccountId}:policy/my-policy
      ...

Outcome

The policy is simply ignored. I don't get an error, but the policy is not attached to the generated role.

Without the parameter it works fine.

Case 3:
Use the literal value and it works fine

  lambda:
    Type: AWS::Serverless::Function
    Properties:
      ...
      Policies: 
        - !Sub arn:aws:iam::123456789:policy/my-policy
      ...

It does only seem to be the Policies element effected by this. For example:

Case 4
Comparing !Ref in different places

  lambda:
    Type: AWS::Serverless::Function
    Properties:
      ...
      Handler: !Ref MyParamName
      Policies:  !Ref MyParamName
      ...

This works for Handler but not for Policies.

So in summary, neither of these functions (and possible more) work in the Policies element. Is this by design or missing functionality?

Most helpful comment

Don't think this issue is limited to policies. I get generic 'internal transform failure' at time of creating change set for similar case in the Events property of AWS::Serverless::Function

Example:

      Events:
        GetByHashAndRange:
          Type: Api
          Properties:
            Path: !Sub '/{${DynamoHashKey}}/{${DynamoRangeKey}}'
            Method: get

Where DynamoHashKey and DynamoRangeKey here are parameters.

All 8 comments

Found one workaround. Explicitly create an AWS::IAM::Role instead of allowing Serverless to create one. Then the !Sub function works fine in ManagedPolicyArns property. This eliminates the need for the Policies property of the AWS::Serverless::Function in favour of the Role property.

  role:
    Type: AWS::IAM::Role
    Properties:
      ...
      ManagedPolicyArns:
        - !Sub arn:aws:iam::${AWS::AccountId}:policy/my-policy
      ...
  lambda:
    Type: AWS::Serverless::Function
    Properties:
      ...
      Role: !GetAtt role.Arn
      ...

I have struggled with this issue as well. My work around has normally been to use policy documents for my lambda functions instead.

That way we are able to create policy documents for our functions that contains intrinsic functions.

  Function:
    Type: AWS::Serverless::Function
    Properties:
      Runtime: nodejs6.10
      Handler: index.handler
      CodeUri: .
      Events:
        GetResource:
          Type: Api
          Properties:
            Path: /
            Method: get
      Policies:
        - Version: '2012-10-17'
          Statement:
            - Effect: Allow
              Action: dynamodb:Query
              Resource: !Sub 'arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${Table}'
      Environment:
        Variables:
          TableName: !Ref Table

Don't think this issue is limited to policies. I get generic 'internal transform failure' at time of creating change set for similar case in the Events property of AWS::Serverless::Function

Example:

      Events:
        GetByHashAndRange:
          Type: Api
          Properties:
            Path: !Sub '/{${DynamoHashKey}}/{${DynamoRangeKey}}'
            Method: get

Where DynamoHashKey and DynamoRangeKey here are parameters.

+1

This is a known bug with fix in progress. Check #172 for updates

@sanathkr I saw that it was fixed in the policies, but still having issue using !Sub in Path.
Events: GetHealth: Type: Api Properties: Path: !Sub '/${ContentPath}/health' Method: get

I get the following error:

Error creating change set: Transform AWS::Serverless-2016-10-31 failed with: Internal transform failure.

@mikecbrant Did you figure out a workaround?

@jnsstnbrg

My workaround was simply to begin with Cloudform templates generated via the server less transform and then modify those. In essence using this transform as a template generator and then just working with the generated templates on an ongoing basis.

@mikecbrant Thanks! I went ahead and used troposphere to generate the template.

Was this page helpful?
0 / 5 - 0 ratings