Skip to content

Commit

Permalink
feat: openapi support for auth usecases (#949)
Browse files Browse the repository at this point in the history
  • Loading branch information
praneetap committed Jun 4, 2019
1 parent 7859f19 commit 675fb89
Show file tree
Hide file tree
Showing 20 changed files with 5,329 additions and 8 deletions.
24 changes: 23 additions & 1 deletion samtranslator/model/api/api_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,29 @@ def _add_auth(self):
self._set_default_authorizer(swagger_editor, authorizers, auth_properties.DefaultAuthorizer)

# Assign the Swagger back to template
self.definition_body = swagger_editor.swagger

self.definition_body = self._openapi_auth_postprocess(swagger_editor.swagger)

def _openapi_auth_postprocess(self, definition_body):
"""
Convert auth components to openapi 3 in definition body if OpenApiVersion flag is specified.
If there is swagger defined in the definition body, we treat it as a swagger spec and do not
make any openapi 3 changes to it.
"""
if definition_body.get('swagger') is not None:
return definition_body

if definition_body.get('openapi') is not None:
if self.open_api_version is None:
self.open_api_version = definition_body.get('openapi')

if self.open_api_version and re.match(SwaggerEditor.get_openapi_version_3_regex(), self.open_api_version):
if definition_body.get('securityDefinitions'):
definition_body['components'] = {}
definition_body['components']['securitySchemes'] = definition_body['securityDefinitions']
del definition_body['securityDefinitions']
return definition_body

def _add_gateway_responses(self):
"""
Expand Down
2 changes: 1 addition & 1 deletion samtranslator/plugins/globals/globals.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ def fix_openapi_definitions(cls, template):
:param dict template: SAM template
:return: Modified SAM template with corrected swagger doc matching the OpenApiVersion.
"""
resources = template["Resources"]
resources = template.get("Resources", {})

for _, resource in resources.items():
if ("Type" in resource) and (resource["Type"] == cls._API_TYPE):
Expand Down
12 changes: 11 additions & 1 deletion tests/plugins/globals/test_globals.py
Original file line number Diff line number Diff line change
Expand Up @@ -811,7 +811,17 @@ class TestGlobalsOpenApi(TestCase):
}
}
},

{
"name": "No Resources",
"input": {
"some": "other",
"swagger": "donottouch"
},
"expected": {
"some": "other",
"swagger": "donottouch"
}
}
]

def test_openapi_postprocess(self):
Expand Down
106 changes: 106 additions & 0 deletions tests/translator/input/api_with_auth_all_maximum_openapi_3.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
Resources:
MyApi:
Type: "AWS::Serverless::Api"
Properties:
StageName: Prod
OpenApiVersion: '3.0.1'
Auth:
DefaultAuthorizer: MyCognitoAuth
Authorizers:
MyCognitoAuth:
UserPoolArn: arn:aws:1
Identity:
Header: MyAuthorizationHeader
ValidationExpression: myauthvalidationexpression

MyCognitoAuthMultipleUserPools:
UserPoolArn:
- arn:aws:2
- arn:aws:3
Identity:
Header: MyAuthorizationHeader2
ValidationExpression: myauthvalidationexpression2

MyLambdaTokenAuth:
FunctionPayloadType: TOKEN
FunctionArn: arn:aws
FunctionInvokeRole: arn:aws:iam::123456789012:role/S3Access
Identity:
Header: MyCustomAuthHeader
ValidationExpression: mycustomauthexpression
ReauthorizeEvery: 20

MyLambdaTokenAuthNoneFunctionInvokeRole:
FunctionArn: arn:aws
FunctionInvokeRole: NONE
Identity:
ReauthorizeEvery: 0

MyLambdaRequestAuth:
FunctionPayloadType: REQUEST
FunctionArn: arn:aws
FunctionInvokeRole: arn:aws:iam::123456789012:role/S3Access
Identity:
Headers:
- Authorization1
QueryStrings:
- Authorization2
StageVariables:
- Authorization3
Context:
- Authorization4
ReauthorizeEvery: 0

MyFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: s3://sam-demo-bucket/thumbnails.zip
Handler: index.handler
Runtime: nodejs8.10
Events:
WithNoAuthorizer:
Type: Api
Properties:
RestApiId: !Ref MyApi
Path: /
Method: get
Auth:
Authorizer: NONE
WithCognitoMultipleUserPoolsAuthorizer:
Type: Api
Properties:
RestApiId: !Ref MyApi
Path: /users
Method: post
Auth:
Authorizer: MyCognitoAuthMultipleUserPools
WithLambdaTokenAuthorizer:
Type: Api
Properties:
RestApiId: !Ref MyApi
Path: /users
Method: get
Auth:
Authorizer: MyLambdaTokenAuth
WithLambdaTokenAuthorizer:
Type: Api
Properties:
RestApiId: !Ref MyApi
Path: /users
Method: patch
Auth:
Authorizer: MyLambdaTokenAuthNoneFunctionInvokeRole
WithLambdaRequestAuthorizer:
Type: Api
Properties:
RestApiId: !Ref MyApi
Path: /users
Method: delete
Auth:
Authorizer: MyLambdaRequestAuth
WithDefaultAuthorizer:
Type: Api
Properties:
RestApiId: !Ref MyApi
Path: /users
Method: put
81 changes: 81 additions & 0 deletions tests/translator/input/api_with_auth_all_minimum_openapi.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
Globals:
Api:
OpenApiVersion: '3.0.1'
Resources:
MyApiWithCognitoAuth:
Type: "AWS::Serverless::Api"
Properties:
StageName: Prod
Auth:
DefaultAuthorizer: MyCognitoAuth
Authorizers:
MyCognitoAuth:
UserPoolArn: !GetAtt MyUserPool.Arn

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

MyApiWithLambdaRequestAuth:
Type: "AWS::Serverless::Api"
Properties:
StageName: Prod
Auth:
DefaultAuthorizer: MyLambdaRequestAuth
Authorizers:
MyLambdaRequestAuth:
FunctionPayloadType: REQUEST
FunctionArn: !GetAtt MyAuthFn.Arn
Identity:
Headers:
- Authorization1
MyAuthFn:
Type: AWS::Serverless::Function
Properties:
CodeUri: s3://bucketname/thumbnails.zip
Handler: index.handler
Runtime: nodejs8.10
MyFn:
Type: AWS::Serverless::Function
Properties:
CodeUri: s3://bucketname/thumbnails.zip
Handler: index.handler
Runtime: nodejs8.10
Events:
Cognito:
Type: Api
Properties:
RestApiId: !Ref MyApiWithCognitoAuth
Method: get
Path: /cognito
LambdaToken:
Type: Api
Properties:
RestApiId: !Ref MyApiWithLambdaTokenAuth
Method: get
Path: /lambda-token
LambdaRequest:
Type: Api
Properties:
RestApiId: !Ref MyApiWithLambdaRequestAuth
Method: get
Path: /lambda-request
MyUserPool:
Type: AWS::Cognito::UserPool
Properties:
UserPoolName: UserPoolName
Policies:
PasswordPolicy:
MinimumLength: 8
UsernameAttributes:
- email
Schema:
- AttributeDataType: String
Name: email
Required: false
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
Globals:
Api:
Name: "some api"
CacheClusterEnabled: True
CacheClusterSize: "1.6"
Auth:
DefaultAuthorizer: MyCognitoAuth
Authorizers:
MyCognitoAuth:
UserPoolArn: !GetAtt MyUserPool.Arn
Variables:
SomeVar: Value

Resources:
ImplicitApiFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: s3://sam-demo-bucket/member_portal.zip
Handler: index.gethtml
Runtime: nodejs4.3
Events:
GetHtml:
Type: Api
Properties:
Path: /
Method: get

ExplicitApi:
Type: AWS::Serverless::Api
Properties:
StageName: SomeStage
DefinitionBody:
openapi: 3.1.1
info:
version: '1.0'
title: !Ref AWS::StackName
paths:
"/":
get:
x-amazon-apigateway-integration:
httpMethod: POST
type: aws_proxy
uri: !Sub arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${ImplicitApiFunction.Arn}/invocations
responses: {}

MyUserPool:
Type: AWS::Cognito::UserPool
Properties:
UserPoolName: UserPoolName
Policies:
PasswordPolicy:
MinimumLength: 8
UsernameAttributes:
- email
Schema:
- AttributeDataType: String
Name: email
Required: false
59 changes: 59 additions & 0 deletions tests/translator/input/api_with_swagger_and_openapi_with_auth.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
Globals:
Api:
Name: "some api"
CacheClusterEnabled: True
CacheClusterSize: "1.6"
Auth:
DefaultAuthorizer: MyCognitoAuth
Authorizers:
MyCognitoAuth:
UserPoolArn: !GetAtt MyUserPool.Arn
Variables:
SomeVar: Value

Resources:
ImplicitApiFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: s3://sam-demo-bucket/member_portal.zip
Handler: index.gethtml
Runtime: nodejs4.3
Events:
GetHtml:
Type: Api
Properties:
Path: /
Method: get

ExplicitApi:
Type: AWS::Serverless::Api
Properties:
StageName: SomeStage
DefinitionBody:
openapi: 3.1.1
swagger: 2.0
info:
version: '1.0'
title: !Ref AWS::StackName
paths:
"/":
get:
x-amazon-apigateway-integration:
httpMethod: POST
type: aws_proxy
uri: !Sub arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${ImplicitApiFunction.Arn}/invocations
responses: {}

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 675fb89

Please sign in to comment.