7
7
from samtranslator .open_api .open_api import OpenApiEditor
8
8
from samtranslator .translator import logical_id_generator
9
9
from samtranslator .model .tags .resource_tagging import get_tag_list
10
+ from samtranslator .model .intrinsics import is_intrinsic
11
+
12
+ _CORS_WILDCARD = "*"
13
+ CorsProperties = namedtuple (
14
+ "_CorsProperties" , ["AllowMethods" , "AllowHeaders" , "AllowOrigins" , "MaxAge" , "ExposeHeaders" , "AllowCredentials" ]
15
+ )
16
+ CorsProperties .__new__ .__defaults__ = (None , None , None , None , None , False )
10
17
11
18
AuthProperties = namedtuple ("_AuthProperties" , ["Authorizers" , "DefaultAuthorizer" ])
12
19
AuthProperties .__new__ .__defaults__ = (None , None )
@@ -25,6 +32,7 @@ def __init__(
25
32
stage_name ,
26
33
tags = None ,
27
34
auth = None ,
35
+ cors_configuration = None ,
28
36
access_log_settings = None ,
29
37
default_route_settings = None ,
30
38
resource_attributes = None ,
@@ -53,6 +61,7 @@ def __init__(
53
61
if not self .stage_name :
54
62
self .stage_name = DefaultStageName
55
63
self .auth = auth
64
+ self .cors_configuration = cors_configuration
56
65
self .tags = tags
57
66
self .access_log_settings = access_log_settings
58
67
self .default_route_settings = default_route_settings
@@ -69,8 +78,11 @@ def _construct_http_api(self):
69
78
70
79
if self .definition_uri and self .definition_body :
71
80
raise InvalidResourceException (
72
- self .logical_id , "Specify either 'DefinitionUri' or 'DefinitionBody' property and not both"
81
+ self .logical_id , "Specify either 'DefinitionUri' or 'DefinitionBody' property and not both. "
73
82
)
83
+ if self .cors_configuration :
84
+ # call this method to add cors in open api
85
+ self ._add_cors ()
74
86
75
87
self ._add_auth ()
76
88
self ._add_tags ()
@@ -84,11 +96,74 @@ def _construct_http_api(self):
84
96
self .logical_id ,
85
97
"'DefinitionUri' or 'DefinitionBody' are required properties of an "
86
98
"'AWS::Serverless::HttpApi'. Add a value for one of these properties or "
87
- "add a 'HttpApi' event to an 'AWS::Serverless::Function'" ,
99
+ "add a 'HttpApi' event to an 'AWS::Serverless::Function'. " ,
88
100
)
89
101
90
102
return http_api
91
103
104
+ def _add_cors (self ):
105
+ """
106
+ Add CORS configuration if CORSConfiguration property is set in SAM.
107
+ Adds CORS configuration only if DefinitionBody is present and
108
+ APIGW extension for CORS is not present in the DefinitionBody
109
+ """
110
+
111
+ if self .cors_configuration and not self .definition_body :
112
+ raise InvalidResourceException (
113
+ self .logical_id , "Cors works only with inline OpenApi specified in 'DefinitionBody' property."
114
+ )
115
+
116
+ # If cors configuration is set to true add * to the allow origins.
117
+ # This also support referencing the value as a parameter
118
+ if isinstance (self .cors_configuration , bool ):
119
+ # if cors config is true add Origins as "'*'"
120
+ properties = CorsProperties (AllowOrigins = [_CORS_WILDCARD ])
121
+
122
+ elif is_intrinsic (self .cors_configuration ):
123
+ # Just set Origin property. Intrinsics will be handledOthers will be defaults
124
+ properties = CorsProperties (AllowOrigins = self .cors_configuration )
125
+
126
+ elif isinstance (self .cors_configuration , dict ):
127
+ # Make sure keys in the dict are recognized
128
+ if not all (key in CorsProperties ._fields for key in self .cors_configuration .keys ()):
129
+ raise InvalidResourceException (self .logical_id , "Invalid value for 'Cors' property." )
130
+
131
+ properties = CorsProperties (** self .cors_configuration )
132
+
133
+ else :
134
+ raise InvalidResourceException (self .logical_id , "Invalid value for 'Cors' property." )
135
+
136
+ if not OpenApiEditor .is_valid (self .definition_body ):
137
+ raise InvalidResourceException (
138
+ self .logical_id ,
139
+ "Unable to add Cors configuration because "
140
+ "'DefinitionBody' does not contain a valid "
141
+ "OpenApi definition." ,
142
+ )
143
+
144
+ if properties .AllowCredentials is True and properties .AllowOrigins == [_CORS_WILDCARD ]:
145
+ raise InvalidResourceException (
146
+ self .logical_id ,
147
+ "Unable to add Cors configuration because "
148
+ "'AllowCredentials' can not be true when "
149
+ "'AllowOrigin' is \" '*'\" or not set." ,
150
+ )
151
+
152
+ editor = OpenApiEditor (self .definition_body )
153
+ # if CORS is set in both definition_body and as a CorsConfiguration property,
154
+ # SAM merges and overrides the cors headers in definition_body with headers of CorsConfiguration
155
+ editor .add_cors (
156
+ properties .AllowOrigins ,
157
+ properties .AllowHeaders ,
158
+ properties .AllowMethods ,
159
+ properties .ExposeHeaders ,
160
+ properties .MaxAge ,
161
+ properties .AllowCredentials ,
162
+ )
163
+
164
+ # Assign the OpenApi back to template
165
+ self .definition_body = editor .openapi
166
+
92
167
def _add_auth (self ):
93
168
"""
94
169
Add Auth configuration to the OAS file, if necessary
0 commit comments