Skip to content

Commit adbe36e

Browse files
committed
deploy: use OpenID Connect instead of RBAC
Apparently after the `publish-profile` deployments stopped working as expected, even RBAC now fails. At least when I tried last, it failed thusly: ▶Run azure/login@v1 Running Azure CLI Login. /usr/bin/az cloud set -n azurecloud Done setting cloud: "azurecloud" Note: Azure/login action also supports OIDC login mechanism. Refer https://github.com/azure/login#configure-a-service-principal-with-a-federated-credential-to-use-oidc-based-authentication for more details. Attempting Azure CLI login by using service principal with secret... Error: AADSTS7000215: Invalid client secret provided. Ensure the secret being sent in the request is the client secret value, not the client secret ID, for a secret added to app '***'. Trace ID: 8b5b5391-5b96-472c-a0e7-11ae90b1c000 Correlation ID: bd635df4-82ca-441c-af9e-154d18e92773 Timestamp: 2026-02-12 16:28:25Z Error: The error may be caused by passing a service principal certificate with --password. Please note that --password no longer accepts a service principal certificate. To pass a service principal certificate, use --certificate instead. Error: Login failed with Error: The process '/usr/bin/az' failed with exit code 1. Double check if the 'auth-type' is correct. Refer to https://github.com/Azure/login#readme for more information. My guess is that even RBAC is considered too insecure. Let's use OpenID Connect, as it is tied to the GitHub workflow and is therefore as secure as it gets. Even if the name of the Managed Identity, the tenant and the subscription IDs are known, an attacker cannot authenticate as that managed identity. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
1 parent 0d66474 commit adbe36e

File tree

2 files changed

+24
-8
lines changed

2 files changed

+24
-8
lines changed

.github/workflows/deploy.yml

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ on:
88
- '.github/workflows/deploy.yml'
99
- 'GitForWindowsHelper/**'
1010

11+
permissions:
12+
contents: read
13+
id-token: write
14+
1115
jobs:
1216
deploy:
1317
if: github.event.repository.fork == false
@@ -16,9 +20,11 @@ jobs:
1620
steps:
1721
- uses: actions/checkout@v6
1822
- name: 'Login via Azure CLI'
19-
uses: azure/login@v1
23+
uses: azure/login@v2
2024
with:
21-
creds: ${{ secrets.AZURE_RBAC_CREDENTIALS }}
25+
client-id: ${{ secrets.AZURE_CLIENT_ID }}
26+
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
27+
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
2228
- uses: Azure/functions-action@v1
2329
with:
2430
app-name: ${{ secrets.AZURE_FUNCTION_NAME || 'GitForWindowsHelper' }}

README.md

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -113,15 +113,25 @@ First of all, a new [Azure Function](https://portal.azure.com/#blade/HubsExtensi
113113

114114
#### Obtaining the Azure credentials
115115

116-
The idea is to use [Role-Based Access Control (RBAC)](https://github.com/Azure/functions-action?tab=readme-ov-file#using-azure-service-principal-for-rbac-as-deployment-credential) to log into Azure in the deploy workflow. Essentially, after the deployment succeeded, in an Azure CLI (for example [the one that is very neatly embedded in the Azure Portal](https://learn.microsoft.com/en-us/azure/cloud-shell/get-started/classic)), run this (after replacing the placeholders `{subscription-id}`, `{resource-group}` and `{app-name}`):
116+
The idea is to use [OpenID Connect](https://docs.github.com/en/actions/concepts/security/openid-connect) to log into Azure in the deploy workflow, _identifying_ as said workflow, via a "Managed Identity". This can be registered after the Azure Function has been successfully created: In an Azure CLI (for example [the one that is very neatly embedded in the Azure Portal](https://learn.microsoft.com/en-us/azure/cloud-shell/get-started/classic)), run this (after replacing the placeholders `{subscription-id}`, `{resource-group}` and `{app-name}`):
117117

118118
```shell
119-
az ad sp create-for-rbac --name "myApp" --role contributor \
120-
--scopes /subscriptions/{subscription-id}/resourceGroups/{resource-group}/providers/Microsoft.Web/sites/{app-name} \
121-
--sdk-auth
119+
az identity create --name <managed-identity-name> -g <resource-group>
120+
az identity federated-credential create \
121+
--identity-name <managed-identity-name> \
122+
--resource-group <resource-group> \
123+
--name github-workflow \
124+
--issuer https://token.actions.githubusercontent.com \
125+
--subject repo:<org>/gfw-helper-github-app:environment:deploy-to-azure \
126+
--audiences api://AzureADTokenExchange
127+
# The scope can be copied from the Azure Portal URL after navigating to the Azure Function
128+
az role assignment create \
129+
--assignee <client-id-of-managed-identity> \
130+
--scope '/subscriptions/<subscription-id>/resourceGroups/<resource-group>/providers/Microsoft.Web/sites/<azure-function-name>' \
131+
--role 'Contributor'
122132
```
123133

124-
The result is called an "Azure Service Principal" in Azure Speak; Essentially it is a tightly-scoped credential that allows deploying this particular Azure Function and that's it. This Azure Service Principal will be the value of the `AZURE_RBAC_CREDENTIALS` Actions secret, more on that below.
134+
The result is a "managed identity", essentially a tightly-scoped credential that allows deploying this particular Azure Function from that particular repository in a GitHub workflow run and that's it. This managed identity is identified via the `AZURE_CLIENT_ID`, `AZURE_TENANT_ID` and `AZURE_SUBSCRIPTION_ID` Actions secrets, more on that below.
125135

126136
#### Some environment variables
127137

@@ -131,7 +141,7 @@ Concretely, the environment variables `GITHUB_WEBHOOK_SECRET`, `GITHUB_APP_PRIVA
131141

132142
### The repository
133143

134-
On https://github.com/, the `+` link on the top was pressed, and an empty, private repository was registered. Nothing was pushed to it yet.
144+
Create a fork of https://github.com/git-for-windows/gfw-helper-github-app. Configure the Azure Managed Identity via Actions secrets, under the keys `AZURE_CLIENT_ID`, `AZURE_TENANT_ID`, and `AZURE_SUBSCRIPTION_ID`. Also, the `AZURE_FUNCTION_NAME` secret needs to be defined (its value is the name of the Azure Function).
135145

136146
After that, the Azure Service Principal needs to be registered as Actions secret, under the name `AZURE_RBAC_CREDENTIALS`.
137147

0 commit comments

Comments
 (0)