Skip to content

Commit

Permalink
Allow explicit AWS::NoValue for Api and HttpApi Gateway Default Autho…
Browse files Browse the repository at this point in the history
…rizer

Use AWS::NoValue rather than NONE to preserve backwards compatibility with any templates that have authorizers named NONE
  • Loading branch information
ethanmills committed Oct 10, 2023
1 parent 9074ad0 commit d5d7f94
Show file tree
Hide file tree
Showing 22 changed files with 6,762 additions and 11 deletions.
3 changes: 2 additions & 1 deletion samtranslator/internal/schema_source/aws_serverless_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
PassThroughProp,
ResourceAttributes,
SamIntrinsicable,
SamIntrinsicableOrNoValue,
get_prop,
passthrough_prop,
)
Expand Down Expand Up @@ -119,7 +120,7 @@ class Auth(BaseModel):
],
]
] = auth("Authorizers")
DefaultAuthorizer: Optional[str] = auth("DefaultAuthorizer")
DefaultAuthorizer: Optional[SamIntrinsicableOrNoValue[str]] = auth("DefaultAuthorizer")
InvokeRole: Optional[str] = auth("InvokeRole")
ResourcePolicy: Optional[ResourcePolicy] = auth("ResourcePolicy")
UsagePlan: Optional[UsagePlan] = auth("UsagePlan")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
PassThroughProp,
ResourceAttributes,
SamIntrinsicable,
SamIntrinsicableOrNoValue,
get_prop,
)

Expand Down Expand Up @@ -62,7 +63,7 @@ class Auth(BaseModel):
],
]
] = auth("Authorizers")
DefaultAuthorizer: Optional[str] = auth("DefaultAuthorizer")
DefaultAuthorizer: Optional[SamIntrinsicableOrNoValue[str]] = auth("DefaultAuthorizer")
EnableIamAuthorizer: Optional[bool] = auth("EnableIamAuthorizer")


Expand Down
2 changes: 2 additions & 0 deletions samtranslator/internal/schema_source/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ class PassThroughProp(pydantic.BaseModel):
T = TypeVar("T")
SamIntrinsicable = Union[Dict[str, Any], T]
SamIntrinsic = Dict[str, Any]
SamIntrinsicNoValue = Dict[Literal["Ref"], Literal["AWS::NoValue"]]
SamIntrinsicableOrNoValue = Union[SamIntrinsicNoValue, T]

# TODO: Get rid of this in favor of proper types
Unknown = Optional[Any]
Expand Down
5 changes: 4 additions & 1 deletion samtranslator/model/api/api_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
InvalidResourceException,
InvalidTemplateException,
)
from samtranslator.model.intrinsics import fnGetAtt, fnSub, is_intrinsic, make_or_condition, ref
from samtranslator.model.intrinsics import fnGetAtt, fnSub, is_intrinsic, is_intrinsic_no_value, make_or_condition, ref
from samtranslator.model.lambda_ import LambdaPermission
from samtranslator.model.route53 import Route53RecordSetGroup
from samtranslator.model.s3_utils.uri_parser import parse_s3_uri
Expand Down Expand Up @@ -1291,6 +1291,9 @@ def _set_default_authorizer(
if not default_authorizer:
return

if is_intrinsic_no_value(default_authorizer):
return

if not isinstance(default_authorizer, str):
raise InvalidResourceException(
self.logical_id,
Expand Down
34 changes: 30 additions & 4 deletions samtranslator/schema/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -251687,9 +251687,22 @@
"type": "object"
},
"DefaultAuthorizer": {
"anyOf": [
{
"additionalProperties": {
"enum": [
"AWS::NoValue"
],
"type": "string"
},
"type": "object"
},
{
"type": "string"
}
],
"markdownDescription": "Specify a default authorizer for an API Gateway API, which will be used for authorizing API calls by default\\. \nIf the Api EventSource for the function associated with this API is configured to use IAM Permissions, then this property must be set to `AWS_IAM`, otherwise an error will result\\.\n*Type*: String \n*Required*: No \n*Default*: None \n*AWS CloudFormation compatibility*: This property is unique to AWS SAM and doesn't have an AWS CloudFormation equivalent\\.",
"title": "DefaultAuthorizer",
"type": "string"
"title": "DefaultAuthorizer"
},
"InvokeRole": {
"markdownDescription": "Sets integration credentials for all resources and methods to this value\\. \n`CALLER_CREDENTIALS` maps to `arn:aws:iam::*:user/*`, which uses the caller credentials to invoke the endpoint\\. \n*Valid values*: `CALLER_CREDENTIALS`, `NONE`, `IAMRoleArn` \n*Type*: String \n*Required*: No \n*Default*: `CALLER_CREDENTIALS` \n*AWS CloudFormation compatibility*: This property is unique to AWS SAM and doesn't have an AWS CloudFormation equivalent\\.",
Expand Down Expand Up @@ -254150,9 +254163,22 @@
"type": "object"
},
"DefaultAuthorizer": {
"anyOf": [
{
"additionalProperties": {
"enum": [
"AWS::NoValue"
],
"type": "string"
},
"type": "object"
},
{
"type": "string"
}
],
"markdownDescription": "Specify the default authorizer to use for authorizing API calls to your API Gateway API\\. You can specify `AWS_IAM` as a default authorizer if `EnableIamAuthorizer` is set to `true`\\. Otherwise, specify an authorizer that you've defined in `Authorizers`\\. \n*Type*: String \n*Required*: No \n*Default*: None \n*AWS CloudFormation compatibility*: This property is unique to AWS SAM and doesn't have an AWS CloudFormation equivalent\\.",
"title": "DefaultAuthorizer",
"type": "string"
"title": "DefaultAuthorizer"
},
"EnableIamAuthorizer": {
"markdownDescription": "Specify whether to use IAM authorization for the API route\\. \n*Type*: Boolean \n*Required*: No \n*AWS CloudFormation compatibility*: This property is unique to AWS SAM and doesn't have an AWS CloudFormation equivalent\\.",
Expand Down
34 changes: 30 additions & 4 deletions schema_source/sam.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -3438,9 +3438,22 @@
"type": "object"
},
"DefaultAuthorizer": {
"anyOf": [
{
"additionalProperties": {
"enum": [
"AWS::NoValue"
],
"type": "string"
},
"type": "object"
},
{
"type": "string"
}
],
"markdownDescription": "Specify a default authorizer for an API Gateway API, which will be used for authorizing API calls by default\\. \nIf the Api EventSource for the function associated with this API is configured to use IAM Permissions, then this property must be set to `AWS_IAM`, otherwise an error will result\\.\n*Type*: String \n*Required*: No \n*Default*: None \n*AWS CloudFormation compatibility*: This property is unique to AWS SAM and doesn't have an AWS CloudFormation equivalent\\.",
"title": "DefaultAuthorizer",
"type": "string"
"title": "DefaultAuthorizer"
},
"InvokeRole": {
"markdownDescription": "Sets integration credentials for all resources and methods to this value\\. \n`CALLER_CREDENTIALS` maps to `arn:aws:iam::*:user/*`, which uses the caller credentials to invoke the endpoint\\. \n*Valid values*: `CALLER_CREDENTIALS`, `NONE`, `IAMRoleArn` \n*Type*: String \n*Required*: No \n*Default*: `CALLER_CREDENTIALS` \n*AWS CloudFormation compatibility*: This property is unique to AWS SAM and doesn't have an AWS CloudFormation equivalent\\.",
Expand Down Expand Up @@ -6639,9 +6652,22 @@
"type": "object"
},
"DefaultAuthorizer": {
"anyOf": [
{
"additionalProperties": {
"enum": [
"AWS::NoValue"
],
"type": "string"
},
"type": "object"
},
{
"type": "string"
}
],
"markdownDescription": "Specify the default authorizer to use for authorizing API calls to your API Gateway API\\. You can specify `AWS_IAM` as a default authorizer if `EnableIamAuthorizer` is set to `true`\\. Otherwise, specify an authorizer that you've defined in `Authorizers`\\. \n*Type*: String \n*Required*: No \n*Default*: None \n*AWS CloudFormation compatibility*: This property is unique to AWS SAM and doesn't have an AWS CloudFormation equivalent\\.",
"title": "DefaultAuthorizer",
"type": "string"
"title": "DefaultAuthorizer"
},
"EnableIamAuthorizer": {
"markdownDescription": "Specify whether to use IAM authorization for the API route\\. \n*Type*: Boolean \n*Required*: No \n*AWS CloudFormation compatibility*: This property is unique to AWS SAM and doesn't have an AWS CloudFormation equivalent\\.",
Expand Down
144 changes: 144 additions & 0 deletions tests/translator/input/api_with_auth_explicit_inline_no_default.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
Resources:
MyApiWithCognitoAuth:
Type: AWS::Serverless::Api
Properties:
StageName: Prod
Auth:
DefaultAuthorizer: !Ref AWS::NoValue
Authorizers:
MyCognitoAuth:
UserPoolArn: !GetAtt MyUserPool.Arn

MyApiWithLambdaTokenAuth:
Type: AWS::Serverless::Api
Properties:
StageName: Prod
Auth:
DefaultAuthorizer: !Ref AWS::NoValue
Authorizers:
MyLambdaTokenAuth:
FunctionArn: !GetAtt MyAuthFn.Arn

MyApiWithLambdaRequestAuth:
Type: AWS::Serverless::Api
Properties:
StageName: Prod
Auth:
DefaultAuthorizer: !Ref AWS::NoValue
Authorizers:
MyLambdaRequestAuth:
FunctionPayloadType: REQUEST
FunctionArn: !GetAtt MyAuthFn.Arn
Identity:
Headers:
- Authorization1
MyAuthFn:
Type: AWS::Serverless::Function
Properties:
CodeUri: s3://bucket/key
Handler: index.handler
Runtime: nodejs12.x
MyFn:
Type: AWS::Serverless::Function
Properties:
CodeUri: s3://bucket/key
Handler: index.handler
Runtime: nodejs12.x
Events:
CognitoNoAuth:
Type: Api
Properties:
RestApiId: !Ref MyApiWithCognitoAuth
Method: get
Path: /cognito/no-auth
CognitoNoAuthAnyMethod:
Type: Api
Properties:
RestApiId: !Ref MyApiWithCognitoAuth
Method: any
Path: /cognito/any/no-auth
Cognito:
Type: Api
Properties:
RestApiId: !Ref MyApiWithCognitoAuth
Method: get
Path: /any/cognito
Auth:
Authorizer: MyCognitoAuth
CognitoAnyMethod:
Type: Api
Properties:
RestApiId: !Ref MyApiWithCognitoAuth
Method: any
Path: /any/cognito
Auth:
Authorizer: MyCognitoAuth
LambdaTokenNoAuth:
Type: Api
Properties:
RestApiId: !Ref MyApiWithLambdaTokenAuth
Method: get
Path: /lambda-token/no-auth
LambdaTokenNoAuthAnyMethod:
Type: Api
Properties:
RestApiId: !Ref MyApiWithLambdaTokenAuth
Method: any
Path: /lambda-token/any/no-auth
LambdaToken:
Type: Api
Properties:
RestApiId: !Ref MyApiWithLambdaTokenAuth
Method: get
Path: /lambda-token
Auth:
Authorizer: MyLambdaTokenAuth
LambdaTokenAnyMethod:
Type: Api
Properties:
RestApiId: !Ref MyApiWithLambdaTokenAuth
Method: any
Path: /any/lambda-token
Auth:
Authorizer: MyLambdaTokenAuth
LambdaRequestNoAuth:
Type: Api
Properties:
RestApiId: !Ref MyApiWithLambdaRequestAuth
Method: get
Path: /lambda-request/no-auth
LambdaRequestNoAuthAnyMethod:
Type: Api
Properties:
RestApiId: !Ref MyApiWithLambdaRequestAuth
Method: any
Path: /lambda-request/any/no-auth
LambdaRequest:
Type: Api
Properties:
RestApiId: !Ref MyApiWithLambdaRequestAuth
Method: get
Path: /lambda-request
Auth:
Authorizer: MyLambdaRequestAuth
LambdaRequestAnyMethod:
Type: Api
Properties:
RestApiId: !Ref MyApiWithLambdaRequestAuth
Method: any
Path: /any/lambda-request
Auth:
Authorizer: MyLambdaRequestAuth
MyUserPool:
Type: AWS::Cognito::UserPool
Properties:
UserPoolName: UserPoolName
Policies:
PasswordPolicy:
MinimumLength: 8
UsernameAttributes:
- email
Schema:
- AttributeDataType: String
Name: email
Required: false
Loading

0 comments on commit d5d7f94

Please sign in to comment.