diff --git a/infrastructure/cf_update.sh b/infrastructure/cf_update.sh old mode 100644 new mode 100755 index 03faa4f0..cc479f99 --- a/infrastructure/cf_update.sh +++ b/infrastructure/cf_update.sh @@ -4,6 +4,9 @@ CLOUDFRONT_DIST_ID=$1 WORKFLOWS_API_ORIGIN_ID=$2 WORKFLOWS_API_DOMAIN_NAME=$3 +WORKFLOWS_API_DOMAIN_NAME=${WORKFLOWS_API_DOMAIN_NAME#http://} +WORKFLOWS_API_DOMAIN_NAME=${WORKFLOWS_API_DOMAIN_NAME#https://} + # Step 1: Retrieve the current CloudFront distribution configuration aws cloudfront get-distribution-config --id $CLOUDFRONT_DIST_ID > current-config.json @@ -13,10 +16,9 @@ DISTRIBUTION_CONFIG=$(jq '.DistributionConfig' current-config.json) # Step 2: Modify the configuration # Add a new origin for the workflows API -MODIFIED_CONFIG=$(echo $DISTRIBUTION_CONFIG | jq --arg origin_id "$WORKFLOWS_API_ORIGIN_ID" --arg domain_name "$WORKFLOWS_API_DOMAIN_NAME" '.Origins.Items += [{"Id": $origin_id, "DomainName": $domain_name, "CustomOriginConfig": {"HTTPPort": 80, "HTTPSPort": 443, "OriginProtocolPolicy": "https-only", "OriginSslProtocols": {"Items": ["TLSv1.2"], "Quantity": 1}, "OriginReadTimeout": 30, "OriginKeepaliveTimeout": 5}}] | .Origins.Quantity += 1') - +MODIFIED_CONFIG=$(echo $DISTRIBUTION_CONFIG | jq --arg origin_id "$WORKFLOWS_API_ORIGIN_ID" --arg domain_name "$WORKFLOWS_API_DOMAIN_NAME" '.Origins.Items += [{"Id": $origin_id, "DomainName": $domain_name, "CustomOriginConfig": {"HTTPPort": 80, "HTTPSPort": 443, "OriginProtocolPolicy": "https-only", "OriginSslProtocols": {"Items": ["TLSv1.2"], "Quantity": 1}, "OriginReadTimeout": 30, "OriginKeepaliveTimeout": 5}, "OriginPath": "", "CustomHeaders": {"Quantity": 0}}] | .Origins.Quantity += 1') # Add a new cache behavior for the workflows API -MODIFIED_CONFIG=$(echo $MODIFIED_CONFIG | jq --arg origin_id "$WORKFLOWS_API_ORIGIN_ID" '.CacheBehaviors.Items += [{"PathPattern": "/api/workflows/*", "TargetOriginId": $origin_id, "ViewerProtocolPolicy": "redirect-to-https", "AllowedMethods": {"Items": ["GET", "HEAD", "OPTIONS", "PUT", "POST", "PATCH", "DELETE"], "Quantity": 7, "CachedMethods": {"Items": ["GET", "HEAD"], "Quantity": 2}}, "ForwardedValues": {"QueryString": true, "Cookies": {"Forward": "all"}, "Headers": {"Items": ["Authorization"], "Quantity": 1}}, "MinTTL": 0, "DefaultTTL": 86400, "MaxTTL": 31536000}] | .CacheBehaviors.Quantity += 1') +MODIFIED_CONFIG=$(echo $MODIFIED_CONFIG | jq --arg origin_id "$WORKFLOWS_API_ORIGIN_ID" '.CacheBehaviors.Items += [{"PathPattern": "/api/workflows/*", "TargetOriginId": $origin_id, "ViewerProtocolPolicy": "redirect-to-https", "AllowedMethods": {"Items": ["GET", "HEAD", "OPTIONS", "PUT", "POST", "PATCH", "DELETE"], "Quantity": 7, "CachedMethods": {"Items": ["GET", "HEAD"], "Quantity": 2}}, "SmoothStreaming": false, "CachePolicyId": "4135ea2d-6df8-44a3-9df3-4b5a84be39ad", "LambdaFunctionAssociations": {"Quantity": 0},"FunctionAssociations": {"Quantity": 0}, "FieldLevelEncryptionId": "", "Compress": true}] | .CacheBehaviors.Quantity += 1') # Step 3: Update the CloudFront distribution with the modified configuration echo $MODIFIED_CONFIG | jq . > modified-config.json diff --git a/infrastructure/main.tf b/infrastructure/main.tf index 57b70d86..0c3d6786 100644 --- a/infrastructure/main.tf +++ b/infrastructure/main.tf @@ -112,13 +112,13 @@ resource "local_file" "mwaa_variables" { # ECR repository to host workflows API image resource "aws_ecr_repository" "workflows_api_lambda_repository" { - name = "workflows-api-function-repository" + name = "workflows-api-lambda-repository" # Provisioner to build and push Docker image provisioner "local-exec" { command = <<-EOT aws ecr get-login-password --region ${local.aws_region} | docker login --username AWS --password-stdin ${aws_ecr_repository.workflows_api_lambda_repository.repository_url} - docker build -t ${aws_ecr_repository.workflows_api_lambda_repository.repository_url}:latest ../workflows_api/ + docker build -t ${aws_ecr_repository.workflows_api_lambda_repository.repository_url}:latest ../workflows_api/runtime/ docker push ${aws_ecr_repository.workflows_api_lambda_repository.repository_url}:latest EOT } @@ -129,24 +129,49 @@ resource "aws_iam_role" "lambda_execution_role" { name = "lambda_execution_role" assume_role_policy = jsonencode({ - Version = "2012-10-17" + Version = "2012-10-17", Statement = [ { - Action = "sts:AssumeRole" - Effect = "Allow" + Action = "sts:AssumeRole", + Effect = "Allow", Principal = { - Service = "lambda.amazonaws.com" - } + Service = "lambda.amazonaws.com", + }, }, - ] + ], }) } +resource "aws_iam_policy" "ecr_access" { + name = "ECR_Access_For_Lambda" + path = "/" + description = "ECR access policy for Lambda function" + policy = jsonencode({ + Version = "2012-10-17", + Statement = [ + { + Effect = "Allow", + Action = [ + "ecr:GetDownloadUrlForLayer", + "ecr:BatchGetImage", + ], + Resource = "${aws_ecr_repository.workflows_api_lambda_repository.arn}", + }, + ], + }) +} + +resource "aws_iam_role_policy_attachment" "ecr_access_attach" { + role = aws_iam_role.lambda_execution_role.name + policy_arn = aws_iam_policy.ecr_access.arn +} + resource "aws_lambda_function" "workflows_api_handler" { function_name = "api_handler" role = aws_iam_role.lambda_execution_role.arn handler = "handler.handler" runtime = "python3.9" + package_type = "Image" image_uri = "${aws_ecr_repository.workflows_api_lambda_repository.repository_url}:latest" environment { @@ -157,7 +182,7 @@ resource "aws_lambda_function" "workflows_api_handler" { CLIENT_SECRET = var.cognito_client_secret STAGE = var.stage DATA_ACCESS_ROLE_ARN = var.data_access_role_arn - WORKFLOW_WOOT_PATH = var.workflow_root_path + WORKFLOW_ROOT_PATH = var.workflow_root_path INGEST_URL = var.ingest_url RASTER_URL = var.raster_url STAC_URL = var.stac_url @@ -195,7 +220,7 @@ resource "null_resource" "update_cloudfront" { } provisioner "local-exec" { - command = "${path.module}/cf_update.sh ${var.cloudfront_id} workflows_api_origin ${aws_apigatewayv2_api.workflows_http_api.api_endpoint}" + command = "${path.module}/cf_update.sh ${var.cloudfront_id} workflows_api_origin \"${aws_apigatewayv2_api.workflows_http_api.api_endpoint}\"" } depends_on = [aws_apigatewayv2_api.workflows_http_api] diff --git a/infrastructure/terraform.tfvars.tmpl b/infrastructure/terraform.tfvars.tmpl index 35906bb5..c9c08cd4 100644 --- a/infrastructure/terraform.tfvars.tmpl +++ b/infrastructure/terraform.tfvars.tmpl @@ -11,3 +11,12 @@ stac_ingestor_api_url="${STAC_INGESTOR_API_URL}" vector_secret_name="${VECTOR_SECRET_NAME}" vector_security_group="${VECTOR_SECURITY_GROUP}" vector_vpc="${VECTOR_VPC}" +data_access_role_arn="${DATA_ACCESS_ROLE_ARN}" +workflow_root_path="${WORKFLOW_ROOT_PATH}" +ingest_url="https://dev.delta-backend.com/api/ingest" +raster_url="https://dev.delta-backend.com/api/raster" +stac_url="https://dev.delta-backend.com/api/stac" +cloudfront_id="${CLOUDFRONT_ID}" +jwks_url="${JWKS_URL}" +cognito_userpool_id="${COGNITO_USERPOOL_ID}" +cognito_client_id="${COGNITO_CLIENT_ID}" diff --git a/infrastructure/variables.tf b/infrastructure/variables.tf index a28e1cf8..c3ab0085 100644 --- a/infrastructure/variables.tf +++ b/infrastructure/variables.tf @@ -50,6 +50,8 @@ variable "cognito_client_id" { } variable "cognito_client_secret" { + description = "Optional secret, if required by cognito user pool" + default = "" type = string } diff --git a/workflows_api/runtime/Dockerfile b/workflows_api/runtime/Dockerfile index 7ecf96b6..215d3703 100644 --- a/workflows_api/runtime/Dockerfile +++ b/workflows_api/runtime/Dockerfile @@ -2,11 +2,11 @@ FROM public.ecr.aws/sam/build-python3.9:latest WORKDIR /tmp -COPY workflows_api/runtime/requirements.txt /tmp/ingestor/requirements.txt +COPY requirements.txt /tmp/ingestor/requirements.txt RUN pip install -r /tmp/ingestor/requirements.txt -t /asset --no-binary pydantic uvicorn RUN rm -rf /tmp/ingestor # TODO this is temporary until we use a real packaging system like setup.py or poetry -COPY workflows_api/runtime/src /asset/src +COPY src /asset/src # # Reduce package size and remove useless files RUN cd /asset && find . -type f -name '*.pyc' | while read f; do n=$(echo $f | sed 's/__pycache__\///' | sed 's/.cpython-[2-3][0-9]//'); cp $f $n; done; @@ -15,6 +15,6 @@ RUN cd /asset && find . -type d -a -name '__pycache__' -print0 | xargs -0 rm -rf RUN find /asset -type d -a -name 'tests' -print0 | xargs -0 rm -rf RUN rm -rdf /asset/numpy/doc/ /asset/boto3* /asset/botocore* /asset/bin /asset/geos_license /asset/Misc -COPY workflows_api/runtime/handler.py /asset/handler.py +COPY handler.py /asset/handler.py CMD ["echo", "hello world"] \ No newline at end of file