def PutOPTIONSMethod(client, api_id, resource_id): logger.runTrace('Create OPTIONS Method for resource', resource_id) response_put_option = client.put_method( restApiId=api_id, resourceId=resource_id, httpMethod='OPTIONS', authorizationType= 'NONE' #NONE for open access, COGNITO_USER_POOLS for cognito ) logger.generatedDebug('OPTIONS Method created', json.dumps(response_put_option)) response_put_integration = client.put_integration( restApiId=api_id, resourceId=resource_id, httpMethod='OPTIONS', type='MOCK', requestTemplates={'application/json': '{"statusCode": 200}' } #this is needed so options will return 200 ) logger.generatedDebug('OPTIONS Integration set type', 'MOCK') response_put_method_response = client.put_method_response( restApiId=api_id, resourceId=resource_id, httpMethod='OPTIONS', statusCode='200') logger.generatedDebug('OPTIONS Method Response set status Code', '200')
def SetIntegrationType(client, api_id, resource_id, method, integration_type, lambda_func, requestTemplates): if method.upper() == 'OPTIONS': # for OPTIONS methods set to MOCK integration_type = 'MOCK' logger.runTrace('integration type', integration_type) response = client.put_integration( restApiId=api_id, resourceId=resource_id, httpMethod=method, type=integration_type, requestTemplates={'application/json': '{"statusCode": 200}'}) else: uri = 'arn:aws:apigateway:us-west-2:lambda:path/2015-03-31/functions/arn:aws:lambda:us-west-2:061431082068:function:${}/invocations' uri = uri.replace('${}', lambda_func) response = client.put_integration( restApiId=api_id, resourceId=resource_id, httpMethod=method, type=integration_type, integrationHttpMethod= 'POST', # ! looks like integrationHttpMethod can only be POST for lambda uri=uri, requestTemplates=requestTemplates) print(json.dumps(response))
def main(): #* set logger logger.setLogger('api_gateway_intergration_set_stage_variable.log') #* get client client = boto3.client('apigateway') #* get api_id api_id = GetAPIId() #* get a dict of resources for the API {resource_name:resource_id,[methods]} resources_dict = GetResources(client, api_id) #* set integration type as lambda integration_type = 'AWS' requestTemplates = { 'application/json': '{\n "body" : $input.json("$"),\n "headers": {\n #foreach($header in $input.params().header.keySet())\n "$header": "$util.escapeJavaScript($input.params().header.get($header))" #if($foreach.hasNext),#end\n\n #end\n },\n "method": "$context.httpMethod",\n "params": {\n #foreach($param in $input.params().path.keySet())\n "$param": "$util.escapeJavaScript($input.params().path.get($param))" #if($foreach.hasNext),#end\n\n #end\n },\n "query": {\n #foreach($queryParam in $input.params().querystring.keySet())\n "$queryParam": "$util.escapeJavaScript($input.params().querystring.get($queryParam))" #if($foreach.hasNext),#end\n\n #end\n } \n}' } for name, value in resources_dict.items(): logger.runTrace('For resource ', name) resource_id = value[0] logger.runTrace('with id', resource_id) methods = value[1] for method in methods: logger.runTrace('on method', method) lambda_func = '${stageVariables.' + name + '_' + method.upper( ) + '}' logger.runTrace('stage varialbe is', lambda_func) #set integration with lambda function SetIntegrationType(client, api_id, resource_id, method, integration_type, lambda_func, requestTemplates)
def GetFunctionName(client_api, api_id, resource_id, http_method): logger.runTrace('for resource_method', resource_id + '_' + http_method) response = client_api.get_integration( restApiId = api_id, resourceId = resource_id, httpMethod = http_method ) logger.runTrace('get integration', json.dumps(response)) function_name ='' # avoid errors with option methods if response['type'] == 'AWS': function_name = response['uri'].rsplit('/', 1)[0] function_name = function_name.split('arn:')[2] function_name = 'arn:' + function_name logger.generatedDebug('Raw Function Name', function_name) return(function_name)
def GetResourcesDict(resources, client_api, api_id): resources_dict = {} for resource in resources: #print(resource) resource_id = resource['id'] resource_path = resource['path'] methods = [] # this gives a dict {resource_id:[[method, statement_id, resource_path],...]} if resource_path != '/': # avoid root path, which don't have methods resource_methods = resource['resourceMethods'] for method in resource_methods: method_statement_id = [] method_statement_id.append(method) #T generate pesudo statement id based on the method statement_id = resource_path.replace('/{', '-') statement_id = statement_id.replace('}/', '-') statement_id = statement_id.replace('}', '-') statement_id = statement_id.replace('_', '-') statement_id = statement_id.replace('/', '') statement_id = statement_id + '-' + method.lower() method_statement_id.append(statement_id) method_statement_id.append(resource_path) methods.append(method_statement_id) resources_dict[resource_id] = methods logger.generatedDebug('Resource Dictionary', json.dumps(resources_dict)) for id, methods in resources_dict.items(): value_sets = [] for method in methods: if method[0] != 'OPTIONS': value_set = [] method_function_pair = {} function_name = GetFunctionName(client_api, api_id, id, method[0]) method_function_pair[method[0]] = function_name value_set.append(method_function_pair) value_set.append(method[1]) source_arn = GetSourceArn(api_id, function_name, method[0], method[2]) value_set.append(source_arn) value_sets.append(value_set) logger.runTrace('value set', json.dumps(value_set)) resources_dict[id] = value_sets return (resources_dict)
def PutCORSResponds(client, api_id, resources_dict, method_respPara, resp_headers_methods, headers_vals, status_code_pattern, responseTemplates): for resource in resources_dict: logger.runTrace('for resource', resource) resource_id = resources_dict[resource][0] logger.runTrace('resource', resource) methods = resources_dict[resource][1] methods_str = ','.join(methods) methods_str = "'" + methods_str + "'" logger.runTrace('with methods', methods_str) integration_mapping = [] for header_val in headers_vals: integration_mapping.append(header_val) integration_mapping.append(methods_str) logger.generatedDebug('Integration Mapping', json.dumps(integration_mapping)) integration_respPara = {} integration_respPara = dict( zip(resp_headers_methods, integration_mapping)) logger.generatedDebug('Integration Parameters', json.dumps(integration_respPara)) for method in methods: logger.runTrace('for method', method) #* Get status codes response_get_method = client.get_method(restApiId=api_id, resourceId=resource_id, httpMethod=method) logger.generatedDebug('Method Detail', json.dumps(response_get_method)) method_responses = response_get_method['methodResponses'] logger.runTrace('Method Responses', json.dumps(method_responses)) status_codes = list(method_responses.keys()) logger.runTrace('Status Codes', json.dumps(status_codes)) #* if status codes not include 200 add 200, as long as it is not OPTIONS if '200' not in status_codes and method != 'OPTIONS': status_codes.append('200') for status_code in status_codes: logger.runTrace('for status code', status_code) logger.runTrace('pattern', status_code_pattern[status_code]) #! delete Method Response Headers if there is one try: response_delete_method = client.delete_method_response( restApiId=api_id, resourceId=resource_id, httpMethod=method, statusCode=status_code) logger.runTrace('Method deletion', json.dumps(response_delete_method)) except: logger.runTrace('Method deletion failed', 'Method does not exist') #! delete Integration Response Headers if there is one try: response_delete_integration = client.delete_integration_response( restApiId=api_id, resourceId=resource_id, httpMethod=method, statusCode=status_code) logger.runTrace('Integration deletion', json.dumps(response_delete_integration)) except: logger.runTrace('Integration deletion failed', 'Integration does not exist') #* put Method Response Headers response_put_method = client.put_method_response( restApiId=api_id, resourceId=resource_id, httpMethod=method, statusCode=status_code, responseParameters=method_respPara) print(response_put_method) logger.createInfo('Method Response', json.dumps(response_put_method)) #* put Integration Responses Header Mappings if status_code_pattern[status_code].lower() == 'default': response_put_integration = client.put_integration_response( restApiId=api_id, resourceId=resource_id, httpMethod=method, statusCode=status_code, responseParameters=integration_respPara, responseTemplates=responseTemplates) else: response_put_integration = client.put_integration_response( restApiId=api_id, resourceId=resource_id, httpMethod=method, statusCode=status_code, selectionPattern=status_code_pattern[status_code], responseParameters=integration_respPara) print(response_put_integration)
def main(): #constant stg_var_name_lst = ['keybundle_GET', 'keybundle_id_DELETE', 'keybundle_id_GET', 'keybundle_id_PUT', 'keyholder_GET', 'keyholder_POST', 'keyholder_id_DELETE', 'keyholder_id_GET', 'keyholder_id_PUT', 'property_GET', 'property_POST', 'property_id_DELETE', 'property_id_GET', 'property_id_PUT', 'property_id_keybundle_GET', 'property_id_keybundle_POST' ] #set logger logger.setLogger('api_gateway_lambda_stage_variable_enable.log') #set client for api client_api = boto3.client('apigateway') #get API api_id = GetAPIId() #get feature stage isFeature = input('Is this for the feature stage?(y/n) ') logger.inputTrace('Is Feature', isFeature) if isFeature.lower() == 'y' or isFeature.lower() == 'yes': feature_funcs = GetFeatureStageFuncs(stg_var_name_lst) isFeature = True else: isFeature = False response_get_resources = client_api.get_resources( restApiId=api_id ) resources = response_get_resources['items'] logger.generatedDebug('Resources of API', json.dumps(resources)) # this gives {resource_id:[{method:functionName}, statement_id, source_arn],[]...} resources_dict = GetResourcesDict(resources, client_api, api_id) logger.generatedDebug('Resource Dictionary with Function Names', json.dumps(resources_dict)) # get boto3 clinet for lambda client_lambda = boto3.client('lambda') # lambda add permission isPandD= input('Is this also for the production and development stages?(y/n) ') logger.inputTrace('Is production and development', isPandD) function_name = '' if isPandD.lower() == 'y' or isPandD.lower() == 'yes': dev_prod_funcs = GetDevProdStageFunc(stg_var_name_lst) for method_set in resources_dict.values(): # print(method_set) for method in method_set: # print(method) logger.runTrace('for method', json.dumps(method)) for k in method[0].values(): function_name = k # print(function_name) logger.runTrace('with stage variable', json.dumps(function_name)) statement_id = method[1] source_arn = method[2] function_name_part = function_name.split('${stageVariables.') # print(function_name_part) function_name_part[1] = function_name_part[1].replace('}', '') # print(dev_prod_funcs.keys()) if function_name_part[1] in dev_prod_funcs.keys(): for val in dev_prod_funcs[function_name_part[1]]: function_name = function_name_part[0] + val.replace('id_','id-') logger.runTrace('invoke function', function_name) try: LambdaRemovePermission(client_lambda, function_name, statement_id) except: logger.runTrace('Permission Removal', 'permission not exist') try: LambdaAddPermission(client_lambda, api_id, function_name, statement_id, source_arn) except: print('AddPermission failed for', function_name) else: print('Development and Production permission successfully added!') if isFeature: for method_set in resources_dict.values(): # print(method_set) for method in method_set: logger.runTrace('for method', json.dumps(method)) for k in method[0].values(): function_name = k # logger.runTrace('with stage variable', json.dumps(function_name)) statement_id = method[1] source_arn = method[2] function_name_part = function_name.split('${stageVariables.') function_name_part[1] = function_name_part[1].replace('}', '') # print(function_name_part) # print(feature_funcs.keys()) if function_name_part[1] in feature_funcs.keys(): function_name = function_name_part[0] + feature_funcs[function_name_part[1]].replace('-id','_id') print(function_name) logger.runTrace('invoke function', function_name) try: LambdaRemovePermission(client_lambda, function_name, statement_id) except: logger.runTrace('Permission Removal', 'permission not exist') try: LambdaAddPermission(client_lambda, api_id, function_name, statement_id, source_arn) except: print('AddPermission failed for', function_name) else: print('Feature permission successfully added!')