diff --git a/.github/workflows/actions/build-lambdas/action.yml b/.github/workflows/actions/build-lambdas/action.yml new file mode 100644 index 00000000..7691bf27 --- /dev/null +++ b/.github/workflows/actions/build-lambdas/action.yml @@ -0,0 +1,36 @@ +name: Build Lambda +description: Builds all Lambda functions + +inputs: + working_directory: + description: The working directory where the code will be built. + required: true + node_version: + description: The node version that will be used. + required: true + +runs: + using: composite + + steps: + - name: Install Node.js + uses: actions/setup-node@v4 + with: + node-version: ${{ env.node_version }} + + - run: npm ci + shell: bash + working-directory: ${{ inputs.working_directory }} + + - run: npm run lint + shell: bash + working-directory: ${{ inputs.working_directory }} + continue-on-error: false + + - run: npm run build + shell: bash + working-directory: ${{ inputs.working_directory }} + + - run: npm run test --if-present + shell: bash + working-directory: ${{ inputs.working_directory }} diff --git a/.github/workflows/actions/deploy-to-aws/action.yml b/.github/workflows/actions/deploy-app/action.yml similarity index 89% rename from .github/workflows/actions/deploy-to-aws/action.yml rename to .github/workflows/actions/deploy-app/action.yml index e1ce40a1..0c26e51b 100644 --- a/.github/workflows/actions/deploy-to-aws/action.yml +++ b/.github/workflows/actions/deploy-app/action.yml @@ -1,5 +1,5 @@ -name: Deploy to AWS -description: Deploy image to AWS Instance +name: Deploy App +description: Deploy web or API image to AWS ECS inputs: environment: @@ -41,11 +41,11 @@ runs: id: vars shell: bash run: | - echo "task_definition_name=${{ inputs.app_name }}-${{ inputs.tier_name }}-task-definition-${{ inputs.environment }}" >> $GITHUB_OUTPUT + echo "task_definition_name=${{ inputs.app_name }}-${{ inputs.tier_name }}-td-${{ inputs.environment }}" >> $GITHUB_OUTPUT echo "container_name=${{ inputs.app_name }}-${{ inputs.tier_name }}-container-${{ inputs.environment }}" >> $GITHUB_OUTPUT - echo "ecs_cluster_name=${{ inputs.app_name }}-ecs-cluster-${{ inputs.environment }}" >> $GITHUB_OUTPUT - echo "ecs_service_name=${{ inputs.app_name }}-ecs-${{ inputs.tier_name }}-service-${{ inputs.environment }}" >> $GITHUB_OUTPUT - echo "full_ecr_repo_url=${{ inputs.aws_account }}.dkr.ecr.${{ inputs.region }}.amazonaws.com/${{ inputs.app_name }}-ecr-repo-${{ inputs.environment }}" >> $GITHUB_OUTPUT + echo "ecs_cluster_name=${{ inputs.app_name }}-app-cluster-${{ inputs.environment }}" >> $GITHUB_OUTPUT + echo "ecs_service_name=${{ inputs.app_name }}-${{ inputs.tier_name }}-ecs-service-${{ inputs.environment }}" >> $GITHUB_OUTPUT + echo "full_ecr_repo_url=${{ inputs.aws_account }}.dkr.ecr.${{ inputs.region }}.amazonaws.com/${{ inputs.app_name }}-app-repo-${{ inputs.environment }}" >> $GITHUB_OUTPUT - name: Log in to the GHCR uses: docker/login-action@v2 @@ -71,7 +71,7 @@ runs: shell: bash run: | IMAGE_TAG=${{ inputs.image_name }}-${{ inputs.short_sha}} - REPOSITORY_NAME=${{ inputs.app_name }}-ecr-repo-${{ inputs.environment }} + REPOSITORY_NAME=${{ inputs.app_name }}-app-repo-${{ inputs.environment }} IMAGE_EXISTS=$(aws ecr describe-images --repository-name $REPOSITORY_NAME --query "imageDetails[?contains(imageTags, '$IMAGE_TAG')]" --output text) diff --git a/.github/workflows/actions/deploy-lambda/action.yml b/.github/workflows/actions/deploy-lambda/action.yml new file mode 100644 index 00000000..7f4b3adc --- /dev/null +++ b/.github/workflows/actions/deploy-lambda/action.yml @@ -0,0 +1,100 @@ +name: Deploy Lambda +description: Deploy image to a Lambda function to AWS + +inputs: + environment: + description: The environment to which the image will be deployed. + required: true + aws_account: + description: The AWS Account ID. + required: true + region: + description: The AWS Region of the AWS Account. + required: true + app_name: + description: The application name. + required: true + resource: + description: The resource path of the lambda function. + required: true + lambda_name: + description: The lambda function name name. + required: true + aws_role_arn: + description: The AWS Role ARN to assume. + required: true + ghcr_token: + description: The token to use to login to the GHCR. + required: true + 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 + +runs: + using: composite + + steps: + - 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: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ inputs.ghcr_token }} + + - name: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@v4 + with: + role-skip-session-tagging: true + aws-region: ${{ inputs.region }} + role-to-assume: ${{ inputs.aws_role_arn }} + role-duration-seconds: 1800 + role-session-name: ci-deployment + + - name: Login to Amazon ECR + uses: aws-actions/amazon-ecr-login@v2 + + - name: Check ECR Image exists + id: ecr-check + shell: bash + run: | + IMAGE_TAG=${{ inputs.resource }}${{ inputs.lambda_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) + + if [ -z "$IMAGE_EXISTS" ]; then + echo "Image with tag $IMAGE_TAG does not exist." + echo "exists=false" >> $GITHUB_OUTPUT + else + echo "Image with tag $IMAGE_TAG already exists." + echo "exists=true" >> $GITHUB_OUTPUT + fi + + - name: Push if Docker image does not exist + 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 }} + + - 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 ${{ env.full_ecr_repo_url }}:${{ inputs.resource }}.${{ inputs.lambda_name }}-${{ inputs.short_sha }} diff --git a/.github/workflows/aws-template-terraform.yml b/.github/workflows/aws-template-terraform.yml index 13e58d72..b63cc51a 100644 --- a/.github/workflows/aws-template-terraform.yml +++ b/.github/workflows/aws-template-terraform.yml @@ -12,9 +12,6 @@ on: CHANGE_FOLDER_NAME: required: true type: string - TEST_BUCKET_NAME: - required: true - type: string APPLY_TF_CODE: required: true default: false @@ -117,7 +114,6 @@ jobs: id: plan env: CONTEXT_FOLDER: ${{ inputs.CONTEXT_FOLDER }} - #TF_VAR_test_s3_bucket_name: ${{ inputs.TEST_BUCKET_NAME }} run: | terraform plan -no-color -input=false -var-file=${{ inputs.ENVIRONMENT_NAME }}.tfvars continue-on-error: true @@ -129,7 +125,6 @@ jobs: if: inputs.APPLY_TF_CODE == true env: CONTEXT_FOLDER: ${{ inputs.CONTEXT_FOLDER }} - #TF_VAR_test_s3_bucket_name: ${{ inputs.TEST_BUCKET_NAME }} run: | terraform apply --auto-approve -input=false -var-file=${{ inputs.ENVIRONMENT_NAME }}.tfvars working-directory: ${{ inputs.CONTEXT_FOLDER }} diff --git a/.github/workflows/build-and-test-lambdas.yml b/.github/workflows/build-and-test-lambdas.yml new file mode 100644 index 00000000..cf43dd89 --- /dev/null +++ b/.github/workflows/build-and-test-lambdas.yml @@ -0,0 +1,28 @@ +name: Build and Test Lambdas + +on: + pull_request: + branches: + - master + paths: + - "aws/**" + + workflow_dispatch: + +env: + WORKING_DIRECTORY: ./aws + NODE_VERSION: 20 + +jobs: + build-and-test: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Building Lambdas codebase + uses: ./.github/workflows/actions/build-lambdas + with: + working_directory: ${{ env.WORKING_DIRECTORY }} + node_version: ${{ env.NODE_VERSION }} diff --git a/.github/workflows/build-infra.yml b/.github/workflows/build-infra.yml index 2eaec906..1a6d36c4 100644 --- a/.github/workflows/build-infra.yml +++ b/.github/workflows/build-infra.yml @@ -22,12 +22,22 @@ on: - prod jobs: + build-initial: + uses: ./.github/workflows/aws-template-terraform.yml + with: + CONTEXT_FOLDER: "./infrastructure/cloud/environments/initial" + CHANGE_FOLDER_NAME: environments/${{ inputs.environment || 'dev' }} + ENVIRONMENT_NAME: ${{ inputs.environment || 'dev' }} + APPLY_TF_CODE: false + secrets: inherit + build: + needs: [build-initial] uses: ./.github/workflows/aws-template-terraform.yml with: CONTEXT_FOLDER: "./infrastructure/cloud/environments/${{ inputs.environment || 'dev' }}" CHANGE_FOLDER_NAME: environments/${{ inputs.environment || 'dev' }} ENVIRONMENT_NAME: ${{ inputs.environment || 'dev' }} - TEST_BUCKET_NAME: jasper-test-bucket APPLY_TF_CODE: false secrets: inherit + \ No newline at end of file diff --git a/.github/workflows/publish-api.yml b/.github/workflows/publish-api.yml index 35eae812..07b3ab14 100644 --- a/.github/workflows/publish-api.yml +++ b/.github/workflows/publish-api.yml @@ -90,7 +90,7 @@ jobs: uses: actions/checkout@v4 - name: Deploy to ${{ env.ENVIRONMENT }} - uses: ./.github/workflows/actions/deploy-to-aws + uses: ./.github/workflows/actions/deploy-app with: environment: ${{ env.ENVIRONMENT }} aws_account: ${{ vars.AWS_ACCOUNT }} @@ -120,7 +120,7 @@ jobs: # Uncomment when infra in AWS in TEST environment has been configured # - name: Deploy to ${{ env.ENVIRONMENT }} - # uses: ./.github/workflows/actions/deploy-to-aws + # uses: ./.github/workflows/actions/deploy-app # with: # environment: ${{ env.ENVIRONMENT }} # aws_account: ${{ vars.AWS_ACCOUNT }} @@ -150,7 +150,7 @@ jobs: # Uncomment when infra in AWS in PROD environment has been configured # - name: Deploy to ${{ env.ENVIRONMENT }} - # uses: ./.github/workflows/actions/deploy-to-aws + # uses: ./.github/workflows/actions/deploy-app # with: # environment: ${{ env.ENVIRONMENT }} # aws_account: ${{ vars.AWS_ACCOUNT }} diff --git a/.github/workflows/publish-infra.yml b/.github/workflows/publish-infra.yml index d08303d0..aac16ade 100644 --- a/.github/workflows/publish-infra.yml +++ b/.github/workflows/publish-infra.yml @@ -20,14 +20,106 @@ on: - dev - test - prod + run_initial: + description: "Run initial Terraform setup?" + required: false + default: "No" + type: choice + options: + - "No" + - "Yes" jobs: + initial: + if: ${{ inputs.run_initial == 'Yes' }} + uses: ./.github/workflows/aws-template-terraform.yml + with: + CONTEXT_FOLDER: "./infrastructure/cloud/environments/initial" + CHANGE_FOLDER_NAME: environments/${{ inputs.environment }} + ENVIRONMENT_NAME: ${{ inputs.environment || 'dev' }} + APPLY_TF_CODE: false + secrets: inherit + + post-initial: + runs-on: ubuntu-latest + needs: initial + if: ${{ inputs.run_initial == 'Yes' }} + environment: ${{ inputs.environment }} + permissions: + id-token: write + packages: write + env: + DUMMY_IMAGE_NAME: dummy-image + GITHUB_IMAGE_REPO: ghcr.io/bcgov/jasper + APP_ECR_REPO_URL: ${{ vars.AWS_ACCOUNT }}.dkr.ecr.${{ vars.AWS_REGION }}.amazonaws.com/${{ vars.APP_NAME }}-app-repo-${{ inputs.environment }} + LAMBDA_ECR_REPO_URL: ${{ vars.AWS_ACCOUNT }}.dkr.ecr.${{ vars.AWS_REGION }}.amazonaws.com/${{ vars.APP_NAME }}-lambda-repo-${{ inputs.environment }} + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Log in to the GHCR + uses: docker/login-action@v2 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Setup Image Metadata + id: meta + uses: docker/metadata-action@v5 + with: + images: | + ${{ env.GITHUB_IMAGE_REPO }}/${{ env.DUMMY_IMAGE_NAME }} + tags: | + type=raw,value=latest + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + with: + driver: docker + + - name: Build ${{ env.DUMMY_IMAGE_NAME }} image + uses: docker/build-push-action@v6 + with: + push: true + file: ./docker/dummy-image/Dockerfile.release + context: . + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + + - name: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@v4 + with: + role-skip-session-tagging: true + aws-region: ${{ vars.AWS_REGION }} + role-to-assume: ${{ vars.AWS_ROLE_ARN }} + role-duration-seconds: 1800 + role-session-name: ci-deployment + + - name: Login to Amazon ECR + uses: aws-actions/amazon-ecr-login@v2 + + - name: Push dummy images to App ECR + shell: bash + run: | + echo 'Deploying ${{ env.DUMMY_IMAGE_NAME }} to App ECR' + docker tag ${{ env.GITHUB_IMAGE_REPO }}/${{ env.DUMMY_IMAGE_NAME }}:latest ${{ env.APP_ECR_REPO_URL }}:${{ env.DUMMY_IMAGE_NAME }} + docker push ${{ env.APP_ECR_REPO_URL }}:${{ env.DUMMY_IMAGE_NAME }} + + - name: Push dummy images to Lambda ECR + shell: bash + run: | + echo 'Deploying ${{ env.env.DUMMY_IMAGE_NAME }} to Lambda ECR' + docker tag ${{ env.GITHUB_IMAGE_REPO }}/${{ env.DUMMY_IMAGE_NAME }}:latest ${{ env.LAMBDA_ECR_REPO_URL }}:${{ env.DUMMY_IMAGE_NAME }} + docker push ${{ env.LAMBDA_ECR_REPO_URL }}:${{ env.DUMMY_IMAGE_NAME }} + deploy: + needs: [initial, post-initial] + if: always() uses: ./.github/workflows/aws-template-terraform.yml with: CONTEXT_FOLDER: "./infrastructure/cloud/environments/${{ inputs.environment || 'dev' }}" CHANGE_FOLDER_NAME: environments/${{ inputs.environment || 'dev' }} ENVIRONMENT_NAME: ${{ inputs.environment || 'dev' }} - TEST_BUCKET_NAME: jasper-test-bucket APPLY_TF_CODE: true secrets: inherit diff --git a/.github/workflows/publish-lambdas.yml b/.github/workflows/publish-lambdas.yml new file mode 100644 index 00000000..bf2203dc --- /dev/null +++ b/.github/workflows/publish-lambdas.yml @@ -0,0 +1,163 @@ +name: Deploy Lambda Functions + +on: + push: + branches: + - master + paths: + - "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 + GITHUB_IMAGE_REPO: ghcr.io/bcgov/jasper + +jobs: + get-lambdas: + runs-on: ubuntu-latest + outputs: + lambda_dir_list: ${{ steps.convert.outputs.LAMBDA_DIR_LIST }} + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Get Lambda directories + id: lambdas + shell: bash + working-directory: ${{ env.WORKING_DIRECTORY }} + run: | + dirs=$(find lambdas -mindepth 2 -maxdepth 2 -type d | sed 's|lambdas/||' | paste -sd ';' -) # Space-separated + echo "LAMBDA_DIRS=$dirs" >> $GITHUB_ENV + + - name: Convert FOLDERS to JSON array + id: convert + shell: bash + working-directory: ${{ env.WORKING_DIRECTORY }} + run: | + LAMBDA_DIR_LIST=$(echo "${LAMBDA_DIRS}" | jq -R 'split(";")' -c) + echo "LAMBDA_DIR_LIST=$LAMBDA_DIR_LIST" >> $GITHUB_OUTPUT + + deploy-to-gchr: + needs: get-lambdas + environment: ${{ inputs.environment }} + 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: + lambda: ${{ fromJSON(needs.get-lambdas.outputs.lambda_dir_list) }} + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Build Lambdas codebase + uses: ./.github/workflows/actions/build-lambdas + with: + working_directory: ${{ env.WORKING_DIRECTORY }} + node_version: ${{ env.NODE_VERSION }} + + - name: Log in to the GHCR + uses: docker/login-action@v2 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Get short SHA + id: short_sha + run: | + echo "SHORT_SHA=$(git rev-parse --short HEAD)" >> $GITHUB_ENV + + - 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: Setup Image Metadata + id: meta + uses: docker/metadata-action@v5 + with: + images: | + ${{ env.GITHUB_IMAGE_REPO }}/${{ env.RESOURCE }}.${{ env.LAMBDA }} + tags: | + type=raw,value=${{ env.SHORT_SHA }} + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + with: + driver: docker + + - name: Build ${{ matrix.lambda }} image + uses: docker/build-push-action@v6 + with: + push: true + file: ./docker/aws/Dockerfile.release + context: ./aws + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + build-args: | + TARGET_FUNCTION=${{ matrix.lambda }} + NODE_VERSION=${{ env.NODE_VERSION }} + + deploy2dev: + name: Deploy to DEV + needs: [get-lambdas, deploy-to-gchr] + env: + ENVIRONMENT: dev + permissions: + id-token: write + packages: write + runs-on: ubuntu-latest + environment: dev + + strategy: + matrix: + lambda: ${{ fromJSON(needs.get-lambdas.outputs.lambda_dir_list) }} + + steps: + - 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 }} + resource: ${{ env.RESOURCE }} + lambda_name: ${{ env.LAMBDA }} + image_name: ${{ env.RESOURCE }}.${{ env.LAMBDA }} + short_sha: ${{ needs.deploy-to-gchr.outputs.short_sha }} diff --git a/.github/workflows/publish-web.yml b/.github/workflows/publish-web.yml index 64ba9dee..8ae85912 100644 --- a/.github/workflows/publish-web.yml +++ b/.github/workflows/publish-web.yml @@ -96,7 +96,7 @@ jobs: uses: actions/checkout@v4 - name: Deploy to ${{ env.ENVIRONMENT }} - uses: ./.github/workflows/actions/deploy-to-aws + uses: ./.github/workflows/actions/deploy-app with: environment: ${{ env.ENVIRONMENT }} aws_account: ${{ vars.AWS_ACCOUNT }} @@ -126,7 +126,7 @@ jobs: # Uncomment when infra in AWS in TEST environment has been configured # - name: Deploy to ${{ env.ENVIRONMENT }} - # uses: ./.github/workflows/actions/deploy-to-aws + # uses: ./.github/workflows/actions/deploy-app # with: # environment: ${{ env.ENVIRONMENT }} # aws_account: ${{ vars.AWS_ACCOUNT }} @@ -156,7 +156,7 @@ jobs: # Uncomment when infra in AWS in PROD environment has been configured # - name: Deploy to ${{ env.ENVIRONMENT }} - # uses: ./.github/workflows/actions/deploy-to-aws + # uses: ./.github/workflows/actions/deploy-app # with: # environment: ${{ env.ENVIRONMENT }} # aws_account: ${{ vars.AWS_ACCOUNT }} diff --git a/.gitignore b/.gitignore index 6079bd30..fc0aa67e 100644 --- a/.gitignore +++ b/.gitignore @@ -481,4 +481,8 @@ dist .yarn/cache .yarn/unplugged .yarn/build-state.yml -.pnp.* \ No newline at end of file +.pnp.* + +# Terraform +.terraform +*.hcl \ No newline at end of file diff --git a/api/Controllers/LocationController.cs b/api/Controllers/LocationController.cs index ff2db7c9..3055a25c 100644 --- a/api/Controllers/LocationController.cs +++ b/api/Controllers/LocationController.cs @@ -44,7 +44,7 @@ public async Task>> GetLocationsAndCourtRooms() foreach (var location in locationList) { location.CourtRooms = courtRooms.Where(cr => cr.Flex == location.LocationId && (cr.ShortDesc == "CRT" || cr.ShortDesc == "HGR")) - .Select(cr => new CourtRoom {LocationId = cr.Flex, Room = cr.Code, Type = cr.ShortDesc}).ToList(); + .Select(cr => new CourtRoom { LocationId = cr.Flex, Room = cr.Code, Type = cr.ShortDesc }).ToList(); } return Ok(locationList); diff --git a/api/Controllers/TestController.cs b/api/Controllers/TestController.cs index 86ba26e1..31a00b19 100644 --- a/api/Controllers/TestController.cs +++ b/api/Controllers/TestController.cs @@ -1,5 +1,10 @@ -using Microsoft.AspNetCore.Authorization; +using System; +using System.Net.Http; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Configuration; +using Scv.Api.Helpers; namespace Scv.Api.Controllers { @@ -7,6 +12,13 @@ namespace Scv.Api.Controllers [ApiController] public class TestController : ControllerBase { + private readonly IConfiguration _configuration; + + public TestController(IConfiguration configuration) + { + _configuration = configuration; + } + [HttpGet] [Route("Headers")] [AllowAnonymous] @@ -15,5 +27,24 @@ public ActionResult Headers() { return Ok(Request.Headers); } + + [HttpGet] + [Route("APIG")] + [AllowAnonymous] + public async Task TestAPIG() + { + var baseUrl = _configuration.GetNonEmptyValue("AWS_API_GATEWAY_URL"); + var apiKey = _configuration.GetNonEmptyValue("AWS_API_GATEWAY_API_KEY"); + + Console.WriteLine(baseUrl); + using var client = new HttpClient(); + client.BaseAddress = new Uri(baseUrl); + client.DefaultRequestHeaders.Clear(); + client.DefaultRequestHeaders.Add("x-api-key", apiKey); + // client.DefaultRequestHeaders.Add("x-origin-verify", "1234456"); + + var response = await client.GetStringAsync("locations/rooms"); + return Ok(response); + } } } diff --git a/api/Infrastructure/ServiceCollectionExtensions.cs b/api/Infrastructure/ServiceCollectionExtensions.cs index eafaa058..43dc10fa 100644 --- a/api/Infrastructure/ServiceCollectionExtensions.cs +++ b/api/Infrastructure/ServiceCollectionExtensions.cs @@ -57,10 +57,12 @@ public static IServiceCollection AddHttpClientsAndScvServices(this IServiceColle services.AddHttpClient(client => { - client.DefaultRequestHeaders.Authorization = new BasicAuthenticationHeaderValue( - configuration.GetNonEmptyValue("LocationServicesClient:Username"), - configuration.GetNonEmptyValue("LocationServicesClient:Password")); + // client.DefaultRequestHeaders.Authorization = new BasicAuthenticationHeaderValue( + // configuration.GetNonEmptyValue("LocationServicesClient:Username"), + // configuration.GetNonEmptyValue("LocationServicesClient:Password")); client.BaseAddress = new Uri(configuration.GetNonEmptyValue("LocationServicesClient:Url").EnsureEndingForwardSlash()); + var apiKey = configuration.GetNonEmptyValue("AWS_API_GATEWAY_API_KEY"); + client.DefaultRequestHeaders.Add("x-api-key", apiKey); }).AddHttpMessageHandler(); services.AddHttpClient(client => diff --git a/aws/esbuild.config.js b/aws/esbuild.config.js new file mode 100644 index 00000000..1f7672a6 --- /dev/null +++ b/aws/esbuild.config.js @@ -0,0 +1,26 @@ +const esbuild = require("esbuild") +const glob = require("glob") +const path = require("path") + +const entryPoints = glob.sync("./lambdas/*/*/*.ts") + +const builds = entryPoints.map((entry) => { + const [category, handlerName] = entry.split(path.sep).slice(-3, -1) + + // Format output file name as 'dist/[category].[handlerName]/index.js' + const outputDir = `dist/${category}.${handlerName}` + + return esbuild.build({ + entryPoints: [entry], + outfile: path.join(outputDir, "index.js"), + bundle: true, + platform: "node", + target: "node14", + format: "cjs", + sourcemap: true, + minify: true + }) +}) + +// Run all builds in parallel +Promise.all(builds).catch(() => process.exit(1)) diff --git a/aws/eslint.config.js b/aws/eslint.config.js new file mode 100644 index 00000000..34ed6b50 --- /dev/null +++ b/aws/eslint.config.js @@ -0,0 +1,20 @@ +// eslint.config.js +module.exports = [ + { + files: ["**/*.ts"], + languageOptions: { + parser: require("@typescript-eslint/parser"), + parserOptions: { + ecmaVersion: 2020, + sourceType: "module" + } + }, + plugins: { + "@typescript-eslint": require("@typescript-eslint/eslint-plugin") + }, + rules: { + ...require("@typescript-eslint/eslint-plugin").configs.recommended.rules + // Add custom rules here + } + } +] diff --git a/aws/helpers/getSecret.ts b/aws/helpers/getSecret.ts new file mode 100644 index 00000000..8ba2428b --- /dev/null +++ b/aws/helpers/getSecret.ts @@ -0,0 +1,24 @@ +import { + GetSecretValueCommand, + SecretsManagerClient +} from "@aws-sdk/client-secrets-manager" + +const secretsManagerClient = new SecretsManagerClient() + +export const getSecret = async (secretName: string): Promise => { + try { + const command = new GetSecretValueCommand({ SecretId: secretName }) + const data = await secretsManagerClient.send(command) + + if (data.SecretString) { + return data.SecretString + } else { + throw new Error( + `Secret with ID ${secretName} does not contain SecretString` + ) + } + } catch (error) { + console.error(`Error retrieving secret ${secretName}:`, error) + throw error + } +} diff --git a/aws/lambdas/files/search-civil-files/index.ts b/aws/lambdas/files/search-civil-files/index.ts new file mode 100644 index 00000000..5da21999 --- /dev/null +++ b/aws/lambdas/files/search-civil-files/index.ts @@ -0,0 +1,15 @@ +import { APIGatewayEvent, APIGatewayProxyResult, Context } from "aws-lambda" + +export const handler = async ( + event: APIGatewayEvent, + context: Context +): Promise => { + console.log(`Event: ${JSON.stringify(event, null, 2)}`) + console.log(`Context: ${JSON.stringify(context, null, 2)}`) + return { + statusCode: 200, + body: JSON.stringify({ + message: "hello from Search Civil" + }) + } +} diff --git a/aws/lambdas/files/search-criminal-files/index.ts b/aws/lambdas/files/search-criminal-files/index.ts new file mode 100644 index 00000000..e47db932 --- /dev/null +++ b/aws/lambdas/files/search-criminal-files/index.ts @@ -0,0 +1,15 @@ +import { APIGatewayEvent, APIGatewayProxyResult, Context } from "aws-lambda" + +export const handler = async ( + event: APIGatewayEvent, + context: Context +): Promise => { + console.log(`Event: ${JSON.stringify(event, null, 2)}`) + console.log(`Context: ${JSON.stringify(context, null, 2)}`) + return { + statusCode: 200, + body: JSON.stringify({ + message: "hello from Search Criminal" + }) + } +} diff --git a/aws/lambdas/locations/get-locations/index.ts b/aws/lambdas/locations/get-locations/index.ts new file mode 100644 index 00000000..e1e7b426 --- /dev/null +++ b/aws/lambdas/locations/get-locations/index.ts @@ -0,0 +1,924 @@ +import { APIGatewayEvent, APIGatewayProxyResult, Context } from "aws-lambda" + +export const handler = async ( + event: APIGatewayEvent, + context: Context +): Promise => { + console.log(event, context) + + return { + statusCode: 200, + body: JSON.stringify([ + { + codeType: "COURT_LOCATIONS", + code: "10230.0001", + shortDesc: "1011", + longDesc: "Alert Bay", + flex: "N" + }, + { + codeType: "COURT_LOCATIONS", + code: "10231.0001", + shortDesc: "1051", + longDesc: "Duncan Law Courts", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "10232.0001", + shortDesc: "1061", + longDesc: "Ganges Provincial Court", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "10233.0001", + shortDesc: "1071", + longDesc: "Gold River Provincial Court", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "10234.0001", + shortDesc: "1111", + longDesc: "Parksville Provincial Court", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "10235.0001", + shortDesc: "1121", + longDesc: "Port Alberni Law Courts", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "10236.0001", + shortDesc: "1141", + longDesc: "Port Hardy Law Courts", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "10237.0001", + shortDesc: "1145", + longDesc: "Powell River Law Courts", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "10238.0001", + shortDesc: "1151", + longDesc: "Sidney Provincial Court", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "10239.0001", + shortDesc: "1171", + longDesc: "Tahsis Provincial Court", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "10240.0001", + shortDesc: "1181", + longDesc: "Tofino Provincial Court", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "10241.0001", + shortDesc: "1191", + longDesc: "Ucluelet Provincial Court", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "10242.0001", + shortDesc: "1207", + longDesc: "Victoria Family and Youth Court", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "10243.0001", + shortDesc: "1211", + longDesc: "Western Communities Provincial Court", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "10244.0001", + shortDesc: "2007", + longDesc: "Bella Bella Law Courts", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "10245.0001", + shortDesc: "2008", + longDesc: "Bella Coola Law Courts", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "10246.0001", + shortDesc: "2021", + longDesc: "Pemberton Provincial Court", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "10247.0001", + shortDesc: "2027", + longDesc: "Richmond Court Small Claims and Family Court", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "10248.0001", + shortDesc: "2031", + longDesc: "Sechelt Provincial Court", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "10249.0001", + shortDesc: "2035", + longDesc: "Squamish Provincial Court", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "10250.0001", + shortDesc: "2045", + longDesc: "Robson Square Provincial Court", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "10251.0001", + shortDesc: "2048", + longDesc: "Vancouver Traffic Court", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "10252.0001", + shortDesc: "2051", + longDesc: "West Vancouver Provincial Court", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "10253.0001", + shortDesc: "3541", + longDesc: "Hope Provincial Court", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "10254.0001", + shortDesc: "3545", + longDesc: "Langley Provincial Court", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "10255.0001", + shortDesc: "3571", + longDesc: "Mission Provincial Court", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "10256.0001", + shortDesc: "4951", + longDesc: "Sparwood Provincial Court", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "10257.0001", + shortDesc: "5775", + longDesc: "Fort Ware Provincial Court", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "10258.0001", + shortDesc: "5805", + longDesc: "Tsay Keh Dene Court", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "10264.0001", + shortDesc: "LECR", + longDesc: "Leech Town Court Registry", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "10265.0001", + shortDesc: "5895", + longDesc: "Prince George Supreme Court", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "10266.0001", + shortDesc: "5911", + longDesc: "Daajing Giids Provincial Crt", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "10267.0001", + shortDesc: "5941", + longDesc: "Stewart Provincial Court", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "10268.0001", + shortDesc: "5955", + longDesc: "Tumbler Ridge Provincial Court", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "104.0001", + shortDesc: "5671", + longDesc: "Alexis Creek Provincial Court", + flex: "N" + }, + { + codeType: "COURT_LOCATIONS", + code: "105.0001", + shortDesc: "5681", + longDesc: "Anahim Lake Provincial Court", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "106.0001", + shortDesc: "5691", + longDesc: "Atlin Provincial Court", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "107.0001", + shortDesc: "5701", + longDesc: "Burns Lake Court", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "108.0001", + shortDesc: "5711", + longDesc: "Cassiar Court", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "109.0001", + shortDesc: "5721", + longDesc: "Chetwynd Provincial Court", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "10912.0026", + shortDesc: "7999", + longDesc: "Leech Town Court House", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "110.0001", + shortDesc: "5731", + longDesc: "Dawson Creek Law Courts", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "111.0001", + shortDesc: "5741", + longDesc: "Dease Lake Provincial Court", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "112.0001", + shortDesc: "5751", + longDesc: "Fort Nelson Law Courts", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "113.0001", + shortDesc: "5761", + longDesc: "Fort St. James Provincial Court", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "114.0001", + shortDesc: "5771", + longDesc: "Fort St. John Law Courts", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "115.0001", + shortDesc: "5781", + longDesc: "Fraser Lake Provincial Court", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "116.0001", + shortDesc: "5791", + longDesc: "Houston Provincial Court", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "117.0001", + shortDesc: "5801", + longDesc: "Hudson's Hope Provincial Court", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "118.0001", + shortDesc: "5811", + longDesc: "Kitimat Law Courts", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "119.0001", + shortDesc: "5821", + longDesc: "Lower Post Provincial Court", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "120.0001", + shortDesc: "5831", + longDesc: "MacKenzie Provincial Court", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "121.0001", + shortDesc: "5841", + longDesc: "Masset Provincial Court", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "122.0001", + shortDesc: "5845", + longDesc: "McBride Provincial Court", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "123.0001", + shortDesc: "5851", + longDesc: "New Aiyansh Provincial Court", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "124.0001", + shortDesc: "5861", + longDesc: "New Hazelton Provincial Court", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "16164.0026", + shortDesc: "4831", + longDesc: "Lytton Provincial Court", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "18817.0045", + shortDesc: "ADJU", + longDesc: "Adjudicator Listing", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "18886.0045", + shortDesc: "SHER", + longDesc: "Sherbrooke Courthouse", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "19057.0002", + shortDesc: "NA01", + longDesc: "Nanaimo Law Courts NAO1", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "19058.0002", + shortDesc: "NA02", + longDesc: "Nanaimo Law Courts NAO2", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "19059.0002", + shortDesc: "NA03", + longDesc: "Nanaimo Law Courts NAO3", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "19060.0002", + shortDesc: "NA04", + longDesc: "Nanaimo Law Courts NAO4", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "19061.0002", + shortDesc: "NA05", + longDesc: "Nanaimo Law Courts NAO5", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "19062.0002", + shortDesc: "NA06", + longDesc: "Nanaimo Law Courts NAO6", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "19063.0002", + shortDesc: "NA07", + longDesc: "Nanaimo Law Courts NAO7", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "19064.0002", + shortDesc: "NA08", + longDesc: "Nanaimo Law Courts NAO8", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "19065.0002", + shortDesc: "NA09", + longDesc: "Nanaimo Law Courts NAO9", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "19066.0002", + shortDesc: "NA10", + longDesc: "Nanaimo Law Courts NA10", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "19187.0734", + shortDesc: "COA", + longDesc: "B.C. Court of Appeal", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "19227.0734", + shortDesc: "5871", + longDesc: "100 Mile House Law Courts", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "19228.0734", + shortDesc: "6011", + longDesc: "Vancouver Law Courts", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "19247.0734", + shortDesc: "2041", + longDesc: "Justice Centre (Judicial)", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "19307.0734", + shortDesc: "2009", + longDesc: "Klemtu Provincial Court", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "19614.0734", + shortDesc: "SRES", + longDesc: "Shared Resource", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "19622.0734", + shortDesc: "CAVA", + longDesc: "Court of Appeal of BC - Vancouver", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "19625.0734", + shortDesc: "CAKA", + longDesc: "Court of Appeal of BC - Kamloops", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "19626.0734", + shortDesc: "CAKE", + longDesc: "Court of Appeal of BC - Kelowna", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "19627.0734", + shortDesc: "CAVI", + longDesc: "Court of Appeal of BC - Victoria", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "19635.0734", + shortDesc: "2049", + longDesc: "Violation Ticket Centre", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "19678.0734", + shortDesc: "KSS", + longDesc: "Kitsilano Secondary School", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "19679.0734", + shortDesc: "KPU", + longDesc: "Kwantlen Polytechnic University", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "22.0001", + shortDesc: "4671", + longDesc: "Ashcroft Provincial Court", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "23.0001", + shortDesc: "4681", + longDesc: "Castlegar Provincial Court", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "27.0001", + shortDesc: "4691", + longDesc: "Chase Provincial Court", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "28.0001", + shortDesc: "4701", + longDesc: "Clearwater Provincial Court", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "29.0001", + shortDesc: "4711", + longDesc: "Cranbrook Law Courts", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "77.0001", + shortDesc: "4721", + longDesc: "Creston Law Courts", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "78.0001", + shortDesc: "4731", + longDesc: "Fernie Law Courts", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "79.0001", + shortDesc: "4741", + longDesc: "Golden Law Court", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "80.0001", + shortDesc: "4751", + longDesc: "Grand Forks Law Courts", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "81.0001", + shortDesc: "4771", + longDesc: "Invermere Law Courts", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "82.0001", + shortDesc: "4781", + longDesc: "Kamloops Court", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "83.0001", + shortDesc: "4801", + longDesc: "Kelowna Law Courts", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "84.0001", + shortDesc: "4811", + longDesc: "Kimberley Provincial Court", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "85.0001", + shortDesc: "4821", + longDesc: "Lillooet Law Courts", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "87.0001", + shortDesc: "4851", + longDesc: "Merritt Law Court", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "88.0001", + shortDesc: "4861", + longDesc: "Nakusp Provincial Court", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "8805.0001", + shortDesc: "1091", + longDesc: "Nanaimo Law Courts", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "8807.0001", + shortDesc: "1201", + longDesc: "Victoria Law Courts", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "8813.0001", + shortDesc: "2040", + longDesc: "Vancouver Provincial Court", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "8823.0001", + shortDesc: "3511", + longDesc: "Burnaby Court", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "8824.0001", + shortDesc: "3521", + longDesc: "Chilliwack Law Courts", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "8834.0001", + shortDesc: "3531", + longDesc: "Port Coquitlam Court", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "8837.0001", + shortDesc: "3551", + longDesc: "Maple Ridge Provincial Court", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "8839.0001", + shortDesc: "3581", + longDesc: "New Westminster Law Courts", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "8841.0001", + shortDesc: "3585", + longDesc: "Surrey Provincial Court", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "8842.0001", + shortDesc: "3587", + longDesc: "Surrey Family Court", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "8844.0001", + shortDesc: "5891", + longDesc: "Prince George Law Courts", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "89.0001", + shortDesc: "4871", + longDesc: "Nelson Law Courts", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "90.0001", + shortDesc: "4881", + longDesc: "Oliver Law Courts", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "9062.0001", + shortDesc: "2025", + longDesc: "Richmond Provincial Court", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "9064.0001", + shortDesc: "2011", + longDesc: "North Vancouver Court", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "9066.0001", + shortDesc: "2010", + longDesc: "Delta Provincial Court", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "9067.0001", + shortDesc: "1031", + longDesc: "Campbell River Court", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "9068.0001", + shortDesc: "1041", + longDesc: "Courtenay Law Courts", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "9070.0001", + shortDesc: "5971", + longDesc: "Williams Lake Law Courts", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "9071.0001", + shortDesc: "5961", + longDesc: "Vanderhoof Law Courts", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "9072.0001", + shortDesc: "5951", + longDesc: "Terrace Law Courts", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "9073.0001", + shortDesc: "5931", + longDesc: "Smithers Law Courts", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "9074.0001", + shortDesc: "5921", + longDesc: "Quesnel Law Courts", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "9075.0001", + shortDesc: "5901", + longDesc: "Prince Rupert Law Courts", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "91.0001", + shortDesc: "4891", + longDesc: "Penticton Law Courts", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "9144.0001", + shortDesc: "5959", + longDesc: "Valemount Provincial Court", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "92.0001", + shortDesc: "4901", + longDesc: "Princeton Law Courts", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "93.0001", + shortDesc: "4911", + longDesc: "Revelstoke Law Courts", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "9393.0001", + shortDesc: "3561", + longDesc: "Abbotsford Law Courts", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "94.0001", + shortDesc: "4921", + longDesc: "Rossland Law Courts", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "95.0001", + shortDesc: "4941", + longDesc: "Salmon Arm Law Courts", + flex: "Y" + }, + { + codeType: "COURT_LOCATIONS", + code: "96.0001", + shortDesc: "4971", + longDesc: "Vernon Law Courts", + flex: "Y" + } + ]) + } +} diff --git a/aws/lambdas/locations/get-rooms/index.ts b/aws/lambdas/locations/get-rooms/index.ts new file mode 100644 index 00000000..814d99c9 --- /dev/null +++ b/aws/lambdas/locations/get-rooms/index.ts @@ -0,0 +1,1939 @@ +import { APIGatewayEvent, APIGatewayProxyResult, Context } from "aws-lambda" + +export const handler = async ( + event: APIGatewayEvent, + context: Context +): Promise => { + console.log(event, context) + + return { + statusCode: 200, + body: JSON.stringify([ + { + codeType: "COURT_ROOMS", + code: "00", + shortDesc: "CRT", + longDesc: "NIDD-00", + flex: "NIDD" + }, + { + codeType: "COURT_ROOMS", + code: "001", + shortDesc: "CRT", + longDesc: "1031-001", + flex: "1031" + }, + { + codeType: "COURT_ROOMS", + code: "001", + shortDesc: "CRT", + longDesc: "1051-001", + flex: "1051" + }, + { + codeType: "COURT_ROOMS", + code: "001", + shortDesc: "CRT", + longDesc: "1201-001", + flex: "1201" + }, + { + codeType: "COURT_ROOMS", + code: "001", + shortDesc: "CRT", + longDesc: "2007-001", + flex: "2007" + }, + { + codeType: "COURT_ROOMS", + code: "001", + shortDesc: "CRT", + longDesc: "2031-001", + flex: "2031" + }, + { + codeType: "COURT_ROOMS", + code: "001", + shortDesc: "CRT", + longDesc: "2040-001", + flex: "2040" + }, + { + codeType: "COURT_ROOMS", + code: "001", + shortDesc: "CRT", + longDesc: "2045-001", + flex: "2045" + }, + { + codeType: "COURT_ROOMS", + code: "001", + shortDesc: "CRT", + longDesc: "2048-001", + flex: "2048" + }, + { + codeType: "COURT_ROOMS", + code: "001", + shortDesc: "CRT", + longDesc: "3531-001", + flex: "3531" + }, + { + codeType: "COURT_ROOMS", + code: "001", + shortDesc: "CRT", + longDesc: "3551-001", + flex: "3551" + }, + { + codeType: "COURT_ROOMS", + code: "001", + shortDesc: "CRT", + longDesc: "3585-001", + flex: "3585" + }, + { + codeType: "COURT_ROOMS", + code: "001", + shortDesc: "CRT", + longDesc: "4681-001", + flex: "4681" + }, + { + codeType: "COURT_ROOMS", + code: "001", + shortDesc: "CRT", + longDesc: "4781-001", + flex: "4781" + }, + { + codeType: "COURT_ROOMS", + code: "001", + shortDesc: "CRT", + longDesc: "4801-001", + flex: "4801" + }, + { + codeType: "COURT_ROOMS", + code: "001", + shortDesc: "CRT", + longDesc: "4891-001", + flex: "4891" + }, + { + codeType: "COURT_ROOMS", + code: "001", + shortDesc: "CRT", + longDesc: "4901-001", + flex: "4901" + }, + { + codeType: "COURT_ROOMS", + code: "001", + shortDesc: "CRT", + longDesc: "4971-001", + flex: "4971" + }, + { + codeType: "COURT_ROOMS", + code: "001", + shortDesc: "CRT", + longDesc: "5671-001", + flex: "5671" + }, + { + codeType: "COURT_ROOMS", + code: "001", + shortDesc: "CRT", + longDesc: "5731-001", + flex: "5731" + }, + { + codeType: "COURT_ROOMS", + code: "001", + shortDesc: "CRT", + longDesc: "5971-001", + flex: "5971" + }, + { + codeType: "COURT_ROOMS", + code: "001", + shortDesc: "CRT", + longDesc: "6011-001", + flex: "6011" + }, + { + codeType: "COURT_ROOMS", + code: "001", + shortDesc: "CRT", + longDesc: "6012-001", + flex: "6012" + }, + { + codeType: "COURT_ROOMS", + code: "001", + shortDesc: "CRT", + longDesc: "702-001", + flex: "702" + }, + { + codeType: "COURT_ROOMS", + code: "001", + shortDesc: "CRT", + longDesc: "7999-001", + flex: "7999" + }, + { + codeType: "COURT_ROOMS", + code: "001", + shortDesc: "CRT", + longDesc: "ADJU-001", + flex: "ADJU" + }, + { + codeType: "COURT_ROOMS", + code: "001", + shortDesc: "CRT", + longDesc: "CAKE-001", + flex: "CAKE" + }, + { + codeType: "COURT_ROOMS", + code: "001", + shortDesc: "CRT", + longDesc: "CAVA-001", + flex: "CAVA" + }, + { + codeType: "COURT_ROOMS", + code: "001", + shortDesc: "CRT", + longDesc: "LECR-001", + flex: "LECR" + }, + { + codeType: "COURT_ROOMS", + code: "001", + shortDesc: "CRT", + longDesc: "SHER-001", + flex: "SHER" + }, + { + codeType: "COURT_ROOMS", + code: "001", + shortDesc: "VCR", + longDesc: "KAIN-001", + flex: "KAIN" + }, + { + codeType: "COURT_ROOMS", + code: "002", + shortDesc: "CRT", + longDesc: "1201-002", + flex: "1201" + }, + { + codeType: "COURT_ROOMS", + code: "002", + shortDesc: "CRT", + longDesc: "2007-002", + flex: "2007" + }, + { + codeType: "COURT_ROOMS", + code: "002", + shortDesc: "CRT", + longDesc: "2040-002", + flex: "2040" + }, + { + codeType: "COURT_ROOMS", + code: "002", + shortDesc: "CRT", + longDesc: "2048-002", + flex: "2048" + }, + { + codeType: "COURT_ROOMS", + code: "002", + shortDesc: "CRT", + longDesc: "3531-002", + flex: "3531" + }, + { + codeType: "COURT_ROOMS", + code: "002", + shortDesc: "CRT", + longDesc: "3551-002", + flex: "3551" + }, + { + codeType: "COURT_ROOMS", + code: "002", + shortDesc: "CRT", + longDesc: "3585-002", + flex: "3585" + }, + { + codeType: "COURT_ROOMS", + code: "002", + shortDesc: "CRT", + longDesc: "4711-002", + flex: "4711" + }, + { + codeType: "COURT_ROOMS", + code: "002", + shortDesc: "CRT", + longDesc: "4781-002", + flex: "4781" + }, + { + codeType: "COURT_ROOMS", + code: "002", + shortDesc: "CRT", + longDesc: "4801-002", + flex: "4801" + }, + { + codeType: "COURT_ROOMS", + code: "002", + shortDesc: "CRT", + longDesc: "4971-002", + flex: "4971" + }, + { + codeType: "COURT_ROOMS", + code: "002", + shortDesc: "CRT", + longDesc: "5671-002", + flex: "5671" + }, + { + codeType: "COURT_ROOMS", + code: "002", + shortDesc: "CRT", + longDesc: "6011-002", + flex: "6011" + }, + { + codeType: "COURT_ROOMS", + code: "002", + shortDesc: "CRT", + longDesc: "6012-002", + flex: "6012" + }, + { + codeType: "COURT_ROOMS", + code: "002", + shortDesc: "CRT", + longDesc: "7999-002", + flex: "7999" + }, + { + codeType: "COURT_ROOMS", + code: "002", + shortDesc: "CRT", + longDesc: "LECR-002", + flex: "LECR" + }, + { + codeType: "COURT_ROOMS", + code: "003", + shortDesc: "CRT", + longDesc: "1201-003", + flex: "1201" + }, + { + codeType: "COURT_ROOMS", + code: "003", + shortDesc: "CRT", + longDesc: "2007-003", + flex: "2007" + }, + { + codeType: "COURT_ROOMS", + code: "003", + shortDesc: "CRT", + longDesc: "2040-003", + flex: "2040" + }, + { + codeType: "COURT_ROOMS", + code: "003", + shortDesc: "CRT", + longDesc: "2048-003", + flex: "2048" + }, + { + codeType: "COURT_ROOMS", + code: "003", + shortDesc: "CRT", + longDesc: "3531-003", + flex: "3531" + }, + { + codeType: "COURT_ROOMS", + code: "003", + shortDesc: "CRT", + longDesc: "3551-003", + flex: "3551" + }, + { + codeType: "COURT_ROOMS", + code: "003", + shortDesc: "CRT", + longDesc: "4801-003", + flex: "4801" + }, + { + codeType: "COURT_ROOMS", + code: "003", + shortDesc: "CRT", + longDesc: "4971-003", + flex: "4971" + }, + { + codeType: "COURT_ROOMS", + code: "003", + shortDesc: "CRT", + longDesc: "5671-003", + flex: "5671" + }, + { + codeType: "COURT_ROOMS", + code: "003", + shortDesc: "CRT", + longDesc: "7999-003", + flex: "7999" + }, + { + codeType: "COURT_ROOMS", + code: "003", + shortDesc: "CRT", + longDesc: "LECR-003", + flex: "LECR" + }, + { + codeType: "COURT_ROOMS", + code: "004", + shortDesc: "CRT", + longDesc: "1201-004", + flex: "1201" + }, + { + codeType: "COURT_ROOMS", + code: "004", + shortDesc: "CRT", + longDesc: "2007-004", + flex: "2007" + }, + { + codeType: "COURT_ROOMS", + code: "004", + shortDesc: "CRT", + longDesc: "2040-004", + flex: "2040" + }, + { + codeType: "COURT_ROOMS", + code: "004", + shortDesc: "CRT", + longDesc: "3531-004", + flex: "3531" + }, + { + codeType: "COURT_ROOMS", + code: "004", + shortDesc: "CRT", + longDesc: "3551-004", + flex: "3551" + }, + { + codeType: "COURT_ROOMS", + code: "004", + shortDesc: "CRT", + longDesc: "4801-004", + flex: "4801" + }, + { + codeType: "COURT_ROOMS", + code: "004", + shortDesc: "CRT", + longDesc: "4971-004", + flex: "4971" + }, + { + codeType: "COURT_ROOMS", + code: "004", + shortDesc: "CRT", + longDesc: "7999-004", + flex: "7999" + }, + { + codeType: "COURT_ROOMS", + code: "004", + shortDesc: "CRT", + longDesc: "LECR-004", + flex: "LECR" + }, + { + codeType: "COURT_ROOMS", + code: "005", + shortDesc: "CRT", + longDesc: "2007-005", + flex: "2007" + }, + { + codeType: "COURT_ROOMS", + code: "005", + shortDesc: "CRT", + longDesc: "2040-005", + flex: "2040" + }, + { + codeType: "COURT_ROOMS", + code: "005", + shortDesc: "CRT", + longDesc: "3531-005", + flex: "3531" + }, + { + codeType: "COURT_ROOMS", + code: "005", + shortDesc: "CRT", + longDesc: "3551-005", + flex: "3551" + }, + { + codeType: "COURT_ROOMS", + code: "005", + shortDesc: "CRT", + longDesc: "4801-005", + flex: "4801" + }, + { + codeType: "COURT_ROOMS", + code: "005", + shortDesc: "CRT", + longDesc: "4971-005", + flex: "4971" + }, + { + codeType: "COURT_ROOMS", + code: "005", + shortDesc: "CRT", + longDesc: "7999-005", + flex: "7999" + }, + { + codeType: "COURT_ROOMS", + code: "005", + shortDesc: "CRT", + longDesc: "LECR-005", + flex: "LECR" + }, + { + codeType: "COURT_ROOMS", + code: "006", + shortDesc: "CRT", + longDesc: "2007-006", + flex: "2007" + }, + { + codeType: "COURT_ROOMS", + code: "006", + shortDesc: "CRT", + longDesc: "3531-006", + flex: "3531" + }, + { + codeType: "COURT_ROOMS", + code: "006", + shortDesc: "CRT", + longDesc: "3551-006", + flex: "3551" + }, + { + codeType: "COURT_ROOMS", + code: "006", + shortDesc: "CRT", + longDesc: "4801-006", + flex: "4801" + }, + { + codeType: "COURT_ROOMS", + code: "006", + shortDesc: "CRT", + longDesc: "4971-006", + flex: "4971" + }, + { + codeType: "COURT_ROOMS", + code: "006", + shortDesc: "CRT", + longDesc: "7999-006", + flex: "7999" + }, + { + codeType: "COURT_ROOMS", + code: "006", + shortDesc: "CRT", + longDesc: "LECR-006", + flex: "LECR" + }, + { + codeType: "COURT_ROOMS", + code: "007", + shortDesc: "CRT", + longDesc: "2007-007", + flex: "2007" + }, + { + codeType: "COURT_ROOMS", + code: "007", + shortDesc: "CRT", + longDesc: "3531-007", + flex: "3531" + }, + { + codeType: "COURT_ROOMS", + code: "007", + shortDesc: "CRT", + longDesc: "3551-007", + flex: "3551" + }, + { + codeType: "COURT_ROOMS", + code: "007", + shortDesc: "CRT", + longDesc: "4801-007", + flex: "4801" + }, + { + codeType: "COURT_ROOMS", + code: "007", + shortDesc: "CRT", + longDesc: "4971-007", + flex: "4971" + }, + { + codeType: "COURT_ROOMS", + code: "007", + shortDesc: "CRT", + longDesc: "7999-007", + flex: "7999" + }, + { + codeType: "COURT_ROOMS", + code: "007", + shortDesc: "CRT", + longDesc: "LECR-007", + flex: "LECR" + }, + { + codeType: "COURT_ROOMS", + code: "008", + shortDesc: "CRT", + longDesc: "2007-008", + flex: "2007" + }, + { + codeType: "COURT_ROOMS", + code: "008", + shortDesc: "CRT", + longDesc: "3531-008", + flex: "3531" + }, + { + codeType: "COURT_ROOMS", + code: "008", + shortDesc: "CRT", + longDesc: "3551-008", + flex: "3551" + }, + { + codeType: "COURT_ROOMS", + code: "008", + shortDesc: "CRT", + longDesc: "7999-008", + flex: "7999" + }, + { + codeType: "COURT_ROOMS", + code: "008", + shortDesc: "CRT", + longDesc: "LECR-008", + flex: "LECR" + }, + { + codeType: "COURT_ROOMS", + code: "008", + shortDesc: "WTM", + longDesc: "4801-008", + flex: "4801" + }, + { + codeType: "COURT_ROOMS", + code: "008", + shortDesc: "WTM", + longDesc: "4971-008", + flex: "4971" + }, + { + codeType: "COURT_ROOMS", + code: "009", + shortDesc: "CRT", + longDesc: "2007-009", + flex: "2007" + }, + { + codeType: "COURT_ROOMS", + code: "009", + shortDesc: "CRT", + longDesc: "3531-009", + flex: "3531" + }, + { + codeType: "COURT_ROOMS", + code: "009", + shortDesc: "CRT", + longDesc: "3551-009", + flex: "3551" + }, + { + codeType: "COURT_ROOMS", + code: "009", + shortDesc: "CRT", + longDesc: "4801-009", + flex: "4801" + }, + { + codeType: "COURT_ROOMS", + code: "009", + shortDesc: "CRT", + longDesc: "4891-009", + flex: "4891" + }, + { + codeType: "COURT_ROOMS", + code: "009", + shortDesc: "CRT", + longDesc: "4971-009", + flex: "4971" + }, + { + codeType: "COURT_ROOMS", + code: "009", + shortDesc: "CRT", + longDesc: "7999-009", + flex: "7999" + }, + { + codeType: "COURT_ROOMS", + code: "009", + shortDesc: "CRT", + longDesc: "LECR-009", + flex: "LECR" + }, + { + codeType: "COURT_ROOMS", + code: "010", + shortDesc: "CRT", + longDesc: "3531-010", + flex: "3531" + }, + { + codeType: "COURT_ROOMS", + code: "010", + shortDesc: "CRT", + longDesc: "7999-010", + flex: "7999" + }, + { + codeType: "COURT_ROOMS", + code: "010", + shortDesc: "WTM", + longDesc: "4801-010", + flex: "4801" + }, + { + codeType: "COURT_ROOMS", + code: "010", + shortDesc: "WTM", + longDesc: "4971-010", + flex: "4971" + }, + { + codeType: "COURT_ROOMS", + code: "011", + shortDesc: "CRT", + longDesc: "3531-011", + flex: "3531" + }, + { + codeType: "COURT_ROOMS", + code: "011", + shortDesc: "CRT", + longDesc: "4801-011", + flex: "4801" + }, + { + codeType: "COURT_ROOMS", + code: "011", + shortDesc: "CRT", + longDesc: "7999-011", + flex: "7999" + }, + { + codeType: "COURT_ROOMS", + code: "012", + shortDesc: "CRT", + longDesc: "3531-012", + flex: "3531" + }, + { + codeType: "COURT_ROOMS", + code: "012", + shortDesc: "CRT", + longDesc: "4801-012", + flex: "4801" + }, + { + codeType: "COURT_ROOMS", + code: "012", + shortDesc: "CRT", + longDesc: "7999-012", + flex: "7999" + }, + { + codeType: "COURT_ROOMS", + code: "013", + shortDesc: "CRT", + longDesc: "4801-013", + flex: "4801" + }, + { + codeType: "COURT_ROOMS", + code: "014", + shortDesc: "CRT", + longDesc: "4801-014", + flex: "4801" + }, + { + codeType: "COURT_ROOMS", + code: "014", + shortDesc: "CRT", + longDesc: "7999-014", + flex: "7999" + }, + { + codeType: "COURT_ROOMS", + code: "015", + shortDesc: "CRT", + longDesc: "4801-015", + flex: "4801" + }, + { + codeType: "COURT_ROOMS", + code: "016", + shortDesc: "CRT", + longDesc: "4801-016", + flex: "4801" + }, + { + codeType: "COURT_ROOMS", + code: "017", + shortDesc: "CRT", + longDesc: "4801-017", + flex: "4801" + }, + { + codeType: "COURT_ROOMS", + code: "018", + shortDesc: "CRT", + longDesc: "4801-018", + flex: "4801" + }, + { + codeType: "COURT_ROOMS", + code: "019", + shortDesc: "CRT", + longDesc: "4801-019", + flex: "4801" + }, + { + codeType: "COURT_ROOMS", + code: "021", + shortDesc: "CRT", + longDesc: "4801-021", + flex: "4801" + }, + { + codeType: "COURT_ROOMS", + code: "022", + shortDesc: "CRT", + longDesc: "4801-022", + flex: "4801" + }, + { + codeType: "COURT_ROOMS", + code: "023", + shortDesc: "CRT", + longDesc: "4801-023", + flex: "4801" + }, + { + codeType: "COURT_ROOMS", + code: "024", + shortDesc: "CRT", + longDesc: "4801-024", + flex: "4801" + }, + { + codeType: "COURT_ROOMS", + code: "025", + shortDesc: "CRT", + longDesc: "4801-025", + flex: "4801" + }, + { + codeType: "COURT_ROOMS", + code: "026", + shortDesc: "CRT", + longDesc: "4801-026", + flex: "4801" + }, + { + codeType: "COURT_ROOMS", + code: "027", + shortDesc: "CRT", + longDesc: "4801-027", + flex: "4801" + }, + { + codeType: "COURT_ROOMS", + code: "028", + shortDesc: "CRT", + longDesc: "4801-028", + flex: "4801" + }, + { + codeType: "COURT_ROOMS", + code: "029", + shortDesc: "CRT", + longDesc: "4801-029", + flex: "4801" + }, + { + codeType: "COURT_ROOMS", + code: "031", + shortDesc: "CRT", + longDesc: "4801-031", + flex: "4801" + }, + { + codeType: "COURT_ROOMS", + code: "032", + shortDesc: "CRT", + longDesc: "4801-032", + flex: "4801" + }, + { + codeType: "COURT_ROOMS", + code: "033", + shortDesc: "CRT", + longDesc: "4801-033", + flex: "4801" + }, + { + codeType: "COURT_ROOMS", + code: "034", + shortDesc: "CRT", + longDesc: "4801-034", + flex: "4801" + }, + { + codeType: "COURT_ROOMS", + code: "035", + shortDesc: "CRT", + longDesc: "4801-035", + flex: "4801" + }, + { + codeType: "COURT_ROOMS", + code: "036", + shortDesc: "CRT", + longDesc: "4801-036", + flex: "4801" + }, + { + codeType: "COURT_ROOMS", + code: "037", + shortDesc: "CRT", + longDesc: "4801-037", + flex: "4801" + }, + { + codeType: "COURT_ROOMS", + code: "038", + shortDesc: "CRT", + longDesc: "4801-038", + flex: "4801" + }, + { + codeType: "COURT_ROOMS", + code: "039", + shortDesc: "CRT", + longDesc: "4801-039", + flex: "4801" + }, + { + codeType: "COURT_ROOMS", + code: "041", + shortDesc: "CRT", + longDesc: "4801-041", + flex: "4801" + }, + { + codeType: "COURT_ROOMS", + code: "042", + shortDesc: "CRT", + longDesc: "4801-042", + flex: "4801" + }, + { + codeType: "COURT_ROOMS", + code: "043", + shortDesc: "CRT", + longDesc: "4801-043", + flex: "4801" + }, + { + codeType: "COURT_ROOMS", + code: "044", + shortDesc: "CRT", + longDesc: "4801-044", + flex: "4801" + }, + { + codeType: "COURT_ROOMS", + code: "045", + shortDesc: "CRT", + longDesc: "4801-045", + flex: "4801" + }, + { + codeType: "COURT_ROOMS", + code: "046", + shortDesc: "CRT", + longDesc: "4801-046", + flex: "4801" + }, + { + codeType: "COURT_ROOMS", + code: "047", + shortDesc: "CRT", + longDesc: "4801-047", + flex: "4801" + }, + { + codeType: "COURT_ROOMS", + code: "048", + shortDesc: "CRT", + longDesc: "4801-048", + flex: "4801" + }, + { + codeType: "COURT_ROOMS", + code: "049", + shortDesc: "CRT", + longDesc: "4801-049", + flex: "4801" + }, + { + codeType: "COURT_ROOMS", + code: "051", + shortDesc: "CRT", + longDesc: "4801-051", + flex: "4801" + }, + { + codeType: "COURT_ROOMS", + code: "052", + shortDesc: "CRT", + longDesc: "4801-052", + flex: "4801" + }, + { + codeType: "COURT_ROOMS", + code: "053", + shortDesc: "CRT", + longDesc: "4801-053", + flex: "4801" + }, + { + codeType: "COURT_ROOMS", + code: "054", + shortDesc: "CRT", + longDesc: "4801-054", + flex: "4801" + }, + { + codeType: "COURT_ROOMS", + code: "055", + shortDesc: "CRT", + longDesc: "4801-055", + flex: "4801" + }, + { + codeType: "COURT_ROOMS", + code: "1", + shortDesc: "CRT", + longDesc: "4821-1", + flex: "4821" + }, + { + codeType: "COURT_ROOMS", + code: "10", + shortDesc: "CRT", + longDesc: "4821-10", + flex: "4821" + }, + { + codeType: "COURT_ROOMS", + code: "100", + shortDesc: "CRT", + longDesc: "1201-100", + flex: "1201" + }, + { + codeType: "COURT_ROOMS", + code: "100", + shortDesc: "CRT", + longDesc: "3585-100", + flex: "3585" + }, + { + codeType: "COURT_ROOMS", + code: "100", + shortDesc: "CRT", + longDesc: "5961-100", + flex: "5961" + }, + { + codeType: "COURT_ROOMS", + code: "100", + shortDesc: "MTG", + longDesc: "KCCA-100", + flex: "KCCA" + }, + { + codeType: "COURT_ROOMS", + code: "101", + shortDesc: "CRT", + longDesc: "1091-101", + flex: "1091" + }, + { + codeType: "COURT_ROOMS", + code: "101", + shortDesc: "CRT", + longDesc: "3585-101", + flex: "3585" + }, + { + codeType: "COURT_ROOMS", + code: "101", + shortDesc: "CRT", + longDesc: "4801-101", + flex: "4801" + }, + { + codeType: "COURT_ROOMS", + code: "101", + shortDesc: "CRT", + longDesc: "4971-101", + flex: "4971" + }, + { + codeType: "COURT_ROOMS", + code: "101", + shortDesc: "CRT", + longDesc: "5961-101", + flex: "5961" + }, + { + codeType: "COURT_ROOMS", + code: "101", + shortDesc: "CRT", + longDesc: "NA01-101", + flex: "NA01" + }, + { + codeType: "COURT_ROOMS", + code: "101", + shortDesc: "CRT", + longDesc: "NA02-101", + flex: "NA02" + }, + { + codeType: "COURT_ROOMS", + code: "101", + shortDesc: "CRT", + longDesc: "NA03-101", + flex: "NA03" + }, + { + codeType: "COURT_ROOMS", + code: "101", + shortDesc: "CRT", + longDesc: "NA04-101", + flex: "NA04" + }, + { + codeType: "COURT_ROOMS", + code: "101", + shortDesc: "CRT", + longDesc: "NA05-101", + flex: "NA05" + }, + { + codeType: "COURT_ROOMS", + code: "101", + shortDesc: "CRT", + longDesc: "NA06-101", + flex: "NA06" + }, + { + codeType: "COURT_ROOMS", + code: "101", + shortDesc: "CRT", + longDesc: "NA07-101", + flex: "NA07" + }, + { + codeType: "COURT_ROOMS", + code: "101", + shortDesc: "CRT", + longDesc: "NA08-101", + flex: "NA08" + }, + { + codeType: "COURT_ROOMS", + code: "101", + shortDesc: "CRT", + longDesc: "NA09-101", + flex: "NA09" + }, + { + codeType: "COURT_ROOMS", + code: "101", + shortDesc: "CRT", + longDesc: "NA10-101", + flex: "NA10" + }, + { + codeType: "COURT_ROOMS", + code: "102", + shortDesc: "CRT", + longDesc: "1091-102", + flex: "1091" + }, + { + codeType: "COURT_ROOMS", + code: "102", + shortDesc: "CRT", + longDesc: "5961-102", + flex: "5961" + }, + { + codeType: "COURT_ROOMS", + code: "102", + shortDesc: "CRT", + longDesc: "NA01-102", + flex: "NA01" + }, + { + codeType: "COURT_ROOMS", + code: "102", + shortDesc: "CRT", + longDesc: "NA02-102", + flex: "NA02" + }, + { + codeType: "COURT_ROOMS", + code: "102", + shortDesc: "CRT", + longDesc: "NA03-102", + flex: "NA03" + }, + { + codeType: "COURT_ROOMS", + code: "102", + shortDesc: "CRT", + longDesc: "NA04-102", + flex: "NA04" + }, + { + codeType: "COURT_ROOMS", + code: "102", + shortDesc: "CRT", + longDesc: "NA05-102", + flex: "NA05" + }, + { + codeType: "COURT_ROOMS", + code: "102", + shortDesc: "CRT", + longDesc: "NA06-102", + flex: "NA06" + }, + { + codeType: "COURT_ROOMS", + code: "102", + shortDesc: "CRT", + longDesc: "NA07-102", + flex: "NA07" + }, + { + codeType: "COURT_ROOMS", + code: "102", + shortDesc: "CRT", + longDesc: "NA08-102", + flex: "NA08" + }, + { + codeType: "COURT_ROOMS", + code: "102", + shortDesc: "CRT", + longDesc: "NA09-102", + flex: "NA09" + }, + { + codeType: "COURT_ROOMS", + code: "102", + shortDesc: "CRT", + longDesc: "NA10-102", + flex: "NA10" + }, + { + codeType: "COURT_ROOMS", + code: "103", + shortDesc: "CRT", + longDesc: "3585-103", + flex: "3585" + }, + { + codeType: "COURT_ROOMS", + code: "103", + shortDesc: "CRT", + longDesc: "5961-103", + flex: "5961" + }, + { + codeType: "COURT_ROOMS", + code: "104", + shortDesc: "CRT", + longDesc: "5961-104", + flex: "5961" + }, + { + codeType: "COURT_ROOMS", + code: "104", + shortDesc: "CRT", + longDesc: "KSS-104", + flex: "KSS" + }, + { + codeType: "COURT_ROOMS", + code: "105", + shortDesc: "CRT", + longDesc: "2040-105", + flex: "2040" + }, + { + codeType: "COURT_ROOMS", + code: "105", + shortDesc: "CRT", + longDesc: "5961-105", + flex: "5961" + }, + { + codeType: "COURT_ROOMS", + code: "11", + shortDesc: "CRT", + longDesc: "4821-11", + flex: "4821" + }, + { + codeType: "COURT_ROOMS", + code: "12", + shortDesc: "CRT", + longDesc: "4821-12", + flex: "4821" + }, + { + codeType: "COURT_ROOMS", + code: "120", + shortDesc: "CRT", + longDesc: "4971-120", + flex: "4971" + }, + { + codeType: "COURT_ROOMS", + code: "1205A", + shortDesc: "CRT", + longDesc: "KPU-1205A", + flex: "KPU" + }, + { + codeType: "COURT_ROOMS", + code: "1205C", + shortDesc: "CRT", + longDesc: "KPU-1205C", + flex: "KPU" + }, + { + codeType: "COURT_ROOMS", + code: "125", + shortDesc: "CRT", + longDesc: "1051-125", + flex: "1051" + }, + { + codeType: "COURT_ROOMS", + code: "12A", + shortDesc: "CRT", + longDesc: "2040-12A", + flex: "2040" + }, + { + codeType: "COURT_ROOMS", + code: "130", + shortDesc: "CRT", + longDesc: "KSS-130", + flex: "KSS" + }, + { + codeType: "COURT_ROOMS", + code: "132", + shortDesc: "CRT", + longDesc: "KSS-132", + flex: "KSS" + }, + { + codeType: "COURT_ROOMS", + code: "2", + shortDesc: "CRT", + longDesc: "4821-2", + flex: "4821" + }, + { + codeType: "COURT_ROOMS", + code: "200", + shortDesc: "CRT", + longDesc: "2040-200", + flex: "2040" + }, + { + codeType: "COURT_ROOMS", + code: "200", + shortDesc: "CRT", + longDesc: "5961-200", + flex: "5961" + }, + { + codeType: "COURT_ROOMS", + code: "200", + shortDesc: "CRT", + longDesc: "6011-200", + flex: "6011" + }, + { + codeType: "COURT_ROOMS", + code: "201", + shortDesc: "CRT", + longDesc: "3561-201", + flex: "3561" + }, + { + codeType: "COURT_ROOMS", + code: "201", + shortDesc: "CRT", + longDesc: "5961-201", + flex: "5961" + }, + { + codeType: "COURT_ROOMS", + code: "202", + shortDesc: "CRT", + longDesc: "3561-202", + flex: "3561" + }, + { + codeType: "COURT_ROOMS", + code: "202", + shortDesc: "CRT", + longDesc: "5961-202", + flex: "5961" + }, + { + codeType: "COURT_ROOMS", + code: "203", + shortDesc: "CRT", + longDesc: "3561-203", + flex: "3561" + }, + { + codeType: "COURT_ROOMS", + code: "204", + shortDesc: "HGR", + longDesc: "6011-204", + flex: "6011" + }, + { + codeType: "COURT_ROOMS", + code: "218", + shortDesc: "CRT", + longDesc: "5771-218", + flex: "5771" + }, + { + codeType: "COURT_ROOMS", + code: "220", + shortDesc: "SCR", + longDesc: "6011-220", + flex: "6011" + }, + { + codeType: "COURT_ROOMS", + code: "3", + shortDesc: "CRT", + longDesc: "4821-3", + flex: "4821" + }, + { + codeType: "COURT_ROOMS", + code: "300", + shortDesc: "CRT", + longDesc: "2040-300", + flex: "2040" + }, + { + codeType: "COURT_ROOMS", + code: "300", + shortDesc: "CRT", + longDesc: "4971-300", + flex: "4971" + }, + { + codeType: "COURT_ROOMS", + code: "300", + shortDesc: "CRT", + longDesc: "5961-300", + flex: "5961" + }, + { + codeType: "COURT_ROOMS", + code: "301", + shortDesc: "CRT", + longDesc: "1201-301", + flex: "1201" + }, + { + codeType: "COURT_ROOMS", + code: "302", + shortDesc: "CRT", + longDesc: "1201-302", + flex: "1201" + }, + { + codeType: "COURT_ROOMS", + code: "303", + shortDesc: "CRT", + longDesc: "1201-303", + flex: "1201" + }, + { + codeType: "COURT_ROOMS", + code: "311", + shortDesc: "CRT", + longDesc: "3585-311", + flex: "3585" + }, + { + codeType: "COURT_ROOMS", + code: "4", + shortDesc: "CRT", + longDesc: "4821-4", + flex: "4821" + }, + { + codeType: "COURT_ROOMS", + code: "401", + shortDesc: "CRT", + longDesc: "1201-401", + flex: "1201" + }, + { + codeType: "COURT_ROOMS", + code: "402", + shortDesc: "CRT", + longDesc: "1201-402", + flex: "1201" + }, + { + codeType: "COURT_ROOMS", + code: "403", + shortDesc: "CRT", + longDesc: "1201-403", + flex: "1201" + }, + { + codeType: "COURT_ROOMS", + code: "411", + shortDesc: "CRT", + longDesc: "3581-411", + flex: "3581" + }, + { + codeType: "COURT_ROOMS", + code: "45534", + shortDesc: "CRT", + longDesc: "4971-45534", + flex: "4971" + }, + { + codeType: "COURT_ROOMS", + code: "5", + shortDesc: "CRT", + longDesc: "4821-5", + flex: "4821" + }, + { + codeType: "COURT_ROOMS", + code: "500", + shortDesc: "CRT", + longDesc: "4971-500", + flex: "4971" + }, + { + codeType: "COURT_ROOMS", + code: "512", + shortDesc: "CRT", + longDesc: "7999-512", + flex: "7999" + }, + { + codeType: "COURT_ROOMS", + code: "533", + shortDesc: "HGR", + longDesc: "1201-533", + flex: "1201" + }, + { + codeType: "COURT_ROOMS", + code: "6", + shortDesc: "CRT", + longDesc: "4821-6", + flex: "4821" + }, + { + codeType: "COURT_ROOMS", + code: "7", + shortDesc: "CRT", + longDesc: "4821-7", + flex: "4821" + }, + { + codeType: "COURT_ROOMS", + code: "766", + shortDesc: "CRT", + longDesc: "4971-766", + flex: "4971" + }, + { + codeType: "COURT_ROOMS", + code: "8", + shortDesc: "CRT", + longDesc: "4821-8", + flex: "4821" + }, + { + codeType: "COURT_ROOMS", + code: "9", + shortDesc: "CRT", + longDesc: "4821-9", + flex: "4821" + }, + { + codeType: "COURT_ROOMS", + code: "900", + shortDesc: "CRT", + longDesc: "2040-900", + flex: "2040" + }, + { + codeType: "COURT_ROOMS", + code: "999", + shortDesc: "CRT", + longDesc: "3551-999", + flex: "3551" + }, + { + codeType: "COURT_ROOMS", + code: "999", + shortDesc: "CRT", + longDesc: "7999-999", + flex: "7999" + }, + { + codeType: "COURT_ROOMS", + code: "BLAH", + shortDesc: "CRT", + longDesc: "4801-BLAH", + flex: "4801" + }, + { + codeType: "COURT_ROOMS", + code: "BLAH", + shortDesc: "CRT", + longDesc: "4971-BLAH", + flex: "4971" + }, + { + codeType: "COURT_ROOMS", + code: "CHB", + shortDesc: "CRT", + longDesc: "1201-CHB", + flex: "1201" + }, + { + codeType: "COURT_ROOMS", + code: "JCM", + shortDesc: "ADM", + longDesc: "3585-JCM", + flex: "3585" + }, + { + codeType: "COURT_ROOMS", + code: "JCM", + shortDesc: "CRT", + longDesc: "4801-JCM", + flex: "4801" + }, + { + codeType: "COURT_ROOMS", + code: "JJP1", + shortDesc: "CRT", + longDesc: "2041-JJP1", + flex: "2041" + }, + { + codeType: "COURT_ROOMS", + code: "JJP2", + shortDesc: "CRT", + longDesc: "2041-JJP2", + flex: "2041" + }, + { + codeType: "COURT_ROOMS", + code: "JJP3", + shortDesc: "CRT", + longDesc: "2041-JJP3", + flex: "2041" + }, + { + codeType: "COURT_ROOMS", + code: "JJP4", + shortDesc: "CRT", + longDesc: "2041-JJP4", + flex: "2041" + }, + { + codeType: "COURT_ROOMS", + code: "JUNK", + shortDesc: "CRT", + longDesc: "4801-JUNK", + flex: "4801" + }, + { + codeType: "COURT_ROOMS", + code: "JUNK", + shortDesc: "CRT", + longDesc: "4971-JUNK", + flex: "4971" + }, + { + codeType: "COURT_ROOMS", + code: "NA", + shortDesc: "CRT", + longDesc: "SRES-NA", + flex: "SRES" + }, + { + codeType: "COURT_ROOMS", + code: "OTH", + shortDesc: "CRT", + longDesc: "4801-OTH", + flex: "4801" + }, + { + codeType: "COURT_ROOMS", + code: "RED", + shortDesc: "CRT", + longDesc: "4971-RED", + flex: "4971" + }, + { + codeType: "COURT_ROOMS", + code: "REG", + shortDesc: "CRT", + longDesc: "1201-REG", + flex: "1201" + }, + { + codeType: "COURT_ROOMS", + code: "REG", + shortDesc: "CRT", + longDesc: "1207-REG", + flex: "1207" + }, + { + codeType: "COURT_ROOMS", + code: "REG", + shortDesc: "CRT", + longDesc: "2007-REG", + flex: "2007" + }, + { + codeType: "COURT_ROOMS", + code: "REG", + shortDesc: "CRT", + longDesc: "2040-REG", + flex: "2040" + }, + { + codeType: "COURT_ROOMS", + code: "REG", + shortDesc: "CRT", + longDesc: "2045-REG", + flex: "2045" + }, + { + codeType: "COURT_ROOMS", + code: "REG", + shortDesc: "CRT", + longDesc: "3531-REG", + flex: "3531" + }, + { + codeType: "COURT_ROOMS", + code: "REG", + shortDesc: "CRT", + longDesc: "3551-REG", + flex: "3551" + }, + { + codeType: "COURT_ROOMS", + code: "REG", + shortDesc: "CRT", + longDesc: "3585-REG", + flex: "3585" + }, + { + codeType: "COURT_ROOMS", + code: "REG", + shortDesc: "CRT", + longDesc: "4801-REG", + flex: "4801" + }, + { + codeType: "COURT_ROOMS", + code: "REG", + shortDesc: "CRT", + longDesc: "4971-REG", + flex: "4971" + }, + { + codeType: "COURT_ROOMS", + code: "REG", + shortDesc: "CRT", + longDesc: "6011-REG", + flex: "6011" + }, + { + codeType: "COURT_ROOMS", + code: "REG", + shortDesc: "CRT", + longDesc: "7999-REG", + flex: "7999" + }, + { + codeType: "COURT_ROOMS", + code: "TAC", + shortDesc: "WTM", + longDesc: "2040-TAC", + flex: "2040" + }, + { + codeType: "COURT_ROOMS", + code: "TD", + shortDesc: "CRT", + longDesc: "2045-TD", + flex: "2045" + }, + { + codeType: "COURT_ROOMS", + code: "TEST", + shortDesc: "CRT", + longDesc: "4801-TEST", + flex: "4801" + }, + { + codeType: "COURT_ROOMS", + code: "TEST", + shortDesc: "CRT", + longDesc: "4971-TEST", + flex: "4971" + }, + { + codeType: "COURT_ROOMS", + code: "TMP", + shortDesc: "CRT", + longDesc: "4801-TMP", + flex: "4801" + }, + { + codeType: "COURT_ROOMS", + code: "VC", + shortDesc: "VCR", + longDesc: "C402-VC", + flex: "C402" + }, + { + codeType: "COURT_ROOMS", + code: "VR1", + shortDesc: "CRT", + longDesc: "4801-VR1", + flex: "4801" + }, + { + codeType: "COURT_ROOMS", + code: "VR1", + shortDesc: "CRT", + longDesc: "5971-VR1", + flex: "5971" + }, + { + codeType: "COURT_ROOMS", + code: "VR2", + shortDesc: "CRT", + longDesc: "5971-VR2", + flex: "5971" + } + ]) + } +} diff --git a/aws/package.json b/aws/package.json new file mode 100644 index 00000000..945c8bfc --- /dev/null +++ b/aws/package.json @@ -0,0 +1,27 @@ +{ + "name": "aws", + "version": "1.0.0", + "description": "Contains lambda functions that calls BCGOV API endpoints.", + "main": "index.js", + "scripts": { + "build": "node esbuild.config.js", + "lint": "eslint ." + }, + "author": "JASPER team", + "license": "ISC", + "devDependencies": { + "@types/aws-lambda": "^8.10.145", + "@types/axios": "^0.9.36", + "@types/node": "^22.9.0", + "@typescript-eslint/eslint-plugin": "^8.14.0", + "@typescript-eslint/parser": "^8.14.0", + "esbuild": "^0.24.0", + "eslint": "^9.14.0", + "eslint-define-config": "^2.1.0" + }, + "dependencies": { + "@aws-sdk/client-secrets-manager": "^3.686.0", + "axios": "^1.7.7", + "glob": "^11.0.0" + } +} diff --git a/aws/services/httpService.ts b/aws/services/httpService.ts new file mode 100644 index 00000000..cdb9cec7 --- /dev/null +++ b/aws/services/httpService.ts @@ -0,0 +1,80 @@ +import axios, { AxiosInstance, AxiosResponse } from "axios" +import * as https from "https" +import { getSecret } from "../helpers/getSecret" + +class HttpService { + private axios: AxiosInstance + + constructor() {} + + async init(baseURL: string) { + const httpsAgent = await this.initHttpsAgent() + + this.axios = axios.create({ + baseURL, + timeout: 5000, + httpsAgent + }) + } + + async initHttpsAgent(): Promise { + const mtlsCertJson = await getSecret(process.env.MTLS_SECRET_NAME) + + // Get and parse mTLS Cert + const { key, ca, cert } = JSON.parse(mtlsCertJson) + const certUtf8 = Buffer.from(cert, "base64").toString("utf-8") + const keyUtf8 = Buffer.from(key, "base64").toString("utf-8") + const caUtf8 = ca ? Buffer.from(ca, "base64").toString("utf-8") : undefined + + // Create the HTTPS Agent with the decoded cert and key + return new https.Agent({ + cert: certUtf8, + key: keyUtf8, + ca: caUtf8 ? caUtf8 : undefined, + rejectUnauthorized: true + }) + } + + async get(url: string, params?: Record): Promise { + try { + const response: AxiosResponse = await this.axios.get(url, { + params + }) + return response.data + } catch (error) { + this.handleError(error) + } + } + + async post(url: string, data?: Record): Promise { + try { + const response: AxiosResponse = await this.axios.post(url, data) + return response.data + } catch (error) { + this.handleError(error) + } + } + + async put(url: string, data?: Record): Promise { + try { + const response: AxiosResponse = await this.axios.put(url, data) + return response.data + } catch (error) { + this.handleError(error) + } + } + + private handleError(error: unknown): never { + if (axios.isAxiosError(error)) { + console.error("Axios error:", error.message) + throw new Error( + `HTTP Error: ${error.response?.status || "Unknown status"}` + ) + } else { + console.error("Unexpected error:", error) + throw new Error("Unexpected error occurred") + } + } +} + +export default HttpService diff --git a/docker/aws/Dockerfile.release b/docker/aws/Dockerfile.release new file mode 100644 index 00000000..91668aa2 --- /dev/null +++ b/docker/aws/Dockerfile.release @@ -0,0 +1,28 @@ +# Use base Node image for building +ARG NODE_VERSION=20 + +FROM node:${NODE_VERSION} AS build + +# Copy package.json to install dependencies once +WORKDIR /app +COPY /package.json . + +RUN npm install + +# Copy the rest of the code +COPY . . + +ARG TARGET_FUNCTION +# Use esbuild to bundle the specific function code +RUN npx esbuild lambdas/${TARGET_FUNCTION}/index.ts --bundle --minify --sourcemap --platform=node --target=es2020 --outfile=/app/dist/index.js + +# Final runtime image with AWS Lambda base +ARG NODE_VERSION +FROM public.ecr.aws/lambda/nodejs:${NODE_VERSION} + +# # Copy only the bundled code for the target function +WORKDIR /var/task +COPY --from=build /app/dist/index.js ./ + +# Set the command for the Lambda handler +CMD ["index.handler"] diff --git a/docker/docker-compose.yaml b/docker/docker-compose.yaml index 3e51565f..889c6bb0 100644 --- a/docker/docker-compose.yaml +++ b/docker/docker-compose.yaml @@ -67,6 +67,8 @@ services: - SplunkCollectorUrl=${SplunkCollectorUrl} - SplunkCollectorId=${SplunkCollectorId} - SplunkToken=${SplunkToken} + - AWS_API_GATEWAY_URL=${AWS_API_GATEWAY_URL} + - AWS_API_GATEWAY_API_KEY=${AWS_API_GATEWAY_API_KEY} ports: - 5000:5000 volumes: diff --git a/docker/dummy-image/Dockerfile.release b/docker/dummy-image/Dockerfile.release new file mode 100644 index 00000000..b4a12cfa --- /dev/null +++ b/docker/dummy-image/Dockerfile.release @@ -0,0 +1,5 @@ +FROM alpine:latest + +RUN echo "This is a dummy image for initial deployment" > /dummy.txt + +CMD ["echo", "Dummy image deployed successfully"] diff --git a/docker/openshift/sync-secrets.sh b/docker/openshift/sync-secrets.sh index dc7e7077..5f930432 100644 --- a/docker/openshift/sync-secrets.sh +++ b/docker/openshift/sync-secrets.sh @@ -14,6 +14,7 @@ secret_keys="\ location_services_client \ lookup_services_client \ misc \ + mtls_cert \ request \ splunk \ user_services_client" diff --git a/infrastructure/cloud/environments/dev/variables.tf b/infrastructure/cloud/environments/dev/variables.tf index 007c64be..5bcaef0d 100644 --- a/infrastructure/cloud/environments/dev/variables.tf +++ b/infrastructure/cloud/environments/dev/variables.tf @@ -67,4 +67,3 @@ variable "cert_domain_name" { description = "The BCGov provisioned certificate domain name" type = string } - diff --git a/infrastructure/cloud/environments/dev/webapp.tf b/infrastructure/cloud/environments/dev/webapp.tf index 273a8285..7f923167 100644 --- a/infrastructure/cloud/environments/dev/webapp.tf +++ b/infrastructure/cloud/environments/dev/webapp.tf @@ -1,68 +1,216 @@ -module "security" { - source = "../../modules/security" - environment = var.environment - app_name = var.app_name - kms_key_name = var.kms_key_name - ecs_web_td_log_group_arn = module.monitoring.ecs_web_td_log_group_arn - ecs_api_td_log_group_arn = module.monitoring.ecs_api_td_log_group_arn - ecr_repository_arn = module.container.ecr_repository_arn - openshift_iam_user = var.openshift_iam_user - iam_user_table_name = var.iam_user_table_name - cert_domain_name = var.cert_domain_name -} - -module "storage" { - source = "../../modules/storage" +# This the rest of JASPER's infra resources. +# Make sure that the "initial" stack has been deployed first. + +# +# Existing Resources +# +data "aws_caller_identity" "current" {} + +# KMS Key +data "aws_kms_key" "kms_key" { + key_id = "alias/${var.kms_key_name}-${var.environment}" +} + +# VPC +data "aws_vpc" "vpc" { + id = var.vpc_id +} + +# Security Groups +data "aws_security_group" "web_sg" { + name = "Web_sg" +} + +data "aws_security_group" "app_sg" { + name = "App_sg" +} + +data "aws_security_group" "data_sg" { + name = "Data_sg" +} + +# App ECR Repo +data "aws_ecr_repository" "app_ecr_repo" { + name = "${var.app_name}-app-repo-${var.environment}" +} + +# Lambda ECR Repo +data "aws_ecr_repository" "lambda_ecr_repo" { + name = "${var.app_name}-lambda-repo-${var.environment}" +} + +# +# Modules +# + +# Create Secrets placeholder for Secrets Manager +module "secrets_manager" { + source = "../../modules/SecretsManager" + environment = var.environment + app_name = var.app_name + region = var.region + kms_key_arn = data.aws_kms_key.kms_key.arn +} + +# Create RDS Database +module "rds" { + source = "../../modules/RDS" + environment = var.environment + app_name = var.app_name + db_username = module.secrets_manager.db_username + db_password = module.secrets_manager.db_password + data_sg_id = data.aws_security_group.data_sg.id + vpc_id = data.aws_vpc.vpc.id + kms_key_arn = data.aws_kms_key.kms_key.arn + rds_db_ca_cert = var.rds_db_ca_cert +} + +# Create IAM Roles/Policies +module "iam" { + source = "../../modules/IAM" environment = var.environment app_name = var.app_name - kms_key_name = module.security.kms_key_alias - test_s3_bucket_name = var.test_s3_bucket_name - data_sg_id = module.networking.data_sg_id - db_username = module.security.db_username - db_password = module.security.db_password - vpc_id = var.vpc_id - kms_key_arn = module.security.kms_key_arn - rds_db_ca_cert = var.rds_db_ca_cert - depends_on = [module.security] -} - -module "networking" { - source = "../../modules/networking" + kms_key_arn = data.aws_kms_key.kms_key.arn + app_ecr_repo_arn = data.aws_ecr_repository.app_ecr_repo.arn + openshift_iam_user = var.openshift_iam_user + iam_user_table_name = var.iam_user_table_name + secrets_arn_list = module.secrets_manager.secrets_arn_list +} + +# Parse Subnets +module "subnets" { + source = "../../modules/Subnets" + web_subnet_names = var.web_subnet_names + app_subnet_names = var.app_subnet_names + data_subnet_names = var.data_subnet_names + vpc_id = data.aws_vpc.vpc.id +} + +# Create Target Groups +module "tg_web" { + source = "../../modules/TargetGroup" + environment = var.environment + app_name = var.app_name + name = "web" + port = 8080 + health_check_path = "/" + vpc_id = data.aws_vpc.vpc.id + protocol = "HTTPS" +} + +module "tg_api" { + source = "../../modules/TargetGroup" + environment = var.environment + app_name = var.app_name + name = "api" + port = 5000 + health_check_path = "/api/test/headers" + vpc_id = data.aws_vpc.vpc.id + protocol = "HTTP" +} + +# Setup ALB Listeners +module "alb" { + source = "../../modules/ALB" + environment = var.environment + app_name = var.app_name + lb_name = var.lb_name + cert_domain_name = var.cert_domain_name + tg_web_arn = module.tg_web.tg_arn + tg_api_arn = module.tg_api.tg_arn +} + +# Create Lambda Functions +module "lambda" { + source = "../../modules/Lambda" environment = var.environment app_name = var.app_name - region = var.region - vpc_id = var.vpc_id - web_subnet_names = var.web_subnet_names - app_subnet_names = var.app_subnet_names - data_subnet_names = var.data_subnet_names - lb_name = var.lb_name - default_lb_cert_arn = module.security.default_lb_cert_arn -} - -module "container" { - source = "../../modules/container" - environment = var.environment - app_name = var.app_name - region = var.region - ecs_execution_role_arn = module.security.ecs_execution_role_arn - web_subnet_ids = module.networking.web_subnets_ids - app_subnet_ids = module.networking.app_subnets_ids - web_sg_id = module.networking.web_sg_id - app_sg_id = module.networking.app_sg_id - web_tg_arn = module.networking.web_tg_arn - api_tg_arn = module.networking.api_tg_arn - ecs_web_td_log_group_name = module.monitoring.ecs_web_td_log_group_name - ecs_api_td_log_group_name = module.monitoring.ecs_api_td_log_group_name - kms_key_id = module.security.kms_key_id - default_lb_dns_name = module.networking.default_lb_dns_name - api_secrets = module.security.api_secrets - web_secrets = module.security.web_secrets - depends_on = [module.monitoring] -} - -module "monitoring" { - source = "../../modules/monitoring" + lambda_role_arn = module.iam.lambda_role_arn + apigw_execution_arn = module.apigw.apigw_execution_arn + lambda_ecr_repo_url = data.aws_ecr_repository.lambda_ecr_repo.repository_url + mtls_secret_name = module.secrets_manager.mtls_secret_name +} + +# Create API Gateway +module "apigw" { + source = "../../modules/APIGateway" + environment = var.environment + app_name = var.app_name + region = var.region + account_id = data.aws_caller_identity.current.account_id + lambda_functions = module.lambda.lambda_functions +} + +# Create ECS Cluster +module "ecs_cluster" { + source = "../../modules/ECS/Cluster" environment = var.environment app_name = var.app_name - kms_key_arn = module.security.kms_key_arn + name = "app" +} + +# Create Web ECS Task Definition +module "ecs_web_td" { + source = "../../modules/ECS/TaskDefinition" + environment = var.environment + app_name = var.app_name + name = "web" + region = var.region + ecs_execution_role_arn = module.iam.ecs_execution_role_arn + ecr_repository_url = data.aws_ecr_repository.app_ecr_repo.repository_url + port = 8080 + secret_env_variables = module.secrets_manager.web_secrets + kms_key_arn = data.aws_kms_key.kms_key.arn +} + +# Create API ECS Task Definition +module "ecs_api_td" { + source = "../../modules/ECS/TaskDefinition" + environment = var.environment + app_name = var.app_name + name = "api" + region = var.region + ecs_execution_role_arn = module.iam.ecs_execution_role_arn + ecr_repository_url = data.aws_ecr_repository.app_ecr_repo.repository_url + port = 5000 + env_variables = [ + { + name = "CORS_DOMAIN" + value = module.alb.default_lb_dns_name + }, + { + name = "AWS_API_GATEWAY_URL" + value = module.apigw.apigw_invoke_url + } + ] + secret_env_variables = module.secrets_manager.api_secrets + kms_key_arn = data.aws_kms_key.kms_key.arn +} + +# Create Web ECS Service +module "ecs_web_service" { + source = "../../modules/ECS/Service" + environment = var.environment + app_name = var.app_name + name = "web" + ecs_cluster_id = module.ecs_cluster.ecs_cluster_id + ecs_td_arn = module.ecs_web_td.ecs_td_arn + tg_arn = module.tg_web.tg_arn + sg_id = data.aws_security_group.app_sg.id + subnet_ids = module.subnets.web_subnets_ids + port = module.ecs_web_td.port +} + +# Create Api ECS Service +module "ecs_api_service" { + source = "../../modules/ECS/Service" + environment = var.environment + app_name = var.app_name + name = "api" + ecs_cluster_id = module.ecs_cluster.ecs_cluster_id + ecs_td_arn = module.ecs_api_td.ecs_td_arn + tg_arn = module.tg_api.tg_arn + sg_id = data.aws_security_group.app_sg.id + subnet_ids = module.subnets.app_subnets_ids + port = module.ecs_api_td.port } diff --git a/infrastructure/cloud/environments/initial/backend.tfvars b/infrastructure/cloud/environments/initial/backend.tfvars new file mode 100644 index 00000000..1c0b5d64 --- /dev/null +++ b/infrastructure/cloud/environments/initial/backend.tfvars @@ -0,0 +1,4 @@ +bucket = "terraform-remote-state-b5e4f5-dev" +dynamodb_table = "terraform-remote-state-lock-b5e4f5" +key = "initial.terraform.tfstate" +region = "ca-central-1" diff --git a/infrastructure/cloud/environments/initial/dev.tfvars b/infrastructure/cloud/environments/initial/dev.tfvars new file mode 100644 index 00000000..1a02c1a4 --- /dev/null +++ b/infrastructure/cloud/environments/initial/dev.tfvars @@ -0,0 +1,10 @@ +region = "ca-central-1" +test_s3_bucket_name = "jasper-test-s3-bucket-dev" +web_subnet_names = ["Web_Dev_aza_net", "Web_Dev_azb_net"] +app_subnet_names = ["App_Dev_aza_net", "App_Dev_azb_net"] +data_subnet_names = ["Data_Dev_aza_net", "Data_Dev_azb_net"] +openshift_iam_user = "openshiftuserdev" +iam_user_table_name = "BCGOV_IAM_USER_TABLE" +lb_name = "default" +rds_db_ca_cert = "rds-ca-rsa2048-g1" +cert_domain_name = "*.example.ca" diff --git a/infrastructure/cloud/environments/initial/main.tf b/infrastructure/cloud/environments/initial/main.tf new file mode 100644 index 00000000..b6f662dd --- /dev/null +++ b/infrastructure/cloud/environments/initial/main.tf @@ -0,0 +1,33 @@ +# This "initial" stack is deployed first to avoid circular dependency to other resources +data "aws_caller_identity" "current" {} + +# Custom KMS Key +module "kms" { + source = "../../modules/KMS" + environment = var.environment + app_name = var.app_name + region = var.region + kms_key_name = var.kms_key_name + openshift_iam_user = var.openshift_iam_user + account_id = data.aws_caller_identity.current.account_id +} + +# UI and API ECR repository +module "app_ecr" { + source = "../../modules/ECR" + environment = var.environment + app_name = var.app_name + region = var.region + kms_key_id = module.kms.kms_key_id + repo_name = "app" +} + +# Lambda functions ECR repository +module "lambda_ecr" { + source = "../../modules/ECR" + environment = var.environment + app_name = var.app_name + region = var.region + kms_key_id = module.kms.kms_key_id + repo_name = "lambda" +} diff --git a/infrastructure/cloud/environments/initial/providers.tf b/infrastructure/cloud/environments/initial/providers.tf new file mode 100644 index 00000000..4cafa436 --- /dev/null +++ b/infrastructure/cloud/environments/initial/providers.tf @@ -0,0 +1,21 @@ +terraform { + required_version = "~> 1.9.0" + required_providers { + aws = { + source = "hashicorp/aws" + version = "~> 5.0" + } + + tls = { + source = "hashicorp/tls" + version = "4.0.5" + } + } + + backend "s3" { + } +} + +provider "aws" { + region = var.region +} diff --git a/infrastructure/cloud/modules/networking/variables.tf b/infrastructure/cloud/environments/initial/variables.tf similarity index 55% rename from infrastructure/cloud/modules/networking/variables.tf rename to infrastructure/cloud/environments/initial/variables.tf index 6638249f..007c64be 100644 --- a/infrastructure/cloud/modules/networking/variables.tf +++ b/infrastructure/cloud/environments/initial/variables.tf @@ -1,3 +1,18 @@ +variable "test_s3_bucket_name" { + description = "The name of the S3 bucket to create for testing" + type = string +} + +variable "region" { + description = "The AWS region" + type = string +} + +variable "kms_key_name" { + description = "Name of KMS key" + type = string +} + variable "app_name" { description = "The name of the application" type = string @@ -8,11 +23,6 @@ variable "environment" { type = string } -variable "region" { - description = "The AWS region" - type = string -} - variable "vpc_id" { description = "The provisioned VPC ID" type = string @@ -33,12 +43,28 @@ variable "data_subnet_names" { type = list(string) } +variable "openshift_iam_user" { + description = "Openshift IAM Username" + type = string +} + +variable "iam_user_table_name" { + description = "The BCGOV DynamoDb IAM user table" + type = string +} + variable "lb_name" { description = "The BCGOV provisioned Load Balancer name" type = string } -variable "default_lb_cert_arn" { - description = "The default Load Balancer certificate ARN" +variable "rds_db_ca_cert" { + description = "The Certifiate Authority identifier used in RDS" + type = string +} + +variable "cert_domain_name" { + description = "The BCGov provisioned certificate domain name" type = string } + diff --git a/infrastructure/cloud/modules/networking/alb.tf b/infrastructure/cloud/modules/ALB/main.tf similarity index 78% rename from infrastructure/cloud/modules/networking/alb.tf rename to infrastructure/cloud/modules/ALB/main.tf index 4457cdf9..0bbf111c 100644 --- a/infrastructure/cloud/modules/networking/alb.tf +++ b/infrastructure/cloud/modules/ALB/main.tf @@ -1,6 +1,10 @@ -# -# Default Load Balancer -# +# Load Balancer Certificate +data "aws_acm_certificate" "default_lb_cert" { + domain = var.cert_domain_name + most_recent = true + statuses = ["ISSUED"] +} + data "aws_lb" "default_lb" { name = var.lb_name } @@ -20,7 +24,7 @@ resource "aws_lb_listener" "http_listener" { port = "443" protocol = "HTTPS" query = "#{query}" - status_code = "HTTP_301" # Use HTTP_302 for temporary redirects + status_code = "HTTP_301" } } } @@ -30,7 +34,7 @@ resource "aws_lb_listener" "https_listener" { load_balancer_arn = data.aws_lb.default_lb.arn port = 443 protocol = "HTTPS" - certificate_arn = var.default_lb_cert_arn + certificate_arn = data.aws_acm_certificate.default_lb_cert.arn default_action { type = "fixed-response" @@ -42,7 +46,7 @@ resource "aws_lb_listener" "https_listener" { } } -# HTTPS Listener Rules +# Web Listener Rule resource "aws_lb_listener_rule" "web_lr" { listener_arn = aws_lb_listener.https_listener.arn priority = 200 @@ -55,7 +59,7 @@ resource "aws_lb_listener_rule" "web_lr" { action { type = "forward" - target_group_arn = aws_lb_target_group.web_target_group.arn + target_group_arn = var.tg_web_arn } tags = { @@ -63,6 +67,7 @@ resource "aws_lb_listener_rule" "web_lr" { } } +# API Listener Rule resource "aws_lb_listener_rule" "api_path_lr" { listener_arn = aws_lb_listener.https_listener.arn priority = 100 @@ -75,7 +80,7 @@ resource "aws_lb_listener_rule" "api_path_lr" { action { type = "forward" - target_group_arn = aws_lb_target_group.api_target_group.arn + target_group_arn = var.tg_api_arn } tags = { diff --git a/infrastructure/cloud/modules/ALB/outputs.tf b/infrastructure/cloud/modules/ALB/outputs.tf new file mode 100644 index 00000000..d9e6ceb3 --- /dev/null +++ b/infrastructure/cloud/modules/ALB/outputs.tf @@ -0,0 +1,3 @@ +output "default_lb_dns_name" { + value = data.aws_lb.default_lb.dns_name +} diff --git a/infrastructure/cloud/modules/ALB/variables.tf b/infrastructure/cloud/modules/ALB/variables.tf new file mode 100644 index 00000000..c7444e05 --- /dev/null +++ b/infrastructure/cloud/modules/ALB/variables.tf @@ -0,0 +1,31 @@ +variable "app_name" { + description = "The name of the application" + type = string +} + +variable "environment" { + description = "The AWS environment to deploy to" + type = string +} + +variable "lb_name" { + description = "The BCGOV provisioned Load Balancer name" + type = string +} + +variable "cert_domain_name" { + description = "The BCGov provisioned certificate domain name" + type = string +} + +variable "tg_web_arn" { + description = "The Web Target Group ARN" + type = string +} + +variable "tg_api_arn" { + description = "The API Target Group ARN" + type = string +} + + diff --git a/infrastructure/cloud/modules/APIGateway/main.tf b/infrastructure/cloud/modules/APIGateway/main.tf new file mode 100644 index 00000000..95dbb2a9 --- /dev/null +++ b/infrastructure/cloud/modules/APIGateway/main.tf @@ -0,0 +1,169 @@ +resource "aws_api_gateway_rest_api" "apigw" { + name = "${var.app_name}-api-gateway-${var.environment}" + +} + +resource "aws_api_gateway_deployment" "apigw_deployment" { + depends_on = [ + aws_api_gateway_integration.get_locations_integration, + aws_api_gateway_integration.get_locations_rooms_integration, + aws_api_gateway_integration.get_files_civil_integration, + aws_api_gateway_integration.get_files_criminal_integration, + ] + rest_api_id = aws_api_gateway_rest_api.apigw.id + stage_name = var.environment +} + +resource "aws_api_gateway_rest_api_policy" "apigw_rest_api_policy" { + rest_api_id = aws_api_gateway_rest_api.apigw.id + + policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Effect = "Allow" + Principal = "*" + Action = "execute-api:Invoke" + Resource = "arn:aws:execute-api:${var.region}:${var.account_id}:${aws_api_gateway_rest_api.apigw.id}/*" + } + ] + }) +} + +resource "aws_api_gateway_usage_plan" "apigw_usage_plan" { + name = "${var.app_name}-apigw-usage-plan-${var.environment}" + + api_stages { + api_id = aws_api_gateway_rest_api.apigw.id + stage = aws_api_gateway_deployment.apigw_deployment.stage_name + } +} + +resource "aws_api_gateway_api_key" "apigw_api_key" { + name = "${var.app_name}-apigw-api-key-${var.environment}" +} + +resource "aws_api_gateway_usage_plan_key" "apigw_usage_plan_key" { + key_id = aws_api_gateway_api_key.apigw_api_key.id + key_type = "API_KEY" + usage_plan_id = aws_api_gateway_usage_plan.apigw_usage_plan.id +} + +# +# /locations Resource +# +resource "aws_api_gateway_resource" "locations_resource" { + rest_api_id = aws_api_gateway_rest_api.apigw.id + parent_id = aws_api_gateway_rest_api.apigw.root_resource_id + path_part = "locations" +} + +# GET /locations +resource "aws_api_gateway_method" "get_locations_method" { + rest_api_id = aws_api_gateway_rest_api.apigw.id + resource_id = aws_api_gateway_resource.locations_resource.id + http_method = var.lambda_functions["get-locations"].http_method + authorization = "NONE" + api_key_required = true + + request_parameters = { + "method.request.header.x-origin-verify" = true + } +} + +resource "aws_api_gateway_integration" "get_locations_integration" { + rest_api_id = aws_api_gateway_rest_api.apigw.id + resource_id = aws_api_gateway_resource.locations_resource.id + http_method = aws_api_gateway_method.get_locations_method.http_method + type = "AWS_PROXY" + integration_http_method = "POST" + uri = var.lambda_functions["get-locations"].invoke_arn +} + +# /locations/rooms Resource +resource "aws_api_gateway_resource" "rooms_resource" { + rest_api_id = aws_api_gateway_rest_api.apigw.id + parent_id = aws_api_gateway_resource.locations_resource.id + path_part = "rooms" +} + +# GET /locations/rooms +resource "aws_api_gateway_method" "get_locations_rooms_method" { + rest_api_id = aws_api_gateway_rest_api.apigw.id + resource_id = aws_api_gateway_resource.rooms_resource.id + http_method = var.lambda_functions["get-rooms"].http_method + authorization = "NONE" + api_key_required = true + + request_parameters = { + "method.request.header.x-origin-verify" = true + } +} + +resource "aws_api_gateway_integration" "get_locations_rooms_integration" { + rest_api_id = aws_api_gateway_rest_api.apigw.id + resource_id = aws_api_gateway_resource.rooms_resource.id + http_method = aws_api_gateway_method.get_locations_rooms_method.http_method + type = "AWS_PROXY" + integration_http_method = "POST" + uri = var.lambda_functions["get-rooms"].invoke_arn +} + +# +# /files Resource +# +resource "aws_api_gateway_resource" "files_resource" { + rest_api_id = aws_api_gateway_rest_api.apigw.id + parent_id = aws_api_gateway_rest_api.apigw.root_resource_id + path_part = "files" +} + +# /files/civil Resource +resource "aws_api_gateway_resource" "civil_resource" { + rest_api_id = aws_api_gateway_rest_api.apigw.id + parent_id = aws_api_gateway_resource.files_resource.id + path_part = "civil" +} + +# GET /files/civil +resource "aws_api_gateway_method" "get_files_civil_method" { + rest_api_id = aws_api_gateway_rest_api.apigw.id + resource_id = aws_api_gateway_resource.civil_resource.id + http_method = var.lambda_functions["search-civil-files"].http_method + authorization = "NONE" + api_key_required = true +} + +resource "aws_api_gateway_integration" "get_files_civil_integration" { + rest_api_id = aws_api_gateway_rest_api.apigw.id + resource_id = aws_api_gateway_resource.civil_resource.id + http_method = aws_api_gateway_method.get_files_civil_method.http_method + type = "AWS_PROXY" + integration_http_method = "POST" + uri = var.lambda_functions["search-civil-files"].invoke_arn +} + +# /files/criminal Resource +resource "aws_api_gateway_resource" "criminal_resource" { + rest_api_id = aws_api_gateway_rest_api.apigw.id + parent_id = aws_api_gateway_resource.files_resource.id + path_part = "criminal" +} + +# GET /files/criminal +resource "aws_api_gateway_method" "get_files_criminal_method" { + rest_api_id = aws_api_gateway_rest_api.apigw.id + resource_id = aws_api_gateway_resource.criminal_resource.id + http_method = var.lambda_functions["search-criminal-files"].http_method + authorization = "NONE" + api_key_required = true +} + +resource "aws_api_gateway_integration" "get_files_criminal_integration" { + rest_api_id = aws_api_gateway_rest_api.apigw.id + resource_id = aws_api_gateway_resource.criminal_resource.id + http_method = aws_api_gateway_method.get_files_criminal_method.http_method + type = "AWS_PROXY" + integration_http_method = "POST" + uri = var.lambda_functions["search-criminal-files"].invoke_arn +} diff --git a/infrastructure/cloud/modules/APIGateway/outputs.tf b/infrastructure/cloud/modules/APIGateway/outputs.tf new file mode 100644 index 00000000..9d2ceb8a --- /dev/null +++ b/infrastructure/cloud/modules/APIGateway/outputs.tf @@ -0,0 +1,11 @@ +output "apigw_id" { + value = aws_api_gateway_rest_api.apigw.id +} + +output "apigw_invoke_url" { + value = aws_api_gateway_deployment.apigw_deployment.invoke_url +} + +output "apigw_execution_arn" { + value = aws_api_gateway_rest_api.apigw.execution_arn +} diff --git a/infrastructure/cloud/modules/APIGateway/variables.tf b/infrastructure/cloud/modules/APIGateway/variables.tf new file mode 100644 index 00000000..1103f6ad --- /dev/null +++ b/infrastructure/cloud/modules/APIGateway/variables.tf @@ -0,0 +1,28 @@ +variable "app_name" { + description = "The name of the application" + type = string +} + +variable "environment" { + description = "The AWS environment to deploy to" + type = string +} + +variable "region" { + description = "The AWS region" + type = string +} + +variable "account_id" { + description = "The current AWS Account Id" + type = string +} + +variable "lambda_functions" { + description = "Lambda functions config" + type = map(object({ + http_method = string + resource_path = string + invoke_arn = string + })) +} diff --git a/infrastructure/cloud/modules/Cloudwatch/LogGroup/main.tf b/infrastructure/cloud/modules/Cloudwatch/LogGroup/main.tf new file mode 100644 index 00000000..004e5cb9 --- /dev/null +++ b/infrastructure/cloud/modules/Cloudwatch/LogGroup/main.tf @@ -0,0 +1,6 @@ +resource "aws_cloudwatch_log_group" "log_group" { + name = "/aws/${var.resource_name}/${var.app_name}-${var.resource_name}-${var.name}-log-group-${var.environment}" + retention_in_days = 90 + kms_key_id = var.kms_key_arn +} + diff --git a/infrastructure/cloud/modules/Cloudwatch/LogGroup/outputs.tf b/infrastructure/cloud/modules/Cloudwatch/LogGroup/outputs.tf new file mode 100644 index 00000000..fbee1a01 --- /dev/null +++ b/infrastructure/cloud/modules/Cloudwatch/LogGroup/outputs.tf @@ -0,0 +1,3 @@ +output "log_group_name" { + value = aws_cloudwatch_log_group.log_group.name +} diff --git a/infrastructure/cloud/modules/Cloudwatch/LogGroup/variables.tf b/infrastructure/cloud/modules/Cloudwatch/LogGroup/variables.tf new file mode 100644 index 00000000..6040d78d --- /dev/null +++ b/infrastructure/cloud/modules/Cloudwatch/LogGroup/variables.tf @@ -0,0 +1,24 @@ +variable "environment" { + description = "The environment to deploy the application to" + type = string +} + +variable "app_name" { + description = "The name of the application" + type = string +} + +variable "kms_key_arn" { + description = "KMS Key ARN" + type = string +} + +variable "resource_name" { + description = "Resource name of the Log Group" + type = string +} + +variable "name" { + description = "Log Group Name" + type = string +} diff --git a/infrastructure/cloud/modules/container/ecr.tf b/infrastructure/cloud/modules/ECR/main.tf similarity index 70% rename from infrastructure/cloud/modules/container/ecr.tf rename to infrastructure/cloud/modules/ECR/main.tf index e22327b7..f7a8c174 100644 --- a/infrastructure/cloud/modules/container/ecr.tf +++ b/infrastructure/cloud/modules/ECR/main.tf @@ -1,5 +1,5 @@ resource "aws_ecr_repository" "ecr_repository" { - name = "${var.app_name}-ecr-repo-${var.environment}" + name = "${var.app_name}-${var.repo_name}-repo-${var.environment}" force_delete = true image_tag_mutability = "IMMUTABLE" @@ -19,6 +19,6 @@ resource "aws_ecr_repository" "ecr_repository" { } tags = { - name = "${var.app_name}-ecr-repo-${var.environment}" + name = "${var.app_name}-${var.repo_name}-repo-${var.environment}" } } diff --git a/infrastructure/cloud/modules/compute/.gitkeep b/infrastructure/cloud/modules/ECR/outputs.tf similarity index 100% rename from infrastructure/cloud/modules/compute/.gitkeep rename to infrastructure/cloud/modules/ECR/outputs.tf diff --git a/infrastructure/cloud/modules/ECR/variables.tf b/infrastructure/cloud/modules/ECR/variables.tf new file mode 100644 index 00000000..9d350403 --- /dev/null +++ b/infrastructure/cloud/modules/ECR/variables.tf @@ -0,0 +1,24 @@ +variable "environment" { + description = "The environment to deploy the application to" + type = string +} + +variable "app_name" { + description = "The name of the application" + type = string +} + +variable "region" { + description = "The AWS region" + type = string +} + +variable "repo_name" { + description = "The ECR Repository name" + type = string +} + +variable "kms_key_id" { + description = "The KMS Key ID" + type = string +} diff --git a/infrastructure/cloud/modules/ECS/Cluster/main.tf b/infrastructure/cloud/modules/ECS/Cluster/main.tf new file mode 100644 index 00000000..055fa0a0 --- /dev/null +++ b/infrastructure/cloud/modules/ECS/Cluster/main.tf @@ -0,0 +1,12 @@ +resource "aws_ecs_cluster" "ecs_cluster" { + name = "${var.app_name}-${var.name}-cluster-${var.environment}" + + setting { + name = "containerInsights" + value = "enabled" + } + + tags = { + name = "${var.app_name}-${var.name}-cluster-${var.environment}" + } +} diff --git a/infrastructure/cloud/modules/ECS/Cluster/outputs.tf b/infrastructure/cloud/modules/ECS/Cluster/outputs.tf new file mode 100644 index 00000000..d9a71f0b --- /dev/null +++ b/infrastructure/cloud/modules/ECS/Cluster/outputs.tf @@ -0,0 +1,3 @@ +output "ecs_cluster_id" { + value = aws_ecs_cluster.ecs_cluster.id +} diff --git a/infrastructure/cloud/modules/monitoring/variables.tf b/infrastructure/cloud/modules/ECS/Cluster/variables.tf similarity index 72% rename from infrastructure/cloud/modules/monitoring/variables.tf rename to infrastructure/cloud/modules/ECS/Cluster/variables.tf index 797fefad..e149226a 100644 --- a/infrastructure/cloud/modules/monitoring/variables.tf +++ b/infrastructure/cloud/modules/ECS/Cluster/variables.tf @@ -8,8 +8,6 @@ variable "app_name" { type = string } -variable "kms_key_arn" { - description = "KMS Key ARN" - type = string +variable "name" { + description = "The name of ECS cluster" } - diff --git a/infrastructure/cloud/modules/ECS/Service/main.tf b/infrastructure/cloud/modules/ECS/Service/main.tf new file mode 100644 index 00000000..946ec9f0 --- /dev/null +++ b/infrastructure/cloud/modules/ECS/Service/main.tf @@ -0,0 +1,23 @@ +resource "aws_ecs_service" "ecs_service" { + name = "${var.app_name}-${var.name}-ecs-service-${var.environment}" + cluster = var.ecs_cluster_id + task_definition = var.ecs_td_arn + launch_type = "FARGATE" + desired_count = 1 + + network_configuration { + subnets = var.subnet_ids + security_groups = [var.sg_id] + assign_public_ip = true + } + + load_balancer { + target_group_arn = var.tg_arn + container_name = "${var.app_name}-${var.name}-container-${var.environment}" + container_port = var.port + } + + lifecycle { + prevent_destroy = true + } +} diff --git a/infrastructure/cloud/modules/ECS/Service/outputs.tf b/infrastructure/cloud/modules/ECS/Service/outputs.tf new file mode 100644 index 00000000..e69de29b diff --git a/infrastructure/cloud/modules/ECS/Service/variables.tf b/infrastructure/cloud/modules/ECS/Service/variables.tf new file mode 100644 index 00000000..6a157bca --- /dev/null +++ b/infrastructure/cloud/modules/ECS/Service/variables.tf @@ -0,0 +1,43 @@ +variable "environment" { + description = "The environment to deploy the application to" + type = string +} + +variable "app_name" { + description = "The name of the application" + type = string +} + +variable "name" { + description = "The name of ECS cluster" +} + +variable "subnet_ids" { + description = "The Subnet IDs" + type = list(string) +} + +variable "sg_id" { + description = "The BCGOV provisioned Security Group" + type = string +} + +variable "tg_arn" { + description = "The Target Group ARN" + type = string +} + +variable "port" { + description = "The Container port number" + type = number +} + +variable "ecs_cluster_id" { + description = "The ECS Cluster Id" + type = string +} + +variable "ecs_td_arn" { + description = "The ECS Task Definition ARN" + type = string +} diff --git a/infrastructure/cloud/modules/ECS/TaskDefinition/main.tf b/infrastructure/cloud/modules/ECS/TaskDefinition/main.tf new file mode 100644 index 00000000..4e2da487 --- /dev/null +++ b/infrastructure/cloud/modules/ECS/TaskDefinition/main.tf @@ -0,0 +1,50 @@ +resource "aws_ecs_task_definition" "ecs_td" { + family = "${var.app_name}-${var.name}-td-${var.environment}" + network_mode = "awsvpc" + requires_compatibilities = ["FARGATE"] + cpu = var.cpu + memory = var.memory_size + execution_role_arn = var.ecs_execution_role_arn + task_role_arn = var.ecs_execution_role_arn + + # lifecycle { + # # Since the dummy-image will be replaced when the GHA pipeline runs, + # # the whole container_definition edits has been ignored. + # ignore_changes = [container_definitions] + # } + + container_definitions = jsonencode([ + { + name = "${var.app_name}-${var.name}-container-${var.environment}" + image = "${var.ecr_repository_url}:${var.image_name}" # This is a placeholder image and will be replaced every deployment of GHA. + essential = true + portMappings = [ + { + containerPort = var.port + hostPort = var.port + protocol = "tcp" + } + ] + logConfiguration = { + logDriver = "awslogs" + options = { + "awslogs-group" = "/ecs/${var.name}-td" + "awslogs-region" = var.region + "awslogs-stream-prefix" = "ecs" + } + } + environment = var.env_variables != null ? [ + for env in var.env_variables : { + name = env.name + value = env.value + } + ] : [] + secrets = [ + for secret in var.secret_env_variables : { + name = secret[0] + valueFrom = secret[1] + } + ] + } + ]) +} diff --git a/infrastructure/cloud/modules/ECS/TaskDefinition/outputs.tf b/infrastructure/cloud/modules/ECS/TaskDefinition/outputs.tf new file mode 100644 index 00000000..50737d20 --- /dev/null +++ b/infrastructure/cloud/modules/ECS/TaskDefinition/outputs.tf @@ -0,0 +1,7 @@ +output "ecs_td_arn" { + value = aws_ecs_task_definition.ecs_td.arn +} + +output "port" { + value = var.port +} diff --git a/infrastructure/cloud/modules/ECS/TaskDefinition/variables.tf b/infrastructure/cloud/modules/ECS/TaskDefinition/variables.tf new file mode 100644 index 00000000..0645b12d --- /dev/null +++ b/infrastructure/cloud/modules/ECS/TaskDefinition/variables.tf @@ -0,0 +1,70 @@ +variable "environment" { + description = "The environment to deploy the application to" + type = string +} + +variable "app_name" { + description = "The name of the application" + type = string +} + +variable "region" { + description = "The AWS region" + type = string +} + +variable "name" { + description = "The name of ECS cluster" +} + +variable "cpu" { + description = "The ECS Task Definition CPU" + type = number + default = 256 +} + +variable "memory_size" { + description = "The ECS Task Definition Memory Size" + type = number + default = 512 +} + +variable "ecs_execution_role_arn" { + description = "The ECS Task Definition Execution role ARN" + type = string +} + +variable "ecr_repository_url" { + description = "The ECR Repository URL where the image will be referenced" + type = string +} + +variable "port" { + description = "The Container port number" + type = number +} + +variable "env_variables" { + description = "The environment variables for the container" + type = list(object({ + name = string + value = string + })) + default = null +} + +variable "secret_env_variables" { + description = "The sensitive environment variables for the container" + type = list(list(string)) +} + +variable "kms_key_arn" { + description = "KMS Key ARN" + type = string +} + +variable "image_name" { + description = "Image name that will be attached to the Task Definition" + type = string + default = "dummy-image" +} diff --git a/infrastructure/cloud/modules/security/iam.tf b/infrastructure/cloud/modules/IAM/main.tf similarity index 71% rename from infrastructure/cloud/modules/security/iam.tf rename to infrastructure/cloud/modules/IAM/main.tf index e1343e5e..19e2fc6a 100644 --- a/infrastructure/cloud/modules/security/iam.tf +++ b/infrastructure/cloud/modules/IAM/main.tf @@ -48,7 +48,7 @@ resource "aws_iam_role_policy" "ecs_execution_policy" { ], Effect = "Allow", Resource = [ - var.ecr_repository_arn + var.app_ecr_repo_arn ] }, { @@ -59,8 +59,7 @@ resource "aws_iam_role_policy" "ecs_execution_policy" { ], Effect = "Allow", Resource = [ - "${var.ecs_web_td_log_group_arn}:*", - "${var.ecs_api_td_log_group_arn}:*" + "arn:aws:logs:*:*:log-group:/aws/ecs/*:*" ] }, { @@ -69,18 +68,7 @@ resource "aws_iam_role_policy" "ecs_execution_policy" { ], Effect = "Allow", Resource = [ - aws_secretsmanager_secret.aspnet_core_secret.arn, - aws_secretsmanager_secret.file_services_client_secret.arn, - aws_secretsmanager_secret.location_services_client_secret.arn, - aws_secretsmanager_secret.lookup_services_client_secret.arn, - aws_secretsmanager_secret.user_services_client_secret.arn, - aws_secretsmanager_secret.keycloak_secret.arn, - aws_secretsmanager_secret.request_secret.arn, - aws_secretsmanager_secret.splunk_secret.arn, - aws_secretsmanager_secret.database_secret.arn, - aws_secretsmanager_secret.aspnet_core_secret.arn, - aws_secretsmanager_secret.misc_secret.arn, - aws_secretsmanager_secret.auth_secret.arn + "arn:aws:secretsmanager:*:*:secret:external/*" ] }, { @@ -88,7 +76,7 @@ resource "aws_iam_role_policy" "ecs_execution_policy" { "kms:Decrypt" ], Effect = "Allow", - Resource = aws_kms_key.kms_key.arn + Resource = var.kms_key_arn }, { "Effect" : "Allow", @@ -217,8 +205,8 @@ resource "aws_iam_policy" "openshift_role_policy" { ], "Effect" : "Allow", "Resource" : [ - "arn:aws:ssm:*:*:parameter/iam_users/*", - "arn:aws:kms:*:*:key/*" + "arn:aws:ssm:*:*:parameter/iam_users/${var.openshift_iam_user}_keys", + var.kms_key_arn ] }, { @@ -227,20 +215,8 @@ resource "aws_iam_policy" "openshift_role_policy" { "secretsmanager:DescribeSecret", "secretsmanager:PutSecretValue", ] - Effect = "Allow" - Resource = [ - aws_secretsmanager_secret.aspnet_core_secret.arn, - aws_secretsmanager_secret.auth_secret.arn, - aws_secretsmanager_secret.database_secret.arn, - aws_secretsmanager_secret.file_services_client_secret.arn, - aws_secretsmanager_secret.keycloak_secret.arn, - aws_secretsmanager_secret.location_services_client_secret.arn, - aws_secretsmanager_secret.lookup_services_client_secret.arn, - aws_secretsmanager_secret.misc_secret.arn, - aws_secretsmanager_secret.request_secret.arn, - aws_secretsmanager_secret.splunk_secret.arn, - aws_secretsmanager_secret.user_services_client_secret.arn - ] + Effect = "Allow" + Resource = var.secrets_arn_list } ] }) @@ -250,3 +226,92 @@ resource "aws_iam_role_policy_attachment" "openshift_role_policy_attachment" { role = aws_iam_role.openshift_role.name policy_arn = aws_iam_policy.openshift_role_policy.arn } + +# +# Lambda +# +resource "aws_iam_role" "lambda_role" { + name = "${var.app_name}-lambda-role-${var.environment}" + + assume_role_policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Effect = "Allow" + Principal = { + Service = "lambda.amazonaws.com" + } + Action = "sts:AssumeRole" + } + ] + }) +} + +resource "aws_iam_policy" "lambda_role_policy" { + name = "${var.app_name}-lambda-role-policy-${var.environment}" + + policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + "Action" : [ + "kms:Encrypt", + "kms:Decrypt" + ], + "Effect" : "Allow", + "Resource" : [ + var.kms_key_arn + ] + }, + { + Action = [ + "secretsmanager:GetSecretValue", + "secretsmanager:DescribeSecret", + "secretsmanager:PutSecretValue", + ] + Effect = "Allow" + Resource = var.secrets_arn_list + }, + { + Effect = "Allow" + Action = [ + "logs:CreateLogGroup", + "logs:CreateLogStream", + "logs:PutLogEvents" + ] + Resource = "arn:aws:logs:*:*:log-group:/aws/lambda/${var.app_name}-*-lambda-${var.environment}:*" + } + ] + }) +} + +resource "aws_iam_role_policy_attachment" "lambda_role_policy_attachment" { + role = aws_iam_role.lambda_role.name + policy_arn = aws_iam_policy.lambda_role_policy.arn +} + +# +# API Gateway +# +resource "aws_iam_role" "apigw_logging_role" { + name = "${var.app_name}-apigw-logging-role-${var.environment}" + + assume_role_policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Effect = "Allow" + Principal = { + Service = "apigateway.amazonaws.com" + } + Action = "sts:AssumeRole" + } + ] + }) +} + +# Attach the AmazonAPIGatewayPushToCloudWatchLogs policy +resource "aws_iam_role_policy_attachment" "apigw_logging_role_policy" { + role = aws_iam_role.apigw_logging_role.name + policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonAPIGatewayPushToCloudWatchLogs" +} diff --git a/infrastructure/cloud/modules/IAM/outputs.tf b/infrastructure/cloud/modules/IAM/outputs.tf new file mode 100644 index 00000000..e9e6f2cf --- /dev/null +++ b/infrastructure/cloud/modules/IAM/outputs.tf @@ -0,0 +1,11 @@ +output "ecs_execution_role_arn" { + value = aws_iam_role.ecs_execution_role.arn +} + +output "lambda_role_arn" { + value = aws_iam_role.lambda_role.arn +} + +output "apigw_logging_role_arn" { + value = aws_iam_role.apigw_logging_role.arn +} diff --git a/infrastructure/cloud/modules/IAM/variables.tf b/infrastructure/cloud/modules/IAM/variables.tf new file mode 100644 index 00000000..87ab8c13 --- /dev/null +++ b/infrastructure/cloud/modules/IAM/variables.tf @@ -0,0 +1,34 @@ +variable "app_name" { + description = "The name of the application" + type = string +} + +variable "environment" { + description = "The AWS environment to deploy to" + type = string +} + +variable "kms_key_arn" { + description = "The KMS Key ARN" + type = string +} + +variable "app_ecr_repo_arn" { + description = "The App (UI/API) ECR Repository ARN" + type = string +} + +variable "openshift_iam_user" { + description = "Openshift IAM Username" + type = string +} + +variable "iam_user_table_name" { + description = "The BCGOV IAM User DynamoDb table name" + type = string +} + +variable "secrets_arn_list" { + description = "List of Secrets ARN" + type = list(string) +} diff --git a/infrastructure/cloud/modules/security/kms.tf b/infrastructure/cloud/modules/KMS/main.tf similarity index 85% rename from infrastructure/cloud/modules/security/kms.tf rename to infrastructure/cloud/modules/KMS/main.tf index ed9cbab0..e6ed8100 100644 --- a/infrastructure/cloud/modules/security/kms.tf +++ b/infrastructure/cloud/modules/KMS/main.tf @@ -1,4 +1,3 @@ -data "aws_caller_identity" "current" {} # kms key for encryption resource "aws_kms_key" "kms_key" { @@ -31,8 +30,8 @@ resource "aws_kms_key_policy" "kms_key_policy" { Effect = "Allow" Principal = { AWS = [ - "arn:aws:iam::${data.aws_caller_identity.current.account_id}:root", - "arn:aws:iam::${data.aws_caller_identity.current.account_id}:user/${var.openshift_iam_user}", + "arn:aws:iam::${var.account_id}:root", + "arn:aws:iam::${var.account_id}:user/${var.openshift_iam_user}" ] } Action = "kms:*" diff --git a/infrastructure/cloud/modules/KMS/outputs.tf b/infrastructure/cloud/modules/KMS/outputs.tf new file mode 100644 index 00000000..b2727b8e --- /dev/null +++ b/infrastructure/cloud/modules/KMS/outputs.tf @@ -0,0 +1,3 @@ +output "kms_key_id" { + value = aws_kms_key.kms_key.id +} diff --git a/infrastructure/cloud/modules/KMS/variables.tf b/infrastructure/cloud/modules/KMS/variables.tf new file mode 100644 index 00000000..180fbb3a --- /dev/null +++ b/infrastructure/cloud/modules/KMS/variables.tf @@ -0,0 +1,29 @@ +variable "environment" { + description = "The environment to deploy the application to" + type = string +} + +variable "app_name" { + description = "The name of the application" + type = string +} + +variable "region" { + description = "The AWS region" + type = string +} + +variable "kms_key_name" { + description = "Name of KMS key" + type = string +} + +variable "openshift_iam_user" { + description = "Openshift IAM Username" + type = string +} + +variable "account_id" { + description = "The current AWS Account Id" + type = string +} diff --git a/infrastructure/cloud/modules/Lambda/main.tf b/infrastructure/cloud/modules/Lambda/main.tf new file mode 100644 index 00000000..e7dde05e --- /dev/null +++ b/infrastructure/cloud/modules/Lambda/main.tf @@ -0,0 +1,50 @@ +locals { + lambda_functions = { + for k, v in var.functions : k => { + name = k + memory_size = lookup(v, "memory_size", 2048) + timeout = lookup(v, "timeout", 30) + http_method = v.http_method + resource_path = v.resource_path + env_variables = v.env_variables + } + } + + default_env_variables = { + MTLS_SECRET_NAME = var.mtls_secret_name + } +} + +resource "aws_lambda_function" "lambda" { + for_each = local.lambda_functions + + function_name = "${var.app_name}-${each.key}-lambda-${var.environment}" + role = var.lambda_role_arn + timeout = each.value.timeout + memory_size = each.value.memory_size + package_type = "Image" + image_uri = "${var.lambda_ecr_repo_url}:dummy-image" # This is a placeholder image and will be replaced every deployment of GHA. + + environment { + variables = merge(local.default_env_variables, each.value.env_variables) + } + + lifecycle { + create_before_destroy = true + ignore_changes = [image_uri] + } + + tracing_config { + mode = "Active" + } +} + +resource "aws_lambda_permission" "lambda_permissions" { + for_each = local.lambda_functions + + statement_id = "AllowAPIGatewayInvoke-${each.key}" + action = "lambda:InvokeFunction" + function_name = aws_lambda_function.lambda[each.key].arn + principal = "apigateway.amazonaws.com" + source_arn = "${var.apigw_execution_arn}/*/${each.value.http_method}${each.value.resource_path}" +} diff --git a/infrastructure/cloud/modules/Lambda/outputs.tf b/infrastructure/cloud/modules/Lambda/outputs.tf new file mode 100644 index 00000000..acf0503c --- /dev/null +++ b/infrastructure/cloud/modules/Lambda/outputs.tf @@ -0,0 +1,10 @@ +output "lambda_functions" { + value = { + for name, lambda in aws_lambda_function.lambda : name => { + name = lambda.function_name + http_method = var.functions[name].http_method + resource_path = var.functions[name].resource_path + invoke_arn = lambda.invoke_arn + } + } +} diff --git a/infrastructure/cloud/modules/Lambda/variables.tf b/infrastructure/cloud/modules/Lambda/variables.tf new file mode 100644 index 00000000..6d9b443f --- /dev/null +++ b/infrastructure/cloud/modules/Lambda/variables.tf @@ -0,0 +1,59 @@ +variable "app_name" { + description = "The name of the application" + type = string +} + +variable "environment" { + description = "The AWS environment to deploy to" + type = string +} + +variable "lambda_role_arn" { + description = "The Lambda IAM Role ARN" + type = string +} + +variable "functions" { + description = "Lambda functions config" + type = map(object({ + http_method = string + resource_path = string + env_variables = optional(map(string), {}) + timeout = optional(number, 300) + memory_size = optional(number, 2048) + })) + default = { + # Keys should match the folder name in lambda code + "get-locations" = { + http_method = "GET" + resource_path = "/locations" + }, + "get-rooms" = { + http_method = "GET" + resource_path = "/locations/rooms" + }, + "search-criminal-files" = { + http_method = "GET" + resource_path = "/files/criminal" + }, + "search-civil-files" = { + http_method = "GET" + resource_path = "/files/civil" + } + } +} + +variable "apigw_execution_arn" { + description = "The API Gateway Execution ARN" + type = string +} + +variable "lambda_ecr_repo_url" { + description = "The Lambda ECR Repository URL" + type = string +} + +variable "mtls_secret_name" { + description = "The secret name of mTLS Cert in Secrets Manager" + type = string +} diff --git a/infrastructure/cloud/modules/storage/rds.tf b/infrastructure/cloud/modules/RDS/main.tf similarity index 89% rename from infrastructure/cloud/modules/storage/rds.tf rename to infrastructure/cloud/modules/RDS/main.tf index 9a990874..f404ffa2 100644 --- a/infrastructure/cloud/modules/storage/rds.tf +++ b/infrastructure/cloud/modules/RDS/main.tf @@ -1,3 +1,7 @@ +data "aws_security_group" "data_sg" { + name = "Data_sg" +} + resource "aws_db_instance" "postgres_db_instance" { allocated_storage = 20 storage_type = "gp2" @@ -8,7 +12,7 @@ resource "aws_db_instance" "postgres_db_instance" { username = var.db_username password = var.db_password parameter_group_name = "default.postgres16" - vpc_security_group_ids = [var.data_sg_id] + vpc_security_group_ids = [data.aws_security_group.data_sg.id] db_subnet_group_name = "default-${var.vpc_id}" storage_encrypted = true kms_key_id = var.kms_key_arn diff --git a/infrastructure/cloud/modules/RDS/outputs.tf b/infrastructure/cloud/modules/RDS/outputs.tf new file mode 100644 index 00000000..e69de29b diff --git a/infrastructure/cloud/modules/storage/variables.tf b/infrastructure/cloud/modules/RDS/variables.tf similarity index 80% rename from infrastructure/cloud/modules/storage/variables.tf rename to infrastructure/cloud/modules/RDS/variables.tf index 0d464bda..019a99fd 100644 --- a/infrastructure/cloud/modules/storage/variables.tf +++ b/infrastructure/cloud/modules/RDS/variables.tf @@ -1,14 +1,3 @@ - -variable "test_s3_bucket_name" { - type = string - description = "The name of the S3 bucket to create for testing" -} - -variable "kms_key_name" { - description = "Name of KMS key" - type = string -} - variable "app_name" { description = "The name of the application" type = string diff --git a/infrastructure/cloud/modules/storage/s3buckets.tf b/infrastructure/cloud/modules/S3/main.tf similarity index 100% rename from infrastructure/cloud/modules/storage/s3buckets.tf rename to infrastructure/cloud/modules/S3/main.tf diff --git a/infrastructure/cloud/modules/security/secretsmanager.tf b/infrastructure/cloud/modules/SecretsManager/main.tf similarity index 84% rename from infrastructure/cloud/modules/security/secretsmanager.tf rename to infrastructure/cloud/modules/SecretsManager/main.tf index 78e99e46..bacd8a49 100644 --- a/infrastructure/cloud/modules/security/secretsmanager.tf +++ b/infrastructure/cloud/modules/SecretsManager/main.tf @@ -1,6 +1,6 @@ resource "aws_secretsmanager_secret" "file_services_client_secret" { name = "external/${var.app_name}-file-services-client-secret-${var.environment}" - kms_key_id = aws_kms_key.kms_key.arn + kms_key_id = var.kms_key_arn } resource "aws_secretsmanager_secret_version" "file_services_client_secret_value" { @@ -14,7 +14,7 @@ resource "aws_secretsmanager_secret_version" "file_services_client_secret_value" resource "aws_secretsmanager_secret" "location_services_client_secret" { name = "external/${var.app_name}-location-services-client-secret-${var.environment}" - kms_key_id = aws_kms_key.kms_key.arn + kms_key_id = var.kms_key_arn } resource "aws_secretsmanager_secret_version" "location_services_client_secret_value" { @@ -28,7 +28,7 @@ resource "aws_secretsmanager_secret_version" "location_services_client_secret_va resource "aws_secretsmanager_secret" "lookup_services_client_secret" { name = "external/${var.app_name}-lookup-services-client-secret-${var.environment}" - kms_key_id = aws_kms_key.kms_key.arn + kms_key_id = var.kms_key_arn } resource "aws_secretsmanager_secret_version" "lookup_services_client_secret_value" { @@ -42,7 +42,7 @@ resource "aws_secretsmanager_secret_version" "lookup_services_client_secret_valu resource "aws_secretsmanager_secret" "user_services_client_secret" { name = "external/${var.app_name}-user-services-client-secret-${var.environment}" - kms_key_id = aws_kms_key.kms_key.arn + kms_key_id = var.kms_key_arn } resource "aws_secretsmanager_secret_version" "user_services_client_secret_value" { @@ -56,7 +56,7 @@ resource "aws_secretsmanager_secret_version" "user_services_client_secret_value" resource "aws_secretsmanager_secret" "keycloak_secret" { name = "external/${var.app_name}-keycloak-secret-${var.environment}" - kms_key_id = aws_kms_key.kms_key.arn + kms_key_id = var.kms_key_arn } resource "aws_secretsmanager_secret_version" "keycloak_secret_value" { @@ -73,7 +73,7 @@ resource "aws_secretsmanager_secret_version" "keycloak_secret_value" { resource "aws_secretsmanager_secret" "request_secret" { name = "external/${var.app_name}-request-secret-${var.environment}" - kms_key_id = aws_kms_key.kms_key.arn + kms_key_id = var.kms_key_arn } resource "aws_secretsmanager_secret_version" "request_secret_value" { @@ -88,7 +88,7 @@ resource "aws_secretsmanager_secret_version" "request_secret_value" { resource "aws_secretsmanager_secret" "splunk_secret" { name = "external/${var.app_name}-splunk-secret-${var.environment}" - kms_key_id = aws_kms_key.kms_key.arn + kms_key_id = var.kms_key_arn } resource "aws_secretsmanager_secret_version" "splunk_secret_value" { @@ -102,7 +102,7 @@ resource "aws_secretsmanager_secret_version" "splunk_secret_value" { resource "aws_secretsmanager_secret" "database_secret" { name = "external/${var.app_name}-database-secret-${var.environment}" - kms_key_id = aws_kms_key.kms_key.arn + kms_key_id = var.kms_key_arn } resource "aws_secretsmanager_secret_version" "database_secret_value" { @@ -122,7 +122,7 @@ data "aws_secretsmanager_secret_version" "current_db_secret_value" { resource "aws_secretsmanager_secret" "aspnet_core_secret" { name = "external/${var.app_name}-aspnet-core-secret-${var.environment}" - kms_key_id = aws_kms_key.kms_key.arn + kms_key_id = var.kms_key_arn } resource "aws_secretsmanager_secret_version" "aspnet_core_secret_value" { @@ -135,7 +135,7 @@ resource "aws_secretsmanager_secret_version" "aspnet_core_secret_value" { resource "aws_secretsmanager_secret" "misc_secret" { name = "external/${var.app_name}-misc-secret-${var.environment}" - kms_key_id = aws_kms_key.kms_key.arn + kms_key_id = var.kms_key_arn } resource "aws_secretsmanager_secret_version" "misc_secret_value" { @@ -148,13 +148,14 @@ resource "aws_secretsmanager_secret_version" "misc_secret_value" { realIpFrom = "", apiUrl = "" siteMinderLogoutUrl = "", - includeSiteMinderHeaders = "" + includeSiteMinderHeaders = "", + mtlsCert = "" }) } resource "aws_secretsmanager_secret" "auth_secret" { name = "external/${var.app_name}-auth-secret-${var.environment}" - kms_key_id = aws_kms_key.kms_key.arn + kms_key_id = var.kms_key_arn } resource "aws_secretsmanager_secret_version" "auth_secret_value" { @@ -162,6 +163,21 @@ resource "aws_secretsmanager_secret_version" "auth_secret_value" { secret_string = jsonencode({ userId = "", userPassword = "", - allowSiteMinderUserType = "" + allowSiteMinderUserType = "", + apigwApiKey = "" + }) +} + +resource "aws_secretsmanager_secret" "mtls_cert_secret" { + name = "external/${var.app_name}-mtls-cert-secret-${var.environment}" + kms_key_id = var.kms_key_arn +} + +resource "aws_secretsmanager_secret_version" "mtls_cert_secret_value" { + secret_id = aws_secretsmanager_secret.mtls_cert_secret.id + secret_string = jsonencode({ + cert = "", + key = "", + ca = "" }) } diff --git a/infrastructure/cloud/modules/security/outputs.tf b/infrastructure/cloud/modules/SecretsManager/output.tf similarity index 83% rename from infrastructure/cloud/modules/security/outputs.tf rename to infrastructure/cloud/modules/SecretsManager/output.tf index add54138..7c3b8803 100644 --- a/infrastructure/cloud/modules/security/outputs.tf +++ b/infrastructure/cloud/modules/SecretsManager/output.tf @@ -1,24 +1,25 @@ - -output "kms_key_alias" { - value = aws_kms_alias.kms_alias.name -} - -output "ecs_execution_role_arn" { - value = aws_iam_role.ecs_execution_role.arn -} - -output "kms_key_id" { - value = aws_kms_key.kms_key.key_id -} - -output "kms_key_arn" { - value = aws_kms_key.kms_key.arn +output "secrets_arn_list" { + value = [ + aws_secretsmanager_secret.aspnet_core_secret.arn, + aws_secretsmanager_secret.auth_secret.arn, + aws_secretsmanager_secret.database_secret.arn, + aws_secretsmanager_secret.file_services_client_secret.arn, + aws_secretsmanager_secret.keycloak_secret.arn, + aws_secretsmanager_secret.location_services_client_secret.arn, + aws_secretsmanager_secret.lookup_services_client_secret.arn, + aws_secretsmanager_secret.misc_secret.arn, + aws_secretsmanager_secret.mtls_cert_secret.arn, + aws_secretsmanager_secret.request_secret.arn, + aws_secretsmanager_secret.splunk_secret.arn, + aws_secretsmanager_secret.user_services_client_secret.arn + ] } output "api_secrets" { value = [ ["ASPNETCORE_URLS", "${aws_secretsmanager_secret.aspnet_core_secret.arn}:urls::"], ["ASPNETCORE_ENVIRONMENT", "${aws_secretsmanager_secret.aspnet_core_secret.arn}:environment::"], + ["AWS_API_GATEWAY_API_KEY", "${aws_secretsmanager_secret.auth_secret.arn}:apigwApiKey::"], ["Auth__UserId", "${aws_secretsmanager_secret.auth_secret.arn}:userId::"], ["Auth__UserPassword", "${aws_secretsmanager_secret.auth_secret.arn}:userPassword::"], ["Auth__AllowSiteMinderUserType", "${aws_secretsmanager_secret.auth_secret.arn}:allowSiteMinderUserType::"], @@ -74,6 +75,6 @@ output "db_password" { sensitive = true } -output "default_lb_cert_arn" { - value = data.aws_acm_certificate.default_lb_cert.arn +output "mtls_secret_name" { + value = aws_secretsmanager_secret.mtls_cert_secret.name } diff --git a/infrastructure/cloud/modules/SecretsManager/variables.tf b/infrastructure/cloud/modules/SecretsManager/variables.tf new file mode 100644 index 00000000..b234206c --- /dev/null +++ b/infrastructure/cloud/modules/SecretsManager/variables.tf @@ -0,0 +1,19 @@ +variable "environment" { + description = "The environment to deploy the application to" + type = string +} + +variable "app_name" { + description = "The name of the application" + type = string +} + +variable "region" { + description = "The AWS region" + type = string +} + +variable "kms_key_arn" { + description = "The KMS Key ARN" + type = string +} diff --git a/infrastructure/cloud/modules/networking/subnets.tf b/infrastructure/cloud/modules/Subnets/main.tf similarity index 64% rename from infrastructure/cloud/modules/networking/subnets.tf rename to infrastructure/cloud/modules/Subnets/main.tf index 237d4a27..71b05998 100644 --- a/infrastructure/cloud/modules/networking/subnets.tf +++ b/infrastructure/cloud/modules/Subnets/main.tf @@ -1,7 +1,7 @@ data "aws_subnets" "all_subnets" { filter { name = "vpc-id" - values = [data.aws_vpc.vpc.id] + values = [var.vpc_id] } } @@ -15,7 +15,10 @@ locals { for tag_value in var.web_subnet_names : tag_value => [ for subnet in data.aws_subnet.subnets : - subnet.id if substr(subnet.tags["Name"], 0, length(tag_value)) == tag_value + { + id = subnet.id + cidr_block = subnet.cidr_block + } if substr(subnet.tags["Name"], 0, length(tag_value)) == tag_value ] } @@ -27,7 +30,10 @@ locals { for tag_value in var.app_subnet_names : tag_value => [ for subnet in data.aws_subnet.subnets : - subnet.id if substr(subnet.tags["Name"], 0, length(tag_value)) == tag_value + { + id = subnet.id + cidr_block = subnet.cidr_block + } if substr(subnet.tags["Name"], 0, length(tag_value)) == tag_value ] } @@ -39,7 +45,10 @@ locals { for tag_value in var.data_subnet_names : tag_value => [ for subnet in data.aws_subnet.subnets : - subnet.id if substr(subnet.tags["Name"], 0, length(tag_value)) == tag_value + { + id = subnet.id + cidr_block = subnet.cidr_block + } if substr(subnet.tags["Name"], 0, length(tag_value)) == tag_value ] } diff --git a/infrastructure/cloud/modules/Subnets/outputs.tf b/infrastructure/cloud/modules/Subnets/outputs.tf new file mode 100644 index 00000000..50894849 --- /dev/null +++ b/infrastructure/cloud/modules/Subnets/outputs.tf @@ -0,0 +1,11 @@ +output "web_subnets_ids" { + value = [for subnet in local.web_subnets : subnet.id] +} + +output "app_subnets_ids" { + value = [for subnet in local.app_subnets : subnet.id] +} + +output "data_subnets_ids" { + value = [for subnet in local.data_subnets : subnet.id] +} diff --git a/infrastructure/cloud/modules/Subnets/variables.tf b/infrastructure/cloud/modules/Subnets/variables.tf new file mode 100644 index 00000000..1e83a401 --- /dev/null +++ b/infrastructure/cloud/modules/Subnets/variables.tf @@ -0,0 +1,19 @@ +variable "web_subnet_names" { + description = "List of Subnets for Web" + type = list(string) +} + +variable "app_subnet_names" { + description = "List of Subnets for App" + type = list(string) +} + +variable "data_subnet_names" { + description = "List of Subnets for Data" + type = list(string) +} + +variable "vpc_id" { + description = "The provisioned VPC ID" + type = string +} diff --git a/infrastructure/cloud/modules/TargetGroup/main.tf b/infrastructure/cloud/modules/TargetGroup/main.tf new file mode 100644 index 00000000..b466c346 --- /dev/null +++ b/infrastructure/cloud/modules/TargetGroup/main.tf @@ -0,0 +1,20 @@ +resource "aws_lb_target_group" "target_group" { + name = "${var.app_name}-${var.name}-tg-${var.environment}" + port = var.port + protocol = var.protocol + vpc_id = var.vpc_id + target_type = "ip" + deregistration_delay = 5 + + health_check { + protocol = var.protocol + path = var.health_check_path + port = var.port + interval = 30 + timeout = 5 + enabled = true + healthy_threshold = 3 + unhealthy_threshold = 3 + matcher = "200" + } +} diff --git a/infrastructure/cloud/modules/TargetGroup/output.tf b/infrastructure/cloud/modules/TargetGroup/output.tf new file mode 100644 index 00000000..2f288873 --- /dev/null +++ b/infrastructure/cloud/modules/TargetGroup/output.tf @@ -0,0 +1,3 @@ +output "tg_arn" { + value = aws_lb_target_group.target_group.arn +} diff --git a/infrastructure/cloud/modules/TargetGroup/variables.tf b/infrastructure/cloud/modules/TargetGroup/variables.tf new file mode 100644 index 00000000..1c84cb1d --- /dev/null +++ b/infrastructure/cloud/modules/TargetGroup/variables.tf @@ -0,0 +1,34 @@ +variable "app_name" { + description = "The name of the application" + type = string +} + +variable "environment" { + description = "The AWS environment to deploy to" + type = string +} + +variable "name" { + description = "The name of Target Group" + type = string +} + +variable "port" { + description = "The port number" + type = number +} + +variable "health_check_path" { + description = "The health check path" + type = string +} + +variable "vpc_id" { + description = "The VPC Id" + type = string +} + +variable "protocol" { + description = "The protocol that will be used by the Target Group and Health Check" + type = string +} diff --git a/infrastructure/cloud/modules/container/ecs.tf b/infrastructure/cloud/modules/container/ecs.tf deleted file mode 100644 index 99f15669..00000000 --- a/infrastructure/cloud/modules/container/ecs.tf +++ /dev/null @@ -1,155 +0,0 @@ -resource "aws_ecs_cluster" "ecs_cluster" { - name = "${var.app_name}-ecs-cluster-${var.environment}" - - setting { - name = "containerInsights" - value = "enabled" - } - - tags = { - name = "${var.app_name}-ecs-cluster-${var.environment}" - } -} - -# Web -resource "aws_ecs_task_definition" "ecs_web_task_definition" { - family = "${var.app_name}-web-task-definition-${var.environment}" - network_mode = "awsvpc" - requires_compatibilities = ["FARGATE"] - cpu = 256 - memory = 512 - execution_role_arn = var.ecs_execution_role_arn - task_role_arn = var.ecs_execution_role_arn - - lifecycle { - ignore_changes = [container_definitions] - } - - container_definitions = jsonencode([ - { - name = "${var.app_name}-web-container-${var.environment}" - image = "${aws_ecr_repository.ecr_repository.repository_url}:jasper-web" - essential = true - portMappings = [ - { - containerPort = 8080 - hostPort = 8080 - protocol = "tcp" - } - ] - logConfiguration = { - logDriver = "awslogs" - options = { - "awslogs-group" = var.ecs_web_td_log_group_name - "awslogs-region" = var.region - "awslogs-stream-prefix" = "ecs" - } - } - secrets = [ - for secret in var.web_secrets : { - name = secret[0] - valueFrom = secret[1] - } - ] - } - ]) -} - -resource "aws_ecs_service" "ecs_web_service" { - name = "${var.app_name}-ecs-web-service-${var.environment}" - cluster = aws_ecs_cluster.ecs_cluster.id - task_definition = aws_ecs_task_definition.ecs_web_task_definition.arn - launch_type = "FARGATE" - desired_count = 1 - enable_execute_command = true - - network_configuration { - subnets = var.web_subnet_ids - security_groups = [var.app_sg_id] - assign_public_ip = true - } - - load_balancer { - target_group_arn = var.web_tg_arn - container_name = "${var.app_name}-web-container-${var.environment}" - container_port = 8080 - } - - lifecycle { - prevent_destroy = true - } -} - -# API -resource "aws_ecs_task_definition" "ecs_api_task_definition" { - family = "${var.app_name}-api-task-definition-${var.environment}" - network_mode = "awsvpc" - requires_compatibilities = ["FARGATE"] - cpu = 256 - memory = 512 - execution_role_arn = var.ecs_execution_role_arn - task_role_arn = var.ecs_execution_role_arn - - lifecycle { - ignore_changes = [container_definitions] - } - - container_definitions = jsonencode([ - { - name = "${var.app_name}-api-container-${var.environment}" - image = "${aws_ecr_repository.ecr_repository.repository_url}:jasper-api" - essential = true - portMappings = [ - { - containerPort = 5000 - hostPort = 5000 - protocol = "tcp" - } - ] - environment = [ - { - name = "CORS_DOMAIN" - value = var.default_lb_dns_name - } - ] - secrets = [ - for secret in var.api_secrets : { - name = secret[0] - valueFrom = secret[1] - } - ] - logConfiguration = { - logDriver = "awslogs" - options = { - "awslogs-group" = var.ecs_api_td_log_group_name - "awslogs-region" = var.region - "awslogs-stream-prefix" = "ecs" - } - } - } - ]) -} - -resource "aws_ecs_service" "ecs_api_service" { - name = "${var.app_name}-ecs-api-service-${var.environment}" - cluster = aws_ecs_cluster.ecs_cluster.id - task_definition = aws_ecs_task_definition.ecs_api_task_definition.arn - launch_type = "FARGATE" - desired_count = 1 - - network_configuration { - subnets = var.app_subnet_ids - security_groups = [var.app_sg_id] - assign_public_ip = true - } - - load_balancer { - target_group_arn = var.api_tg_arn - container_name = "${var.app_name}-api-container-${var.environment}" - container_port = 5000 - } - - lifecycle { - prevent_destroy = true - } -} diff --git a/infrastructure/cloud/modules/container/outputs.tf b/infrastructure/cloud/modules/container/outputs.tf deleted file mode 100644 index 349fdf78..00000000 --- a/infrastructure/cloud/modules/container/outputs.tf +++ /dev/null @@ -1,7 +0,0 @@ -output "ecr_url" { - value = try(aws_ecr_repository.ecr_repository.repository_url, "") -} - -output "ecr_repository_arn" { - value = aws_ecr_repository.ecr_repository.arn -} diff --git a/infrastructure/cloud/modules/container/variables.tf b/infrastructure/cloud/modules/container/variables.tf deleted file mode 100644 index 7b623789..00000000 --- a/infrastructure/cloud/modules/container/variables.tf +++ /dev/null @@ -1,79 +0,0 @@ -variable "environment" { - description = "The environment to deploy the application to" - type = string -} - -variable "app_name" { - description = "The name of the application" - type = string -} - -variable "region" { - description = "The AWS region" - type = string -} - -variable "ecs_execution_role_arn" { - description = "ECS Execution Role ARN" - type = string -} - -variable "web_subnet_ids" { - description = "The Web Subnet IDs" - type = list(string) -} - -variable "app_subnet_ids" { - description = "The App Subnet IDs" - type = list(string) -} - -variable "web_sg_id" { - description = "The BCGOV provisioned Web Security Group" - type = string -} - -variable "app_sg_id" { - description = "The BCGOV provisioned App Security Group" - type = string -} - -variable "web_tg_arn" { - description = "The Web Target Group ARN" - type = string -} - -variable "api_tg_arn" { - description = "The API Target Group ARN" - type = string -} - -variable "ecs_web_td_log_group_name" { - description = "ECS Web Task Definition Log Group Name in CloudWatch" - type = string -} - -variable "ecs_api_td_log_group_name" { - description = "ECS API Task Definition Log Group Name in CloudWatch" - type = string -} - -variable "kms_key_id" { - description = "The KMS Key ID" - type = string -} - -variable "default_lb_dns_name" { - description = "The BCGov Load Balancer DNS Name" - type = string -} - -variable "api_secrets" { - description = "List if env variable secrets used in API" - type = list(list(string)) -} - -variable "web_secrets" { - description = "List if env variable secrets used in Web" - type = list(list(string)) -} diff --git a/infrastructure/cloud/modules/monitoring/logs.tf b/infrastructure/cloud/modules/monitoring/logs.tf deleted file mode 100644 index 61c74f30..00000000 --- a/infrastructure/cloud/modules/monitoring/logs.tf +++ /dev/null @@ -1,13 +0,0 @@ -resource "aws_cloudwatch_log_group" "ecs_web_td_log_group" { - name = "/aws/ecs/${var.app_name}-ecs-web-td-log-group-${var.environment}" - retention_in_days = 90 - - kms_key_id = var.kms_key_arn -} - -resource "aws_cloudwatch_log_group" "ecs_api_td_log_group" { - name = "/aws/ecs/${var.app_name}-ecs-api-td-log-group-${var.environment}" - retention_in_days = 90 - - kms_key_id = var.kms_key_arn -} diff --git a/infrastructure/cloud/modules/monitoring/outputs.tf b/infrastructure/cloud/modules/monitoring/outputs.tf deleted file mode 100644 index 7b277a6b..00000000 --- a/infrastructure/cloud/modules/monitoring/outputs.tf +++ /dev/null @@ -1,15 +0,0 @@ -output "ecs_web_td_log_group_name" { - value = aws_cloudwatch_log_group.ecs_web_td_log_group.name -} - -output "ecs_web_td_log_group_arn" { - value = aws_cloudwatch_log_group.ecs_web_td_log_group.arn -} - -output "ecs_api_td_log_group_name" { - value = aws_cloudwatch_log_group.ecs_api_td_log_group.name -} - -output "ecs_api_td_log_group_arn" { - value = aws_cloudwatch_log_group.ecs_api_td_log_group.arn -} diff --git a/infrastructure/cloud/modules/networking/outputs.tf b/infrastructure/cloud/modules/networking/outputs.tf deleted file mode 100644 index 313ef830..00000000 --- a/infrastructure/cloud/modules/networking/outputs.tf +++ /dev/null @@ -1,34 +0,0 @@ -output "web_tg_arn" { - value = aws_lb_target_group.web_target_group.arn -} - -output "api_tg_arn" { - value = aws_lb_target_group.api_target_group.arn -} - -output "web_sg_id" { - value = data.aws_security_group.web_sg.id -} - -output "app_sg_id" { - value = data.aws_security_group.app_sg.id -} - -output "web_subnets_ids" { - value = local.web_subnets -} - -output "app_subnets_ids" { - value = local.app_subnets -} -output "data_subnets_ids" { - value = local.data_subnets -} - -output "default_lb_dns_name" { - value = data.aws_lb.default_lb.dns_name -} - -output "data_sg_id" { - value = data.aws_security_group.data_sg.id -} diff --git a/infrastructure/cloud/modules/networking/securitygroup.tf b/infrastructure/cloud/modules/networking/securitygroup.tf deleted file mode 100644 index 0dc0f892..00000000 --- a/infrastructure/cloud/modules/networking/securitygroup.tf +++ /dev/null @@ -1,161 +0,0 @@ -# -# BCGOV provisioned security groups -# -data "aws_security_group" "web_sg" { - name = "Web_sg" -} - -data "aws_security_group" "app_sg" { - name = "App_sg" -} - -data "aws_security_group" "data_sg" { - name = "Data_sg" -} - -# # -# # Load Balancer Security Group -# # -# resource "aws_security_group" "lb_sg" { -# name = "${var.app_name}-lb-sg-${var.environment}" -# vpc_id = data.aws_vpc.vpc.id -# description = "Security Group for the Application Load Balancer" - -# tags = { -# Name = "${var.app_name}_lb_sg_${var.environment}" -# } -# } - -# # Load Balancer Ingress Rules. This will change once we get the public load balancer details from cloud team. -# resource "aws_vpc_security_group_ingress_rule" "lb_sg_ingress_http_allow_80" { -# security_group_id = aws_security_group.lb_sg.id -# description = "Allow inbound HTTP traffic on port 80" -# ip_protocol = "tcp" -# from_port = 80 -# to_port = 80 -# cidr_ipv4 = "0.0.0.0/0" -# } - -# resource "aws_vpc_security_group_ingress_rule" "lb_sg_ingress_http_allow_8080" { -# security_group_id = aws_security_group.lb_sg.id -# description = "Allow inbound HTTP traffic on port 8080" -# ip_protocol = "tcp" -# from_port = 8080 -# to_port = 8080 -# cidr_ipv4 = "0.0.0.0/0" -# } - -# # Load Balancer Egress Rules -# resource "aws_vpc_security_group_egress_rule" "lb_sg_egress_allow_to_ecs_sg" { -# security_group_id = aws_security_group.lb_sg.id -# referenced_security_group_id = aws_security_group.ecs_sg.id -# description = "Allow all outbound traffic to ECS SG from Load Balancer SG" -# ip_protocol = "-1" -# } - -# # -# # ECS Security Group -# # -# resource "aws_security_group" "ecs_sg" { -# name = "${var.app_name}-ecs-sg-${var.environment}" -# vpc_id = data.aws_vpc.vpc.id -# description = "Security Group for ECS services" - -# tags = { -# Name = "${var.app_name}_ecs_sg_${var.environment}" -# } -# } - -# # ECS Ingress Rules -# # Remove ecs_sg_ingress_allow_icmp and ecs_sg_ingress_allow_ssh once the JASPER -# # is publicly accessible. These ingress rules is for tesing SG-SG connectivity using -# # EC2 Instance and EC2 Instance Connect Endpoint -# resource "aws_vpc_security_group_ingress_rule" "ecs_sg_ingress_allow_from_web_sg" { -# security_group_id = aws_security_group.ecs_sg.id -# referenced_security_group_id = data.aws_security_group.web_sg.id -# description = "Allow all inbound traffic from Web SG" -# ip_protocol = -1 -# } - -# resource "aws_vpc_security_group_ingress_rule" "ecs_sg_ingress_allow_from_lambda_sg" { -# security_group_id = aws_security_group.ecs_sg.id -# referenced_security_group_id = aws_security_group.lambda_sg.id -# description = "Allow all inbound traffic from Lambda SG" -# ip_protocol = -1 -# } - -# resource "aws_vpc_security_group_ingress_rule" "ecs_sg_ingress_allow_icmp" { -# security_group_id = aws_security_group.ecs_sg.id -# description = "Allow inbound ICMP traffic to ECS SG to allow pinging the Lambda SG" -# ip_protocol = "icmp" -# from_port = -1 -# to_port = -1 -# cidr_ipv4 = "0.0.0.0/0" -# } - -# resource "aws_vpc_security_group_ingress_rule" "ecs_sg_ingress_allow_ssh" { -# security_group_id = aws_security_group.ecs_sg.id -# description = "Allow inbound SSH traffic to ECS SG" -# ip_protocol = "tcp" -# from_port = 22 -# to_port = 22 -# cidr_ipv4 = data.aws_vpc.vpc.cidr_block -# } - -# # ECS Egress Rules -# resource "aws_vpc_security_group_egress_rule" "ecs_sg_egress_allow_to_anywhere" { -# security_group_id = aws_security_group.ecs_sg.id -# description = "Unrestricted" -# ip_protocol = "-1" -# cidr_ipv4 = "0.0.0.0/0" -# } - -# # -# # Lambda Security Group -# # -# resource "aws_security_group" "lambda_sg" { -# name = "${var.app_name}-lambda-sg-${var.environment}" -# vpc_id = data.aws_vpc.vpc.id -# description = "Security Group for Lambda functions" - -# tags = { -# Name = "${var.app_name}_lambda_sg_${var.environment}" -# } -# } - -# # Lambda Ingress Rules -# # Remove lambda_sg_ingress_allow_icmp and lambda_sg_ingress_allow_ssh once the JASPER -# # is publicly accessible. These ingress rules is for tesing SG-SG connectivity using -# # EC2 Instance and EC2 Instance Connect Endpoint -# resource "aws_vpc_security_group_ingress_rule" "lambda_sg_ingress_allow_from_ecs_sg" { -# security_group_id = aws_security_group.lambda_sg.id -# referenced_security_group_id = aws_security_group.ecs_sg.id -# description = "Allow all inbound traffic from ECS SG" -# ip_protocol = -1 -# } - -# resource "aws_vpc_security_group_ingress_rule" "lambda_sg_ingress_allow_icmp" { -# security_group_id = aws_security_group.lambda_sg.id -# description = "Allow inbound ICMP traffic to Lambda SG to allow pinging the ECS SG" -# ip_protocol = "icmp" -# from_port = -1 -# to_port = -1 -# cidr_ipv4 = "0.0.0.0/0" -# } - -# resource "aws_vpc_security_group_ingress_rule" "lambda_sg_ingress_allow_ssh" { -# security_group_id = aws_security_group.lambda_sg.id -# description = "Allow inbound SSH traffic to Lambda SG" -# ip_protocol = "tcp" -# from_port = 22 -# to_port = 22 -# cidr_ipv4 = data.aws_vpc.vpc.cidr_block -# } - -# # Lambda Egress Rules -# resource "aws_vpc_security_group_egress_rule" "lambda_sg_egress_allow_to_anywhere" { -# security_group_id = aws_security_group.lambda_sg.id -# description = "Unrestricted" -# ip_protocol = "-1" -# cidr_ipv4 = "0.0.0.0/0" -# } diff --git a/infrastructure/cloud/modules/networking/targetgroups.tf b/infrastructure/cloud/modules/networking/targetgroups.tf deleted file mode 100644 index cf6faff2..00000000 --- a/infrastructure/cloud/modules/networking/targetgroups.tf +++ /dev/null @@ -1,42 +0,0 @@ -# Web -resource "aws_lb_target_group" "web_target_group" { - name = "${var.app_name}-web-tg-${var.environment}" - port = 8080 - protocol = "HTTPS" - vpc_id = data.aws_vpc.vpc.id - target_type = "ip" - deregistration_delay = 5 - - health_check { - protocol = "HTTPS" - path = "/" - port = 8080 - interval = 30 - timeout = 5 - enabled = true - healthy_threshold = 3 - unhealthy_threshold = 3 - matcher = "200" - } -} - -# API -resource "aws_lb_target_group" "api_target_group" { - name = "${var.app_name}-api-tg-${var.environment}" - port = 5000 - protocol = "HTTP" - vpc_id = data.aws_vpc.vpc.id - target_type = "ip" - deregistration_delay = 5 - - health_check { - path = "/api/test/headers" - port = 5000 - interval = 30 - timeout = 5 - enabled = true - healthy_threshold = 3 - unhealthy_threshold = 3 - matcher = "200" - } -} diff --git a/infrastructure/cloud/modules/networking/vpc.tf b/infrastructure/cloud/modules/networking/vpc.tf deleted file mode 100644 index 34f36776..00000000 --- a/infrastructure/cloud/modules/networking/vpc.tf +++ /dev/null @@ -1,3 +0,0 @@ -data "aws_vpc" "vpc" { - id = var.vpc_id -} diff --git a/infrastructure/cloud/modules/security/acm.tf b/infrastructure/cloud/modules/security/acm.tf deleted file mode 100644 index e8369d8d..00000000 --- a/infrastructure/cloud/modules/security/acm.tf +++ /dev/null @@ -1,5 +0,0 @@ -data "aws_acm_certificate" "default_lb_cert" { - domain = var.cert_domain_name - most_recent = true - statuses = ["ISSUED"] -} diff --git a/infrastructure/cloud/modules/security/variables.tf b/infrastructure/cloud/modules/security/variables.tf deleted file mode 100644 index 651ba3d2..00000000 --- a/infrastructure/cloud/modules/security/variables.tf +++ /dev/null @@ -1,44 +0,0 @@ -variable "kms_key_name" { - description = "Name of KMS key" - type = string -} - -variable "app_name" { - description = "The name of the application" - type = string -} - -variable "environment" { - description = "The AWS environment to deploy to" - type = string -} - -variable "ecs_web_td_log_group_arn" { - description = "The ECS Web Task Definition Log Group ARN" - type = string -} - -variable "ecs_api_td_log_group_arn" { - description = "The ECS API Task Definition Log Group ARN" - type = string -} - -variable "ecr_repository_arn" { - description = "The ECR Repository ARN" - type = string -} - -variable "openshift_iam_user" { - description = "Openshift IAM Username" - type = string -} - -variable "iam_user_table_name" { - description = "The BCGOV IAM User DynamoDb table name" - type = string -} - -variable "cert_domain_name" { - description = "The BCGov provisioned certificate domain name" - type = string -}