def __init__(self, scope: core.Construct, id: str, **kwargs) -> None: super().__init__(scope, id, **kwargs) # API Gateway needs to have resource policy granting FHIR Works on AWS lambda # execute permissions. Lambda function ARN will be passed during deployment as CDK context variable # FHIR Works lambda will need to have policy attached to its execution role # allowing it to invoke API # From --context resource-router-lambda-role="arn:aws:iam::123456789012:role/rolename" imported_resource_router_lambda_role = self.node.try_get_context( "resource-router-lambda-role" ) # Amazon ECS on AWS Fargate container implementing connection manager # will be launched into a VPC that needs to have private and public subnets # and NAT gateway or instance # From --context vpc-id="vpc-123456" vpc_id = self.node.try_get_context("vpc-id") # The following parameters specify name of the HL7 server # that will be receiving transformed HL7v2 messages and TCP port # that it will be listening on # From --context hl7-server-name="hl7.example.com" # From --context hl7-port="2575" hl7_server_name = self.node.try_get_context("hl7-server-name") hl7_port = self.node.try_get_context("hl7-port") # In this proof of concept source of data for read interactions # is S3 bucket where mock HL7 server stores processed HL7 messages # From --context test-server-output-bucket-name="DOC-EXAMPLE-BUCKET" test_server_output_bucket_name = self.node.try_get_context( "test-server-output-bucket-name" ) # SQS queue # Custom transform lambda communicates with Connectivity Manager using this SQS queue queue = sqs.Queue( self, f"{COMPONENT_PREFIX}Queue", encryption=sqs.QueueEncryption.KMS_MANAGED ) # S3 Bucket to retrieve HL7v2 messages in proof of concept deployment test_server_output_bucket = s3.Bucket.from_bucket_name( self, f"{COMPONENT_PREFIX}OutputBucket", test_server_output_bucket_name ) # Transform Lambda # Reference implementation of Custom Transform component of Transform Execution Environment transform_lambda = lambda_.Function( self, f"{COMPONENT_PREFIX}TransformLambda", handler="transform.handler", runtime=lambda_.Runtime.PYTHON_3_8, code=lambda_.Code.from_asset( path.join(dirname, "../../lambda"), bundling={ "image": lambda_.Runtime.PYTHON_3_8.bundling_docker_image, "command": [ "bash", "-c", " && ".join( [ "pip install --no-cache-dir -r requirements.txt -t /asset-output", "(tar -c --exclude-from=exclude.lst -f - .)|(cd /asset-output; tar -xf -)", ] ), ], }, ), timeout=core.Duration.seconds(60), environment=dict( SQS_QUEUE=queue.queue_url, # The following parameter is optional S3_BUCKET_NAME=test_server_output_bucket_name, ), ) queue.grant_send_messages(transform_lambda) # API Gateway with Lambda construct (using https://aws.amazon.com/solutions/constructs/patterns) # Reference implementation of Custom Transform component of Transform Execution Environment api_lambda = apigw_lambda.ApiGatewayToLambda( self, "ApiGw", existing_lambda_obj=transform_lambda, api_gateway_props=apigw.LambdaRestApiProps( handler=transform_lambda, proxy=False, rest_api_name=f"{COMPONENT_PREFIX_DASHES}-api", endpoint_export_name=f"{COMPONENT_PREFIX}ApiEndPoint", description=f"{COMPONENT_PREFIX} APIGW with Transform Lambda (FHIR to HL7v2)", default_method_options=apigw.MethodOptions( authorization_type=apigw.AuthorizationType.IAM, ), policy=iam.PolicyDocument( statements=[ iam.PolicyStatement( actions=["execute-api:Invoke"], effect=iam.Effect.ALLOW, principals=[ iam.ArnPrincipal(imported_resource_router_lambda_role), ], resources=["execute-api:/*/*/*"], ) ] ), ), ) rest_api = api_lambda.api_gateway persistence = rest_api.root.add_resource("persistence") resource_type = persistence.add_resource("{resource_type}") resource_type.add_method("POST") resource_id = resource_type.add_resource("{id}") resource_id.add_method("GET") resource_id.add_method("PUT") resource_id.add_method("DELETE") # ECS Fargate Container (HL7v2 sender) # This container implements Connectivity Manager component # of Transform Execution Environment vpc = ec2.Vpc.from_lookup(self, "DefaultVpc", vpc_id=vpc_id) cluster = ecs.Cluster(self, f"{COMPONENT_PREFIX}Cluster", vpc=vpc) ecs_patterns.QueueProcessingFargateService( self, f"{COMPONENT_PREFIX}Service", cluster=cluster, image=ecs.ContainerImage.from_asset(path.join(dirname, "../../container")), queue=queue, desired_task_count=1, log_driver=ecs.LogDriver.aws_logs( stream_prefix=f"{COMPONENT_PREFIX}HL7Client", log_retention=logs.RetentionDays.ONE_DAY, ), environment=dict( SERVER_NAME=hl7_server_name, PORT_NUMBER=hl7_port, ), ) # The following permission grants are needed to support # read interactions with integration transform test_server_output_bucket.grant_read(transform_lambda) transform_lambda.add_to_role_policy( iam.PolicyStatement( actions=["s3:ListBucket"], effect=iam.Effect.ALLOW, resources=[test_server_output_bucket.bucket_arn], ) ) transform_lambda.add_to_role_policy( iam.PolicyStatement( actions=["s3:GetObject"], effect=iam.Effect.ALLOW, resources=[test_server_output_bucket.arn_for_objects("*")], ) ) # CloudFormation Stack outputs # The following outputs needed to configure FHIR Works on AWS API interface core.CfnOutput( self, "TransformApiRootUrl", value=rest_api.url, export_name="TransformApiRootUrl", ) core.CfnOutput( self, "TransformApiRegion", value=self.region, export_name="TransformApiRegion", ) core.CfnOutput( self, "TransformApiAccountId", value=self.account, export_name="TransformApiAccountId", )
def __init__(self, scope: core.Construct, id: str, **kwargs) -> None: super().__init__(scope, id, **kwargs) self.current_dir = os.path.dirname(__file__) self.website_bucket = s3.Bucket( self, "qs-embed-bucket", bucket_name=f'quicksight-embed-{core.Aws.ACCOUNT_ID}', website_index_document="index.html", public_read_access=True) self.quicksight_embed_lambda_role = iam.Role( self, 'quicksight-embed-lambda-role', description='Role for the Quicksight dashboard embed Lambdas', role_name='quicksight-embed-lambda-role', max_session_duration=core.Duration.seconds(3600), assumed_by=iam.ServicePrincipal('lambda.amazonaws.com'), inline_policies={ 'AllowAccess': iam.PolicyDocument(statements=[ iam.PolicyStatement( effect=iam.Effect.ALLOW, actions=[ 'logs:CreateLogGroup', 'logs:CreateLogStream', 'logs:PutLogEvents' ], resources=[ f'arn:aws:logs:{core.Aws.REGION}:{core.Aws.ACCOUNT_ID}:*' ]), iam.PolicyStatement( effect=iam.Effect.ALLOW, actions=["sts:AssumeRole", "iam:ListRoles"], resources=[ "arn:aws:iam::*:role/quicksight-migration-*-assume-role" ]), iam.PolicyStatement( effect=iam.Effect.ALLOW, actions=["secrets:GetSecretValue"], resources=[ f"arn:aws:secretsmanager:{core.Aws.REGION}:{core.Aws.ACCOUNT_ID}:secret:*" ]), iam.PolicyStatement(effect=iam.Effect.ALLOW, actions=[ "quicksight:*", ], resources=["*"]) ]) }) self.quicksight_migration_lambda = _lambda.Function( self, 'quicksight-migration-lambda', handler='quicksight_embed.lambda_handler', runtime=_lambda.Runtime.PYTHON_3_8, code=_lambda.Code.from_asset( os.path.join(self.current_dir, '../lambda/quicksight_embed/')), function_name='quicksight_embed_lambda', role=self.quicksight_embed_lambda_role, timeout=core.Duration.minutes(3), memory_size=512, environment={ 'DASHBOARD_ID': '938b365e-c001-4723-9a27-029654da7531', 'QUICKSIGHT_USER_ARN': f'arn:aws:quicksight:us-east-1:{core.Aws.ACCOUNT_ID}:user/default/quicksight-migration-user' }) self.apigw_lambda = ApiGatewayToLambda( self, "ApiGatewayToLambdaQSEmbed", existing_lambda_obj=self.quicksight_migration_lambda, api_gateway_props=apigw.LambdaRestApiProps( rest_api_name="quicksight-embed", handler=self.quicksight_migration_lambda, deploy=True, proxy=False, default_method_options=apigw.MethodOptions( authorization_type=apigw.AuthorizationType.NONE), default_cors_preflight_options=apigw.CorsOptions( allow_origins=apigw.Cors.ALL_ORIGINS, allow_methods=apigw.Cors.ALL_METHODS, allow_headers=[ 'Access-Control-Allow-Origin', 'Access-Control-Allow-Headers', 'Content-Type' ]), policy=iam.PolicyDocument(statements=[ iam.PolicyStatement(effect=iam.Effect.ALLOW, actions=['execute-api:Invoke'], resources=["execute-api:/prod/*"], principals=[iam.ArnPrincipal("*")]) ]))) self.embedurl = self.apigw_lambda.api_gateway.root.add_resource( "embedurl") self.embedurl.add_method("GET")
def __init__(self, scope: core.Construct, id: str, **kwargs) -> None: super().__init__(scope, id, **kwargs) self.current_dir = os.path.dirname(__file__) self.website_bucket = s3.Bucket( self, "qs-embed-bucket", bucket_name=f'quicksight-embed-{core.Aws.ACCOUNT_ID}', block_public_access=s3.BlockPublicAccess.BLOCK_ALL) self.quicksight_embed_lambda_role = iam.Role( self, 'quicksight-embed-lambda-role', description='Role for the Quicksight dashboard embed Lambdas', role_name='quicksight-embed-lambda-role', max_session_duration=core.Duration.seconds(3600), assumed_by=iam.ServicePrincipal('lambda.amazonaws.com'), inline_policies={ 'AllowAccess': iam.PolicyDocument(statements=[ iam.PolicyStatement( effect=iam.Effect.ALLOW, actions=[ 'logs:CreateLogGroup', 'logs:CreateLogStream', 'logs:PutLogEvents' ], resources=[ f'arn:aws:logs:{core.Aws.REGION}:{core.Aws.ACCOUNT_ID}:*' ]), iam.PolicyStatement( effect=iam.Effect.ALLOW, actions=["secrets:GetSecretValue"], resources=[ f"arn:aws:secretsmanager:{core.Aws.REGION}:{core.Aws.ACCOUNT_ID}:secret:*" ]), iam.PolicyStatement(effect=iam.Effect.ALLOW, actions=[ "quicksight:GetDashboardEmbedUrl", "quicksight:GetAuthCode" ], resources=["*"]) ]) }) self.quicksight_migration_lambda = _lambda.Function( self, 'quicksight-migration-lambda', handler='quicksight_embed.lambda_handler', runtime=_lambda.Runtime.PYTHON_3_8, code=_lambda.Code.from_asset( os.path.join(self.current_dir, '../lambda/quicksight_embed/')), function_name='quicksight_embed_lambda', role=self.quicksight_embed_lambda_role, timeout=core.Duration.minutes(3), memory_size=512, environment={ 'DASHBOARD_ID': 'CHANGEME_DASHBOARD_ID', 'QUICKSIGHT_USER_ARN': f'arn:aws:quicksight:us-east-1:{core.Aws.ACCOUNT_ID}:user/default/quicksight-migration-user' }) self.apigw_lambda = ApiGatewayToLambda( self, "ApiGatewayToLambdaQSEmbed", existing_lambda_obj=self.quicksight_migration_lambda, api_gateway_props=apigw.LambdaRestApiProps( rest_api_name="quicksight-embed", handler=self.quicksight_migration_lambda, deploy=True, proxy=False, default_method_options=apigw.MethodOptions( authorization_type=apigw.AuthorizationType.NONE), policy=iam.PolicyDocument(statements=[ iam.PolicyStatement(effect=iam.Effect.ALLOW, actions=['execute-api:Invoke'], resources=["execute-api:/prod/*"], principals=[iam.ArnPrincipal("*")]) ]))) self.embedurl = self.apigw_lambda.api_gateway.root.add_resource( "embedurl") self.embedurl.add_method( "GET", method_responses=[{ 'statusCode': '200', 'responseParameters': { 'method.response.header.Access-Control-Allow-Headers': True, 'method.response.header.Access-Control-Allow-Methods': True, 'method.response.header.Access-Control-Allow-Origin': True } }], integration=apigw.LambdaIntegration( self.quicksight_migration_lambda, proxy=False, integration_responses=[{ 'statusCode': '200', 'responseTemplates': { "application/json": "" }, 'responseParameters': { 'method.response.header.Access-Control-Allow-Headers': "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token'", 'method.response.header.Access-Control-Allow-Origin': "'*'", 'method.response.header.Access-Control-Allow-Methods': "'GET'" } }])) self.embedurl.add_method( 'OPTIONS', apigw.MockIntegration(integration_responses=[{ 'statusCode': '200', 'responseParameters': { 'method.response.header.Access-Control-Allow-Headers': "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token'", 'method.response.header.Access-Control-Allow-Origin': "'*'", 'method.response.header.Access-Control-Allow-Methods': "'GET,OPTIONS'" } }], passthrough_behavior=apigw. PassthroughBehavior.WHEN_NO_MATCH, request_templates={ "application/json": "{\"statusCode\":200}" }), method_responses=[{ 'statusCode': '200', 'responseParameters': { 'method.response.header.Access-Control-Allow-Headers': True, 'method.response.header.Access-Control-Allow-Methods': True, 'method.response.header.Access-Control-Allow-Origin': True } }]) # Cloudfront Distribution for authentication self.embed_auth_lambda_role = iam.Role( self, 'embed-auth-lambda-role', description= 'Role for the Quicksight dashboard embed authentication Lambda', role_name='embed-auth-lambda-role', max_session_duration=core.Duration.seconds(3600), assumed_by=iam.ServicePrincipal('lambda.amazonaws.com'), inline_policies={ 'AllowAccess': iam.PolicyDocument(statements=[ iam.PolicyStatement( effect=iam.Effect.ALLOW, actions=[ 'logs:CreateLogGroup', 'logs:CreateLogStream', 'logs:PutLogEvents' ], resources=[ f'arn:aws:logs:{core.Aws.REGION}:{core.Aws.ACCOUNT_ID}:*' ]) ]) }) self.embed_auth_lambda = _lambda.Function( self, 'embed-auth-lambda', handler='index.handler', description= "A Lambda@Edge function for QuickSight embed authentication via CloudFront Distribution", runtime=_lambda.Runtime.NODEJS_14_X, code=_lambda.Code.from_asset( os.path.join(self.current_dir, '../lambda/embed_auth/')), function_name='embed_auth_lambda', role=self.embed_auth_lambda_role, timeout=core.Duration.seconds(5), memory_size=128) self.embed_auth_dist = cloudfront.Distribution( self, "embed-auth-dist", enabled=True, default_root_object="index.html", default_behavior=cloudfront.BehaviorOptions( origin=origins.S3Origin(self.website_bucket), allowed_methods=cloudfront.AllowedMethods.ALLOW_GET_HEAD, edge_lambdas=[{ "functionVersion": self.embed_auth_lambda.current_version, "eventType": cloudfront.LambdaEdgeEventType.VIEWER_REQUEST, "includeBody": True }])) core.CfnOutput(self, "EmbedAPIGatewayURL", value=self.apigw_lambda.api_gateway.url + "embedurl?", description="Embed API GW URL") core.CfnOutput(self, "EmbedCloudFrontURL", value="https://" + self.embed_auth_dist.distribution_domain_name, description="CloudFront Distribution URL")
def __init__(self, scope: cdk.Construct, construct_id: str, **kwargs) -> None: super().__init__(scope, construct_id, **kwargs) table = dynamo_db.Table(self, "MysfitsQuestionsTable", table_name="MysfitsQuestionsTable", partition_key=dynamo_db.Attribute( name="QuestionId", type=dynamo_db.AttributeType.STRING), stream=dynamo_db.StreamViewType.NEW_IMAGE) post_question_lambda_function_policy_stm_ddb = _iam.PolicyStatement() post_question_lambda_function_policy_stm_ddb.add_actions( "dynamodb:PutItem") post_question_lambda_function_policy_stm_ddb.add_resources( table.table_arn) lambda_function_policy_stm_xray = _iam.PolicyStatement() lambda_function_policy_stm_xray.add_actions( "xray:PutTraceSegments", "xray:PutTelemetryRecords", "xray:GetSamplingRules", "xray:GetSamplingTargets", "xray:GetSamplingStatisticSummaries") lambda_function_policy_stm_xray.add_all_resources() # Lambda processor function mysfits_post_question = _lambda.Function( self, 'PostQuestionFunction', handler="mysfitsPostQuestion.postQuestion", runtime=_lambda.Runtime.PYTHON_3_6, description= 'A microservice Lambda function that receives a new question submitted to the MythicalMysfits' ' website from a user and inserts it into a DynamoDB database table.', memory_size=128, code=_lambda.Code.asset('./lambda_questions/PostQuestionsService'), timeout=cdk.Duration.seconds(30), initial_policy=[ post_question_lambda_function_policy_stm_ddb, lambda_function_policy_stm_xray ], tracing=_lambda.Tracing.ACTIVE) topic = sns.Topic(self, 'Topic', display_name='MythicalMysfitsQuestionsTopic', topic_name='MythicalMysfitsQuestionsTopic') topic.add_subscription(subs.EmailSubscription(receiver_email)) post_question_lambda_function_policy_stm_sns = _iam.PolicyStatement() post_question_lambda_function_policy_stm_sns.add_actions("sns:Publish") post_question_lambda_function_policy_stm_sns.add_resources( topic.topic_arn) mysfits_process_questions_stream = _lambda.Function( self, 'ProcessQuestionStreamFunction', handler="mysfitsProcessStream.processStream", runtime=_lambda.Runtime.PYTHON_3_6, description= 'An AWS Lambda function that will process all new questions posted to mythical mysfits' ' and notify the site administrator of the question that was asked.', memory_size=128, code=_lambda.Code.asset( './lambda_questions/ProcessQuestionsStream'), timeout=cdk.Duration.seconds(30), initial_policy=[ post_question_lambda_function_policy_stm_sns, lambda_function_policy_stm_xray ], environment={'SNS_TOPIC_ARN': topic.topic_arn}, tracing=_lambda.Tracing.ACTIVE, events=[ event.DynamoEventSource( table, starting_position=_lambda.StartingPosition.TRIM_HORIZON, batch_size=1) ]) questions_api_role = _iam.Role( self, 'QuestionsApiRole', assumed_by=_iam.ServicePrincipal('apigateway.amazonaws.com')) api_policy = _iam.PolicyStatement() api_policy.add_actions("lambda:InvokeFunction") api_policy.add_resources(mysfits_post_question.function_arn) api_policy.effect = _iam.Effect.ALLOW # Associate policy to role _iam.Policy(self, "QuestionsApiPolicy", policy_name="questions_api_policy", statements=[api_policy], roles=[questions_api_role]) # Create API gateway questions_integration = apigw.LambdaIntegration( mysfits_post_question, credentials_role=questions_api_role, integration_responses=[ apigw.IntegrationResponse( status_code='200', response_templates={"application/json": '{"status":"OK"}'}) ], ) api = apigw.LambdaRestApi( self, 'APIEndpoint', handler=mysfits_post_question, options=apigw.LambdaRestApiProps( rest_api_name='QuestionsAPI', deploy_options=apigw.StageOptions(tracing_enabled=True), handler=mysfits_post_question), proxy=False) questions_method = api.root.add_resource('questions') questions_method.add_method( 'POST', questions_integration, method_responses=[apigw.MethodResponse(status_code='200')], authorization_type=apigw.AuthorizationType.NONE) questions_method.add_method( 'OPTIONS', integration=apigw.MockIntegration(integration_responses=[ apigw.IntegrationResponse( status_code='200', response_parameters={ 'method.response.header.Access-Control-Allow-Headers': "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token,X-Amz-User-Agent'", 'method.response.header.Access-Control-Allow-Origin': "'*'", 'method.response.header.Access-Control-Allow-Credentials': "'false'", 'method.response.header.Access-Control-Allow-Methods': "'OPTIONS,GET,PUT,POST,DELETE'" }) ], passthrough_behavior=apigw. PassthroughBehavior.NEVER, request_templates={ "application/json": '{"statusCode": 200}' }), method_responses=[ apigw.MethodResponse( status_code='200', response_parameters={ "method.response.header.Access-Control-Allow-Headers": True, "method.response.header.Access-Control-Allow-Methods": True, "method.response.header.Access-Control-Allow-Credentials": True, "method.response.header.Access-Control-Allow-Origin": True }) ])
def __init__(self, scope: cdk.Construct, construct_id: str, **kwargs) -> None: super().__init__(scope, construct_id, **kwargs) # # Create role and policiy for the SageMaker notebook # mysfits_notebook_role = _iam.Role( # self, 'MysfitsNotbookRole', # assumed_by=_iam.ServicePrincipal('sagemaker.amazonaws.com') # ) # # mysfits_notebook_policy_stm = _iam.PolicyStatement() # mysfits_notebook_policy_stm.add_actions('sagemaker:*', # 'ecr:GetAuthorizationToken', # 'ecr:GetDownloadUrlForLayer', # 'ecr:BatchGetImage', # 'ecr:BatchCheckLayerAvailability', # 'cloudwatch:PutMetricData', # 'logs:CreateLogGroup', # 'logs:CreateLogStream', # 'logs:DescribeLogStreams', # 'logs:PutLogEvents', # 'logs:GetLogEvents', # 's3:CreateBucket', # 's3:ListBucket', # 's3:GetBucketLocation', # 's3:GetObject', # 's3:PutObject', # 's3:DeleteObject') # mysfits_notebook_policy_stm.add_all_resources() # # mysfits_notebook_policy_passrole_stm = _iam.PolicyStatement() # mysfits_notebook_policy_passrole_stm.add_actions('iam:PassRole') # mysfits_notebook_policy_passrole_stm.add_all_resources() # mysfits_notebook_policy_passrole_stm.add_condition( # 'StringEquals', # { # 'iam:PassedToService': 'sagemaker.amazonaws.com', # } # ) # # _iam.Policy( # self, 'MysfitsNotebookPolicy', # statements=[ # mysfits_notebook_policy_stm, # mysfits_notebook_policy_passrole_stm # ], # roles=[mysfits_notebook_role] # ) # # # Create notebook # notebook_instance = sagemaker.CfnNotebookInstance( # self, 'MythicalMysfits-SageMaker-Notebook', # instance_type='ml.t2.medium', # role_arn=mysfits_notebook_role.role_arn # ) # Create the recommendations lambda function with its policy for use with the inference endpoint recommendations_lambda_function_policy_stm = _iam.PolicyStatement() recommendations_lambda_function_policy_stm.add_actions( 'sagemaker:InvokeEndpoint') recommendations_lambda_function_policy_stm.add_all_resources() mysfits_recommendations = _lambda.Function( self, 'RecommendationsFunction', handler="recommendations.recommend", runtime=_lambda.Runtime.PYTHON_3_6, description= 'A microservice backend to invoke a SageMaker endpoint.', memory_size=128, code=_lambda.Code.asset('./lambda_recommendations/service'), timeout=cdk.Duration.seconds(30), initial_policy=[recommendations_lambda_function_policy_stm], # tracing=_lambda.Tracing.ACTIVE ) # Create APIGateway with policy recommendations_api_role = _iam.Role( self, 'RecommendationsApiRole', assumed_by=_iam.ServicePrincipal('apigateway.amazonaws.com')) api_policy = _iam.PolicyStatement() api_policy.add_actions("lambda:InvokeFunction") api_policy.add_resources(mysfits_recommendations.function_arn) api_policy.effect = _iam.Effect.ALLOW # Associate policy to role _iam.Policy(self, "RecommendationsApiPolicy", policy_name="recommendations_api_policy", statements=[api_policy], roles=[recommendations_api_role]) api = apigw.LambdaRestApi( self, 'APIEndpoint', handler=mysfits_recommendations, options=apigw.LambdaRestApiProps( rest_api_name='RecommendationsAPI', deploy_options=apigw.StageOptions(tracing_enabled=True), handler=mysfits_recommendations), proxy=False) # Create methods recommendations_integration = apigw.LambdaIntegration( mysfits_recommendations, credentials_role=recommendations_api_role, integration_responses=[ apigw.IntegrationResponse( status_code='200', response_templates={"application/json": '{"status":"OK"}'}, # response_parameters={ # "method.response.header.Access-Control-Allow-Headers": "'Content-Type'", # "method.response.header.Access-Control-Allow-Methods": "'OPTIONS,POST'", # "method.response.header.Access-Control-Allow-Origin": "'*'" # } ) ], ) recommendations_method = api.root.add_resource('recommendations') recommendations_method.add_method( 'POST', recommendations_integration, method_responses=[ apigw.MethodResponse( status_code='200', response_parameters={ 'method.response.header.Access-Control-Allow-Headers': True, 'method.response.header.Access-Control-Allow-Methods': True, 'method.response.header.Access-Control-Allow-Origin': True, }) ], authorization_type=apigw.AuthorizationType.NONE) recommendations_method.add_method( 'OPTIONS', integration=apigw.MockIntegration(integration_responses=[ apigw.IntegrationResponse( status_code='200', response_parameters={ 'method.response.header.Access-Control-Allow-Headers': "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token,X-Amz-User-Agent'", 'method.response.header.Access-Control-Allow-Origin': "'*'", 'method.response.header.Access-Control-Allow-Credentials': "'false'", 'method.response.header.Access-Control-Allow-Methods': "'OPTIONS,GET,PUT,POST,DELETE'", }) ], passthrough_behavior=apigw. PassthroughBehavior.NEVER, request_templates={ "application/json": '{"statusCode": 200}' }), method_responses=[ apigw.MethodResponse( status_code='200', response_parameters={ 'method.response.header.Access-Control-Allow-Headers': True, 'method.response.header.Access-Control-Allow-Methods': True, 'method.response.header.Access-Control-Allow-Credentials': True, 'method.response.header.Access-Control-Allow-Origin': True }) ])