Skip to content
Merged
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
2 changes: 1 addition & 1 deletion docs/deployment/deployment-pipeline.md
Original file line number Diff line number Diff line change
Expand Up @@ -422,7 +422,7 @@ The ADO managed identity holds:

The managed identity does **not** hold `Key Vault Secrets Officer` — it cannot write secrets. Cloud API tokens must be provisioned separately by the team managing the cloud application.

The managed identity also does **not** hold `AppRoleAssignment.ReadWrite.All`. Microsoft Graph requires this explicit application permission to create app role assignments — being an owner of the enterprise app service principal is insufficient in application auth context. Granting this tenant-wide permission is not permitted under the organisation's Entra policy. Arc machine managed identity app role assignments are therefore granted manually by running `make <env> resource-group-init` under a user account with ownership of `spn-manbrs-web-api-<env>` — see [`scripts/bash/assign_arc_app_roles.sh`](../../scripts/bash/assign_arc_app_roles.sh) and the [Onboard Hospital VM runbook](./runbooks/onboard-hospital-vm.md#step-4--grant-api-access).
The managed identity also does **not** hold `AppRoleAssignment.ReadWrite.All`. Microsoft Graph requires this explicit application permission to create app role assignments — being an owner of the enterprise app service principal is insufficient in application auth context. Granting this tenant-wide permission is not permitted under the organisation's Entra policy. Arc machine managed identity app role assignments are therefore granted manually by running `make <env> assign-arc-app-roles` under a user account with ownership of `spn-manbrs-web-api-<env>` — see [`scripts/bash/assign_arc_app_roles.sh`](../../scripts/bash/assign_arc_app_roles.sh) and the [Onboard Hospital VM runbook](./runbooks/onboard-hospital-vm.md#step-3--grant-api-access).

### Separation of environments

Expand Down
8 changes: 4 additions & 4 deletions docs/deployment/infrastructure/create-environment.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ az provider show --namespace Microsoft.GuestConfiguration --query registrationSt

- Confirm the web API enterprise application exists:
- Name: `spn-manbrs-web-api-[environment]`
- If it does not exist, raise a ServiceNow request for the platform team to create it — the `resource-group-init` Bicep deployment and the `assign_arc_app_roles.sh` script both depend on it
- If it does not exist, raise a ServiceNow request for the platform team to create it — the `resource-group-init` Bicep deployment and the `assign-arc-app-roles` make target both depend on it
- [Form for ServiceNow](https://nhsdigitallive.service-now.com/nhs_digital?id=sc_cat_item&sys_id=28f3ab4f1bf3ca1078ac4337b04bcb78&sysparm_category=114fced51bdae1502eee65b9bd4bcbdc)

## Code
Expand Down Expand Up @@ -239,10 +239,10 @@ Terraform automatically discovers Arc machines registered in the Arc-enabled ser
make [environment] terraform-apply
```

After Terraform provisions the Hybrid Connection, re-run `resource-group-init` to assign the `Gateway.Access` app role to the new machine's managed identity:
After Terraform provisions the Hybrid Connection, run `assign-arc-app-roles` to assign the `Gateway.Access` app role to the new machine's managed identity:

```bash
make [environment] resource-group-init
make [environment] assign-arc-app-roles
```

> **Why is this a separate step?** The pipeline managed identity cannot create app role assignments — `AppRoleAssignment.ReadWrite.All` is required in application auth context regardless of SP ownership, and this permission is not permitted under the organisation's Entra policy. Running `resource-group-init` under a user account with ownership of `spn-manbrs-web-api-[environment]` is sufficient. Without this step the gateway will fail to authenticate against the cloud web API. See [Onboard Hospital VM — Step 4](../runbooks/onboard-hospital-vm.md#step-4--grant-api-access).
> **Why is this a separate step?** The pipeline managed identity cannot create app role assignments — `AppRoleAssignment.ReadWrite.All` is required in application auth context regardless of SP ownership, and this permission is not permitted under the organisation's Entra policy. Running `assign-arc-app-roles` under a user account with ownership of `spn-manbrs-web-api-[environment]` is sufficient. Without this step the gateway will fail to authenticate against the cloud web API. See [Onboard Hospital VM — Step 3](../runbooks/onboard-hospital-vm.md#step-3--grant-api-access).
28 changes: 14 additions & 14 deletions docs/deployment/runbooks/onboard-hospital-vm.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
- [ ] Trust ODS code confirmed via the [ODS portal](https://odsportal.nhsbsa.nhs.uk/)
- [ ] NHS region confirmed (`nw` | `neyh` | `mids` | `eoe` | `lon` | `se` | `sw`)
- [ ] Deployment ring agreed with the programme team
- [ ] `arc-onboarding-spn-client-id` and `arc-onboarding-spn-client-secret` retrieved from Key Vault
- [ ] `arc-onboarding-spn-client-id` retrieved from Entra ID; new `arc-onboarding-spn-client-secret` generated with 1-day expiry and shared with the hospital trust IT team before the onboarding call

---

Expand Down Expand Up @@ -91,32 +91,32 @@ Logs are written to `C:\ArcSetup\ArcSetup.log`.

**Verify**: In the Azure portal, navigate to `rg-mbsgw-<env>-uks-arc-enabled-servers` → Azure Arc machines → `gw-hull-university-teaching-hospitals-nhs-trust-rwa-01`. Status should be **Connected**.

## Step 3 — Trigger Terraform to provision the Hybrid Connection

Run the ADO pipeline **Deploy Arc Infrastructure - \<env\>** manually. Terraform discovers the new Arc machine and creates:

- `hc-gw-hull-university-teaching-hospitals-nhs-trust-rwa-01` in the relay namespace (`relay-manbrs-<env>`)
- `listen` auth rule on that Hybrid Connection

**Verify**: In the Azure portal, navigate to `relay-manbrs-<env>` → Hybrid Connections → `hc-gw-hull-university-teaching-hospitals-nhs-trust-rwa-01` is present.

## Step 4 — Grant API access
## Step 3 — Grant API access

> [!IMPORTANT]
> Without this step the gateway services will start but fail to authenticate against the cloud web API. The Arc machine's managed identity must be assigned the `Gateway.Access` app role on `spn-manbrs-web-api-<env>` before the first deployment.

Run from a developer machine with Owner access to the enterprise application:

```bash
make <env> resource-group-init
make <env> assign-arc-app-roles
```

This calls [`scripts/bash/assign_arc_app_roles.sh`](../../../scripts/bash/assign_arc_app_roles.sh) which discovers all Arc machines in `rg-mbsgw-<env>-uks-arc-enabled-servers` and assigns the `Gateway.Access` role to each machine's managed identity.

> **Why is this manual?** The pipeline managed identity (`mi-mbsgw-<env>-adotoaz-uks`) cannot create app role assignments via the pipeline — Microsoft Graph requires `AppRoleAssignment.ReadWrite.All` in application auth context regardless of SP ownership, and this permission cannot be granted under the organisation's Entra policy. Running `resource-group-init` under a user account with ownership of the enterprise app SP is sufficient. See [Deployment Pipeline — Section 12](../deployment-pipeline.md#12-pipeline-identities-and-permissions) for details.
> **Why is this manual?** The pipeline managed identity (`mi-mbsgw-<env>-adotoaz-uks`) cannot create app role assignments via the pipeline — Microsoft Graph requires `AppRoleAssignment.ReadWrite.All` in application auth context regardless of SP ownership, and this permission cannot be granted under the organisation's Entra policy. Running `assign-arc-app-roles` under a user account with ownership of the enterprise app SP is sufficient. See [Deployment Pipeline — Section 12](../deployment-pipeline.md#12-pipeline-identities-and-permissions) for details.

**Verify**: In the Azure portal navigate to **Enterprise Applications → spn-manbrs-web-api-\<env\> → Users and groups**. The Arc machine (`gw-hull-university-teaching-hospitals-nhs-trust-rwa-01`) should appear with the `Gateway.Access` role.

## Step 4 — Trigger Terraform to provision the Hybrid Connection

Run the ADO pipeline **Deploy Arc Infrastructure - \<env\>** manually. Terraform discovers the new Arc machine and creates:

- `hc-gw-hull-university-teaching-hospitals-nhs-trust-rwa-01` in the relay namespace (`relay-manbrs-<env>`)
- `listen` auth rule on that Hybrid Connection

**Verify**: In the Azure portal, navigate to `relay-manbrs-<env>` → Hybrid Connections → `hc-gw-hull-university-teaching-hospitals-nhs-trust-rwa-01` is present.

## Step 5 — Deploy the gateway application

Run the ADO pipeline **Deploy Gateway - \<env\>** with:
Expand Down Expand Up @@ -172,7 +172,7 @@ Check Log Analytics Workspace for an initial heartbeat within 5 minutes of servi
Check `C:\ArcSetup\ArcSetup.log` on the VM. Common causes:

- **Firewall blocking outbound** — confirm the VM can reach `*.arc.azure.com` on port 443
- **SPN credentials wrong** — verify client ID and secret from Key Vault are current
- **SPN credentials wrong** — confirm the one-time secret shared before the call has not expired (1-day validity); generate a new one and retry if needed
- **VM already registered** — if the machine was previously connected under a different name, disconnect first: `azcmagent disconnect`

### Script execution blocked
Expand Down
4 changes: 3 additions & 1 deletion scripts/terraform/terraform.mk
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,11 @@ ci: # Skip manual approvals when running in CI - make ci <env> <action>
set-azure-account: # Set the Azure account for the environment - make <env> set-azure-account
[ "${SKIP_AZURE_LOGIN}" != "true" ] && az account set -s ${AZURE_SUBSCRIPTION} || true

resource-group-init: set-azure-account get-subscription-ids # Initialise resources required by terraform and assign Gateway.Access role to Arc machine managed identities - make <env> resource-group-init
resource-group-init: set-azure-account get-subscription-ids # Initialise resources required by terraform - make <env> resource-group-init
$(eval STORAGE_ACCOUNT_NAME=sa${APP_SHORT_NAME}${ENV_CONFIG}tfstate)
scripts/bash/resource_group_init.sh "${REGION}" "${HUB_SUBSCRIPTION_ID}" "${ENABLE_SOFT_DELETE}" "${ENV_CONFIG}" "${STORAGE_ACCOUNT_RG}" "${STORAGE_ACCOUNT_NAME}" "${APP_SHORT_NAME}" "${ARM_SUBSCRIPTION_ID}"

assign-arc-app-roles: set-azure-account get-subscription-ids # Assign Gateway.Access app role to Arc machine managed identities - make <env> assign-arc-app-roles
scripts/bash/assign_arc_app_roles.sh "${ENV_CONFIG}" "${ARM_SUBSCRIPTION_ID}"

get-subscription-ids: # Retrieve the hub subscription ID based on the subscription name in ${HUB_SUBSCRIPTION} - make <env> get-subscription-ids
Expand Down
Loading