Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JASPER-289: Lambda Function Integration #173

Merged
merged 35 commits into from
Feb 13, 2025
Merged
Show file tree
Hide file tree
Changes from 28 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
90dc7cf
- Added generic lambda that will handle all BC Gov request
Feb 5, 2025
cab6b5b
Removed unnecessary lambda functions
Feb 5, 2025
f512f29
Added prefix to identify which bc gov the request is routed to
Feb 5, 2025
693c2fa
- Updates to proxy lambda to handle incoming request and forward to t…
Feb 5, 2025
369c475
- Log the base url used in proxy lambda
Feb 6, 2025
91e6fb4
Log the whole event and qp
Feb 6, 2025
7d8a81d
Update authorizer so that it returns a generic policy to take advanta…
Feb 6, 2025
13c8563
Add logs
Feb 6, 2025
dd6dfbc
- Add query params sanitization to pass it as is
Feb 7, 2025
0049335
Replace methodArn with wildcard
Feb 7, 2025
0aac51f
Update regex to replace the url correctly
Feb 7, 2025
3863aa1
- Simplify lambda functions to a single proxy that handles all reques…
Feb 7, 2025
7614dcc
Force apigw redeployment when apigw settings is updated
Feb 7, 2025
8349a7f
Add deploy2test stage
Feb 10, 2025
d4eeb38
Revert workflow_dispatch temporarily
Feb 10, 2025
06edf83
Added prod stage for deploying lambdas
Feb 10, 2025
18b1198
Merge branch 'master' into feature/JASPER-289
Feb 10, 2025
28f97a4
Pass the allowed headers to BC Gov request
Feb 11, 2025
3111666
Added vitest and unit tests
Feb 11, 2025
bd2a669
Removed unused variable
Feb 11, 2025
d29e750
Changed how qs is imported
Feb 11, 2025
149e3e4
Removed as any
Feb 11, 2025
2208a88
Add --run
Feb 11, 2025
95bc4f4
Publish lambda cleanup
Feb 12, 2025
6fe65cf
Addressed SonarCloud issues:
Feb 12, 2025
1967817
Combined "Parse Resource and Lambda" and "Deploy" steps
Feb 12, 2025
a6efbd0
renamed lambda_name to lambda
Feb 12, 2025
6f6dbdc
Adding "Accept" as an allowed header
Feb 12, 2025
49f3adb
Stringify headers and body to make it visible in the logs and adjust …
Feb 12, 2025
4d55f72
- Removed passing of application/json header since it is passed on ea…
Feb 12, 2025
d0c96e7
Fixed build error
Feb 12, 2025
1fe0ede
Revert IMAGE_NAME
Feb 12, 2025
8a3cd88
Fixed param expansion for RESOURCE and LAMBDA
Feb 12, 2025
968d86d
Save the var result first before concatenating
Feb 12, 2025
8600e97
Specify Content-Type as application/json unless specified in Accept
Feb 12, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 18 additions & 12 deletions .github/workflows/actions/deploy-lambda/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ inputs:
app_name:
description: The application name.
required: true
lambda_name:
description: The lambda function name name.
lambda:
description: The lambda function info.
required: true
aws_role_arn:
description: The AWS Role ARN to assume.
Expand All @@ -26,9 +26,6 @@ inputs:
github_image_repo:
description: The GCHR repo where images are stored.
required: true
image_name:
description: The name of the image to be deployed.
required: true
short_sha:
description: The short SHA used to tag image in GCHR.
required: true
Expand All @@ -37,14 +34,23 @@ runs:
using: composite

steps:
- name: Parse Resource and Lambda Name
shell: bash
run: |
echo "Lambda: ${{ inputs.lambda }}"
RESOURCE=$(echo "${{ inputs.lambda }}" | cut -d'/' -f1)
LAMBDA=$(echo "${{ inputs.lambda }}" | cut -d'/' -f2)
echo "RESOURCE=$RESOURCE" >> $GITHUB_ENV
echo "LAMBDA=$LAMBDA" >> $GITHUB_ENV
echo "IMAGE_NAME=$RESOURCE.$LAMBDA" >> $GITHUB_ENV

- name: Set reusable variables
id: vars
shell: bash
run: |
echo "full_ecr_repo_url=${{ inputs.aws_account }}.dkr.ecr.${{ inputs.region }}.amazonaws.com/${{ inputs.app_name }}-lambda-repo-${{ inputs.environment }}" >> $GITHUB_OUTPUT
echo "container_name=${{ inputs.app_name }}-${{ inputs.tier_name }}-container-${{ inputs.environment }}" >> $GITHUB_OUTPUT


- name: Log in to the GHCR
uses: docker/login-action@v2
with:
Expand All @@ -68,7 +74,7 @@ runs:
id: ecr-check
shell: bash
run: |
IMAGE_TAG=${{ inputs.image_name }}-${{ inputs.short_sha }}
IMAGE_TAG=${{ env.IMAGE_NAME }}-${{ inputs.short_sha }}
REPOSITORY_NAME=${{ inputs.app_name }}-lambda-repo-${{ inputs.environment }}

IMAGE_EXISTS=$(aws ecr describe-images --repository-name $REPOSITORY_NAME --query "imageDetails[?contains(imageTags, '$IMAGE_TAG')]" --output text)
Expand All @@ -85,13 +91,13 @@ runs:
if: steps.ecr-check.outputs.exists == 'false'
shell: bash
run: |
docker pull ${{ inputs.github_image_repo }}/${{ inputs.image_name }}:${{ inputs.short_sha}}
docker tag ${{ inputs.github_image_repo }}/${{ inputs.image_name }}:${{ inputs.short_sha}} ${{ steps.vars.outputs.full_ecr_repo_url }}:${{ inputs.image_name }}-${{ inputs.short_sha }}
docker push ${{ steps.vars.outputs.full_ecr_repo_url }}:${{ inputs.image_name }}-${{ inputs.short_sha }}
docker pull ${{ inputs.github_image_repo }}/${{ env.IMAGE_NAME }}:${{ inputs.short_sha}}
docker tag ${{ inputs.github_image_repo }}/${{ env.IMAGE_NAME }}:${{ inputs.short_sha}} ${{ steps.vars.outputs.full_ecr_repo_url }}:${{ env.IMAGE_NAME }}-${{ inputs.short_sha }}
docker push ${{ steps.vars.outputs.full_ecr_repo_url }}:${{ env.IMAGE_NAME }}-${{ inputs.short_sha }}

- name: Update Lambda Function
shell: bash
run: |
aws lambda update-function-code \
--function-name ${{ inputs.app_name }}-${{ inputs.lambda_name }}-lambda-${{ inputs.environment }} \
--image-uri ${{ steps.vars.outputs.full_ecr_repo_url }}:${{ inputs.image_name }}-${{ inputs.short_sha }}
--function-name ${{ inputs.app_name }}-${{ env.LAMBDA }}-lambda-${{ inputs.environment }} \
--image-uri ${{ steps.vars.outputs.full_ecr_repo_url }}:${{ env.IMAGE_NAME }}-${{ inputs.short_sha }}
89 changes: 66 additions & 23 deletions .github/workflows/publish-lambdas.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,7 @@ on:
- "aws/**"

workflow_dispatch:
inputs:
environment:
description: "Select target environment"
required: true
default: "dev"
type: choice
options:
- dev
- test
- prod

env:
WORKING_DIRECTORY: ./aws
NODE_VERSION: 20
Expand Down Expand Up @@ -51,15 +42,13 @@ jobs:

deploy2gchr:
needs: get-lambdas
environment: ${{ inputs.environment }}
environment: dev
outputs:
short_sha: ${{ steps.short_sha.outputs.SHORT_SHA }}
permissions:
id-token: write
packages: write
runs-on: ubuntu-latest
env:
LAMBDA_ECR_REPO_URL: ${{ vars.AWS_ACCOUNT }}.dkr.ecr.${{ vars.AWS_REGION }}.amazonaws.com/${{ vars.APP_NAME }}-lambda-repo-${{ vars.ENVIRONMENT_NAME }}

strategy:
matrix:
Expand Down Expand Up @@ -141,14 +130,69 @@ jobs:
- name: Checkout
uses: actions/checkout@v4

- name: Parse Resource and Lambda Name
id: parse
run: |
echo "Lambda: ${{ matrix.lambda }}"
RESOURCE=$(echo "${{ matrix.lambda }}" | cut -d'/' -f1)
LAMBDA=$(echo "${{ matrix.lambda }}" | cut -d'/' -f2)
echo "RESOURCE=$RESOURCE" >> $GITHUB_ENV
echo "LAMBDA=$LAMBDA" >> $GITHUB_ENV
- name: Deploy to ${{ env.ENVIRONMENT }}
uses: ./.github/workflows/actions/deploy-lambda
with:
environment: ${{ env.ENVIRONMENT }}
aws_account: ${{ vars.AWS_ACCOUNT }}
region: ${{ vars.AWS_REGION }}
app_name: ${{ vars.APP_NAME }}
aws_role_arn: ${{ vars.AWS_ROLE_ARN }}
ghcr_token: ${{ secrets.GITHUB_TOKEN }}
github_image_repo: ${{ env.GITHUB_IMAGE_REPO }}
lambda: ${{ matrix.lambda }}
short_sha: ${{ needs.deploy2gchr.outputs.short_sha }}

deploy2test:
name: Deploy to TEST
needs: [get-lambdas, deploy2gchr, deploy2dev]
env:
ENVIRONMENT: test
permissions:
id-token: write
packages: write
runs-on: ubuntu-latest
environment: test

strategy:
matrix:
lambda: ${{ fromJSON(needs.get-lambdas.outputs.lambda_dir_list) }}

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Deploy to ${{ env.ENVIRONMENT }}
uses: ./.github/workflows/actions/deploy-lambda
with:
environment: ${{ env.ENVIRONMENT }}
aws_account: ${{ vars.AWS_ACCOUNT }}
region: ${{ vars.AWS_REGION }}
app_name: ${{ vars.APP_NAME }}
aws_role_arn: ${{ vars.AWS_ROLE_ARN }}
ghcr_token: ${{ secrets.GITHUB_TOKEN }}
github_image_repo: ${{ env.GITHUB_IMAGE_REPO }}
lambda: ${{ matrix.lambda }}
short_sha: ${{ needs.deploy2gchr.outputs.short_sha }}

deploy2prod:
name: Deploy to PROD
needs: [get-lambdas, deploy2gchr, deploy2dev, deploy2test]
env:
ENVIRONMENT: prod
permissions:
id-token: write
packages: write
runs-on: ubuntu-latest
environment: prod

strategy:
matrix:
lambda: ${{ fromJSON(needs.get-lambdas.outputs.lambda_dir_list) }}

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Deploy to ${{ env.ENVIRONMENT }}
uses: ./.github/workflows/actions/deploy-lambda
Expand All @@ -160,6 +204,5 @@ jobs:
aws_role_arn: ${{ vars.AWS_ROLE_ARN }}
ghcr_token: ${{ secrets.GITHUB_TOKEN }}
github_image_repo: ${{ env.GITHUB_IMAGE_REPO }}
lambda_name: ${{ env.LAMBDA }}
image_name: ${{ env.RESOURCE }}.${{ env.LAMBDA }}
lambda: ${{ matrix.lambda }}
short_sha: ${{ needs.deploy2gchr.outputs.short_sha }}
40 changes: 21 additions & 19 deletions api/Infrastructure/ServiceCollectionExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ public static class ServiceCollectionExtensions
{
const string X_APIGW_KEY_HEADER = "x-api-key";
const string X_ORIGIN_VERIFY_HEADER = "x-origin-verify";
const string X_TARGET_APP = "x-target-app";

public static IServiceCollection AddMapster(this IServiceCollection services, Action<TypeAdapterConfig> options = null)
{
Expand Down Expand Up @@ -89,30 +90,31 @@ public static IServiceCollection AddHttpClientsAndScvServices(this IServiceColle

private static void ConfigureHttpClient(HttpClient client, IConfiguration configuration, string prefix, int timeoutInSecs = 100)
{
// Comment out for now until the pattern for creating handlers has been finalized so that it would be easier
// to redirect network traffic between WSGW (local) and AWS API Gateway (dev, test and prod).

// var apigwUrl = configuration.GetValue<string>("AWS_API_GATEWAY_URL");
// var apigwKey = configuration.GetValue<string>("AWS_API_GATEWAY_API_KEY");
// var authorizerKey = configuration.GetValue<string>("AuthorizerKey");
var apigwUrl = configuration.GetValue<string>("AWS_API_GATEWAY_URL");
var apigwKey = configuration.GetValue<string>("AWS_API_GATEWAY_API_KEY");
var authorizerKey = configuration.GetValue<string>("AuthorizerKey");

client.Timeout = TimeSpan.FromSeconds(timeoutInSecs);

// Defaults to BC Gov API if any config setting is missing
// if (string.IsNullOrWhiteSpace(apigwUrl) || string.IsNullOrWhiteSpace(apigwKey) || string.IsNullOrWhiteSpace(authorizerKey))
// {
client.DefaultRequestHeaders.Authorization = new BasicAuthenticationHeaderValue(
configuration.GetNonEmptyValue($"{prefix}:Username"),
configuration.GetNonEmptyValue($"{prefix}:Password"));
client.BaseAddress = new Uri(configuration.GetNonEmptyValue($"{prefix}:Url").EnsureEndingForwardSlash());
//}
if (string.IsNullOrWhiteSpace(apigwUrl) || string.IsNullOrWhiteSpace(apigwKey) || string.IsNullOrWhiteSpace(authorizerKey))
{
Console.WriteLine($"Redirecting traffic to: {configuration.GetNonEmptyValue($"{prefix}:Url")}");
client.DefaultRequestHeaders.Authorization = new BasicAuthenticationHeaderValue(
configuration.GetNonEmptyValue($"{prefix}:Username"),
configuration.GetNonEmptyValue($"{prefix}:Password"));
client.BaseAddress = new Uri(configuration.GetNonEmptyValue($"{prefix}:Url").EnsureEndingForwardSlash());
}
// Requests are routed to JASPER's API Gateway. Lambda functions are triggered by these requests and are responsible for communicating with the BC Gov API.
// else
// {
// client.BaseAddress = new Uri(apigwUrl.EnsureEndingForwardSlash());
// client.DefaultRequestHeaders.Add(X_APIGW_KEY_HEADER, apigwKey);
// client.DefaultRequestHeaders.Add(X_ORIGIN_VERIFY_HEADER, authorizerKey);
// }
else
{
Console.WriteLine($"Redirecting traffic to: {apigwUrl}");
client.BaseAddress = new Uri(apigwUrl.EnsureEndingForwardSlash());
client.DefaultRequestHeaders.Add(X_APIGW_KEY_HEADER, apigwKey);
client.DefaultRequestHeaders.Add(X_ORIGIN_VERIFY_HEADER, authorizerKey);
// The prefix will help determine where will the request is routed (e.g. lookup, CatsAPI or DARS)
client.DefaultRequestHeaders.Add(X_TARGET_APP, prefix);
}
}
}
}
19 changes: 6 additions & 13 deletions aws/lambdas/auth/authorizer/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import {
PolicyDocument,
StatementEffect,
} from "aws-lambda";
import { v4 as uuidv4 } from "uuid";
import SecretsManagerService from "../../../services/secretsManagerService";
import { replaceWithWildcard } from "../../../util";

const X_ORIGIN_VERIFY_HEADER = "x-origin-verify";

Expand All @@ -18,7 +18,6 @@ export const handler = async (
console.log(`Event: ${JSON.stringify(event, null, 2)}`);
console.log(`Context: ${JSON.stringify(context, null, 2)}`);

const correlationId: string = event.requestContext.requestId || uuidv4();
const logger = new Logger({
serviceName: "auth.authorizer",
});
Expand Down Expand Up @@ -59,13 +58,9 @@ export const handler = async (
throw new Error("Error: invalid token");
}

const policy = generatePolicy(
correlationId,
"user",
"Allow",
event.methodArn
);
const policy = generatePolicy("Allow", event.methodArn);

logger.info("Authorized");
logger.info(JSON.stringify(policy));

return policy;
Expand All @@ -77,8 +72,6 @@ export const handler = async (
};

const generatePolicy = (
correlationId: string,
principalId: string,
effect: StatementEffect,
resource: string
): APIGatewayAuthorizerResult => {
Expand All @@ -88,15 +81,15 @@ const generatePolicy = (
{
Action: "execute-api:Invoke",
Effect: effect,
Resource: resource,
Resource: replaceWithWildcard(resource),
},
],
};

const authResponse: APIGatewayAuthorizerResult = {
principalId,
principalId: "user",
context: {
correlation_id: correlationId,
correlation_id: "generic",
},
policyDocument,
};
Expand Down
15 changes: 0 additions & 15 deletions aws/lambdas/files/search-civil-files/index.ts

This file was deleted.

15 changes: 0 additions & 15 deletions aws/lambdas/files/search-criminal-files/index.ts

This file was deleted.

28 changes: 0 additions & 28 deletions aws/lambdas/locations/get-locations/index.ts

This file was deleted.

Loading
Loading