Skip to content

Commit 3e26f39

Browse files
NPA-5244: Composite token and end to end testing (#46)
# Pull Request ## 🧾 Ticket Link https://nhsd-jira.digital.nhs.uk/browse/NPA-5244 --- ## 📄 Description/Summary of Changes <!-- Describe the changes made in this PR. Include the purpose/scope/impact/context of the changes --> - Added support for mock composite token - Added happy and unhappy path end to end tests - Enabled end to end tests for PR check workflow and CI/CD internal-qa workflow - Added documentation on manual steps required for enabling mock composite token against ephemeral developments - Added documentation for NHS developer hub - Added documentation for alternative Proxygen installation method - Updated vale acceptance list - Updated uv version --- ## 🧪 Developer Testing Carried Out <!-- Describe what tests (automated/unit/manual etc.) have been done for the ticket. Include: --> <!-- - Any tests added/updated --> <!-- - Evidence that each acceptance criterion from the Jira ticket is met --> - [Successful CI/CD run](https://github.com/NHSDigital/im1-pfs-auth/actions/runs/18531838040) - [Successful PR check run](https://github.com/NHSDigital/im1-pfs-auth/actions/runs/18534306013) --- ## ✅ Developer Checklist <!-- To be completed by the developer --> - [x] I have set the PR title to follow the format: `NPA-XXXX: <short-description>` - [x] My branch name follows the convention: `<type>/NPA-XXXX/<short-description>` - [x] My commit messages follow the template: `NPA-XXXX: <short-description>` - [x] I have updated the documentation accordingly - [x] I have set assignees and added appropriate labels --- ## 👀 Reviewer Checklist <!-- To be completed by the reviewer --> - [ ] Changes meet the acceptance criteria of the Jira ticket - [ ] Code is able to be merged (no conflicts and adheres to coding standards) - [ ] Sufficient test evidence is provided (manual and/or automated) --- ## Sensitive Information Declaration To ensure the utmost confidentiality and protect your and others privacy, we kindly ask you to NOT including [PII (Personal Identifiable Information) / PID (Personal Identifiable Data)](https://digital.nhs.uk/data-and-information/keeping-data-safe-and-benefitting-the-public) or any other sensitive data in this PR (Pull Request) and the codebase changes. We will remove any PR that do contain any sensitive information. We really appreciate your cooperation in this matter. - [x] I confirm that neither PII/PID nor sensitive data are included in this PR and the codebase changes.
1 parent 9b0ea15 commit 3e26f39

File tree

16 files changed

+459
-54
lines changed

16 files changed

+459
-54
lines changed

.github/actions/run-end-to-end-tests/action.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ name: "Run End to End Tests"
22
description: Run End to End Tests
33

44
inputs:
5+
PROXY_NAME:
6+
description: "The name of the proxy, e.g. 'im1-pfs-auth'"
7+
required: true
58
APIGEE_PROXY_NAME:
69
description: "The name of the proxy to test, e.g. 'im1-pfs-auth--internal-dev--im1-pfs-auth-pr-31'"
710
required: true

.github/workflows/cicd-stage-1-deploy-to-internal-qa.yml

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,34 @@ jobs:
1919
PROXYGEN_KEY_ID: ${{ secrets.PROXYGEN_KEY_ID }}
2020
PROXYGEN_PRIVATE_KEY: ${{ secrets.PROXYGEN_PRIVATE_KEY }}
2121

22-
# Add int end-to-end tests
22+
run-end-to-end-tests:
23+
name: "Run End to End Tests"
24+
runs-on: ubuntu-latest
25+
needs: deploy-qa-app
26+
steps:
27+
- name: Checkout Repository
28+
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
29+
with:
30+
fetch-depth: 0
31+
persist-credentials: false
32+
- name: Setup Python Dependencies
33+
uses: ./.github/actions/setup-python-dependencies
34+
- name: Setup proxygen
35+
uses: ./.github/actions/setup-proxygen
36+
with:
37+
PROXYGEN_CLIENT_ID: ${{ secrets.PROXYGEN_CLIENT_ID }}
38+
PROXYGEN_KEY_ID: ${{ secrets.PROXYGEN_KEY_ID }}
39+
PROXYGEN_PRIVATE_KEY: ${{ secrets.PROXYGEN_PRIVATE_KEY }}
40+
- name: Run End to End Tests
41+
uses: ./.github/actions/run-end-to-end-tests
42+
env:
43+
PROXYGEN_URL_PATH: "im1-pfs-auth"
44+
PROXY_NAME: "im1-pfs-auth"
45+
APIGEE_PROXY_NAME: "im1-pfs-auth--internal-qa--im1-pfs-auth"
46+
TEST_APP_KEYCLOAK_CLIENT_ID: ${{ secrets.TEST_APP_KEYCLOAK_CLIENT_ID }}
47+
TEST_APP_KEYCLOAK_CLIENT_SECRET: ${{ secrets.TEST_APP_KEYCLOAK_CLIENT_SECRET }}
48+
TEST_APP_API_KEY: ${{ secrets.TEST_APP_API_KEY }}
49+
TEST_APP_PRIVATE_KEY: ${{ secrets.TEST_APP_PRIVATE_KEY }}
2350

2451
# TODO: Reuse docker container for sandbox deployment, don't rebuild docker container
2552
deploy-qa-sandbox:

.github/workflows/pull-request-checks.yml

Lines changed: 28 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -38,30 +38,34 @@ jobs:
3838
PROXYGEN_KEY_ID: ${{ secrets.PROXYGEN_KEY_ID }}
3939
PROXYGEN_PRIVATE_KEY: ${{ secrets.PROXYGEN_PRIVATE_KEY }}
4040

41-
# Uncomment the following section to enable end-to-end tests once the tests are fixed in NPA-5244
42-
# run-end-to-end-tests:
43-
# name: "Run End to End Tests"
44-
# runs-on: ubuntu-latest
45-
# needs: deploy-dev-app
46-
# steps:
47-
# - name: Checkout Repository
48-
# uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
49-
# with:
50-
# fetch-depth: 0
51-
# persist-credentials: false
52-
# - name: Setup Python Dependencies
53-
# uses: ./.github/actions/setup-python-dependencies
54-
# - name: Setup proxygen
55-
# uses: ./.github/actions/setup-proxygen
56-
# with:
57-
# PROXYGEN_CLIENT_ID: ${{ secrets.PROXYGEN_CLIENT_ID }}
58-
# PROXYGEN_KEY_ID: ${{ secrets.PROXYGEN_KEY_ID }}
59-
# PROXYGEN_PRIVATE_KEY: ${{ secrets.PROXYGEN_PRIVATE_KEY }}
60-
# - name: Run End to End Tests
61-
# uses: ./.github/actions/run-end-to-end-tests
62-
# env:
63-
# PROXYGEN_URL_PATH: ${{ needs.deploy-dev-app.outputs.proxygen_url_path }}
64-
# APIGEE_PROXY_NAME: "im1-pfs-auth--internal-dev--${{ needs.deploy-dev-app.outputs.proxygen_url_path }}"
41+
run-end-to-end-tests:
42+
name: "Run End to End Tests"
43+
runs-on: ubuntu-latest
44+
needs: deploy-dev-app
45+
steps:
46+
- name: Checkout Repository
47+
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
48+
with:
49+
fetch-depth: 0
50+
persist-credentials: false
51+
- name: Setup Python Dependencies
52+
uses: ./.github/actions/setup-python-dependencies
53+
- name: Setup proxygen
54+
uses: ./.github/actions/setup-proxygen
55+
with:
56+
PROXYGEN_CLIENT_ID: ${{ secrets.PROXYGEN_CLIENT_ID }}
57+
PROXYGEN_KEY_ID: ${{ secrets.PROXYGEN_KEY_ID }}
58+
PROXYGEN_PRIVATE_KEY: ${{ secrets.PROXYGEN_PRIVATE_KEY }}
59+
- name: Run End to End Tests
60+
uses: ./.github/actions/run-end-to-end-tests
61+
env:
62+
PROXYGEN_URL_PATH: ${{ needs.deploy-dev-app.outputs.proxygen_url_path }}
63+
PROXY_NAME: "im1-pfs-auth"
64+
APIGEE_PROXY_NAME: "im1-pfs-auth--internal-dev--${{ needs.deploy-dev-app.outputs.proxygen_url_path }}"
65+
TEST_APP_KEYCLOAK_CLIENT_ID: ${{ secrets.TEST_APP_KEYCLOAK_CLIENT_ID }}
66+
TEST_APP_KEYCLOAK_CLIENT_SECRET: ${{ secrets.TEST_APP_KEYCLOAK_CLIENT_SECRET }}
67+
TEST_APP_API_KEY: ${{ secrets.TEST_APP_API_KEY }}
68+
TEST_APP_PRIVATE_KEY: ${{ secrets.TEST_APP_PRIVATE_KEY }}
6569

6670
deploy-dev-sandbox:
6771
name: "Deploy Pull Request Sandbox Environment"

Makefile

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,12 +166,17 @@ sandbox-unit-test:
166166
# Runs End to End tests against a deployed environment
167167
e2e-tests end-to-end-tests:
168168
# Mandatory arguments:
169+
# TEST_APP_KEYCLOAK_CLIENT_ID: Client Id issued to the mocked authorisation provider client. Obtained by the GET Keycloak credentials endpoint.
170+
# TEST_APP_KEYCLOAK_SECRET: Secret assigned to the mocked authorisation provider client. Obtained by the GET Keycloak credentials endpoint.
171+
# TEST_APP_API_KEY: API Key for test application in the developer portal (https://dos-internal.ptl.api.platform.nhs.uk/MyApplications)
172+
# TEST_APP_PRIVATE_KEY: Private Key from key pair for test application in the developer portal (https://dos-internal.ptl.api.platform.nhs.uk/MyApplications)
169173
# APIGEE_ACCESS_TOKEN: "proxygen pytest-nhsd-apim --api=im1-pfs-auth get-token | jq -r .pytest_nhsd_apim_token"
170174
# APIGEE_PROXY_NAME: The name of the proxy to test (e.g., im1-pfs-auth--internal-dev--im1-pfs-auth-pr-31)
171175
# PROXYGEN_URL_PATH: The URL path for the Proxygen API (e.g. im1-pfs-auth-pr-31)
172176
uv run pytest tests/end_to_end \
173177
--api-name=im1-pfs-auth --proxy-name=${APIGEE_PROXY_NAME} \
174-
--disable-warnings -o log_cli_level=INFO
178+
--disable-warnings -o log_cli_level=INFO \
179+
${PYTEST_ARGS}
175180

176181
# ==============================================================================
177182

README.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,9 +149,17 @@ To run end to end tests use the following commands:
149149
150150
```shell
151151
export APIGEE_ACCESS_TOKEN=$(proxygen pytest-nhsd-apim --api=im1-pfs-auth get-token | jq -r .pytest_nhsd_apim_token)
152-
make end-to-end-test PROXYGEN_URL_PATH=<proxygen_url_path> PROXY_NAME=<proxy_name> APIGEE_PROXY_NAME=<apigee_proxy_name>
152+
export TEST_APP_KEYCLOAK_CLIENT_ID=KEYCLOAK_CLIENT_ID
153+
export TEST_APP_KEYCLOAK_CLIENT_SECRET=KEYCLOAK_SECRET
154+
export TEST_APP_API_KEY=APP_CLIENT_API_KEY
155+
export TEST_APP_PRIVATE_KEY=$(cat {path_to_private_key.pem})
156+
make end-to-end-tests PROXYGEN_URL_PATH=im1-pfs-auth-pr-46 PROXY_NAME=im1-pfs-auth APIGEE_PROXY_NAME=im1-pfs-auth--internal-dev--im1-pfs-auth-pr-46
153157
```
154158

159+
- `TEST_APP_KEYCLOAK_CLIENT_ID`: Client Id issued to the mocked authorisation provider client. Obtained by the GET Keycloak credentials endpoint.
160+
- `TEST_APP_KEYCLOAK_CLIENT_SECRET`: Secret assigned to the mocked authorisation provider client. Obtained by the GET Keycloak credentials endpoint.
161+
- `TEST_APP_API_KEY`: API Key for test application in the developer portal (https://dos-internal.ptl.api.platform.nhs.uk/MyApplications)
162+
- `TEST_APP_PRIVATE_KEY`: Private Key from key pair for test application in the developer portal (https://dos-internal.ptl.api.platform.nhs.uk/MyApplications)
155163
- `PROXYGEN_URL_PATH`: The URL path for the Proxygen API (e.g. im1-pfs-auth-pr-31)
156164
- `PROXY_NAME`: The name of the proxy (e.g. im1-pfs-auth)
157165
- `APIGEE_PROXY_NAME`: The name of the proxy to test (e.g., im1-pfs-auth--internal-dev--im1-pfs-auth-pr-31)

app/api/app.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ def authentication() -> Response:
3131
response = route_and_forward(forward_request)
3232
return make_response(
3333
jsonify(response.model_dump()),
34-
HTTPStatus.OK,
34+
HTTPStatus.CREATED,
3535
)
3636
except ApiError as e:
3737
return make_response(jsonify(message=e.message), e.status_code)

app/api/tests/test_app.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ def test_authentication_post(
4040
actual_result = client.post("/authentication")
4141

4242
# Assert
43-
assert actual_result.status_code == 200
43+
assert actual_result.status_code == 201
4444
assert actual_result.get_json() == mocked_forward_request_response
4545
mock_forward_request.assert_called_once()
4646
mock_route_and_forward.assert_called_once_with(mock_forward_request.return_value)
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# Guide: NHS developer hub
2+
3+
## Overview
4+
5+
The NHS developer hub is the platform for managing applications which interact with NHS APIs. The primary use case for IM1 is for the management of API keys and credentials used in accessing the mock credentials service used in testing.
6+
7+
## Registration
8+
9+
There are two instances of NHS developer hub, [production](https://onboarding.prod.api.platform.nhs.uk) and [internal](https://dos-internal.ptl.api.platform.nhs.uk). Developers are encouraged to register for both platforms however, for the purposes of IM1 development, the internal instance is of higher priority.
10+
11+
## Proxy Dev Team
12+
13+
Once registered with the developer hub, developers must be added to the `Proxy Dev Team`. This must be done by the one of the `Proxy Dev Team` owners.
14+
15+
## IM1 PFS Auth Developer Test App
16+
17+
The `Proxy Dev Team` maintains the IM1 PFS Auth Developer Test App on the internal NHS developer hub. This application is responsible for the management of API keys and public signing key.
18+
19+
### API keys
20+
21+
From the application page, the API key can be accessed via `Security details` -> `Active API keys` -> `Edit`. Here keys can be rotated, created, and revoked. This key is used as `TEST_APP_API_KEY` in our environment variables.
22+
23+
### Public key
24+
25+
The public signing key can be changed via `Security details` -> `Public key URL` -> `Edit`, where generation of the public key is documented under [Section 3](https://digital.nhs.uk/developer/guides-and-documentation/security-and-authorisation/user-restricted-restful-apis-nhs-login-separate-authentication-and-authorisation#step-3-generate-a-key-pair) of [User-restricted RESTful APIs - NHS login separate authentication](https://digital.nhs.uk/developer/guides-and-documentation/security-and-authorisation/user-restricted-restful-apis-nhs-login-separate-authentication-and-authorisation).

docs/user-guides/Proxygen_CLI.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,18 @@ The proxygen CLI is a dedicated command-line interface tool designed to streamli
2828
pip install proxygen-cli
2929
```
3030

31+
Alternative proxygen install
32+
33+
Proxygen currently, 2025-10-09, fails to build with Python 3.13, the version used in the IM1 repository, due to an inability to build `lxml==4.9.4`.
34+
35+
A workaround is to create a separate virtual environment at a lower Python version, then build proxygen for that environment, and transfer the binary to the IM1 repository virtual environment.
36+
37+
```shell
38+
uv venv -p 3.12 # In a directory not containing the IM1 repository
39+
uv pip install proxygen-cli
40+
cp .venv/bin/proxygen <IM1 Repository>/.venv/bin/
41+
```
42+
3143
2. Confirm the installation by checking the version:
3244

3345
```shell
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
# Guide: Setup end to end tests
2+
3+
- [Guide: Setup end to end tests](#guide-setup-end-to-end-tests)
4+
- [Overview](#overview)
5+
- [Associating ephemeral deployments with IM1 PFS Auth Developer Test App](#associating-ephemeral-deployments-with-im1-pfs-auth-developer-test-app)
6+
- [Launching the ephemeral deployment](#launching-the-ephemeral-deployment)
7+
- [Associating the deployment with the developer app](#associating-the-deployment-with-the-developer-app)
8+
- [Testing](#testing)
9+
10+
## Overview
11+
12+
When performing end to end tests, a composite authentication token is retrieved from APIM's `mock-jwks` API. Composite tokens are currently, 2025-10-13, only enabled for the `internal-dev` environment. Therefore they cannot be ran against `internal-qa` in the CI/CD pipeline.
13+
14+
End to end tests can be ran from `internal-dev`, including ephemeral deployments created by PRs. For ephemeral deployments however, this requires associating the API Product with the IM1 PFS Auth Developer Test App, which has access to the correct instance of `mock-jwks`, as outlined below.
15+
16+
## Associating ephemeral deployments with IM1 PFS Auth Developer Test App
17+
18+
### Launching the ephemeral deployment
19+
20+
<!-- markdownlint-disable-next-line no-inline-html -->
21+
22+
A deployment is automatically span up upon the [creation of a PR](./Workflows.md#core-workflows) with the naming pattern `im1-pfs-auth-pr-<pr_number>`. The deployment can be verified by searching for `im1` in the APIGEE > Develop > API Proxies UI, the API proxy will be shown as `im1-pfs-auth--internal-dev--im1-pfs-auth-pr-<pr_number>`.
23+
24+
### Associating the deployment with the developer app
25+
26+
To allow the ephemeral deployment to access the `mock-jwks` service, it must be associated with the IM1 PFS Auth Developer Test App. To do so you must first be added to the `Proxy Dev Team` on the [NHS Internal Developer Hub](./NHS_developer_hub.md).
27+
28+
Once added to the `Proxy Dev Team`, the deployment can be associated to the developer app using [Apigee](https://apigee.com/edge) under the `nhsd-nonprod` organisation. To associate the deployment with the developer app:
29+
30+
- Navigate to `Publish` -> `Apps`
31+
- Search for `IM1`
32+
- Note: searching can be a slow process due to indexing time)
33+
- Select IM1 PFS Auth Developer Test App
34+
- Select `Edit` in the top right of the page
35+
- Under `Credentials` select `Add product`
36+
- Search for `pr-<pr_number>`
37+
- Add the `IM1 PFS Auth API - IM1 PFS Auth - P9 User Restriced Access (dev) (Internal Development)` product
38+
- Note: This is **not** the `(Internal Development Sandbox)` product
39+
- Finalise the change by selecting `Save` in the top right of the page
40+
41+
## Testing
42+
43+
The deployment should now be associated with the app and end to end tests can be run as part of the [pull request checks GitHub workflow](../../.github/workflows/pull-request-checks.yml).
44+
45+
For the general overview of running end to end tests locally, see the relevant section of the README. The additional required inputs are:
46+
47+
- `PROXYGEN_URL_PATH`: `im1-pfs-auth-pr-<pr_number>`
48+
- `APIGEE_PROXY_NAME` `im1-pfs-auth--internal-dev--im1-pfs-auth-pr-<pr_number>`
49+
50+
### `TEST_APP_PRIVATE_KEY`
51+
52+
The private key counterpart to the key pair registered on the internal NHS Developer Hub platform is required. This can be requested from the development team.

0 commit comments

Comments
 (0)