Skip to content

Commit e077ff0

Browse files
authored
Merge pull request #143 from AaronCrawfis/aacrawfi/service-principals
Switch auth handler to `getHandlerFromToken` to allow service principals
2 parents e92c7d6 + 2ab6108 commit e077ff0

File tree

2 files changed

+85
-4
lines changed

2 files changed

+85
-4
lines changed

README.md

Lines changed: 82 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,84 @@ Update Azure DevOps work item when a GitHub Issue is updated
1212

1313
The id of the Work Item created or updated
1414

15-
## Example
15+
## Examples
16+
17+
### Entra ID Service Principal
18+
19+
1. Register an [Entra ID app registration](https://learn.microsoft.com/en-us/entra/identity-platform/quickstart-register-app)
20+
1. Configure the app registration with a [federated identity for GitHub Actions](https://learn.microsoft.com/en-us/entra/workload-id/workload-identity-federation-create-trust?pivots=identity-wif-apps-methods-azp#github-actions)
21+
1. Add your Entra ID app registration [to your Azure DevOps organization](https://learn.microsoft.com/en-us/azure/devops/integrate/get-started/authentication/service-principal-managed-identity?view=azure-devops#2-add-and-manage-service-principals-in-an-azure-devops-organization), with work item write permissions
22+
1. [Create Actions variables or secrets](https://learn.microsoft.com/en-us/azure/devops/integrate/get-started/authentication/service-principal-managed-identity?view=azure-devops#2-add-and-manage-service-principals-in-an-azure-devops-organization) for the application ID (`ENTRA_APP_CLIENT_ID`) and tenant ID (`ENTRA_APP_TENANT_ID`)
23+
1. Add an optional secret named `GH_PERSONAL_ACCESS_TOKEN` containing a [GitHub Personal Access Token](https://help.github.com/en/enterprise/2.17/user/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line) with "repo" permissions. See optional information below.
24+
1. Add a workflow file which responds to issue events, generates an Entra ID token, and syncs the issue
25+
26+
- Set Azure DevOps organization and project details.
27+
- Set specific work item type settings (type, new state, closed state)
28+
29+
Optional Env Variables
30+
31+
- `ado_area_path`: To set a specific area path you want your work items created in. If providing a full qualified path such as `area\sub_area`, then be sure to use the format of: `ado_area_path: "area\\area"` to avoid parsing failures.
32+
- `ado_iteration_path`: To set a specific iteration path you want your work items created in. If providing a full qualified path such as `iteration\sub iteration`, then be sure to use the format of: `ado_iteration_path: "iteration\\iteration"` to avoid parsing failures.
33+
- `github_token`: Used to update the Issue with AB# syntax to link the work item to the issue. This will only work if the project is configured to use the [GitHub Azure Boards](https://github.com/marketplace/azure-boards) app. If you do not define this value, the action will still work, but the experience is not as nice.
34+
- `ado_bypassrules`: Used to bypass any rules on the form to ensure the work item gets created in Azure DevOps. However, some organizations getting bypassrules permissions for the token owner can go against policy. By default the bypassrules will be set to false. If you have rules on your form that prevent the work item to be created with just Title and Description, then you will need to set to true.
35+
- `log_level`: Used to set the logging verbosity to help with debugging in a production environment. 100 is the default.
36+
37+
**Warning:** Setting `log_level` to 300 will log out environment info, work items, and issue data. Only use 300 when debugging issues.
38+
39+
```yaml
40+
name: Sync issue to Azure DevOps work item
41+
42+
on:
43+
issues:
44+
types:
45+
[opened, edited, deleted, closed, reopened, labeled, unlabeled, assigned]
46+
issue_comment:
47+
types: [created, edited, deleted]
48+
49+
concurrency:
50+
group: issue-${{ github.event.issue.number }}
51+
cancel-in-progress: false
52+
53+
# Extra permissions needed to login with Entra ID service principal via federated identity
54+
permissions:
55+
id-token: write
56+
issues: write
57+
58+
jobs:
59+
alert:
60+
if: ${{ !github.event.issue.pull_request }}
61+
runs-on: ubuntu-latest
62+
steps:
63+
- name: Login to Azure
64+
uses: azure/login@v2
65+
with:
66+
client-id: ${{ secrets.ENTRA_APP_CLIENT_ID }}
67+
tenant-id: ${{ secrets.ENTRA_APP_TENANT_ID }}
68+
allow-no-subscriptions: true
69+
- name: Get Azure DevOps token
70+
id: get_ado_token
71+
run:
72+
# The resource ID for Azure DevOps is always 499b84ac-1321-427f-aa17-267ca6975798
73+
# https://learn.microsoft.com/azure/devops/integrate/get-started/authentication/service-principal-managed-identity
74+
echo "ado_token=$(az account get-access-token --resource 499b84ac-1321-427f-aa17-267ca6975798 --query "accessToken" --output tsv)" >> $GITHUB_ENV
75+
- uses: danhellem/github-actions-issue-to-work-item@master
76+
env:
77+
ado_token: "${{ env.ado_token }}"
78+
github_token: "${{ secrets.GH_PERSONAL_ACCESS_TOKEN }}"
79+
ado_organization: "ado_organization_name"
80+
ado_project: "your_project_name"
81+
ado_area_path: "optional_area_path\\optional_area_path"
82+
ado_iteration_path: "optional_iteration_path\\optional_iteration_path"
83+
ado_wit: "User Story"
84+
ado_new_state: "New"
85+
ado_active_state: "Active"
86+
ado_close_state: "Closed"
87+
ado_bypassrules: true
88+
log_level: 100
89+
```
90+
91+
92+
### Personal Access Token
1693
1794
1. Add a secret named `ADO_PERSONAL_ACCESS_TOKEN` containing an [Azure Personal Access Token](https://docs.microsoft.com/en-us/azure/devops/organizations/accounts/use-personal-access-tokens-to-authenticate) with "read & write" permission for Work Items
1895

@@ -45,6 +122,10 @@ on:
45122
issue_comment:
46123
types: [created, edited, deleted]
47124
125+
concurrency:
126+
group: issue-${{ github.event.issue.number }}
127+
cancel-in-progress: false
128+
48129
jobs:
49130
alert:
50131
if: ${{ !github.event.issue.pull_request }}

index.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,7 @@ async function create(vm) {
229229
console.log(patchDocument);
230230
}
231231

232-
let authHandler = azdev.getPersonalAccessTokenHandler(vm.env.adoToken);
232+
let authHandler = azdev.getHandlerFromToken(vm.env.adoToken);
233233
let connection = new azdev.WebApi(vm.env.orgUrl, authHandler);
234234
let client = await connection.getWorkItemTrackingApi();
235235
let workItemSaveResult = null;
@@ -493,7 +493,7 @@ async function unlabel(vm, workItem) {
493493
async function find(vm) {
494494
if (vm.env.logLevel >= 200) console.log(`Starting 'find' method...`);
495495

496-
let authHandler = azdev.getPersonalAccessTokenHandler(vm.env.adoToken);
496+
let authHandler = azdev.getHandlerFromToken(vm.env.adoToken);
497497
let connection = new azdev.WebApi(vm.env.orgUrl, authHandler);
498498
let client = null;
499499
let workItem = null;
@@ -572,7 +572,7 @@ async function find(vm) {
572572
async function updateWorkItem(patchDocument, id, env) {
573573
if (env.logLevel >= 200) console.log(`Starting 'updateWorkItem' method...`);
574574

575-
let authHandler = azdev.getPersonalAccessTokenHandler(env.adoToken);
575+
let authHandler = azdev.getHandlerFromToken(env.adoToken);
576576
let connection = new azdev.WebApi(env.orgUrl, authHandler);
577577
let client = await connection.getWorkItemTrackingApi();
578578
let workItemSaveResult = null;

0 commit comments

Comments
 (0)