Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

WFPREV-30 Configure Amazon Cloudfront for WFPREV UI (#223) #226

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 11 additions & 9 deletions .github/workflows/build-full-environment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,7 @@ on:
description: Additional tag to add to built images

jobs:
wfprev-ui:
uses: ./.github/workflows/mvn-build.yml
secrets: inherit
with:
COMPONENT_NAME: wfprev-war
TAG: latest
COMPONENT_TYPE: client


wfprev-api:
uses: ./.github/workflows/mvn-build.yml
secrets: inherit
Expand All @@ -49,8 +42,17 @@ jobs:

terragrunt-deploy-dev:
uses: ./.github/workflows/terragrunt-deploy.yml
needs: [wfprev-ui, wfprev-api, liquibase-build]
needs: [wfprev-api, liquibase-build]
with:
DEFAULT_APPLICATION_ENVIRONMENT: dev
IMAGE_TAG: latest
secrets: inherit

wfprev-ui:
uses: ./.github/workflows/client-build.yml
needs: [terragrunt-deploy-dev]
with:
DEFAULT_APPLICATION_ENVIRONMENT: dev
IMAGE_TAG: latest
secrets: inherit

85 changes: 85 additions & 0 deletions .github/workflows/client-build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
name: Deploy Angular App to S3 and CloudFront

on:
push:
branches:
- main # Adjust to your deployment branch
workflow_call:
inputs:
DEFAULT_APPLICATION_ENVIRONMENT:
required: true
type: string
IMAGE_TAG:
required: true
type: string

env:
TF_VERSION: 1.8.5

jobs:
build-and-deploy:
runs-on: ubuntu-latest

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

- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ secrets.AWS_TERRAFORM_ROLE_TO_ASSUME }}
role-session-name: wfprev-terraform-s3
aws-region: ca-central-1

- name: Set up Terraform
uses: hashicorp/setup-terraform@v2
with:
terraform_version: ${{ env.TF_VERSION }}

- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: '20'

- name: Install dependencies
run: npm install

- name: Build Angular App
run: npm run build --prod

- name: Initialize Terraform
run: terraform init

# Fetch CloudFront Distribution ID in order to invalidate cache
- name: Fetch CloudFront Distribution ID
id: get_cf_id
run: |
export CLOUDFRONT_ID=$(terraform output -raw cloudfront_distribution_id)
echo "CLOUDFRONT_DISTRIBUTION_ID=$CLOUDFRONT_ID" >> $GITHUB_ENV

- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ secrets.AWS_S3_PUSH_ROLE }}
role-session-name: wfprev-push-s3
aws-region: ca-central-1

# this will require the bucket to exist
# so terraform step will need to run first
- name: Sync files to S3
run: |
aws s3 sync ./dist/wfprev s3://wfprev_site_bucket \
--delete \
--cache-control max-age=31536000,public \
--exclude index.html
aws s3 cp ./dist/wfprev/index.html s3://wfprev_site_bucket/index.html \
--cache-control max-age=0,no-cache,no-store,must-revalidate

- name: Invalidate CloudFront Cache
run: |
aws cloudfront create-invalidation \
--distribution-id ${{ env.CLOUDFRONT_DISTRIBUTION_ID }} \
--paths "/*"
# see distribution ID section in terraform scripts
# Like the sync, this means we need to run terraform first, then
# trigger this action with the returned distribution ID
2 changes: 1 addition & 1 deletion .github/workflows/liquibase-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ jobs:
packages: write

steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4

- id: trimBranchName
name: trim branch name if necessary
Expand Down
54 changes: 5 additions & 49 deletions .github/workflows/mvn-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ on:
type: choice
options:
- server
- client
- libs
workflow_call:
inputs:
Expand All @@ -44,16 +43,16 @@ jobs:
environment:
name: ${{ inputs.ENVIRONMENT }}
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
if: ${{ inputs.IS_HOTFIX != 'true' }}

- uses: actions/checkout@v3
- uses: actions/checkout@v4
if: ${{ inputs.IS_HOTFIX == 'true' }}
with:
ref: ${{ inputs.BRANCH }}

- name: Set up Node.js 20.x
uses: actions/setup-node@v3
uses: actions/setup-node@v4
with:
node-version: '20.x'

Expand All @@ -65,29 +64,6 @@ jobs:

- name: Add .npmrc file
run: echo -e $NPMRC > ~/.npmrc


- name: Install dependencies for Angular project
if: ${{ inputs.COMPONENT_TYPE == 'client' }}
run: |
cd ${{ inputs.COMPONENT_TYPE }}/wfprev-war/src/main/angular
npm install
- name: Build Angular app
if: ${{ inputs.COMPONENT_TYPE == 'client' }}
run: |
cd ${{ inputs.COMPONENT_TYPE }}/wfprev-war/src/main/angular
npm run build -- --configuration=production --base-href=/pub/wfprev/

- name: Copy client built files to necessary folder
if: ${{ inputs.COMPONENT_TYPE == 'client' }}
run: mkdir -p staging-client && cp -r ${{ inputs.COMPONENT_TYPE }}/wfprev-war/src/main/angular/dist/wfprev/* staging-client/

- name: Upload client artifact
if: ${{ inputs.COMPONENT_TYPE == 'client' }}
uses: actions/upload-artifact@v3
with:
name: ${{ inputs.COMPONENT_NAME }}-package
path: staging-client

- name: Build API with Maven
if: ${{ inputs.COMPONENT_TYPE == 'server' }}
Expand Down Expand Up @@ -121,7 +97,7 @@ jobs:
packages: write

steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
if: ${{ github.event.inputs.IS_HOTFIX != 'true' }}

- id: trimBranchName
Expand All @@ -131,20 +107,11 @@ jobs:
trimTag="${branchTag##*/}"
echo "BRANCH_TAG=$trimTag" >> $GITHUB_OUTPUT

# - uses: actions/checkout@v3
# - uses: actions/checkout@v4
# if: ${{ github.event.inputs.IS_HOTFIX == 'true' }}
# with:
# ref: ${{ inputs.BRANCH }}


# Download client artifact
- name: download client artifact
uses: actions/download-artifact@v3
if: ${{ inputs.COMPONENT_TYPE == 'client' }}
with:
name: wfprev-war-package
path: client/wfprev-war/dist/wfprev

- name: download server artifact
uses: actions/download-artifact@v3
with:
Expand Down Expand Up @@ -180,17 +147,6 @@ jobs:
type=ref,event=tag
type=raw,value=${{ inputs.TAG }}

- name: Build and push Client Docker image
if: ${{ inputs.COMPONENT_TYPE == 'client' }}
uses: docker/build-push-action@v6
with:
context: client/wfprev-war
build-args: |
CONTAINER_NAME=wfprev-war
push: true
tags: ${{ steps.meta_pr.outputs.tags }}
labels: ${{ steps.meta_pr.outputs.labels }}

- name: Build and push Docker image
uses: docker/build-push-action@v6
with:
Expand Down
7 changes: 2 additions & 5 deletions .github/workflows/terragrunt-deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ jobs:
contents: read # This is required for actions/checkout

steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
# - name: retrieve lambda artifacts
# uses: actions/download-artifact@v3
# with:
Expand Down Expand Up @@ -105,7 +105,7 @@ jobs:
echo "IMAGE_UI_BY_DIGEST=$(docker inspect --format='{{index .RepoDigests 0}}' $IMAGE)" >> $GITHUB_OUTPUT

- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v2
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ secrets.AWS_TERRAFORM_ROLE_TO_ASSUME }}
role-session-name: wfprev-terraform-s3
Expand All @@ -114,7 +114,6 @@ jobs:
- uses: hashicorp/setup-terraform@v2
with:
terraform_version: ${{ env.TF_VERSION }}
cli_config_credentials_token: ${{ secrets.TFC_TEAM_TOKEN }}

- uses: peter-murray/[email protected]
with:
Expand Down Expand Up @@ -149,8 +148,6 @@ jobs:
# WFPREV UI
CLIENT_IMAGE: ${{ steps.getDigestUI.outputs.IMAGE_UI_BY_DIGEST }}
WEBADE_OAUTH2_WFPREV_UI_CLIENT_SECRET: ${{ secrets.WEBADE_OAUTH2_WFPREV_UI_CLIENT_SECRET }}
WFPREV_CLIENT_MEMORY: ${{vars.WFPREV_CLIENT_MEMORY}}
WFPREV_CLIENT_CPU_UNITS : ${{vars.WFPREV_CLIENT_CPU_UNITS}}

# DB
WFPREV_USERNAME: ${{secrets.WFPREV_USERNAME}}
Expand Down
14 changes: 13 additions & 1 deletion terraform/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ The api_gateway.tf file configures an API Gateway to expose the WFPREV API for e
autoscaling.tf:
The autoscaling.tf file sets up auto scaling for multiple ECS services within the WFPrev application, including the main service, nginx, and client. It utilizes AWS Application Auto Scaling to dynamically adjust the number of tasks running in each service based on CPU utilization. The file defines scaling targets, step scaling policies for both scaling up and down, and associated CloudWatch alarms. These alarms monitor CPU utilization, triggering scale-up actions when utilization exceeds 50% and scale-down actions when it falls below 10%. The configuration allows each service to scale between 1 and 10 tasks, with a 60-second cooldown period between scaling actions. This setup ensures that the application can efficiently handle varying loads while optimizing resource usage and costs.

cloudfront.tf:
The cloudfront.tf file defines a CloudFront distribution to serve content from an S3 bucket securely, using an Origin Access Identity (OAI) to restrict bucket access. It specifies caching behavior with customizable TTL settings, enforces HTTPS via a viewer protocol policy, and restricts query string and cookie forwarding to optimize performance. The configuration enables IPv6, sets index.html as the default root object, and uses a default CloudFront certificate for HTTPS. Additionally, it outputs the distribution ID, making it easy to reference in other workflows or scripts.

ecs.tf:
This file sets up an ECS cluster for deploying the WFPREV server and client applications using FARGATE and FARGATE_SPOT capacity providers. It defines task definitions for both server and client containers, including resource allocations, environment variables, and logging configurations. The wfprev_client and wfprev_server task definitons here are setting iam roles for execution, network mode, provisionsing CPU and memory allocation, and setting volumes on the cluster for deployment of the client and server. The wfprev-liquibase task definition does the same allocation and runs database migrations. The file also creates ECS services to manage these tasks, linking them to the appropriate load balancers for traffic routing and health checks. The network condiguration sets a custom wfprev_tomcat_access security group, subnets and assigns the container a public IP address. This file also includes logConfiguration sections within the container definitions for both the WFPrev server and client task definitions. These configurations use the "awslogs" log driver, which is designed to send container logs directly to Amazon CloudWatch Logs. The options specified in each logConfiguration block determine how the logs are organized in CloudWatch. The "awslogs-create-group" option set to "true" allows ECS to automatically create the log group if it doesn't exist. The "awslogs-group" option specifies the name of the log group in CloudWatch where the logs will be sent, typically following the pattern "/ecs/{container-name}". The "awslogs-region" option ensures logs are sent to the correct AWS region, while "awslogs-stream-prefix" adds a prefix to the log stream names for easier identification. With these configurations in place, when the ECS tasks run, the Amazon ECS container agent automatically collects the stdout and stderr outputs from the containers and sends them to CloudWatch Logs without any additional setup required. This seamless integration allows for centralized logging and monitoring of ECS tasks. The CloudWatch logs can be accessed in the Log groups section of the CloudWatch service in the AWS console.

Expand All @@ -16,8 +19,17 @@ This file defines IAM roles and policies to grant necessary permissions for ECS
main.tf:
The main.tf file sets up the Terraform configuration, specifying the required AWS provider version (~> 4.0) and ensuring Terraform itself is version 1.1.0 or higher. This establishes the foundation for managing AWS resources within the project

rds.tf:
This file sets up a PostgreSQL database instance in AWS, along with its subnet group. The database is configured for high availability with multi-AZ support, encrypted storage, and automated backups with a retention period of 7 days. It is not publicly accessible and uses a specified VPC security group for access. CloudWatch logging is enabled for monitoring, and the configuration allows updates to major versions but skips the final snapshot upon deletion. The associated subnet group defines the subnets in which the database operates.

s3.tf:
The s3.tf file creates a public S3 bucket for website hosting, with index.html as the default and error page. It includes a policy for public read access and outputs the bucket name for use in other workflows. Asset uploads are intended to be handled via GitHub Actions.

secrets.tf:
The secrets.tf file manages GitHub credentials in AWS Secrets Manager. It creates a secret named bcws_wfprev_creds_${var.TARGET_ENV} and stores the GitHub username and token in a secret version for secure access and management.

security.tf:
The security.tf file defines security groups for a web application environment. It includes data lookups for existing security groups (Web_sg, App_sg, and Data_sg) and creates two new security groups. The wfprev_tomcat_access group allows unrestricted access on a specified API port, while the jumphost group permits RDP access (port 3389) from the Web_sg and App_sg security groups within the same VPC. These groups help manage and secure traffic flow in the environment.

terragrunt-deploy.yml:
The terragrunt-deploy.yml GitHub Actions workflow automates the deployment process for the WFPREV application using Terragrunt. It supports multiple environments (dev, test, prod) and various configuration options, such as image tags and schema names. The workflow sets up AWS credentials, Terraform, and Terragrunt, then applies the Terragrunt configurations to deploy the application infrastructure and services. It also determines which Liquibase command to run for database changes and manages environment-specific variables for the deployment process.
The terragrunt-deploy.yml GitHub Actions workflow automates the deployment process for the WFPREV application using Terragrunt. It supports multiple environments (dev, test, prod) and various configuration options, such as image tags and schema names. The workflow sets up AWS credentials, Terraform, and Terragrunt, then applies the Terragrunt configurations to deploy the application infrastructure and services. It also determines which Liquibase command to run for database changes and manages environment-specific variables for the deployment process. After the Liquibase and API deployments are completed via Terraform and Terragrunt, the UI portion of the application is built and the distribution files are stored as static resources via an S3 bucket, which is served via CloudFront, a content delivery network (CDN) that caches content closer to users through a globally distributed network of edge locations.
34 changes: 0 additions & 34 deletions terraform/alb.tf
Original file line number Diff line number Diff line change
Expand Up @@ -70,21 +70,6 @@ resource "aws_lb_listener_rule" "wfprev-api" {
}
}

resource "aws_lb_listener_rule" "wfprev-ui" {
listener_arn = aws_lb_listener.wfprev_main.arn

action {
type = "forward"
target_group_arn = aws_alb_target_group.wfprev_ui.arn
}

condition {
path_pattern {
values = [for sn in var.PREVENTION_WAR_NAMES : "/${aws_apigatewayv2_stage.wfprev_stage.name}/${sn}"]
}
}
}

//////////////////////////////
/// TARGET GROUP RESOURCES ///
//////////////////////////////
Expand All @@ -108,22 +93,3 @@ resource "aws_alb_target_group" "wfprev_api" {

# tags = local.
}

resource "aws_alb_target_group" "wfprev_ui" {
name = "wfprev-ui-${var.TARGET_ENV}"
port = var.WFPREV_CLIENT_PORT
protocol = "HTTP"
vpc_id = module.network.aws_vpc.id
target_type = "ip"
deregistration_delay = 30

health_check {
healthy_threshold = "2"
interval = "300"
protocol = "HTTP"
matcher = "200"
timeout = "3"
path = "/${aws_apigatewayv2_stage.wfprev_stage.name}/${var.PREVENTION_WAR_NAMES[0]}/"
unhealthy_threshold = "2"
}
}
Loading
Loading