serverless-application-model
serverless-application-model copied to clipboard
ApiKeyRequired flag set to true does not result in API key being required on API Gateway
Description:
Upon configuring SAM .yaml template for a simple Lambda functiion, with ApiKeyRequired flag set to true for the Auth under AWS::Serverless::Api, the resulting API Gateway that is created after deployment does not require an API key.
Steps to reproduce the issue:
- Configure the .yaml with
ApiKeyRequiredset totrue. - Build and deploy the function, using the following commands: sam build sam deploy --guided
- View the gateway in the AWS console.
Observed result: The gateway does not require an API key.
Expected result: The gateway requires an API key.
Sample configurations file attached. One is very straightforward - it should work. The other is what I had after trying to create everything explicitly - still no dice. template.txt template2.txt
The same outcome (no API key required) is also achieved by setting ApiKeyRequired to true underneath an ApiFunctionAuth within an Api EventSource, indicating some similar bug.
In fact, I observe the following unexpected(?) behavior: if ApiKeyRequired attribute exists and is set to the result of the expression then it is always 'true' no matter what the result of the expression is:
ValidationApi:
Type: 'AWS::Serverless::Api'
Properties:
Auth:
ApiKeyRequired:
!If [UseApiKey, 'true', 'false']
And yes, I checked 10x that the condition UseApiKey behaves as expected
I'm just experiencing the scenario exposed by @paul-michalik . I'm using a function to parameterize the ApiKey requirement when I deploy my stack using a CI. No matter what the comparator or function gives, as a result, the value of ApiKeyRequired is always true.
An ugly workaround is to set a default value for a parameter like.UseApiKey to an empty string '' and set the ApiKeyRequired to !Ref UseApiKey
So, if I pass UseApiKey with any value (which includes false or wololo), it will be transformed to true, but if I don't pass that parameter, it will be set to the default empty string, and it will be transformed to false.
Facing the same issue, would like to enable ApiKeyRequired for the Api Gateway generically without having to enable it for each individual function but it is not applying. Any updates on this?
A workaround for now is to just enable it at function level but its not really ideal.
Any update on the issue experienced by @rcarrillodev ? I just had the same problem as well, and their workaround saved my day.
Oddly enough, it seems an empty parameter is really required. I've tried the following statement:
ApiKeyRequired: !If [IsUsingAPIKey, true, '']
With IsUsingAPIKey being a condition based on UseAPIKey parameter.
It didn't work. I really had to set UseAPIKey parameter to '' and then wrote the following statement:
ApiKeyRequired: !Ref UseAPIKey
Hey @nullpointer800, I deployed your sample template but wasn't able to reproduce the issue. As you can see from the screenshot of the AWS Console, the API Key is required when I deploy your template.txt. Can you check if the issue still persists on your end?
TL;DR: Add AWS::LanguageExtensions to the Transform section. See https://github.com/aws/serverless-application-model/issues/2533.
Tried reproducing with:
Transform: AWS::Serverless-2016-10-31
Resources:
MyApi:
Type: AWS::Serverless::Api
Properties:
StageName: prod
Auth:
ApiKeyRequired: true
HelloWorldFunction:
Type: AWS::Serverless::Function
Properties:
InlineCode: foo
Handler: bar
Runtime: python3.8
Events:
HelloWorld:
Type: Api
Properties:
Path: /hello
Method: get
RestApiId: !Ref MyApi
Deploy with:
sam deploy --region us-west-2 --resolve-s3 --capabilities CAPABILITY_IAM --stack-name test-1553 --template template.yaml
API key is required, as expected.
So then I try with an intrinsic functions, similar to what @guillaume-gc and @rcarrillodev describe:
Transform: AWS::Serverless-2016-10-31
Parameters:
Foo:
Default: "false"
Type: String
Conditions:
UseApiKey:
Fn::Equals:
- !Ref Foo
- "true"
Resources:
MyApi:
Type: AWS::Serverless::Api
Properties:
StageName: prod
Auth:
ApiKeyRequired: !If [UseApiKey, true, false]
HelloWorldFunction:
Type: AWS::Serverless::Function
Properties:
InlineCode: foo
Handler: bar
Runtime: python3.8
Events:
HelloWorld:
Type: Api
Properties:
Path: /hello
Method: get
RestApiId: !Ref MyApi
It still shows API key is required, although Foo is "false".
The suspicious behavior seems to come from here:
https://github.com/aws/serverless-application-model/blob/56d34ff9761da6a64cc4f7424f1fb46919c5b3e6/samtranslator/model/eventsources/push.py#L795-L807
Basically, as long as ApiKeyRequired is truthy, it'll follow the logic to require the API key. And since the SAM transform receives the template as-is (including the intrinsic function), if it doesn't to resolve the intrinsic !If it'll still be considered truthy (!If shows up as a non-empty object in the SAM transform input).
So it looks like an issue with unresolved intrinsic being evaluated as truthy. To fix this, we can add AWS::LanguageExtensions to the Transform section, as it resolves any intrinsic functions known before deployment:
Transform:
- AWS::LanguageExtensions
- AWS::Serverless-2016-10-31
Parameters:
Foo:
Default: "false"
Type: String
Conditions:
UseApiKey:
Fn::Equals:
- !Ref Foo
- "true"
Resources:
MyApi:
Type: AWS::Serverless::Api
Properties:
StageName: prod
Auth:
ApiKeyRequired: !If [UseApiKey, true, false]
HelloWorldFunction:
Type: AWS::Serverless::Function
Properties:
InlineCode: foo
Handler: bar
Runtime: python3.8
Events:
HelloWorld:
Type: Api
Properties:
Path: /hello
Method: get
RestApiId: !Ref MyApi
And this deploys with API key disabled, as expected. See https://github.com/aws/serverless-application-model/issues/2533 for more information.
Adding AWS::LanguageExtensions will cause the other parameter parsing failure.
For example:
Parameters:
...
LambdaMemorySize:
Description: Default lambda function size
Type: Number
Default: 128
...
Resources
ApiFunction:
Type: AWS::Serverless::Function
Properties:
...
Runtime: python3.9
MemorySize: !Ref LambdaMemorySize
The code above will report an invalid type for MemorySize
@hf-qin Right, AWS::LangagueExtensions resolves it as a string, which CloudFormation accepts but SAM doesn't. We've fixed it in https://github.com/aws/serverless-application-model/pull/2928 and will roll out over the coming weeks.