From 258b1887e4834e69926eb6720cb53ada6cb35166 Mon Sep 17 00:00:00 2001 From: james-willis-nhse Date: Wed, 10 Sep 2025 16:16:37 +0100 Subject: [PATCH 01/18] inital commit for new APIM workflow --- .github/workflows/build-deploy-apim.yaml | 52 ++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 .github/workflows/build-deploy-apim.yaml diff --git a/.github/workflows/build-deploy-apim.yaml b/.github/workflows/build-deploy-apim.yaml new file mode 100644 index 0000000000..6dc96ca7c2 --- /dev/null +++ b/.github/workflows/build-deploy-apim.yaml @@ -0,0 +1,52 @@ +name: APIM Build & Deploy + +on: + pull_request: + branches: + - main + - task/DOSIS* + +jobs: + build-and-deploy: + runs-on: ubuntu-latest + + env: + ENVIRONMENT: internal-dev + API_NAME: dos-search + FHIR_VERSION: FHIR_R4 + ISSUE_TAG: ${{ github.head_ref }} # branch name or PR ref + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up yq + run: | + sudo wget https://github.com/mikefarah/yq/releases/download/v4.44.1/yq_linux_amd64 -O /usr/local/bin/yq + sudo chmod +x /usr/local/bin/yq + + - name: Install proxygen CLI + run: | + curl -sSL https://example.com/proxygen/install.sh | bash + echo "$HOME/.proxygen/bin" >> $GITHUB_PATH + + - name: Preprocess OAS file + run: | + # Prefix title with issue tag + yq '.info.title = "[" + env.ISSUE_TAG + "] " + .info.title' \ + apis/${{ env.API_NAME }}.yaml > apis/${{ env.API_NAME }}-${{ env.ISSUE_TAG }}.yaml + + - name: Validate OpenAPI spec + run: | + npx @redocly/cli lint apis/${{ env.API_NAME }}-${{ env.ISSUE_TAG }}.yaml + + - name: Deploy to APIM + run: | + proxygen instance deploy \ + $ENVIRONMENT \ + "${API_NAME}-${ISSUE_TAG}_${FHIR_VERSION}" \ + "apis/${API_NAME}-${ISSUE_TAG}.yaml" + + - name: Post-deployment check + run: | + proxygen instance list $ENVIRONMENT | grep "${API_NAME}-${ISSUE_TAG}_${FHIR_VERSION}" \ No newline at end of file From bbe4b28f2675c42102f0537646f0c43c5f841444 Mon Sep 17 00:00:00 2001 From: james-willis-nhse Date: Thu, 11 Sep 2025 13:17:46 +0100 Subject: [PATCH 02/18] inital commit for new APIM workflow --- .github/workflows/build-deploy-apim.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-deploy-apim.yaml b/.github/workflows/build-deploy-apim.yaml index 6dc96ca7c2..259690bdf7 100644 --- a/.github/workflows/build-deploy-apim.yaml +++ b/.github/workflows/build-deploy-apim.yaml @@ -49,4 +49,4 @@ jobs: - name: Post-deployment check run: | - proxygen instance list $ENVIRONMENT | grep "${API_NAME}-${ISSUE_TAG}_${FHIR_VERSION}" \ No newline at end of file + proxygen instance list $ENVIRONMENT | grep "${API_NAME}-${ISSUE_TAG}_${FHIR_VERSION}" From 241c4478a5391a1a1777bf817b0b1a4d3c808c37 Mon Sep 17 00:00:00 2001 From: james-willis-nhse Date: Thu, 11 Sep 2025 13:48:39 +0100 Subject: [PATCH 03/18] inital commits for new APIM workflow --- .github/workflows/build-deploy-apim.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/build-deploy-apim.yaml b/.github/workflows/build-deploy-apim.yaml index 259690bdf7..f8ce8d334b 100644 --- a/.github/workflows/build-deploy-apim.yaml +++ b/.github/workflows/build-deploy-apim.yaml @@ -1,5 +1,9 @@ name: APIM Build & Deploy +permissions: + id-token: write + contents: read + on: pull_request: branches: From a17eb51021149541cc5e2b6df0b1b13e9b003a0f Mon Sep 17 00:00:00 2001 From: james-willis-nhse Date: Sun, 14 Sep 2025 22:45:00 +0100 Subject: [PATCH 04/18] inital commits for new APIM workflow --- .github/workflows/build-deploy-apim.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-deploy-apim.yaml b/.github/workflows/build-deploy-apim.yaml index f8ce8d334b..ecd12ef0fe 100644 --- a/.github/workflows/build-deploy-apim.yaml +++ b/.github/workflows/build-deploy-apim.yaml @@ -31,7 +31,7 @@ jobs: - name: Install proxygen CLI run: | - curl -sSL https://example.com/proxygen/install.sh | bash + pip install proxygen-cli echo "$HOME/.proxygen/bin" >> $GITHUB_PATH - name: Preprocess OAS file From fefefa59291f769793f66e875213e2e659cf36ed Mon Sep 17 00:00:00 2001 From: james-willis-nhse Date: Mon, 15 Sep 2025 15:32:25 +0100 Subject: [PATCH 05/18] inital commits for new APIM workflow --- .github/workflows/build-deploy-apim.yaml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build-deploy-apim.yaml b/.github/workflows/build-deploy-apim.yaml index ecd12ef0fe..60c8c849cb 100644 --- a/.github/workflows/build-deploy-apim.yaml +++ b/.github/workflows/build-deploy-apim.yaml @@ -38,19 +38,19 @@ jobs: run: | # Prefix title with issue tag yq '.info.title = "[" + env.ISSUE_TAG + "] " + .info.title' \ - apis/${{ env.API_NAME }}.yaml > apis/${{ env.API_NAME }}-${{ env.ISSUE_TAG }}.yaml + docs/specification/dos-search.yaml > docs/specification/dos-search.yaml - name: Validate OpenAPI spec run: | - npx @redocly/cli lint apis/${{ env.API_NAME }}-${{ env.ISSUE_TAG }}.yaml + npx @redocly/cli lint docs/specification/dos-search.yaml - name: Deploy to APIM run: | proxygen instance deploy \ $ENVIRONMENT \ - "${API_NAME}-${ISSUE_TAG}_${FHIR_VERSION}" \ - "apis/${API_NAME}-${ISSUE_TAG}.yaml" + "${ISSUE_TAG}-${API_NAME}_${FHIR_VERSION}" \ + "docs/specification/dos-search.yaml" - name: Post-deployment check run: | - proxygen instance list $ENVIRONMENT | grep "${API_NAME}-${ISSUE_TAG}_${FHIR_VERSION}" + proxygen instance list $ENVIRONMENT | grep "${ISSUE_TAG}-${API_NAME}_${FHIR_VERSION}" From 1529ecab240003a984a20b8eb6a216c38313d9a2 Mon Sep 17 00:00:00 2001 From: james-willis-nhse Date: Mon, 15 Sep 2025 15:37:30 +0100 Subject: [PATCH 06/18] inital commits for new APIM workflow --- .github/workflows/build-deploy-apim.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-deploy-apim.yaml b/.github/workflows/build-deploy-apim.yaml index 60c8c849cb..580f3536aa 100644 --- a/.github/workflows/build-deploy-apim.yaml +++ b/.github/workflows/build-deploy-apim.yaml @@ -37,7 +37,7 @@ jobs: - name: Preprocess OAS file run: | # Prefix title with issue tag - yq '.info.title = "[" + env.ISSUE_TAG + "] " + .info.title' \ + yq '.info.title = "[" + ${env.ISSUE_TAG} + "] " + .info.title' \ docs/specification/dos-search.yaml > docs/specification/dos-search.yaml - name: Validate OpenAPI spec @@ -53,4 +53,4 @@ jobs: - name: Post-deployment check run: | - proxygen instance list $ENVIRONMENT | grep "${ISSUE_TAG}-${API_NAME}_${FHIR_VERSION}" + proxygen instance list $ENVIRONMENT | grep "${env.ISSUE_TAG}-${API_NAME}_${FHIR_VERSION}" From 0ede60ce1ece775c01897f9f22d61a83010dd5b6 Mon Sep 17 00:00:00 2001 From: james-willis-nhse Date: Mon, 15 Sep 2025 16:08:45 +0100 Subject: [PATCH 07/18] inital commits for new APIM workflow --- .github/workflows/build-deploy-apim.yaml | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build-deploy-apim.yaml b/.github/workflows/build-deploy-apim.yaml index 580f3536aa..16a7513716 100644 --- a/.github/workflows/build-deploy-apim.yaml +++ b/.github/workflows/build-deploy-apim.yaml @@ -11,6 +11,10 @@ on: - task/DOSIS* jobs: + + metadata: + name: "Get CI/CD metadata" + uses: ./.github/workflows/metadata.yaml build-and-deploy: runs-on: ubuntu-latest @@ -18,7 +22,7 @@ jobs: ENVIRONMENT: internal-dev API_NAME: dos-search FHIR_VERSION: FHIR_R4 - ISSUE_TAG: ${{ github.head_ref }} # branch name or PR ref + WORKSPACE: ${{ needs.metadata.outputs.workspace }} # branch name or PR ref steps: - name: Checkout code @@ -37,7 +41,7 @@ jobs: - name: Preprocess OAS file run: | # Prefix title with issue tag - yq '.info.title = "[" + ${env.ISSUE_TAG} + "] " + .info.title' \ + yq '.info.title = "[" + ${WORKSPACE} + "] " + .info.title' \ docs/specification/dos-search.yaml > docs/specification/dos-search.yaml - name: Validate OpenAPI spec @@ -48,9 +52,9 @@ jobs: run: | proxygen instance deploy \ $ENVIRONMENT \ - "${ISSUE_TAG}-${API_NAME}_${FHIR_VERSION}" \ + "${WORKSPACE}-${API_NAME}_${FHIR_VERSION}" \ "docs/specification/dos-search.yaml" - name: Post-deployment check run: | - proxygen instance list $ENVIRONMENT | grep "${env.ISSUE_TAG}-${API_NAME}_${FHIR_VERSION}" + proxygen instance list $ENVIRONMENT | grep "${WORKSPACE}-${API_NAME}_${FHIR_VERSION}" From 69c1a7813ce57820562faf6922d154639fd70d62 Mon Sep 17 00:00:00 2001 From: james-willis-nhse Date: Tue, 16 Sep 2025 17:23:55 +0100 Subject: [PATCH 08/18] inital commits for new APIM workflow --- .github/workflows/build-deploy-apim.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-deploy-apim.yaml b/.github/workflows/build-deploy-apim.yaml index 16a7513716..15b55ade77 100644 --- a/.github/workflows/build-deploy-apim.yaml +++ b/.github/workflows/build-deploy-apim.yaml @@ -5,7 +5,7 @@ permissions: contents: read on: - pull_request: + push: branches: - main - task/DOSIS* @@ -41,7 +41,7 @@ jobs: - name: Preprocess OAS file run: | # Prefix title with issue tag - yq '.info.title = "[" + ${WORKSPACE} + "] " + .info.title' \ + yq '.info.title = "[" + "${WORKSPACE}" + "] " + .info.title' \ docs/specification/dos-search.yaml > docs/specification/dos-search.yaml - name: Validate OpenAPI spec From a7bc1e8f75e4ed28515e6b1f0d4b2cef6a94670e Mon Sep 17 00:00:00 2001 From: DomBaker Date: Thu, 18 Sep 2025 09:25:03 +0100 Subject: [PATCH 09/18] DOSIS-1812 restructure pipeline and included jobs --- .github/workflows/build-deploy-apim.yaml | 145 +++++++++++++++++++++-- 1 file changed, 133 insertions(+), 12 deletions(-) diff --git a/.github/workflows/build-deploy-apim.yaml b/.github/workflows/build-deploy-apim.yaml index 15b55ade77..7cfd3ea77c 100644 --- a/.github/workflows/build-deploy-apim.yaml +++ b/.github/workflows/build-deploy-apim.yaml @@ -8,16 +8,17 @@ on: push: branches: - main - - task/DOSIS* + - 'task/DOSIS*' jobs: - metadata: name: "Get CI/CD metadata" uses: ./.github/workflows/metadata.yaml + build-and-deploy: + name: "Build and Deploy API" runs-on: ubuntu-latest - + needs: metadata env: ENVIRONMENT: internal-dev API_NAME: dos-search @@ -28,33 +29,153 @@ jobs: - name: Checkout code uses: actions/checkout@v4 + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: '18' + cache: 'npm' + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: '3.11' + cache: 'pip' + - name: Set up yq run: | sudo wget https://github.com/mikefarah/yq/releases/download/v4.44.1/yq_linux_amd64 -O /usr/local/bin/yq sudo chmod +x /usr/local/bin/yq - - name: Install proxygen CLI + - name: Install dependencies run: | + npm install @redocly/cli pip install proxygen-cli + echo "$HOME/.local/bin" >> $GITHUB_PATH echo "$HOME/.proxygen/bin" >> $GITHUB_PATH + - name: Verify workspace variable + run: | + echo "Workspace: ${{ env.WORKSPACE }}" + echo "Environment: ${{ env.ENVIRONMENT }}" + echo "API Name: ${{ env.API_NAME }}" + echo "FHIR Version: ${{ env.FHIR_VERSION }}" + + - name: Backup original OAS file + run: | + cp docs/specification/dos-search.yaml docs/specification/dos-search.yaml.backup + - name: Preprocess OAS file run: | - # Prefix title with issue tag - yq '.info.title = "[" + "${WORKSPACE}" + "] " + .info.title' \ - docs/specification/dos-search.yaml > docs/specification/dos-search.yaml + # Prefix title with workspace tag + yq eval '.info.title = "[" + "${{ env.WORKSPACE }}" + "] " + .info.title' \ + docs/specification/dos-search.yaml.backup > docs/specification/dos-search.yaml + + - name: Display modified OAS info + run: | + echo "Modified OAS title:" + yq eval '.info.title' docs/specification/dos-search.yaml - name: Validate OpenAPI spec run: | - npx @redocly/cli lint docs/specification/dos-search.yaml + npx @redocly/cli lint docs/specification/dos-search.yaml --format=stylish + + - name: Security scan OpenAPI spec + run: | + # Optional: Add security scanning + echo "Running security checks..." + # npx @42crunch/api-security-audit docs/specification/dos-search.yaml || true - name: Deploy to APIM run: | + API_INSTANCE_NAME="${{ env.WORKSPACE }}-${{ env.API_NAME }}_${{ env.FHIR_VERSION }}" + echo "Deploying API instance: ${API_INSTANCE_NAME}" + proxygen instance deploy \ - $ENVIRONMENT \ - "${WORKSPACE}-${API_NAME}_${FHIR_VERSION}" \ + "${{ env.ENVIRONMENT }}" \ + "${API_INSTANCE_NAME}" \ "docs/specification/dos-search.yaml" - - name: Post-deployment check + - name: Post-deployment verification + run: | + API_INSTANCE_NAME="${{ env.WORKSPACE }}-${{ env.API_NAME }}_${{ env.FHIR_VERSION }}" + echo "Verifying deployment of: ${API_INSTANCE_NAME}" + + # List instances and check if our API exists + if proxygen instance list "${{ env.ENVIRONMENT }}" | grep -q "${API_INSTANCE_NAME}"; then + echo "✅ API instance deployed successfully: ${API_INSTANCE_NAME}" + else + echo "❌ API instance not found: ${API_INSTANCE_NAME}" + echo "Available instances:" + proxygen instance list "${{ env.ENVIRONMENT }}" + exit 1 + fi + + - name: Generate deployment report + if: always() + run: | + cat > deployment-report.md << EOF + # Deployment Report + + ## Details + - **Environment**: ${{ env.ENVIRONMENT }} + - **API Name**: ${{ env.API_NAME }} + - **FHIR Version**: ${{ env.FHIR_VERSION }} + - **Workspace**: ${{ env.WORKSPACE }} + - **Instance Name**: ${{ env.WORKSPACE }}-${{ env.API_NAME }}_${{ env.FHIR_VERSION }} + - **Commit**: ${{ github.sha }} + - **Branch**: ${{ github.ref_name }} + - **Actor**: ${{ github.actor }} + - **Timestamp**: $(date -u +"%Y-%m-%d %H:%M:%S UTC") + + ## Status + - Validation: ${{ job.status == 'success' && '✅ Passed' || '❌ Failed' }} + - Deployment: ${{ job.status == 'success' && '✅ Successful' || '❌ Failed' }} + + ## Links + - [Workflow Run](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}) + - [Commit](${{ github.server_url }}/${{ github.repository }}/commit/${{ github.sha }}) + EOF + + - name: Upload deployment artifacts + uses: actions/upload-artifact@v3 + if: always() + with: + name: deployment-artifacts-${{ env.WORKSPACE }} + path: | + docs/specification/dos-search.yaml + docs/specification/dos-search.yaml.backup + deployment-report.md + retention-days: 30 + + - name: Cleanup on failure + if: failure() + run: | + echo "Deployment failed, attempting cleanup..." + API_INSTANCE_NAME="${{ env.WORKSPACE }}-${{ env.API_NAME }}_${{ env.FHIR_VERSION }}" + + # Optional: Remove failed deployment + # proxygen instance delete "${{ env.ENVIRONMENT }}" "${API_INSTANCE_NAME}" || true + + echo "Cleanup completed" + + notify: + name: "Notify deployment status" + runs-on: ubuntu-latest + needs: [metadata, build-and-deploy] + if: always() + + steps: + - name: Notify on success + if: needs.build-and-deploy.result == 'success' + run: | + echo "🎉 Deployment successful!" + echo "Environment: internal-dev" + echo "API Instance: ${{ needs.metadata.outputs.workspace }}-dos-search_FHIR_R4" + # Add notification logic here (Slack, Teams, email, etc.) + + - name: Notify on failure + if: needs.build-and-deploy.result == 'failure' run: | - proxygen instance list $ENVIRONMENT | grep "${WORKSPACE}-${API_NAME}_${FHIR_VERSION}" + echo "💥 Deployment failed!" + echo "Check the workflow logs for details" + # Add error notification logic here From bf8a06f5bc6e8b683b5d9e569038cc6ef094592d Mon Sep 17 00:00:00 2001 From: DomBaker Date: Thu, 18 Sep 2025 09:47:06 +0100 Subject: [PATCH 10/18] DOSIS-1812 remove validation tests and security scan --- .github/workflows/build-deploy-apim.yaml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/build-deploy-apim.yaml b/.github/workflows/build-deploy-apim.yaml index 7cfd3ea77c..cb404306e0 100644 --- a/.github/workflows/build-deploy-apim.yaml +++ b/.github/workflows/build-deploy-apim.yaml @@ -75,15 +75,15 @@ jobs: echo "Modified OAS title:" yq eval '.info.title' docs/specification/dos-search.yaml - - name: Validate OpenAPI spec - run: | - npx @redocly/cli lint docs/specification/dos-search.yaml --format=stylish - - - name: Security scan OpenAPI spec - run: | - # Optional: Add security scanning - echo "Running security checks..." - # npx @42crunch/api-security-audit docs/specification/dos-search.yaml || true + # - name: Validate OpenAPI spec + # run: | + # npx @redocly/cli lint docs/specification/dos-search.yaml --format=stylish + + # - name: Security scan OpenAPI spec + # run: | + # # Optional: Add security scanning + # echo "Running security checks..." + # # npx @42crunch/api-security-audit docs/specification/dos-search.yaml || true - name: Deploy to APIM run: | From a931885456cb8a7a0d6b12619c6bab6b0cf9ec81 Mon Sep 17 00:00:00 2001 From: DomBaker Date: Thu, 18 Sep 2025 09:50:20 +0100 Subject: [PATCH 11/18] DOSIS-1812 Update upload artifact job --- .github/workflows/build-deploy-apim.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-deploy-apim.yaml b/.github/workflows/build-deploy-apim.yaml index cb404306e0..47c2505422 100644 --- a/.github/workflows/build-deploy-apim.yaml +++ b/.github/workflows/build-deploy-apim.yaml @@ -137,7 +137,7 @@ jobs: EOF - name: Upload deployment artifacts - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: always() with: name: deployment-artifacts-${{ env.WORKSPACE }} From fcfada98431b75e88ba852744f09720d23f29bea Mon Sep 17 00:00:00 2001 From: DomBaker Date: Thu, 18 Sep 2025 09:56:06 +0100 Subject: [PATCH 12/18] DOSIS-1812 Remove unused dependency --- .github/workflows/build-deploy-apim.yaml | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/.github/workflows/build-deploy-apim.yaml b/.github/workflows/build-deploy-apim.yaml index 47c2505422..a0a99d878b 100644 --- a/.github/workflows/build-deploy-apim.yaml +++ b/.github/workflows/build-deploy-apim.yaml @@ -29,12 +29,6 @@ jobs: - name: Checkout code uses: actions/checkout@v4 - - name: Set up Node.js - uses: actions/setup-node@v4 - with: - node-version: '18' - cache: 'npm' - - name: Set up Python uses: actions/setup-python@v4 with: @@ -46,9 +40,8 @@ jobs: sudo wget https://github.com/mikefarah/yq/releases/download/v4.44.1/yq_linux_amd64 -O /usr/local/bin/yq sudo chmod +x /usr/local/bin/yq - - name: Install dependencies + - name: Install proxygen CLI run: | - npm install @redocly/cli pip install proxygen-cli echo "$HOME/.local/bin" >> $GITHUB_PATH echo "$HOME/.proxygen/bin" >> $GITHUB_PATH From b20215d807d6b2b29a6f05eadf8922d04c6de47f Mon Sep 17 00:00:00 2001 From: DomBaker Date: Thu, 18 Sep 2025 13:50:54 +0100 Subject: [PATCH 13/18] DOSIS-1812 Add secret managers for proxygen --- infrastructure/stacks/gp_search/secrets.tf | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 infrastructure/stacks/gp_search/secrets.tf diff --git a/infrastructure/stacks/gp_search/secrets.tf b/infrastructure/stacks/gp_search/secrets.tf new file mode 100644 index 0000000000..20745aafa2 --- /dev/null +++ b/infrastructure/stacks/gp_search/secrets.tf @@ -0,0 +1,13 @@ +resource "aws_secretsmanager_secret" "proxygen_private_key" { + # checkov:skip=CKV2_AWS_57: TODO https://nhsd-jira.digital.nhs.uk/browse/FDOS-405 + # checkov:skip=CKV_AWS_149: TODO https://nhsd-jira.digital.nhs.uk/browse/FDOS-405 + name = "/${var.project}/${var.environment}/proxygen-private-key" + description = "private key for proxygen" +} + +resource "aws_secretsmanager_secret" "proxygen_public_key" { + # checkov:skip=CKV2_AWS_57: TODO https://nhsd-jira.digital.nhs.uk/browse/FDOS-405 + # checkov:skip=CKV_AWS_149: TODO https://nhsd-jira.digital.nhs.uk/browse/FDOS-405 + name = "/${var.project}/${var.environment}/proxygen-public-key" + description = "public key for proxygen" +} From 20cec3664c105fbb6c06d0f1e022184313bf11ee Mon Sep 17 00:00:00 2001 From: DomBaker Date: Thu, 18 Sep 2025 14:45:55 +0100 Subject: [PATCH 14/18] DOSIS-1812 Add secret managers for proxygen --- infrastructure/stacks/gp_search/secrets.tf | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/infrastructure/stacks/gp_search/secrets.tf b/infrastructure/stacks/gp_search/secrets.tf index 20745aafa2..a74639224e 100644 --- a/infrastructure/stacks/gp_search/secrets.tf +++ b/infrastructure/stacks/gp_search/secrets.tf @@ -11,3 +11,17 @@ resource "aws_secretsmanager_secret" "proxygen_public_key" { name = "/${var.project}/${var.environment}/proxygen-public-key" description = "public key for proxygen" } + +resource "aws_secretsmanager_secret" "proxygen_public_key" { + # checkov:skip=CKV2_AWS_57: TODO https://nhsd-jira.digital.nhs.uk/browse/FDOS-405 + # checkov:skip=CKV_AWS_149: TODO https://nhsd-jira.digital.nhs.uk/browse/FDOS-405 + name = "/${var.project}/${var.environment}/proxygen-key-id" + description = "key id for proxygen" +} + +resource "aws_secretsmanager_secret" "proxygen_public_key" { + # checkov:skip=CKV2_AWS_57: TODO https://nhsd-jira.digital.nhs.uk/browse/FDOS-405 + # checkov:skip=CKV_AWS_149: TODO https://nhsd-jira.digital.nhs.uk/browse/FDOS-405 + name = "/${var.project}/${var.environment}/proxygen-client-id" + description = "client id for proxygen" +} From 4401bd454e812a88d4227442f989d0c28941e084 Mon Sep 17 00:00:00 2001 From: DomBaker Date: Thu, 18 Sep 2025 14:47:47 +0100 Subject: [PATCH 15/18] DOSIS-1812 rename secret manager names in tf --- infrastructure/stacks/gp_search/secrets.tf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/infrastructure/stacks/gp_search/secrets.tf b/infrastructure/stacks/gp_search/secrets.tf index a74639224e..4ebd47bb32 100644 --- a/infrastructure/stacks/gp_search/secrets.tf +++ b/infrastructure/stacks/gp_search/secrets.tf @@ -12,14 +12,14 @@ resource "aws_secretsmanager_secret" "proxygen_public_key" { description = "public key for proxygen" } -resource "aws_secretsmanager_secret" "proxygen_public_key" { +resource "aws_secretsmanager_secret" "proxygen_key_id" { # checkov:skip=CKV2_AWS_57: TODO https://nhsd-jira.digital.nhs.uk/browse/FDOS-405 # checkov:skip=CKV_AWS_149: TODO https://nhsd-jira.digital.nhs.uk/browse/FDOS-405 name = "/${var.project}/${var.environment}/proxygen-key-id" description = "key id for proxygen" } -resource "aws_secretsmanager_secret" "proxygen_public_key" { +resource "aws_secretsmanager_secret" "proxygen_client_id" { # checkov:skip=CKV2_AWS_57: TODO https://nhsd-jira.digital.nhs.uk/browse/FDOS-405 # checkov:skip=CKV_AWS_149: TODO https://nhsd-jira.digital.nhs.uk/browse/FDOS-405 name = "/${var.project}/${var.environment}/proxygen-client-id" From 9dfddc0eca498e57ce224bcb933e783b8b1d2595 Mon Sep 17 00:00:00 2001 From: DomBaker Date: Thu, 18 Sep 2025 15:59:18 +0100 Subject: [PATCH 16/18] DOSIS-1812 update descriptions for secret managers --- infrastructure/stacks/gp_search/secrets.tf | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/infrastructure/stacks/gp_search/secrets.tf b/infrastructure/stacks/gp_search/secrets.tf index 4ebd47bb32..f8d5f61961 100644 --- a/infrastructure/stacks/gp_search/secrets.tf +++ b/infrastructure/stacks/gp_search/secrets.tf @@ -2,26 +2,26 @@ resource "aws_secretsmanager_secret" "proxygen_private_key" { # checkov:skip=CKV2_AWS_57: TODO https://nhsd-jira.digital.nhs.uk/browse/FDOS-405 # checkov:skip=CKV_AWS_149: TODO https://nhsd-jira.digital.nhs.uk/browse/FDOS-405 name = "/${var.project}/${var.environment}/proxygen-private-key" - description = "private key for proxygen" + description = "Private key for proxygen" } resource "aws_secretsmanager_secret" "proxygen_public_key" { # checkov:skip=CKV2_AWS_57: TODO https://nhsd-jira.digital.nhs.uk/browse/FDOS-405 # checkov:skip=CKV_AWS_149: TODO https://nhsd-jira.digital.nhs.uk/browse/FDOS-405 name = "/${var.project}/${var.environment}/proxygen-public-key" - description = "public key for proxygen" + description = "Public key for proxygen" } resource "aws_secretsmanager_secret" "proxygen_key_id" { # checkov:skip=CKV2_AWS_57: TODO https://nhsd-jira.digital.nhs.uk/browse/FDOS-405 # checkov:skip=CKV_AWS_149: TODO https://nhsd-jira.digital.nhs.uk/browse/FDOS-405 name = "/${var.project}/${var.environment}/proxygen-key-id" - description = "key id for proxygen" + description = "Key id for proxygen" } resource "aws_secretsmanager_secret" "proxygen_client_id" { # checkov:skip=CKV2_AWS_57: TODO https://nhsd-jira.digital.nhs.uk/browse/FDOS-405 # checkov:skip=CKV_AWS_149: TODO https://nhsd-jira.digital.nhs.uk/browse/FDOS-405 name = "/${var.project}/${var.environment}/proxygen-client-id" - description = "client id for proxygen" + description = "Client id for proxygen" } From 62c02431ce062289ac4083ccfe342273178065ca Mon Sep 17 00:00:00 2001 From: DomBaker Date: Fri, 19 Sep 2025 15:34:59 +0100 Subject: [PATCH 17/18] DOSIS-1812 Add script for setup and deploying to proxygen and s3 bucket --- infrastructure/stacks/gp_search/s3.tf | 7 + scripts/workflow/deploy-apim-proxy.sh | 292 ++++++++++++++++++++++++++ 2 files changed, 299 insertions(+) create mode 100644 scripts/workflow/deploy-apim-proxy.sh diff --git a/infrastructure/stacks/gp_search/s3.tf b/infrastructure/stacks/gp_search/s3.tf index 1d9601f04e..58b1a7161d 100644 --- a/infrastructure/stacks/gp_search/s3.tf +++ b/infrastructure/stacks/gp_search/s3.tf @@ -4,3 +4,10 @@ module "s3" { force_destroy = true s3_logging_bucket = local.s3_logging_bucket } + +module "s3" { + source = "../../modules/s3" + bucket_name = "${local.resource_prefix}-${var.s3_bucket_name}-proxygen" + force_destroy = true + s3_logging_bucket = local.s3_logging_bucket +} diff --git a/scripts/workflow/deploy-apim-proxy.sh b/scripts/workflow/deploy-apim-proxy.sh new file mode 100644 index 0000000000..f6b9db4386 --- /dev/null +++ b/scripts/workflow/deploy-apim-proxy.sh @@ -0,0 +1,292 @@ +#!/bin/bash + +# AWS Secrets Manager retrieval and Proxygen deployment script for GitHub Actions +# This script fetches secrets, retrieves private key from S3, sets up Proxygen credentials, and deploys + +set -euo pipefail + +# Define the secret paths (excluding private key which will come from S3) +SECRETS=( + "/ftrs-dos/dev/proxygen-key-id" + "/ftrs-dos/dev/proxygen-client-id" + "/ftrs-dos/dev/proxygen-public-key" + "/temp/dev/api-ca-cert" + "/temp/dev/api-ca-pk" +) + +# Define corresponding output variable names +OUTPUT_VARS=( + "PROXYGEN_KEY_ID" + "PROXYGEN_CLIENT_ID" + "PROXYGEN_PUBLIC_KEY" + "API_CA_CERT" + "API_CA_PK" +) + +# S3 configuration for private key +S3_BUCKET="" +S3_PRIVATE_KEY_PATH="ftrs-dos/dev/proxygen-private-key" +PROXYGEN_PRIVATE_KEY_FILE="/tmp/proxygen-private-key.pem" + +# Proxygen configuration +PROXYGEN_INSTANCE="internal-dev" +PROXYGEN_SERVICE_NAME="ftrs-search-" # not sure how to handle workspace here +OASPEC_FILE="docs/specification/dos-search.yaml" +PROXYGEN_CONFIG_FILE="/tmp/proxygen-config.json" + +echo "=== Starting Proxygen Deployment Process ===" + +# Check if required CLI tools are available +check_dependencies() { + local deps=("aws" "proxygen" "yq") + for dep in "${deps[@]}"; do + if ! command -v "$dep" &> /dev/null; then + echo "Error: $dep is not installed or not in PATH" + exit 1 + fi + done + echo "✓ All dependencies available (including Proxygen CLI and yq)" +} + +# Function to retrieve and output secret +retrieve_secret() { + local secret_path="$1" + local output_var="$2" + + echo "Retrieving secret: $secret_path" + + # Retrieve the secret value + local secret_value + if secret_value=$(aws secretsmanager get-secret-value --secret-id "$secret_path" --query 'SecretString' --output text 2>/dev/null); then + # Export as environment variable + export "$output_var"="$secret_value" + + # Mask the secret in GitHub Actions logs + echo "::add-mask::$secret_value" + echo "$output_var=***MASKED***" >> $GITHUB_ENV + + echo "✓ Successfully retrieved $output_var" + else + echo "Error: Failed to retrieve secret $secret_path" + exit 1 + fi +} + +# Function to retrieve private key from S3 +retrieve_private_key_from_s3() { + echo "Retrieving private key from S3: s3://$S3_BUCKET/$S3_PRIVATE_KEY_PATH" + + if aws s3 cp "s3://$S3_BUCKET/$S3_PRIVATE_KEY_PATH" "$PROXYGEN_PRIVATE_KEY_FILE" 2>/dev/null; then + # Set proper permissions for private key + chmod 600 "$PROXYGEN_PRIVATE_KEY_FILE" + + # Export path as environment variable + export PROXYGEN_PRIVATE_KEY="$PROXYGEN_PRIVATE_KEY_FILE" + echo "PROXYGEN_PRIVATE_KEY=$PROXYGEN_PRIVATE_KEY_FILE" >> $GITHUB_ENV + + echo "✓ Successfully retrieved private key from S3" + else + echo "Error: Failed to retrieve private key from S3" + exit 1 + fi +} + +# Function to set up Proxygen CLI credentials +setup_proxygen_auth() { + echo "Setting up Proxygen CLI credentials..." + + # Set Proxygen credentials using the credentials set command + echo "Running: proxygen credentials set private_key_path $PROXYGEN_PRIVATE_KEY key_id $PROXYGEN_KEY_ID client_id $PROXYGEN_CLIENT_ID" + + if proxygen credentials set \ + private_key_path "$PROXYGEN_PRIVATE_KEY" \ + key_id "$PROXYGEN_KEY_ID" \ + client_id "$PROXYGEN_CLIENT_ID"; then + echo "✓ Proxygen CLI credentials configured successfully" + + # Verify credentials are set + echo "Verifying Proxygen credentials..." + if proxygen credentials show 2>/dev/null; then + echo "✓ Credentials verification successful" + else + echo "⚠ Could not verify credentials, but set command succeeded" + fi + else + echo "Error: Failed to set Proxygen CLI credentials" + echo "Command failed: proxygen credentials set private_key_path $PROXYGEN_PRIVATE_KEY key_id $PROXYGEN_KEY_ID client_id $PROXYGEN_CLIENT_ID" + exit 1 + fi +} + +# Function to preprocess OAS specification file +preprocess_oaspec() { + echo "Preprocessing OpenAPI specification file..." + + local workspace="${WORKSPACE:-dev}" + local backup_file="${OASPEC_FILE}.backup" + + # Create backup of original file + if [[ -f "$OASPEC_FILE" ]]; then + echo "Creating backup: $backup_file" + cp "$OASPEC_FILE" "$backup_file" + else + echo "Error: OpenAPI spec file '$OASPEC_FILE' not found" + exit 1 + fi + + # Preprocess the OAS file - prefix title with workspace tag + echo "Prefixing title with workspace tag: [$workspace]" + + if yq eval ".info.title = \"[\" + \"$workspace\" + \"] \" + .info.title" "$backup_file" > "$OASPEC_FILE"; then + echo "✓ Successfully preprocessed OAS file" + + # Show the updated title for verification + local new_title + if new_title=$(yq eval '.info.title' "$OASPEC_FILE" 2>/dev/null); then + echo "Updated title: $new_title" + fi + else + echo "Error: Failed to preprocess OAS file" + echo "Restoring original file..." + mv "$backup_file" "$OASPEC_FILE" + exit 1 + fi + + # Optionally show other info that was modified + echo "OAS file preprocessing completed successfully" +} + +# Function to validate OpenAPI spec file +validate_oaspec() { + echo "Validating OpenAPI specification file..." + + if [[ ! -f "$OASPEC_FILE" ]]; then + echo "Error: OpenAPI spec file '$OASPEC_FILE' not found" + echo "Please ensure the oaspec.yaml file exists in the current directory" + exit 1 + fi + + # Basic validation of YAML format + if ! yq eval '.' "$OASPEC_FILE" > /dev/null 2>&1; then + echo "Error: OpenAPI spec file has YAML syntax issues" + exit 1 + fi + + # Validate that required OpenAPI fields exist + local title version + title=$(yq eval '.info.title // ""' "$OASPEC_FILE" 2>/dev/null) + version=$(yq eval '.info.version // ""' "$OASPEC_FILE" 2>/dev/null) + + if [[ -z "$title" ]]; then + echo "Warning: OpenAPI spec missing info.title" + fi + + if [[ -z "$version" ]]; then + echo "Warning: OpenAPI spec missing info.version" + fi + + echo "✓ OpenAPI specification file validated: $OASPEC_FILE" + [[ -n "$title" ]] && echo " Title: $title" + [[ -n "$version" ]] && echo " Version: $version" +} + +# Function to deploy to Proxygen using CLI +deploy_to_proxygen() { + echo "Starting deployment to Proxygen using CLI..." + + # Expand workspace variable if it exists + local service_name="$PROXYGEN_SERVICE_NAME" + if [[ "$service_name" == *""* ]]; then + # Replace with actual workspace value if available + local workspace="${WORKSPACE:-dev}" + service_name="${service_name//$workspace}" + echo "Expanded service name: $service_name" + fi + + echo "Deploying with parameters:" + echo " Instance: $PROXYGEN_INSTANCE" + echo " Service: $service_name" + echo " Spec file: $OASPEC_FILE" + + # Execute the Proxygen deployment command + echo "Running: proxygen instance deploy $PROXYGEN_INSTANCE $service_name $OASPEC_FILE" + + if proxygen instance deploy "$PROXYGEN_INSTANCE" "$service_name" "$OASPEC_FILE"; then + echo "✅ Proxygen deployment completed successfully!" + + # Get deployment status + echo "Checking deployment status..." + if proxygen instance status "$PROXYGEN_INSTANCE" "$service_name"; then + echo "✓ Deployment status retrieved successfully" + else + echo "⚠ Could not retrieve deployment status, but deployment command succeeded" + fi + + else + echo "❌ Proxygen deployment failed!" + echo "Command: proxygen instance deploy $PROXYGEN_INSTANCE $service_name $OASPEC_FILE" + exit 1 + fi +} + +# Function to list Proxygen deployments (optional verification) +list_proxygen_deployments() { + echo "Listing current Proxygen deployments for verification..." + + if proxygen instance list "$PROXYGEN_INSTANCE"; then + echo "✓ Successfully listed deployments" + else + echo "⚠ Could not list deployments, but this is non-critical" + fi +} + +# Cleanup function +cleanup() { + echo "Cleaning up temporary files..." + rm -f "$PROXYGEN_PRIVATE_KEY_FILE" "$PROXYGEN_CONFIG_FILE" + + # Clean up OAS backup file + local backup_file="${OASPEC_FILE}.backup" + if [[ -f "$backup_file" ]]; then + rm -f "$backup_file" + echo "Removed OAS backup file: $backup_file" + fi +} + +# Set up cleanup trap +trap cleanup EXIT + +# Main execution flow +main() { + echo "=== Phase 1: Dependency Check ===" + check_dependencies + + echo -e "\n=== Phase 2: Retrieving Secrets ===" + for i in "${!SECRETS[@]}"; do + retrieve_secret "${SECRETS[$i]}" "${OUTPUT_VARS[$i]}" + done + + echo -e "\n=== Phase 3: Retrieving Private Key from S3 ===" + retrieve_private_key_from_s3 + + echo -e "\n=== Phase 4: Preprocessing OpenAPI Specification ===" + preprocess_oaspec + + echo -e "\n=== Phase 5: Validating OpenAPI Specification ===" + validate_oaspec + + echo -e "\n=== Phase 7: Setting Proxygen CLI Credentials ===" + setup_proxygen_auth + + echo -e "\n=== Phase 8: Deploying to Proxygen ===" + deploy_to_proxygen + + echo -e "\n=== Phase 9: Verification ===" + list_proxygen_deployments + + echo -e "\n🎉 Proxygen deployment process completed successfully!" + echo "Proxy is now deployed and ready to handle requests." +} + +# Run main function +main "$@" From 7937a12a851fd9444ec2625fb7d43007b881e21f Mon Sep 17 00:00:00 2001 From: DomBaker Date: Fri, 19 Sep 2025 15:38:29 +0100 Subject: [PATCH 18/18] DOSIS-1812 Rename terraform bucket name for proxygen s3 --- infrastructure/stacks/gp_search/s3.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/infrastructure/stacks/gp_search/s3.tf b/infrastructure/stacks/gp_search/s3.tf index 58b1a7161d..3e517cbdbc 100644 --- a/infrastructure/stacks/gp_search/s3.tf +++ b/infrastructure/stacks/gp_search/s3.tf @@ -5,7 +5,7 @@ module "s3" { s3_logging_bucket = local.s3_logging_bucket } -module "s3" { +module "proxygen-s3" { source = "../../modules/s3" bucket_name = "${local.resource_prefix}-${var.s3_bucket_name}-proxygen" force_destroy = true