3 O4\h@sPddlZddlmZddlmZddlmZddlmZmZGddde Z dS)N) string_types)ref)make_conditional)InvalidDocumentExceptionInvalidTemplateExceptionc@s eZdZdZdZdZdZdZdZddZ d d Z d;d d Z ddZ ddZ ddZddZdddZddZd d!Zd?d"d#Zd@d$d%Zd&d'Zd(d)Zd*d+Zd,d-ZdAd/d0Zd1d2Zed3d4Ze d5d6Z!e d7d8Z"e d9d:Z#d S)B SwaggerEditorad Wrapper class capable of parsing and generating Swagger JSON. This implements Swagger spec just enough that SAM cares about. It is built to handle "partial Swagger" ie. Swagger that is incomplete and won't pass the Swagger spec. But this is necessary for SAM because it iteratively builds the Swagger starting from an empty skeleton. optionszx-amazon-apigateway-integrationzFn::Ifz%x-amazon-apigateway-gateway-responseszx-amazon-apigateway-any-methodcCsPtj|stdtj||_|jd|_|jjdi|_|jj|j i|_ dS)aB Initialize the class with a swagger dictionary. This class creates a copy of the Swagger and performs all modifications on this copy. :param dict doc: Swagger document as a dictionary :raises ValueError: If the input Swagger document does not meet the basic Swagger requirements. zInvalid Swagger documentpathssecurityDefinitionsN) ris_valid ValueErrorcopydeepcopy_docr getsecurity_definitions_X_APIGW_GATEWAY_RESPONSESgateway_responses)selfdocr/Users/sshvans/Documents/Work/Quickstart/python-virtual-environments/env/lib/python3.6/site-packages/samtranslator/swagger/swagger.py__init__s   zSwaggerEditor.__init__cCs2|jj|}t|tr.|j|kr.||jd}|S)N)r r isinstancedict_CONDITIONAL_IF)rpath path_dictrrrget_path(s zSwaggerEditor.get_pathNcCs0|j|}|j|}|dk }|r,|o*||kS|S)z Returns True if this Swagger has the given path and optional method :param string path: Path name :param string method: HTTP method :return: True, if this path/method is present in the document N)_normalize_method_namer)rrmethodrZpath_dict_existsrrrhas_path.s    zSwaggerEditor.has_pathcCs&x |j|D]}|j|r dSq WdS)a Returns true if the given method contains a valid method definition. This uses the get_method_contents function to handle conditionals. :param dict method: method dictionary :return: true if method has one or multiple integrations TF)get_method_contents!method_definition_has_integration)rr!method_definitionrrrmethod_has_integration>s z$SwaggerEditor.method_has_integrationcCs|j|jrdSdS)z Checks a method definition to make sure it has an apigw integration :param dict method_defintion: method definition dictionary :return: True if an integration exists TF)r_X_APIGW_INTEGRATION)rr%rrrr$Ks z/SwaggerEditor.method_definition_has_integrationcCs"|j|kr||jddS|gS)ac Returns the swagger contents of the given method. This checks to see if a conditional block has been used inside of the method, and, if so, returns the method contents that are inside of the conditional. :param dict method: method dictionary :return: list of swagger component dictionaries for the method rN)r)rr!rrrr#Vs z!SwaggerEditor.get_method_contentscCs<|j|}|j|}|j||o:t||to:|j||S)z Checks if an API Gateway integration is already present at the given path/method :param string path: Path name :param string method: HTTP method :return: True, if an API Gateway integration is already present )r rr"rrr&)rrr!rrrrhas_integrationcs    zSwaggerEditor.has_integrationcCs^|j|}|jj|i}t|ts6ttdj|g|j|krN||jd}|j|idS)z Adds the path/method combination to the Swagger, if not already present :param string path: Path name :param string method: HTTP method :raises ValueError: If the value of `path` in Swagger is not a dictionary zBValue of '{}' path must be a dictionary according to Swagger spec.rN) r r setdefaultrrrrformatr)rrr!rrrradd_pathrs    zSwaggerEditor.add_pathcCs|j|}|j||r&tdj|||j|||r@t||}|j|}dd|d|||j<|pfi}|pni}|jddks|jddkr| r|j |jd|jdd |j |||jd <||j d i|rt|||||<d S) z Adds aws_proxy APIGW integration to the given path+method. :param string path: Path name :param string method: HTTP Method :param string integration_uri: URI for the integration. z7Lambda integration already exists on Path={}, Method={}Z aws_proxyPOST)typeZ httpMethodZuri AuthorizerAWS_IAMDefaultAuthorizerZ InvokeRole)method_invoke_roleapi_invoke_roleZ credentials responsesN) r r(r r*r+rrr'r!_generate_integration_credentialsr r))rrr!Zintegration_uriZmethod_auth_configZapi_auth_config conditionrrrradd_lambda_integrations(     "z$SwaggerEditor.add_lambda_integrationcCst||j||j|<dS)zS Wrap entire API path definition in a CloudFormation if condition. N)rr )rrr5rrrmake_path_conditionalsz#SwaggerEditor.make_path_conditionalcCs|j|p |S)N)_get_invoke_role)rr1r2rrrr4sz/SwaggerEditor._generate_integration_credentialscCsd}|r|dkr|S|S)Nzarn:aws:iam::*:user/*ZCALLER_CREDENTIALSr)rZ invoke_roleZCALLER_CREDENTIALS_ARNrrrr8szSwaggerEditor._get_invoke_roleccs"x|jjD]\}}|Vq WdS)z Yields all the paths available in the Swagger. As a caller, if you add new paths to Swagger while iterating, they will not show up in this iterator :yields string: Path name N)r items)rrvaluerrr iter_on_pathszSwaggerEditor.iter_on_pathcCsr|j||jrdS|std|s6|j|}dj|}|dk rBd}|j||j|j||||||j||j<dS)a Add CORS configuration to this path. Specifically, we will add a OPTIONS response config to the Swagger that will return headers required for CORS. Since SAM uses aws_proxy integration, we cannot inject the headers into the actual response returned from Lambda function. This is something customers have to implement themselves. If OPTIONS method is already present for the Path, we will skip adding CORS configuration Following this guide: https://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-cors.html#enable-cors-for-resource-using-swagger-importer-tool :param string path: Path to add the CORS configuration to. :param string/dict allowed_origins: Comma separate list of allowed origins. Value can also be an intrinsic function dict. :param string/dict allowed_headers: Comma separated list of allowed headers. Value can also be an intrinsic function dict. :param string/dict allowed_methods: Comma separated list of allowed methods. Value can also be an intrinsic function dict. :param integer/dict max_age: Maximum duration to cache the CORS Preflight request. Value is set on Access-Control-Max-Age header. Value can also be an intrinsic function dict. :param bool/None allow_credentials: Flags whether request is allowed to contain credentials. :raises ValueError: When values for one of the allowed_* variables is empty Nz3Invalid input. Value for AllowedOrigins is requiredz'{}'TF)r"_OPTIONS_METHODr #_make_cors_allowed_methods_for_pathr*r+!_options_method_response_for_corsr)rrallowed_originsallowed_headersallowed_methodsmax_ageallow_credentialsrrradd_corss  zSwaggerEditor.add_corscCsd}d}d}d} d} dd} | ||i} |dd ii} |rP|| | |<dd i| |<|rl|| | |<dd i| |<|d k r|| | | <dd i| | <|d krd | | | <dd i| | <ddddgddg|jdddidd| ddididddd| diiS)aX Returns a Swagger snippet containing configuration for OPTIONS HTTP Method to configure CORS. This snippet is taken from public documentation: https://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-cors.html#enable-cors-for-resource-using-swagger-importer-tool :param string/dict allowed_origins: Comma separate list of allowed origins. Value can also be an intrinsic function dict. :param string/dict allowed_headers: Comma separated list of allowed headers. Value can also be an intrinsic function dict. :param string/dict allowed_methods: Comma separated list of allowed methods. Value can also be an intrinsic function dict. :param integer/dict max_age: Maximum duration to cache the CORS Preflight request. Value is set on Access-Control-Max-Age header. Value can also be an intrinsic function dict. :param bool allow_credentials: Flags whether request is allowed to contain credentials. :return dict: Dictionary containing Options method configuration for CORS zAccess-Control-Allow-OriginzAccess-Control-Allow-HeaderszAccess-Control-Allow-MethodszAccess-Control-Max-Agez Access-Control-Allow-CredentialscSsd|S)Nzmethod.response.header.r)xrrrszASwaggerEditor._options_method_response_for_cors..r-stringNintegerTz'true'summaryz CORS supportZconsumeszapplication/jsonZproducesZmockz{ "statusCode" : 200 } defaultZ200z{} )Z statusCodeZresponseParametersZresponseTemplates)r-ZrequestTemplatesr3r3z Default response for CORS method) descriptionheaders)r')rr?r@rArBrCZ ALLOW_ORIGINZ ALLOW_HEADERSZ ALLOW_METHODSZMAX_AGEZALLOW_CREDENTIALSZHEADER_RESPONSEZresponse_parametersZresponse_headersrrrr>sF          z/SwaggerEditor._options_method_response_for_corscCstdddddddg}|j|s dSt|j|j}|j|krB|}n|}|jd td d |D}|jd j|S) a Creates the value for Access-Control-Allow-Methods header for given path. All HTTP methods defined for this path will be included in the result. If the path contains "ANY" method, then *all available* HTTP methods will be returned as result. :param string path: Path to generate AllowMethods value for :return string: String containing the value of AllowMethods, if the path contains any methods. Empty string, otherwise ZOPTIONSGETZHEADr,PUTZDELETEZPATCHrcSsh|] }|jqSr)upper).0mrrr |szDSwaggerEditor._make_cors_allowed_methods_for_path..,)r"listrkeys _X_ANY_METHODappendsortjoin)rrZall_http_methodsmethodsZ allow_methodsrrrr=Ys    z1SwaggerEditor._make_cors_allowed_methods_for_pathcCs4|jpi|_x"|jD]\}}|j|j|<qWdS)z Add Authorizer definitions to the securityDefinitions part of Swagger. :param list authorizers: List of Authorizer configurations which get translated to securityDefinitions. N)rr9generate_swagger)r authorizersauthorizer_nameZ authorizerrrradd_authorizerss zSwaggerEditor.add_authorizersc Cs6x0|j|jD]\}}|j|||||ddqWdS)a Sets the DefaultAuthorizer for each method on this path. The DefaultAuthorizer won't be set if an Authorizer was defined at the Function/Path/Method level :param string path: Path name :param string default_authorizer: Name of the authorizer to use as the default. Must be a key in the authorizers param. :param list authorizers: List of Authorizer configurations defined on the related Api. T)default_authorizer is_defaultN)rr9set_method_authorizer)rrr`r] method_namer!rrrset_path_default_authorizers  z)SwaggerEditor.set_path_default_authorizerc CsN|o |jd}|rJ|jd}|o(|jd}|o6|jd}|j|||||dS)a: Adds auth settings for this path/method. Auth settings currently consist solely of Authorizers but this method will eventually include setting other auth settings such as API Key, Resource Policy, etc. :param string path: Path name :param string method_name: Method name :param dict auth: Auth configuration such as Authorizers, ApiKey, ResourcePolicy (only Authorizers supported currently) :param dict api: Reference to the related Api's properties as defined in the template. r.ZAuthZ Authorizersr0N)rrb) rrrcZauthZapiZmethod_authorizerZapi_authZapi_authorizersr`rrradd_auth_to_methods  z SwaggerEditor.add_auth_to_methodFcCs|j|}xp|j|j||D]V}|j|s4q"|jdg} dg} |rX| j|jt| } g} g} x0| D](}| j|jr| j |qn| j |qnWd }g}|r x4t | D](\}}t dd|jD}|r|}PqW|d kr| |=n| r| }ni}g||<|g}ni}g||<|g}| |}|r"||d<d|ddkr"dddd d d i}|j sd||_ q"d|j kr"|j j |q"WdS)Nsecurityr/rcss|]}|dkVqdS)NONENr)rQkeyrrr sz6SwaggerEditor.set_method_authorizer..rZawsSigv4ZapiKeyZ Authorizationheader)zx-amazon-apigateway-authtyper-nameinrm)r r#rr$rextendrVset isdisjointrX enumerateanyrupdate)rrrcr^r]r`raZnormalized_method_namer%Zexisting_securityZauthorizer_listZauthorizer_namesZ existing_non_authorizer_securityZexisting_authorizer_securityrfZnone_idxZauthorizer_securityidxZis_noneZ security_dictZaws_iam_security_definitionrrrrbs\       z#SwaggerEditor.set_method_authorizercCs4|jpi|_x"|jD]\}}|j|j|<qWdS)z Add Gateway Response definitions to Swagger. :param dict gateway_responses: Dictionary of GatewayResponse configuration which gets translated. N)rr9r\)rrZ response_typeresponserrradd_gateway_responsess z#SwaggerEditor.add_gateway_responsescCs>|j|jd<|jr|j|jd<|jr2|j|j|j<tj|jS)z Returns a **copy** of the Swagger document as a dictionary. :return dict: Dictionary containing the Swagger document r r )r rrrrr r)rrrrswaggers  zSwaggerEditor.swaggercCs0t|o.t|to.t|jdo.t|jdtS)z Checks if the input data is a Swagger document :param dict data: Data to be validated :return: True, if data is a Swagger rwr )boolrrr)datarrrr !s zSwaggerEditor.is_validcCsddtddidS)z Method to make an empty swagger file, with just some basic structure. Just enough to pass validator. :return dict: Dictionary of a skeleton swagger document z2.0z1.0zAWS::StackName)versiontitle)rwinfor )rrrrr gen_skeleton.s zSwaggerEditor.gen_skeletoncCs4| st|t r|S|j}|dkr,tjS|SdS)aN Returns a lower case, normalized version of HTTP Method. It also know how to handle API Gateway specific methods like "ANY" NOTE: Always normalize before using the `method` value passed in as input :param string method: Name of the HTTP Method :return string: Normalized method name rrN)rrlowerrrW)r!rrrr ?s z$SwaggerEditor._normalize_method_name)N)N)NNN)NN)NNNN)NNNN)F)$__name__ __module__ __qualname____doc__r<r'rrrWrrr"r&r$r#r(r+r6r7r4r8r;rDr>r=r_rdrerbrvpropertyrw staticmethodr r}r rrrrr sB      +   2 X)  T  r) r sixrZsamtranslator.model.intrinsicsrrZsamtranslator.model.exceptionsrrobjectrrrrrs