Skip to content

Commit 64b33d2

Browse files
authored
Add Packaging WIF Handshake for Packaging Authenticate Tasks (#342)
* Add Entra Auth User WIF service connection utility for Packaging tasks * Update module strings and bump version * bump package version * Correct login url * Address PR comments
1 parent 04f7c52 commit 64b33d2

File tree

5 files changed

+180
-491
lines changed

5 files changed

+180
-491
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export declare function getFederatedWorkloadIdentityCredentials(serviceConnectionName: string, tenantId?: string) : Promise<string | undefined>
2+
export declare function getFeedTenantId(feedUrl: string) : Promise<string | undefined>
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import path = require("path");
2+
import * as tl from 'azure-pipelines-task-lib/task';
3+
import { getSystemAccessToken } from "./webapi";
4+
import fetch from "node-fetch";
5+
6+
tl.setResourcePath(path.join(__dirname, 'module.json'), true);
7+
8+
const ADO_RESOURCE : string = "499b84ac-1321-427f-aa17-267ca6975798/.default";
9+
const CLIENT_ASSERTION_TYPE : string = "urn:ietf:params:oauth:client-assertion-type:jwt-bearer";
10+
const GRANT_TYPE = "client_credentials";
11+
12+
export async function getFederatedWorkloadIdentityCredentials(serviceConnectionName: string, tenantId?: string) : Promise<string | undefined>
13+
{
14+
try {
15+
let tenant = tenantId ?? tl.getEndpointAuthorizationParameterRequired(serviceConnectionName, "TenantId");
16+
tl.debug(tl.loc('Info_UsingTenantId', tenantId));
17+
const systemAccessToken = getSystemAccessToken();
18+
const url = process.env["SYSTEM_OIDCREQUESTURI"]+"?api-version=7.1&serviceConnectionId="+serviceConnectionName;
19+
20+
const ADOResponse: {oidcToken: string} = await (await fetch(url,
21+
{
22+
method: 'POST',
23+
headers:
24+
{
25+
'Content-Type': 'application/json',
26+
'Authorization': 'Bearer '+ systemAccessToken
27+
}
28+
})).json() as {oidcToken: string};
29+
30+
tl.setSecret(ADOResponse.oidcToken);
31+
let entraURI = "https://login.windows.net/"+tenant+"/oauth2/v2.0/token";
32+
let clientId = tl.getEndpointAuthorizationParameterRequired(serviceConnectionName, "ServicePrincipalId");
33+
34+
let body = {
35+
'scope': ADO_RESOURCE,
36+
'client_id': clientId,
37+
'client_assertion_type': CLIENT_ASSERTION_TYPE,
38+
'client_assertion': ADOResponse.oidcToken,
39+
'grant_type': GRANT_TYPE
40+
};
41+
42+
let formBody = Object.keys(body)
43+
.map(key => encodeURIComponent(key) + '=' + encodeURIComponent(body[key]))
44+
.join('&');
45+
46+
const entraResponse: {access_token: string} = await (await fetch(entraURI,
47+
{
48+
method: 'POST',
49+
body: formBody,
50+
headers:
51+
{
52+
'Content-Type': 'application/x-www-form-urlencoded'
53+
}
54+
})).json() as {access_token: string};
55+
tl.setSecret(entraResponse.access_token);
56+
return entraResponse.access_token;
57+
}
58+
catch (error)
59+
{
60+
tl.error(tl.loc("Error_FederatedTokenAquisitionFailed", error));
61+
return undefined;
62+
}
63+
}
64+
65+
export async function getFeedTenantId(feedUrl: string) : Promise<string | undefined>
66+
{
67+
try
68+
{
69+
const feedResponse = await fetch(feedUrl);
70+
return feedResponse?.headers?.get('X-VSS-ResourceTenant');
71+
}
72+
catch (error)
73+
{
74+
tl.warning(tl.loc("Error_GetFeedTenantIdFailed", error));
75+
return undefined;
76+
}
77+
}

common-npm-packages/artifacts-common/module.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,14 @@
1313
"CredProvider_SettingUpForOrgFeeds": "Setting up the credential provider to use the identity '%s' for feeds in your organization/collection starting with:",
1414
"CredProvider_SettingUpForServiceConnections": "Setting up the credential provider for these service connections:",
1515
"ErrorInSettingUpSubscription": "Error in setting up subscription",
16+
"Error_FederatedTokenAquisitionFailed": "Failed to aquire federated token. %s",
17+
"Error_GetFeedTenantIdFailed": "Failed to find tenantId for feedUrl. %s",
1618
"LoginFailed": "Azure login failed",
1719
"MSILoginFailed": "Azure login failed using Managed Service Identity",
1820
"ServiceConnections_Error_FailedToParseServiceEndpoint_MissingParameter": "Failed to parse the service endpoint '%s' because it was missing the parameter '%s'",
1921
"ServiceConnections_Error_FailedToParseServiceEndpoint_BadScheme": "Failed to parse the service endpoint '%s' because the auth scheme '%s' was invalid",
2022
"SettingAzureCloud": "Setting active cloud to: %s",
21-
"Info_GotAndMaskAuth":"Got auth token, setting it as secret so it does not print in console log"
23+
"Info_GotAndMaskAuth":"Got auth token, setting it as secret so it does not print in console log",
24+
"Info_UsingTenantId" : "Using tenant id: %s"
2225
}
2326
}

0 commit comments

Comments
 (0)