serverless-application-model icon indicating copy to clipboard operation
serverless-application-model copied to clipboard

Can not use Fn::if within CustomStatements:

Open eerb-kyruus opened this issue 5 years ago • 1 comments

Description:

I am attempting to write a custom policy for my Serverless api that depends on deployment type. The serverless transform expects a list inside the CustomStatements: label, preventing use of fn:If to conditionally set policies. The obvious work-around is to specify the entire swagger document myself, but this creates lots of duplication and a huge template.

Steps to reproduce the issue: NOTE: Confidential parts of the template have been redacted

  1. Create a serverless API template with this in the conditional section: Conditions: IsProd:
  2. Create a conditional resource policy like the following in the AWS:Serverless:Api Auth: section:
        ResourcePolicy:
           CustomStatements:
            Fn::If:
            - IsProd
            - - Principal: '*'
                Effect: Allow
                Action: <redacted>
                Resource: <redacted>
            - - Principal: '*'
                Effect: Allow
                Action: <redacted>
                Resource: <redacted>
                Condition:
                  <redacted>

Observed result: The macro creates the following within the swagger doc, reformatted for readability. Note carefully the extra set of square brackets around the policy statement:

"x-amazon-apigateway-policy":
  {
  "Version":"2012-10-17","Statement":
    [
      [
        {
        Condition":
          {
             <redacted>
         },
        "Action": <redacted>
        "Resource": <redacted>
        "Effect":"Allow",
        "Principal":"*"
        }
      ]
   ]
  },

The deploy fails due to that extra set of square brackets in the policy statement

Expected result: The swagger gateway policy is created with a single set of square brackets and the deploy succeeds.

eerb-kyruus avatar Oct 23 '19 19:10 eerb-kyruus

@eerb-kyruus Thanks for reporting this. Looks like this code isn't taking intrinsic functions into account:

https://github.com/awslabs/serverless-application-model/blob/440790a8c2278fc16acbe34c83183668c5f40c38/samtranslator/swagger/swagger.py#L987-L988

For now, a possible workaround would be to embed the Fn::If inside each statement, e.g.,:

        ResourcePolicy:
           CustomStatements:
            - !If
              - IsProd
              - Principal: '*'
                Effect: Allow
                Action: <redacted>
                Resource: <redacted>
              - !Ref AWS::NoValue
            - !If
              - IsProd
              - Principal: '*'
                Effect: Allow
                Action: <redacted>
                Resource: <redacted>
                Condition:
                  <redacted>
              - !Ref AWS::NoValue

I'm not sure what CloudFormation will do in the case that all custom statements have this condition and the condition is false. Hopefully it will treat this as an empty list. However, it may throw an error due to all child values resolving to AWS::NoValue.

jlhood avatar Oct 23 '19 21:10 jlhood

You might be able to get this to work by adding AWS::LanguageExtensions to Transform as such:

Transform:
  - AWS::LanguageExtensions
  - AWS::Serverless-2016-10-31

AWS::LanguageExtensions resolves intrinsic functions if the value is known when Transforms are run.

See https://github.com/aws/serverless-application-model/issues/2533 for more information.

hoffa avatar Oct 17 '22 21:10 hoffa

Closing in favor of https://github.com/aws/serverless-application-model/issues/2533.

hoffa avatar Nov 03 '22 23:11 hoffa