generated from NHSDigital/repository-template
-
Notifications
You must be signed in to change notification settings - Fork 1
[GPCAPIM-278]: Deploy/redeploy a proxy instance for PRs #61
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
Merged
davidhamill1-nhs
merged 1 commit into
main
from
feature/GPCAPIM-278_automate_proxy_deployment_for_pr_envs
Feb 5, 2026
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| name: Configure Proxygen | ||
| description: Install yq for yaml, install proxygen-cli and configure the account | ||
|
|
||
| inputs: | ||
| proxygen-key-secret: | ||
| description: 'Proxygen private key secret' | ||
| required: true | ||
| proxygen-key-id: | ||
| description: 'Proxygen key ID' | ||
| required: true | ||
| proxygen-api-name: | ||
| description: 'Proxygen API name' | ||
| required: true | ||
| proxygen-client-id: | ||
| description: 'Proxygen client ID' | ||
| required: true | ||
|
|
||
| runs: | ||
| using: composite | ||
| steps: | ||
| - name: Install yq for YAML template processing | ||
| uses: mikefarah/yq@2be0094729a1006f61e8339ce9934bfb3cbb549f # v4.52.2 | ||
|
|
||
| - name: Install Proxygen CLI | ||
| shell: bash | ||
| run: | | ||
| pip install proxygen-cli | ||
| proxygen --version | ||
|
|
||
| - name: Configure proxygen account details | ||
| shell: bash | ||
| working-directory: proxygen | ||
| run: | | ||
| cp settings.template.yaml $HOME/.proxygen/settings.yaml | ||
| yq eval '.api = "${{ inputs.proxygen-api-name }}"' -i $HOME/.proxygen/settings.yaml | ||
|
|
||
| printf "%s" "${{ inputs.proxygen-key-secret }}" > /tmp/proxygen_private_key.pem | ||
| cp credentials.template.yaml $HOME/.proxygen/credentials.yaml | ||
| yq eval '.private_key_path = "/tmp/proxygen_private_key.pem"' -i $HOME/.proxygen/credentials.yaml | ||
| yq eval '.key_id = "${{ inputs.proxygen-key-id }}"' -i $HOME/.proxygen/credentials.yaml | ||
| yq eval '.client_id = "${{ inputs.proxygen-client-id }}"' -i $HOME/.proxygen/credentials.yaml | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,48 @@ | ||
| name: Deploy API Proxy | ||
| description: Deploy the API proxy instance using Proxygen | ||
|
|
||
| inputs: | ||
| mtls-secret-name: | ||
| description: 'mTLS secret name for the proxy' | ||
| required: true | ||
| target-url: | ||
| description: 'Target URL to which the proxy will forward requests' | ||
| required: true | ||
| proxy-base-path: | ||
| description: 'A unique base path for the proxy instance' | ||
| required: true | ||
| proxygen-key-secret: | ||
| description: 'Proxygen private key secret' | ||
| required: true | ||
| proxygen-key-id: | ||
| description: 'Proxygen key ID' | ||
| required: true | ||
| proxygen-api-name: | ||
| description: 'Proxygen API name' | ||
| required: true | ||
| proxygen-client-id: | ||
| description: 'Proxygen client ID' | ||
| required: true | ||
|
|
||
| runs: | ||
| using: composite | ||
| steps: | ||
| - name: Configure Proxygen | ||
| uses: ./.github/actions/proxy/configure-proxygen | ||
| with: | ||
| proxygen-key-secret: ${{ inputs.proxygen-key-secret }} | ||
| proxygen-key-id: ${{ inputs.proxygen-key-id }} | ||
| proxygen-api-name: ${{ inputs.proxygen-api-name }} | ||
| proxygen-client-id: ${{ inputs.proxygen-client-id }} | ||
|
|
||
| - name: Inject secrets into openapi.yaml for deploying proxy | ||
| shell: bash | ||
| run: | | ||
| cat gateway-api/openapi.yaml proxygen/x-nhsd-apim.template.yaml > /tmp/proxy-specification.yaml | ||
|
|
||
| yq eval '.x-nhsd-apim.target.url = "${{ inputs.target-url }}" | .x-nhsd-apim.target.security.secret = "${{ inputs.mtls-secret-name }}"' -i /tmp/proxy-specification.yaml | ||
|
|
||
| - name: Deploy API proxy | ||
| shell: bash | ||
| run: | | ||
| proxygen instance deploy internal-dev ${{ inputs.proxy-base-path }} /tmp/proxy-specification.yaml --no-confirm |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| name: Tear Down API Proxy | ||
| description: Delete the API proxy instance using Proxygen | ||
|
|
||
| inputs: | ||
| proxy-base-path: | ||
| description: 'A unique base path for the proxy instance' | ||
| required: true | ||
| proxygen-key-secret: | ||
| description: 'Proxygen private key secret' | ||
| required: true | ||
| proxygen-key-id: | ||
| description: 'Proxygen key ID' | ||
| required: true | ||
| proxygen-api-name: | ||
| description: 'Proxygen API name' | ||
| required: true | ||
| proxygen-client-id: | ||
| description: 'Proxygen client ID' | ||
| required: true | ||
|
|
||
| runs: | ||
| using: composite | ||
| steps: | ||
| - name: Configure Proxygen | ||
| uses: ./.github/actions/proxy/configure-proxygen | ||
| with: | ||
| proxygen-key-secret: ${{ inputs.proxygen-key-secret }} | ||
| proxygen-key-id: ${{ inputs.proxygen-key-id }} | ||
| proxygen-api-name: ${{ inputs.proxygen-api-name }} | ||
| proxygen-client-id: ${{ inputs.proxygen-client-id }} | ||
|
|
||
| - name: Tear down preview API proxy | ||
| shell: bash | ||
| run: | | ||
| proxygen instance delete internal-dev ${{ inputs.proxy-base-path }} --no-confirm |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| # Bruno | ||
|
|
||
| ## `gateway-api` Workspace | ||
|
|
||
| ### Preview Environment | ||
|
|
||
| #### Environment Setup | ||
|
|
||
| The collection pulls in secrets from a `.env` file from the top level of the collection, `bruno/gateway-api/preview-env`. To reference these variables within the collection you use `{{process.env.<key>}}`, where `<key>` is the environment variable name in `.env`. | ||
|
|
||
| There is a template `.env` file, `bruno/gateway-api/collections/preview-env/.env.template`, to fill in as described below. | ||
|
|
||
| ##### Test application | ||
|
|
||
| The proxy for Gateway API is hosted in Apigee. In order to call an Apigee proxy, a consumer of the API needs an Apigee application. As such, we need an Apigee application through which we can test our API. A static test application has been created for this purpose. You can view its details by going through In order to view its details, go to [the Clinical Data Sharing APIs applications](https://dos-internal.ptl.api.platform.nhs.uk/). when making a call to the API through the proxy, the test applications API key and secret are fed in to the OAuth 2.0 journey as the `CLIENT_KEY` and `CLIENT_SECRET` respectively. As such, you will need a `bruno/gateway-api/preview-preview-env/.env` file containing | ||
|
|
||
| ```plaintext | ||
| CLIENT_ID=<test application's api key> | ||
| CLIENT_SECRET=<test application's api secret> | ||
| ``` | ||
|
|
||
| Bruno then uses these values when making an auth journey for you. | ||
|
|
||
| Given the API is currently set up with CIS2 user-restricted access, and with the above set, when a HTTP request is sent, you will be prompted for username. [Here is a list of available test users](https://digital.nhs.uk/developer/guides-and-documentation/security-and-authorisation/testing-apis-with-our-mock-authorisation-service#test-users-for-cis2-authentication). | ||
|
|
||
| ##### Proxy instance | ||
|
|
||
| The proxy base path defines to which proxy instance your request will be directed. For preview environments, the proxy base path has the GitHub PR number appended to it. As such you will need to add this to your `.env` file so that Bruno can correctly build the URL. | ||
|
|
||
| ```plaintext | ||
| PR_NNUMBER=<pr number from GitHub> | ||
| ``` |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| # See README.md | ||
| PR_NUMBER=<pr number> | ||
|
|
||
| CLIENT_ID=<Application's API key> | ||
| CLIENT_SECRET=<Application's API secret> |
31 changes: 31 additions & 0 deletions
31
bruno/gateway-api/collections/preview-env/Access_Structured_Record.bru
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| meta { | ||
| name: Access Record Structured | ||
| type: http | ||
| seq: 1 | ||
| } | ||
|
|
||
| post { | ||
| url: https://{{apigee_env}}.api.service.nhs.uk/{{proxy_base_path}}/patient/$gpc.getstructuredrecord | ||
| body: json | ||
| auth: inherit | ||
| } | ||
|
|
||
DWolfsNHS marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| body:json { | ||
| { | ||
| "resourceType": "Parameters", | ||
| "parameter": [ | ||
| { | ||
| "name": "patientNHSNumber", | ||
| "valueIdentifier": { | ||
| "system": "https://fhir.nhs.uk/Id/nhs-number", | ||
| "value": "9999999999" | ||
| } | ||
| } | ||
| ] | ||
| } | ||
| } | ||
|
|
||
| settings { | ||
| encodeUrl: true | ||
| timeout: 0 | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| { | ||
| "version": "1", | ||
| "name": "preview-env", | ||
| "type": "collection", | ||
| "ignore": [ | ||
| "node_modules", | ||
| ".git" | ||
| ] | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| headers { | ||
| Ssp-TraceID: test-teace-id | ||
| ODS-from: test-ods-code | ||
| } | ||
|
|
||
| auth { | ||
| mode: oauth2 | ||
| } | ||
|
|
||
| auth:oauth2 { | ||
| grant_type: authorization_code | ||
| callback_url: https://www.example.com/callback | ||
| authorization_url: https://internal-dev.api.service.nhs.uk/oauth2-mock/authorize | ||
| access_token_url: https://internal-dev.api.service.nhs.uk/oauth2-mock/token | ||
| refresh_token_url: | ||
| client_id: {{process.env.CLIENT_ID}} | ||
| client_secret: {{process.env.CLIENT_SECRET}} | ||
| scope: | ||
| state: {{$guid}} | ||
| pkce: false | ||
| credentials_placement: body | ||
| credentials_id: Mock Auth Token | ||
| token_placement: header | ||
| token_header_prefix: Bearer | ||
| auto_fetch_token: true | ||
| auto_refresh_token: false | ||
| } | ||
|
|
||
| vars:pre-request { | ||
| apigee_env: internal-dev | ||
| proxy_base_path: clinical-data-gateway-api-poc-pr-{{process.env.PR_NUMBER}} | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| opencollection: 1.0.0 | ||
| info: | ||
| name: "gateway" | ||
| type: workspace | ||
|
|
||
| collections: | ||
| - name: "steel_thread" | ||
| path: "collections\\steel_thread" | ||
| - name: "steel_thread" | ||
| path: "collections\\preview-env" | ||
|
|
||
| specs: | ||
|
|
||
| docs: '' |
DWolfsNHS marked this conversation as resolved.
Show resolved
Hide resolved
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| # Proxygen | ||
|
|
||
| Proxygen is the tool created by the API Platform team to support the deployment of NHS APIs. | ||
|
|
||
| We use this tool in the pipelines (and manually) to create, destroy and interact more generally with the proxy instances. | ||
|
|
||
| For more information on Proxygen, [read the docs](https://nhsd-confluence.digital.nhs.uk/spaces/APM/pages/375329782/Proxygen). | ||
|
|
||
| Proxygen needs: | ||
|
|
||
| * a settings file stating which API we are attempting to update; | ||
| * a credentials file to authenticate us as the owner/maintainer of the API; | ||
| * a specification file that outlines the behaviour of the proxy. | ||
|
|
||
| ## Settings File | ||
|
|
||
| This is stored at `proxygen/settings.yaml` and is read by the Proxygen command line tool when it has been requested to make updates to an API. | ||
|
|
||
| ## Credentials File | ||
|
|
||
| A template is stored at `proxygen/credentials.template.yaml` where the `<proxygen_secret_path>` needs to be inserted. This is a path to a file that holds the secret that identifies us as the owner/maintainer of the API. | ||
|
|
||
| During the GitHub workflows, the secret is pulled from AWS secrets manager, written to a file and the path to that file is inserted in to `credentials.template.yaml`. | ||
|
|
||
| ## Specification file | ||
|
|
||
| Proxygen deploys an instance of a proxy using a specification file. This is of the OpenAPI format with a custom extension, `x-nhsd-apim` which provide Proxygen with information as to how the proxy should behave. This includes: | ||
|
|
||
| * the target endpoint, to which it will forward traffic; | ||
| * the scopes that a user needs in order to access the proxy's endpoint; | ||
| * a key that the points to the mTLS certificate which the targeted backend expects to be used. | ||
|
|
||
| A template, `proxygen/x-nhsd-api.tempalte.yaml`, is concatenated with the general OpenAPI specification for the API, `gateway-api/openapi.yaml`, and the key to the mTLS certificate to be used for that proxy is written in. All of which is then written to a file and the path to that file is passed to Proxygen to deploy the proxy in the stated environment. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| base_url: https://identity.prod.api.platform.nhs.uk/realms/api-producers | ||
| client_id: <proxygen machine user client id> | ||
| client_secret: '' | ||
| key_id: <proxygen_key_id> | ||
| password: '' | ||
| private_key_path: <proxygen_private_key_path> | ||
| username: '' |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| api: <proxygen_api_name> | ||
| endpoint_url: https://proxygen.prod.api.platform.nhs.uk | ||
| spec_output_format: yaml |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.