Skip to content

Commit 58b1bb9

Browse files
committed
deploy: use OpenID Connect instead of a publish profile
Apparently the `publish-profile` deployments are no longer working as expected for recently-created Azure Functions. That is, the existing `gitgitgadget` Function still works, obviously, but when I registered a new Function as described in the `README.md` and tried to deploy it the same way as `gitgitgadget`, it failed thusly: ▶ Run Azure/functions-action@v1 Successfully parsed SCM credential from publish-profile format. Using SCM credential for authentication, GitHub Action will not perform resource validation. (node:1549) [DEP0005] DeprecationWarning: Buffer() is deprecated due to security and usability issues. Please use the Buffer.alloc(), Buffer.allocUnsafe(), or Buffer.from() methods instead. (Use `node --trace-deprecation ...` to show where the warning was created) Error: Execution Exception (state: ValidateAzureResource) (step: Invocation) Error: When request Azure resource at ValidateAzureResource, Get Function App Settings : Failed to acquire app settings from https://<scmsite>/api/settings with publish-profile Error: Failed to fetch Kudu App Settings. Unauthorized (CODE: 401) Error: Error: Failed to fetch Kudu App Settings. Unauthorized (CODE: 401) at Kudu.<anonymous> (/home/runner/work/_actions/Azure/functions-action/v1/lib/appservice-rest/Kudu/azure-app-kudu-service.js:69:23) at Generator.next (<anonymous>) at fulfilled (/home/runner/work/_actions/Azure/functions-action/v1/lib/appservice-rest/Kudu/azure-app-kudu-service.js:5:58) at processTicksAndRejections (node:internal/process/task_queues:96:5) Error: Deployment Failed! My guess is that finally the reality of publish profiles being highly insecure has caught up with new Azure Function registrations, and it is now required to use much more secure methods instead. 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 <[email protected]>
1 parent 0299d1b commit 58b1bb9

File tree

2 files changed

+31
-6
lines changed

2 files changed

+31
-6
lines changed

.github/workflows/deploy.yml

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,24 @@ on:
99
- '.github/workflows/deploy.yml'
1010
- 'GitGitGadget/**'
1111

12+
permissions:
13+
contents: read
14+
id-token: write
15+
1216
jobs:
1317
deploy:
1418
if: github.event.repository.fork == false
1519
environment: deploy-to-azure
1620
runs-on: ubuntu-latest
1721
steps:
1822
- uses: actions/checkout@v5
23+
- name: 'Login via Azure CLI'
24+
uses: azure/login@v2
25+
with:
26+
client-id: ${{ secrets.AZURE_CLIENT_ID }}
27+
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
28+
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
1929
- uses: Azure/functions-action@v1
2030
with:
2131
app-name: ${{ secrets.AZURE_FUNCTION_NAME || 'GitGitGadget' }}
22-
publish-profile: ${{ secrets.AZURE_FUNCTIONAPP_PUBLISH_PROFILE }}
2332
respect-funcignore: true

README.md

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,27 @@ This process looks a bit complex, the main reason for that being that three thin
5353

5454
First of all, a new [Azure Function](https://portal.azure.com/#blade/HubsExtension/BrowseResourceBlade/resourceType/Microsoft.Web%2Fsites/kind/functionapp) was created. A Linux one was preferred, for cost and performance reasons. Deployment with GitHub was _not_ yet configured.
5555

56-
#### Getting the "publish profile"
56+
#### Obtaining the Azure credentials
57+
58+
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}`):
59+
60+
```shell
61+
az identity create --name <managed-identity-name> -g <resource-group>
62+
az identity federated-credential create \
63+
--identity-name <managed-identity-name> \
64+
--resource-group <resource-group> \
65+
--name github-workflow \
66+
--issuer https://token.actions.githubusercontent.com \
67+
--subject repo:<org>/gitgitgadget-github-app:environment:deploy-to-azure \
68+
--audiences api://AzureADTokenExchange
69+
# The scope can be copied from the Azure Portal URL after navigating to the Azure Function
70+
az role assignment create \
71+
--assignee <client-id-of-managed-identity> \
72+
--scope '/subscriptions/<subscription-id>/resourceGroups/<resource-group>/providers/Microsoft.Web/sites/<azure-function-name>' \
73+
--role 'Contributor'
74+
```
5775

58-
After the deployment succeeded, in the "Overview" tab, there is a "Get publish profile" link on the right panel at the center top. Clicking it will automatically download a `.json` file whose contents will be needed later.
76+
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.
5977

6078
#### Some environment variables
6179

@@ -67,9 +85,7 @@ Also, the `GITHUB_APP_ID` and `GITHUB_APP_PRIVATE_KEY` variables are needed in o
6785

6886
### The repository
6987

70-
On https://github.com/, the `+` link on the top was pressed, and an empty, private repository was registered. Nothing was pushed to it yet.
71-
72-
After that, the contents of the publish profile that [was downloaded earlier](#getting-the-publish-profile) were registered as Actions secret, under the name `AZURE_FUNCTIONAPP_PUBLISH_PROFILE`.
88+
Create a fork of https://github.com/gitgitgadget/gitgitgadget-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).
7389

7490
This repository was initialized locally by forking https://github.com/gitgitgadget/gitgitgadget and separating out the Azure Functions part of it. Then, the test suite was developed and the GitHub workflows were adapted from https://github.com/git-for-windows/gfw-helper-github-app. After that, the `origin` remote was set to the newly registered repository on GitHub.
7591

0 commit comments

Comments
 (0)