Skip to content

Commit 4efb9df

Browse files
authored
fix: openapi postprocess bug in request models with security definitions (#990)
1 parent 88df20c commit 4efb9df

File tree

5 files changed

+476
-246
lines changed

5 files changed

+476
-246
lines changed

samtranslator/model/api/api_generator.py

Lines changed: 8 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -314,29 +314,7 @@ def _add_auth(self):
314314

315315
# Assign the Swagger back to template
316316

317-
self.definition_body = self._openapi_auth_postprocess(swagger_editor.swagger)
318-
319-
def _openapi_auth_postprocess(self, definition_body):
320-
"""
321-
Convert auth components to openapi 3 in definition body if OpenApiVersion flag is specified.
322-
323-
If there is swagger defined in the definition body, we treat it as a swagger spec and do not
324-
make any openapi 3 changes to it.
325-
"""
326-
if definition_body.get('swagger') is not None:
327-
return definition_body
328-
329-
if definition_body.get('openapi') is not None:
330-
if self.open_api_version is None:
331-
self.open_api_version = definition_body.get('openapi')
332-
333-
if self.open_api_version and re.match(SwaggerEditor.get_openapi_version_3_regex(), self.open_api_version):
334-
if definition_body.get('securityDefinitions'):
335-
components = definition_body.get('components', {})
336-
components['securitySchemes'] = definition_body['securityDefinitions']
337-
definition_body['components'] = components
338-
del definition_body['securityDefinitions']
339-
return definition_body
317+
self.definition_body = self._openapi_postprocess(swagger_editor.swagger)
340318

341319
def _add_gateway_responses(self):
342320
"""
@@ -407,9 +385,9 @@ def _add_models(self):
407385

408386
# Assign the Swagger back to template
409387

410-
self.definition_body = self._openapi_models_postprocess(swagger_editor.swagger)
388+
self.definition_body = self._openapi_postprocess(swagger_editor.swagger)
411389

412-
def _openapi_models_postprocess(self, definition_body):
390+
def _openapi_postprocess(self, definition_body):
413391
"""
414392
Convert definitions to openapi 3 in definition body if OpenApiVersion flag is specified.
415393
@@ -424,6 +402,11 @@ def _openapi_models_postprocess(self, definition_body):
424402
self.open_api_version = definition_body.get('openapi')
425403

426404
if self.open_api_version and re.match(SwaggerEditor.get_openapi_version_3_regex(), self.open_api_version):
405+
if definition_body.get('securityDefinitions'):
406+
components = definition_body.get('components', {})
407+
components['securitySchemes'] = definition_body['securityDefinitions']
408+
definition_body['components'] = components
409+
del definition_body['securityDefinitions']
427410
if definition_body.get('definitions'):
428411
components = definition_body.get('components', {})
429412
components['schemas'] = definition_body['definitions']

tests/translator/input/api_request_model_openapi_3.yaml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,19 @@ Resources:
1515
RequestModel:
1616
Model: User
1717
Required: true
18+
Iam:
19+
Type: Api
20+
Properties:
21+
RequestModel:
22+
Model: User
23+
Required: true
24+
RestApiId:
25+
Ref: HtmlApi
26+
Method: get
27+
Path: /iam
28+
Auth:
29+
Authorizer: AWS_IAM
30+
1831

1932
HtmlApi:
2033
Type: AWS::Serverless::Api

tests/translator/output/api_request_model_openapi_3.json

Lines changed: 160 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -1,129 +1,158 @@
11
{
22
"Resources": {
3-
"HtmlFunction": {
4-
"Type": "AWS::Lambda::Function",
3+
"HtmlFunctionIamPermissionTest": {
4+
"Type": "AWS::Lambda::Permission",
55
"Properties": {
6-
"Code": {
7-
"S3Bucket": "sam-demo-bucket",
8-
"S3Key": "member_portal.zip"
9-
},
10-
"Handler": "index.gethtml",
11-
"Role": {
12-
"Fn::GetAtt": [
13-
"HtmlFunctionRole",
14-
"Arn"
6+
"Action": "lambda:invokeFunction",
7+
"Principal": "apigateway.amazonaws.com",
8+
"FunctionName": {
9+
"Ref": "HtmlFunction"
10+
},
11+
"SourceArn": {
12+
"Fn::Sub": [
13+
"arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/${__Stage__}/GET/iam",
14+
{
15+
"__Stage__": "*",
16+
"__ApiId__": {
17+
"Ref": "HtmlApi"
18+
}
19+
}
1520
]
16-
},
17-
"Runtime": "nodejs4.3",
18-
"Tags": [
19-
{
20-
"Key": "lambda:createdBy",
21-
"Value": "SAM"
22-
}
23-
]
21+
}
2422
}
25-
},
23+
},
2624
"HtmlFunctionRole": {
27-
"Type": "AWS::IAM::Role",
25+
"Type": "AWS::IAM::Role",
2826
"Properties": {
27+
"ManagedPolicyArns": [
28+
"arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
29+
],
2930
"AssumeRolePolicyDocument": {
30-
"Version": "2012-10-17",
31+
"Version": "2012-10-17",
3132
"Statement": [
3233
{
3334
"Action": [
3435
"sts:AssumeRole"
35-
],
36-
"Effect": "Allow",
36+
],
37+
"Effect": "Allow",
3738
"Principal": {
3839
"Service": [
3940
"lambda.amazonaws.com"
4041
]
4142
}
4243
}
4344
]
44-
},
45-
"ManagedPolicyArns": [
46-
"arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
47-
]
45+
}
4846
}
49-
},
50-
"HtmlFunctionGetHtmlPermissionTest": {
51-
"Type": "AWS::Lambda::Permission",
47+
},
48+
"HtmlApiProdStage": {
49+
"Type": "AWS::ApiGateway::Stage",
5250
"Properties": {
53-
"Action": "lambda:invokeFunction",
54-
"FunctionName": {
55-
"Ref": "HtmlFunction"
56-
},
57-
"Principal": "apigateway.amazonaws.com",
58-
"SourceArn": {
59-
"Fn::Sub": [
60-
"arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/${__Stage__}/GET/",
61-
{
62-
"__ApiId__": "HtmlApi",
63-
"__Stage__": "*"
64-
}
65-
]
66-
}
51+
"DeploymentId": {
52+
"Ref": "HtmlApiDeployment47f78fe7d9"
53+
},
54+
"RestApiId": {
55+
"Ref": "HtmlApi"
56+
},
57+
"StageName": "Prod"
6758
}
68-
},
69-
"HtmlFunctionGetHtmlPermissionProd": {
70-
"Type": "AWS::Lambda::Permission",
59+
},
60+
"HtmlFunctionIamPermissionProd": {
61+
"Type": "AWS::Lambda::Permission",
7162
"Properties": {
72-
"Action": "lambda:invokeFunction",
63+
"Action": "lambda:invokeFunction",
64+
"Principal": "apigateway.amazonaws.com",
7365
"FunctionName": {
7466
"Ref": "HtmlFunction"
75-
},
76-
"Principal": "apigateway.amazonaws.com",
67+
},
7768
"SourceArn": {
7869
"Fn::Sub": [
79-
"arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/${__Stage__}/GET/",
70+
"arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/${__Stage__}/GET/iam",
8071
{
81-
"__ApiId__": "HtmlApi",
82-
"__Stage__": "Prod"
72+
"__Stage__": "Prod",
73+
"__ApiId__": {
74+
"Ref": "HtmlApi"
75+
}
8376
}
8477
]
8578
}
8679
}
87-
},
80+
},
8881
"HtmlApi": {
89-
"Type": "AWS::ApiGateway::RestApi",
82+
"Type": "AWS::ApiGateway::RestApi",
9083
"Properties": {
9184
"Body": {
9285
"info": {
93-
"version": "1.0",
86+
"version": "1.0",
9487
"title": {
9588
"Ref": "AWS::StackName"
9689
}
97-
},
90+
},
9891
"paths": {
99-
"/": {
92+
"/iam": {
10093
"get": {
94+
"requestBody": {
95+
"content": {
96+
"application/json": {
97+
"schema": {
98+
"$ref": "#/components/schemas/user"
99+
}
100+
}
101+
},
102+
"required": true
103+
},
101104
"x-amazon-apigateway-integration": {
102-
"type": "aws_proxy",
103-
"httpMethod": "POST",
105+
"httpMethod": "POST",
106+
"type": "aws_proxy",
104107
"uri": {
105108
"Fn::Sub": "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${HtmlFunction.Arn}/invocations"
109+
},
110+
"credentials": "arn:aws:iam::*:user/*"
111+
},
112+
"security": [
113+
{
114+
"AWS_IAM": []
106115
}
107-
},
108-
"responses": {},
116+
],
117+
"responses": {}
118+
}
119+
},
120+
"/": {
121+
"get": {
109122
"requestBody": {
110123
"content": {
111124
"application/json": {
112125
"schema": {
113126
"$ref": "#/components/schemas/user"
114127
}
115128
}
116-
},
129+
},
117130
"required": true
118-
}
131+
},
132+
"x-amazon-apigateway-integration": {
133+
"httpMethod": "POST",
134+
"type": "aws_proxy",
135+
"uri": {
136+
"Fn::Sub": "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${HtmlFunction.Arn}/invocations"
137+
}
138+
},
139+
"responses": {}
119140
}
120141
}
121-
},
122-
"openapi": "3.0.1",
142+
},
143+
"openapi": "3.0.1",
123144
"components": {
145+
"securitySchemes": {
146+
"AWS_IAM": {
147+
"x-amazon-apigateway-authtype": "awsSigv4",
148+
"type": "apiKey",
149+
"name": "Authorization",
150+
"in": "header"
151+
}
152+
},
124153
"schemas": {
125154
"user": {
126-
"type": "object",
155+
"type": "object",
127156
"properties": {
128157
"username": {
129158
"type": "string"
@@ -134,26 +163,75 @@
134163
}
135164
}
136165
}
137-
},
138-
"HtmlApiDeployment1cc40869ce": {
139-
"Type": "AWS::ApiGateway::Deployment",
166+
},
167+
"HtmlApiDeployment47f78fe7d9": {
168+
"Type": "AWS::ApiGateway::Deployment",
140169
"Properties": {
141-
"Description": "RestApi deployment id: 1cc40869cebf8364cbef858c24289beee3338228",
142170
"RestApiId": {
143171
"Ref": "HtmlApi"
172+
},
173+
"Description": "RestApi deployment id: 47f78fe7d91eb5d2070674ad77943842c49dab89"
174+
}
175+
},
176+
"HtmlFunctionGetHtmlPermissionTest": {
177+
"Type": "AWS::Lambda::Permission",
178+
"Properties": {
179+
"Action": "lambda:invokeFunction",
180+
"Principal": "apigateway.amazonaws.com",
181+
"FunctionName": {
182+
"Ref": "HtmlFunction"
183+
},
184+
"SourceArn": {
185+
"Fn::Sub": [
186+
"arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/${__Stage__}/GET/",
187+
{
188+
"__Stage__": "*",
189+
"__ApiId__": "HtmlApi"
190+
}
191+
]
144192
}
145193
}
146-
},
147-
"HtmlApiProdStage": {
148-
"Type": "AWS::ApiGateway::Stage",
194+
},
195+
"HtmlFunctionGetHtmlPermissionProd": {
196+
"Type": "AWS::Lambda::Permission",
149197
"Properties": {
150-
"DeploymentId": {
151-
"Ref": "HtmlApiDeployment1cc40869ce"
152-
},
153-
"RestApiId": {
154-
"Ref": "HtmlApi"
155-
},
156-
"StageName": "Prod"
198+
"Action": "lambda:invokeFunction",
199+
"Principal": "apigateway.amazonaws.com",
200+
"FunctionName": {
201+
"Ref": "HtmlFunction"
202+
},
203+
"SourceArn": {
204+
"Fn::Sub": [
205+
"arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/${__Stage__}/GET/",
206+
{
207+
"__Stage__": "Prod",
208+
"__ApiId__": "HtmlApi"
209+
}
210+
]
211+
}
212+
}
213+
},
214+
"HtmlFunction": {
215+
"Type": "AWS::Lambda::Function",
216+
"Properties": {
217+
"Handler": "index.gethtml",
218+
"Code": {
219+
"S3Bucket": "sam-demo-bucket",
220+
"S3Key": "member_portal.zip"
221+
},
222+
"Role": {
223+
"Fn::GetAtt": [
224+
"HtmlFunctionRole",
225+
"Arn"
226+
]
227+
},
228+
"Runtime": "nodejs4.3",
229+
"Tags": [
230+
{
231+
"Value": "SAM",
232+
"Key": "lambda:createdBy"
233+
}
234+
]
157235
}
158236
}
159237
}

0 commit comments

Comments
 (0)