def add_method(self, resource, integration, method_config): """ Creates a Method as a part of this api and adds it to the template. :param resource: The resource that has been created for this api/method pair. :param integration: An Integration object for this method. :param method_config: The method_config object with details for the method. """ method = Method( '{0}Method'.format(method_config.method_name), RestApiId=Ref(self.api), AuthorizationType=method_config.authorizationtype, ResourceId=Ref(resource), HttpMethod=method_config.httpmethod, Integration=integration, MethodResponses=self.method_responses ) if method_config.request.parameters: method.RequestParameters = method_config.request.parameters self.method_responses = [] self.integration_responses = [] self.methods.append(method) self.template.add_resource(method)
def _lambda_method_obj(resource, suffix): resource = self.template.add_resource(resource) return self.template.add_resource( Method( f"APIGatewayLambdaMatomoEventReceiver{suffix}", DependsOn="LambdaMatomoEventReceiver", RestApiId=Ref(api_gateway), AuthorizationType="NONE", ResourceId=Ref(resource), HttpMethod="ANY", Integration=Integration( Credentials=GetAtt("LambdaExecutionRole", "Arn"), Type="AWS_PROXY", IntegrationHttpMethod="POST", Uri=Join( "", [ f"arn:aws:apigateway:{self.region_name}:lambda:path/2015-03-31/functions/", GetAtt("LambdaMatomoEventReceiver", "Arn"), "/invocations", ], ), ), ), )
def generate_proxy_method(self, name, auth, uriParams, resource, api): return Method( name, AuthorizationType=auth, HttpMethod='ANY', Integration=Integration( IntegrationHttpMethod='POST', Type='AWS_PROXY', Uri=Sub( 'arn:${AWS::Partition}:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/arn:${AWS::Partition}:lambda:${AWS::Region}:${AWS::AccountId}:function:${FunctionName}/invocations', **uriParams), ), ResourceId=resource, RestApiId=api, )
def add_method(self, resource, integration, method_config): """ Creates a Method as a part of this api and adds it to the template. :param resource: The resource that has been created for this api/method pair. :param integration: An Integration object for this method. :param method_config: The method_config object with details for the method. """ method = Method('{0}Method'.format(method_config.method_name), RestApiId=Ref(self.api), AuthorizationType=method_config.authorizationtype, ResourceId=Ref(resource), HttpMethod=method_config.httpmethod, Integration=integration, MethodResponses=self.method_responses) if method_config.request.parameters: method.RequestParameters = method_config.request.parameters self.method_responses = [] self.integration_responses = [] self.methods.append(method) self.template.add_resource(method)
def add_method_to_apigateway(t: Template, lambda_function: Function, apigwlambda_role: Role, rest_api: RestApi, resource: Resource, method_type: str): return t.add_resource( Method( f'Method{lambda_function.name}', DependsOn=lambda_function, RestApiId=Ref(rest_api), AuthorizationType="NONE", ResourceId=Ref(resource), HttpMethod=method_type, Integration=Integration( Credentials=GetAtt(apigwlambda_role, "Arn"), Type="AWS", IntegrationHttpMethod='POST', IntegrationResponses=[IntegrationResponse(StatusCode='200')], Uri=Join("", [ "arn:aws:apigateway:eu-west-1:lambda:path/2015-03-31/functions/", GetAtt(lambda_function, "Arn"), "/invocations" ])), MethodResponses=[MethodResponse("CatResponse", StatusCode='200')]))
RestApiId=Ref(rest_api), PathPart="foobar", ParentId=GetAtt("ExampleApi", "RootResourceId"), )) # Create a Lambda API method for the Lambda resource method = t.add_resource( Method( "LambdaMethod", DependsOn='FoobarFunction', RestApiId=Ref(rest_api), AuthorizationType="NONE", ResourceId=Ref(resource), HttpMethod="GET", Integration=Integration( Credentials=GetAtt("LambdaExecutionRole", "Arn"), Type="AWS", IntegrationHttpMethod='POST', IntegrationResponses=[IntegrationResponse(StatusCode='200')], Uri=Join("", [ "arn:aws:apigateway:eu-west-1:lambda:path/2015-03-31/functions/", GetAtt("FoobarFunction", "Arn"), "/invocations" ])), MethodResponses=[MethodResponse("CatResponse", StatusCode='200')])) # Create a deployment stage_name = 'v1' deployment = t.add_resource( Deployment( "%sDeployment" % stage_name,
# /subscribe (POST) subscribe_resource = t.add_resource( Resource("subscribeResource", RestApiId=Ref(rest_api), PathPart="subscribe", ParentId=GetAtt("EmailListApi", "RootResourceId"))) subscribe_method = t.add_resource( Method("subscribeMethod", DependsOn="EmailSubscribeFunction", RestApiId=Ref(rest_api), AuthorizationType="NONE", ResourceId=Ref(subscribe_resource), HttpMethod="POST", Integration=Integration( Type="AWS", IntegrationHttpMethod="POST", IntegrationResponses=[IntegrationResponse(StatusCode="200")], Uri=Join("", [ "arn:aws:apigateway:", Ref('AWS::Region'), ":lambda:path/2015-03-31/functions/", GetAtt(EmailSubscribeFunction, "Arn"), "/invocations" ])), MethodResponses=[MethodResponse("CatResponse", StatusCode="200")])) # /unsubscribe unsubscribe_resource = t.add_resource( Resource("unsubscribeResource", RestApiId=Ref(rest_api), PathPart="unsubscribe", ParentId=GetAtt("EmailListApi", "RootResourceId")))
def initiate_api_gateway_creation(self): self.template.set_version('2010-09-09') self.template.set_description('Creates a API Gateway which is ' 'used to get data from dynamoDB.') role = self.template.add_resource( Role('RootRole', RoleName="monty-cloud-api-role", Path='/', AssumeRolePolicyDocument={ "Version": "2012-10-17", "Statement": [{ "Action": ["sts:AssumeRole"], "Effect": "Allow", "Principal": { "Service": [ "apigateway.amazonaws.com", "lambda.amazonaws.com", "dynamodb.amazonaws.com" ] } }] })) self.template.add_resource( ManagedPolicy( 'RolePolicies', ManagedPolicyName='api-gw-policy', Description='This policy is used for the DynamoDB table ', PolicyDocument={ "Version": "2012-10-17", "Statement": [{ "Action": ["dynamodb:*", "lambda:*", "s3:*"], "Resource": [ "arn:aws:dynamodb:*:*:table/*", "arn:aws:lambda:*:*:function:*" ], "Effect": "Allow" }] }, Roles=[Ref(role)])) name = self.template.add_resource( RestApi('restApiName', Name='monty-cloud-get-api', Description='Monty Cloud API Gateway', EndpointConfiguration=EndpointConfiguration( Types=['REGIONAL']))) self.template.add_resource( Permission("lambdaApiGatewayInvoke", Action="lambda:InvokeFunction", FunctionName="arn:aws:lambda:{}:{}:function:" "get_data".format(self.region, self.account_number), Principal="apigateway.amazonaws.com", SourceArn="arn:aws:execute-api:{}:{}:*/*" "/GET/get-details".format(self.region, self.account_number))) get_api_resource = self.template.add_resource( Resource('restApiGetDetailsResource', RestApiId=Ref(name), ParentId=GetAtt(name, 'RootResourceId'), PathPart='get-details', DependsOn=name)) get_api_method = self.template.add_resource( Method('restApiGetDetailsMethod', AuthorizationType='None', ApiKeyRequired=False, HttpMethod='GET', ResourceId=Ref(get_api_resource), RestApiId=Ref(name), Integration=Integration(Type='AWS_PROXY', IntegrationHttpMethod='POST', Uri=self.uri.format( self.region, self.region, self.account_number), Credentials=GetAtt(role, "Arn")), MethodResponses=[ MethodResponse( StatusCode='200', ResponseModels={'application/json': 'Empty'}) ], DependsOn=get_api_resource)) deployment = self.template.add_resource( Deployment('restApiDeployment', RestApiId=Ref(name), DependsOn=[get_api_method])) self.template.add_resource( Stage('restApiStage', DeploymentId=Ref(deployment), Description='Prod Stage', MethodSettings=[ MethodSetting(ResourcePath='/get-details', HttpMethod='GET') ], RestApiId=Ref(name), StageName='prod')) return self.template.to_yaml()
def add_api_gateway(self, apigateway_name): self.log.info('Adding API Gateway %s' % apigateway_name) assert (self.lambda_function is not None) # define all value used by api gateway lambda_method_name = '%sLambdaMethod' % apigateway_name lambda_permission_name = '%sLambdaPermission' % apigateway_name resource_name = '%sResource' % apigateway_name deployment_name = '%sDeployment' % self.stage_name apikey_name = '%sApiKey' % apigateway_name # start creating api gateway template self.apigateway = RestApi(apigateway_name, Name=apigateway_name) self.template.add_resource(self.apigateway) resource = Resource(resource_name, RestApiId=Ref(self.apigateway), PathPart='{proxy+}', ParentId=GetAtt(apigateway_name, 'RootResourceId')) self.template.add_resource(resource) permission = Permission(lambda_permission_name, Action='lambda:invokeFunction', FunctionName=GetAtt(self.lambda_function, 'Arn'), Principal='apigateway.amazonaws.com', SourceArn=Join("", [ 'arn:aws:execute-api:', Ref('AWS::Region'), ':', Ref('AWS::AccountId'), ':', Ref(self.apigateway), '/*' ])) self.template.add_resource(permission) method = Method( lambda_method_name, DependsOn=lambda_permission_name, RestApiId=Ref(self.apigateway), ResourceId=Ref(resource), HttpMethod='ANY', AuthorizationType='NONE', Integration=Integration( Type='AWS_PROXY', IntegrationHttpMethod='POST', Uri=Join("", [ 'arn:aws:apigateway:', Ref('AWS::Region'), ':lambda:path/2015-03-31/functions/', GetAtt(self.lambda_function, 'Arn'), '/invocations' ])), MethodResponses=[MethodResponse(StatusCode='200')]) self.template.add_resource(method) # create a deployment deployment = Deployment(deployment_name, DependsOn=lambda_method_name, RestApiId=Ref(self.apigateway)) self.template.add_resource(deployment) stage = Stage('%sStage' % self.stage_name, StageName=self.stage_name, RestApiId=Ref(self.apigateway), DeploymentId=Ref(deployment)) self.template.add_resource(stage) key = ApiKey(apikey_name, StageKeys=[ StageKey(RestApiId=Ref(self.apigateway), StageName=Ref(stage)) ]) self.template.add_resource(key)
Civ6Notif_GW_Resource = Resource( "Civ6NotifResource", RestApiId=Ref(Civ6Notif_GW), PathPart="civ6", ParentId=GetAtt("Civ6NotifGW", "RootResourceId"), ) Civ6Notif_PostMethod = Method( "Civ6NotifPostMethod", DependsOn='Civ6NotifFunction', RestApiId=Ref(Civ6Notif_GW), AuthorizationType="NONE", ResourceId=Ref(Civ6Notif_GW_Resource), HttpMethod="POST", Integration=Integration( Credentials=GetAtt("Civ6NotifLambdaExecutionRole", "Arn"), Type="AWS", IntegrationHttpMethod='POST', IntegrationResponses=[IntegrationResponse(StatusCode='200')], Uri=Join("", [ "arn:aws:apigateway:", Ref("AWS::Region"), ":lambda:path/2015-03-31/functions/", GetAtt("Civ6NotifFunction", "Arn"), "/invocations" ])), MethodResponses=[MethodResponse("CatResponse", StatusCode='200')]) stage_name = "prod" Civ6Notif_GW_Deployment = Deployment(f'{stage_name}Deployment', RestApiId=Ref(Civ6Notif_GW), DependsOn="Civ6NotifPostMethod")
def register_resources_template(self, template): deployment_resources = [] api = RestApi( self.in_project_cf_name, Name=troposphere.Join("-", [self.name, troposphere.Ref('Stage')]), Description=self.settings.get('description', '') ) template.add_resource(api) deployment_resources.append(api) invoke_lambda_role = troposphere.iam.Role( utils.valid_cloudformation_name(self.name, 'Role'), AssumeRolePolicyDocument={ "Version": "2012-10-17", "Statement": [{ "Effect": "Allow", "Principal": { "Service": ["apigateway.amazonaws.com"] }, "Action": ["sts:AssumeRole"] }] }, Policies=[ troposphere.iam.Policy( PolicyName=utils.valid_cloudformation_name(self.name, 'Role', 'Policy'), PolicyDocument={ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "lambda:InvokeFunction" ], "Resource": [ "*" ] } ] } ) ] ) template.add_resource(invoke_lambda_role) deployment_resources.append(invoke_lambda_role) deployment_dependencies = [] for path, resource in six.iteritems(self.settings.get('resources', {})): resource_reference = self.get_or_create_resource(path, api, template) methods = resource['methods'] if isinstance(methods, six.string_types): methods = [methods] if not isinstance(methods, dict): method_properties = copy.deepcopy(resource) method_properties.pop('methods', None) methods = dict([[method, method_properties] for method in methods]) for method, configuration in six.iteritems(methods): method_name = [self.name] method_name.extend(path.split('/')) method_name.append(method) extra = {} if 'parameters' in configuration: extra['RequestParameters'] = configuration['parameters'] m = Method( utils.valid_cloudformation_name(*method_name), HttpMethod=method, AuthorizationType=self.get_authorization_type(configuration), ApiKeyRequired=self.get_api_key_required(configuration), Integration=self.get_integration(configuration, invoke_lambda_role), MethodResponses=self.get_method_responses(configuration), ResourceId=resource_reference, RestApiId=troposphere.Ref(api), **extra ) template.add_resource(m) deployment_dependencies.append(m.name) deployment_resources.append(m) deploy_hash = hashlib.sha1(six.text_type(uuid.uuid4()).encode('utf-8')).hexdigest() deploy = Deployment( utils.valid_cloudformation_name(self.name, "Deployment", deploy_hash[:8]), DependsOn=sorted(deployment_dependencies), StageName=troposphere.Ref('Stage'), RestApiId=troposphere.Ref(api) ) template.add_resource(deploy) if self._get_true_false('cli-output', 't'): template.add_output([ troposphere.Output( utils.valid_cloudformation_name("Clioutput", self.in_project_name), Value=troposphere.Join( "", [ "https://", troposphere.Ref(api), ".execute-api.", troposphere.Ref(troposphere.AWS_REGION), ".amazonaws.com/", troposphere.Ref('Stage') ] ), ) ])
"ResourceConvert", RestApiId=Ref(rest_api), PathPart="convert", ParentId=GetAtt("ApiGateway", "RootResourceId"), )) # create a Lambda API method for the Lambda resource method = t.add_resource(Method( "MethodConvert", DependsOn="Lambda", # The Lambda Ref RestApiId=Ref(rest_api), AuthorizationType="NONE", ResourceId=Ref(resource), HttpMethod="POST", Integration=Integration( Credentials=GetAtt("LambdaExecutionRole", "Arn"), Type="AWS_PROXY", IntegrationHttpMethod='POST', Uri=Join("", [ "arn:aws:apigateway:" + args.region + ":lambda:path/2015-03-31/functions/", GetAtt("Lambda", "Arn"), "/invocations" ]) ), )) # allow the API Gateway to invoke Lambda permission = t.add_resource(Permission( "Permission", Action="lambda:InvokeFunction", FunctionName=GetAtt("Lambda", "Arn"), Principal="apigateway.amazonaws.com",
method + "Query", RestApiId=Ref(rest_api), PathPart="{" + method + "}", ParentId=Ref(method + "Date"), )) # Create a Lambda API method for the Lambda resource method = t.add_resource( Method( "CrimeDataAPIMethod" + method, DependsOn='CrimeDataAPIFunction', RestApiId=Ref(rest_api), AuthorizationType="NONE", ResourceId=Ref(query), HttpMethod="GET", Integration=Integration( Credentials=GetAtt("CrimeDataExecutionRole", "Arn"), Type="AWS_PROXY", IntegrationHttpMethod='POST', Uri=Join("", [ "arn:aws:apigateway:eu-west-1:lambda:path/2015-03-31/functions/", GetAtt("CrimeDataAPIFunction", "Arn"), "/invocations" ])), )) # Allow the gateway to invoke Lambda permission = t.add_resource( Permission("CrimeDataAPILambdaPermission", Action="lambda:InvokeFunction", FunctionName=GetAtt("CrimeDataAPIFunction", "Arn"), Principal="apigateway.amazonaws.com", SourceArn=Join("", [
getmethod = t.add_resource( Method( "getmethod", RestApiId=Ref(rest_api), AuthorizationType="NONE", ResourceId=Ref(resource), HttpMethod="GET", MethodResponses=[ MethodResponse("CatResponse", StatusCode='200', ResponseModels={'application/json': 'Empty'}) ], Integration=Integration( Credentials=GetAtt("LambdaExecutionRole", "Arn"), PassthroughBehavior='WHEN_NO_MATCH', Type="AWS", IntegrationHttpMethod='POST', IntegrationResponses=[ IntegrationResponse( StatusCode='200', ResponseTemplates={'application/json': ''}, ) ], Uri=Join("", [ "arn:aws:apigateway:us-east-1:lambda:path/2015-03-31/functions/", GetAtt("function", "Arn"), "/invocations" ]), RequestTemplates={'application/json': '{"statusCode": 200}'}, ), ))
health_method = template.add_resource(Method( "HealthMethod", ApiKeyRequired=True, RestApiId=Ref(api_gateway), AuthorizationType="NONE", ResourceId=Ref(health_resource), HttpMethod="GET", OperationName='mock', Integration=Integration( Type='MOCK', IntegrationResponses=[IntegrationResponse( ResponseTemplates={ 'application/json': "{\"message\": \"OK\"}" }, StatusCode='200' )], PassthroughBehavior='WHEN_NO_TEMPLATES', RequestTemplates={ 'application/json': "{\"statusCode\": 200, \"message\": \"OK\"}" }, ), MethodResponses=[ MethodResponse( 'HealthResponse', ResponseModels={ 'application/json': Ref(health_model), }, StatusCode='200', ) ], ))
def get_framework_template(self): from troposphere import ( GetAtt, Ref, Sub, Tags, Template, ) from troposphere.apigateway import ( BasePathMapping, Deployment, DomainName, Integration, IntegrationResponse, Method, MethodResponse, Resource, RestApi, Stage, ) from troposphere.ec2 import ( VPCEndpoint, ) from troposphere.s3 import ( Bucket, BucketPolicy, VersioningConfiguration, ) t = Template() ############### # API Gateway # ############### api = t.add_resource( RestApi( 'ApiGateway', Name=self.args.stack + 'Api', Description= 'API for portal and redirects for the Cornell AppStream Service', )) #################### # Redirect Methods # #################### stack_url = "'https://shibidp.cit.cornell.edu/idp/profile/SAML2/Unsolicited/SSO?providerId=urn:amazon:webservices&target=https://appstream2.{region}.aws.amazon.com/saml?accountId={account}%26stack={stack}'" stack_link = '<li><a href="./{redirect_nal}">{redirect}</a></li>' methods = [] stack_links = '' for redirect in sorted(self.config['Redirects'].keys()): redirect_info = self.config['Redirects'][redirect] redirect_nal = re.sub('\W+', '', redirect) redirect_url = stack_url.format(account=redirect_info['account'], region=redirect_info['region'], stack=redirect_info['stack']) methods.append('ApiGatewayRedirect' + redirect_nal) stack_links += stack_link.format(redirect=redirect, redirect_nal=redirect_nal) resource = t.add_resource( Resource( 'ApiGatewayResource' + redirect_nal, ParentId=GetAtt(api, 'RootResourceId'), PathPart=redirect_nal, RestApiId=Ref(api), )) method = t.add_resource( Method( 'ApiGatewayRedirect' + redirect_nal, AuthorizationType='None', HttpMethod='ANY', Integration=Integration( Type='MOCK', IntegrationResponses=[ IntegrationResponse( ResponseParameters={ 'method.response.header.Location': redirect_url, }, ResponseTemplates={ 'application/json': '{"redirect": 302}' }, StatusCode='302', ), ], RequestTemplates={ 'application/json': '{"statusCode":200}' }, ), MethodResponses=[ MethodResponse( ResponseParameters={ 'method.response.header.Location': True, }, StatusCode='302', ), ], ResourceId=Ref(resource), RestApiId=Ref(api), )) ########################### # API Gateway Root Method # ########################### with open('./include/root_integration_template.html', 'r') as rootTemplateHTML: rootTemplate = rootTemplateHTML.read() root_method = t.add_resource( Method( 'ApiGatewayRootMethod', AuthorizationType='None', HttpMethod='ANY', Integration=Integration( Type='MOCK', IntegrationResponses=[ IntegrationResponse( ResponseParameters={ 'method.response.header.Content-Type': "'text/html'", }, ResponseTemplates={ 'text/html': rootTemplate.format(stack_links=stack_links), }, StatusCode='200', ), ], RequestTemplates={ 'application/json': '{"statusCode":200}' }, ), MethodResponses=[ MethodResponse( ResponseParameters={ 'method.response.header.Content-Type': True, }, StatusCode='200', ), ], ResourceId=GetAtt(api, 'RootResourceId'), RestApiId=Ref(api), )) ##################### # API Gateway Stage # ##################### api_deployment = t.add_resource( Deployment( 'ApiGatewayDeployment' + self.run_time, Description= 'Deployment for API portal and redirects for the Cornell AppStream Service', RestApiId=Ref(api), DependsOn=methods + ['ApiGatewayRootMethod'], )) api_stage = t.add_resource( Stage( 'ApiGatewayStage', DeploymentId=Ref(api_deployment), Description= 'Stage for API portal and redirects for the Cornell AppStream Service', RestApiId=Ref(api), StageName='apps', )) ###################### # API Gateway Domain # ###################### api_domain = t.add_resource( DomainName( 'ApiGatewayDomain', CertificateArn=self.config['ACM_ARN'], DomainName=self.config['DomainName'], )) api_domain_mapping = t.add_resource( BasePathMapping( 'ApiGatewayDomainMapping', DomainName=Ref(api_domain), RestApiId=Ref(api), Stage=Ref(api_stage), )) ################### # VPC S3 Endpoint # ################### s3_endpoint = t.add_resource( VPCEndpoint( 'S3VPCEndpoint', ServiceName=Sub('com.amazonaws.${AWS::Region}.s3'), VpcId=self.config['VPC'], RouteTableIds=self.config['RouteTables'], )) #################### # S3 Bucket Policy # #################### sub_args = { 'bucket_name': self.config['Bucket'], 'vpc_id': self.config['VPC'] } with open('./include/bucket_policy.json', 'r') as bucketPolicyJSON: bucket_policy_document = bucketPolicyJSON.read() bucket_policy = t.add_resource( BucketPolicy( 'FrameworkBucketPolicy', Bucket=self.config['Bucket'], PolicyDocument=Sub(bucket_policy_document, **sub_args), )) with open('./cloudformation/framework.json', 'w') as frameworkTemplate: frameworkTemplate.write(t.to_json()) return t