Skip to content

Commit

Permalink
Add API Gateway
Browse files Browse the repository at this point in the history
Use OpenAPI schema to define REST API, then add logging and IAM execution permissions.

Add an account-level IAM role for logging to CloudWatch.

Remove lambda function URLs. Test against REST API base URL.

Fixes VEGA-2014 #minor
  • Loading branch information
gregtyler committed Oct 20, 2023
1 parent 1a80069 commit 1711202
Show file tree
Hide file tree
Showing 22 changed files with 495 additions and 13 deletions.
65 changes: 65 additions & 0 deletions .github/workflows/account-deploy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
name: "[Job] Plan/Deploy to Account"

on:
workflow_call:
inputs:
workspace_name:
description: "The terraform workspace to target for account actions"
required: true
type: string
secrets:
aws_access_key_id:
description: "AWS Access Key ID"
required: true
aws_secret_access_key:
description: "AWS Secret Access Key"
required: true

jobs:
terraform_account_workflow:
runs-on: ubuntu-latest
environment:
name: ${{ inputs.workspace_name }} account
steps:
- uses: actions/checkout@v4
with:
fetch-depth: "0"
- uses: unfor19/install-aws-cli-action@v1
- uses: hashicorp/setup-terraform@v2
with:
terraform_version: 1.4.6
terraform_wrapper: false
- name: Configure AWS Credentials For Terraform
uses: aws-actions/configure-aws-credentials@v2
with:
aws-access-key-id: ${{ secrets.aws_access_key_id }}
aws-secret-access-key: ${{ secrets.aws_secret_access_key }}
aws-region: eu-west-1
role-duration-seconds: 3600
role-session-name: OPGLpaStoreGithubAction

- name: Lint Terraform
run: terraform fmt -check -recursive
working-directory: ./terraform/account
continue-on-error: true

- name: Terraform Init
run: terraform init -input=false
working-directory: ./terraform/account

- name: Terraform Plan
env:
TF_WORKSPACE: ${{ inputs.workspace_name }}
run: |
terraform workspace show
echo "plan_summary=$(terraform plan -no-color -lock-timeout=300s -input=false -parallelism=30 | grep -ioE 'Plan: [[:digit:]]+ to add, [[:digit:]]+ to change, [[:digit:]]+ to destroy|No changes. Your infrastructure matches the configuration.')" >> $GITHUB_OUTPUT
terraform plan -lock-timeout=300s -input=false -parallelism=30
working-directory: ./terraform/account

- name: Terraform Apply
if: github.ref == 'refs/heads/main'
env:
TF_WORKSPACE: ${{ inputs.workspace_name }}
run: |
terraform apply -lock-timeout=300s -input=false -auto-approve -parallelism=30
working-directory: ./terraform/account
6 changes: 3 additions & 3 deletions .github/workflows/env-deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ on:
description: "Github Token"
required: true
outputs:
create_url:
description: "URL of the create endpoint"
base_url:
description: "Base URL of API"
value: ${{ jobs.terraform_environment_workflow.outputs.url }}

jobs:
Expand Down Expand Up @@ -85,5 +85,5 @@ jobs:
TF_WORKSPACE: ${{ inputs.workspace_name }}
TF_VAR_app_version: ${{ inputs.version_tag }}
run: |
echo "url=$(terraform output -raw lambda_url)" >> $GITHUB_OUTPUT
echo "url=$(terraform output -raw base_url)" >> $GITHUB_OUTPUT
working-directory: ./terraform/environment
2 changes: 2 additions & 0 deletions .github/workflows/env-destroy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ jobs:
working-directory: ./terraform/environment

- name: Destroy deployment environment
env:
GH_TOKEN: ${{ github.token }}
run: |
gh api \
--method DELETE \
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/env-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ name: "[Job] Test environment"
on:
workflow_call:
inputs:
create_url:
description: "URL of the create endpoint"
base_url:
description: "Base URL of API"
required: true
type: string
secrets:
Expand Down Expand Up @@ -48,5 +48,5 @@ jobs:
role-session-name: GitHubActions
- name: POST to server
env:
URL: ${{ inputs.create_url }}
URL: ${{ inputs.base_url }}
run: make test-api
11 changes: 10 additions & 1 deletion .github/workflows/workflow-pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,15 @@ jobs:
aws_access_key_id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws_secret_access_key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}

plan-dev-account:
name: TF Plan Dev Account
uses: ./.github/workflows/account-deploy.yml
with:
workspace_name: development
secrets:
aws_access_key_id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws_secret_access_key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}

deploy-pr-env:
name: Deploy PR Environment
needs: [build, generate-tags, generate-environment-workspace-name]
Expand All @@ -88,7 +97,7 @@ jobs:
needs: [deploy-pr-env]
uses: ./.github/workflows/env-test.yml
with:
create_url: ${{ needs.deploy-pr-env.outputs.create_url }}
base_url: ${{ needs.deploy-pr-env.outputs.base_url }}
secrets:
aws_access_key_id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws_secret_access_key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ up:
down:
docker compose down

test-api: URL ?= http://localhost:9000/create
test-api: URL ?= http://localhost:9000/
test-api:
go build -o ./signer/test-api ./signer && \
chmod +x ./signer/test-api && \
./signer/test-api POST $(URL) '{"uid":"M-AL9A-7EY3-075D","version":"1"}'
./signer/test-api PUT $(URL)/lpas/M-AL9A-7EY3-075D '{"uid":"M-AL9A-7EY3-075D","version":"1"}'

create-tables:
docker compose run --rm aws dynamodb describe-table --table-name deeds || \
Expand Down
112 changes: 111 additions & 1 deletion docs/openapi/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,114 @@ servers:
description: Development
security:
- {}
paths: {}
paths:
/lpas/{uid}:
parameters:
- name: uid
in: path
required: true
description: The UID of the complaint
schema:
type: string
pattern: "M-([A-Z0-9]{4})-([A-Z0-9]{4})-([A-Z0-9]{4})"
example: M-789Q-P4DF-4UX3
put:
operationId: putLpa
summary: Store an LPA
requestBody:
content:
application/json:
schema:
type: object
additionalProperties: false
responses:
"201":
description: Case created
"400":
description: Invalid request
content:
application/json:
schema:
$ref: "#/components/schemas/BadRequestError"
x-amazon-apigateway-auth:
type: "AWS_IAM"
x-amazon-apigateway-integration:
uri: ${lambda_create_invoke_arn}
httpMethod: "POST"
type: "aws_proxy"
contentHandling: "CONVERT_TO_TEXT"
/health:
get:
operationId: healthCheck
summary: Health check endpoint for external services to consume
responses:
200:
description: Healthy
content:
application/json:
schema:
type: object
properties:
status:
type: string
example: OK
additionalProperties: false
503:
description: Service unavailable
content:
application/json:
schema:
type: object
properties:
status:
type: string
example: Unhealthy
additionalProperties: false
x-amazon-apigateway-auth:
type: "AWS_IAM"
x-amazon-apigateway-integration:
type: "mock"
responses:
default:
statusCode: 200
responseTemplates:
application/json: '{"status":"ok", "statusCode":200}'
requestTemplates:
application/json: '{"statusCode": 200}'
passthroughBehavior: "when_no_templates"

components:
schemas:
AbstractError:
type: object
required:
- code
- detail
properties:
code:
type: string
detail:
type: string
BadRequestError:
allOf:
- $ref: "#/components/schemas/AbstractError"
- type: object
properties:
code:
enum: ["INVALID_REQUEST"]
errors:
type: array
items:
type: object
required:
- source
- detail
properties:
source:
type: string
format: jsonpointer
detail:
type: string
example:
- source: "/uid"
detail: "invalid uid format"
2 changes: 1 addition & 1 deletion signer/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ func main() {

req.Header.Add("Content-type", "application/json")

signer.Sign(req, body, "lambda", "eu-west-1", time.Now())
signer.Sign(req, body, "execute-api", "eu-west-1", time.Now())

client := http.Client{}
resp, err := client.Do(req)
Expand Down
6 changes: 6 additions & 0 deletions terraform/account/.envrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Terraform
export TF_WORKSPACE=development
export TF_VAR_default_role=operator
export TF_VAR_management_role=operator

export TF_CLI_ARGS_init="-backend-config=role_arn=arn:aws:iam::311462405659:role/operator"
25 changes: 25 additions & 0 deletions terraform/account/.terraform.lock.hcl

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 20 additions & 0 deletions terraform/account/apigateway.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
resource "aws_iam_role" "api_gateway_cloudwatch" {
name = "api-gateway-cloudwatch-global"
assume_role_policy = data.aws_iam_policy_document.api_gateway_assume_role.json
}

data "aws_iam_policy_document" "api_gateway_assume_role" {
statement {
actions = ["sts:AssumeRole"]

principals {
type = "Service"
identifiers = ["apigateway.amazonaws.com"]
}
}
}

resource "aws_iam_role_policy_attachment" "api_gateway_log_to_cloudwatch" {
role = aws_iam_role.api_gateway_cloudwatch.id
policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonAPIGatewayPushToCloudWatchLogs"
}
31 changes: 31 additions & 0 deletions terraform/account/terraform.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
terraform {
backend "s3" {
bucket = "opg.terraform.state"
key = "opg-data-lpa-deed-account/terraform.tfstate"
encrypt = true
region = "eu-west-1"
role_arn = "arn:aws:iam::311462405659:role/lpa-store-ci"
dynamodb_table = "remote_lock"
}

required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 5.8.0"
}
}
required_version = ">= 1.4.0"
}

provider "aws" {
region = "eu-west-1"

assume_role {
role_arn = "arn:aws:iam::${local.account.account_id}:role/${var.default_role}"
session_name = "terraform-session"
}

default_tags {
tags = local.default_tags
}
}
9 changes: 9 additions & 0 deletions terraform/account/terraform.tfvars.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"accounts": {
"development": {
"account_id": "493907465011",
"account_name": "development",
"is_production": false
}
}
}
Loading

0 comments on commit 1711202

Please sign in to comment.