serverless-application-model
serverless-application-model copied to clipboard
Can not use Fn::if within CustomStatements:
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
- Create a serverless API template with this in the conditional section:
Conditions:
IsProd:
- 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 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
.
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 Transform
s are run.
See https://github.com/aws/serverless-application-model/issues/2533 for more information.
Closing in favor of https://github.com/aws/serverless-application-model/issues/2533.