Skip to content

Commit

Permalink
Add Packaging WIF Handshake for Packaging Authenticate Tasks (#342)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
embetten authored Jul 3, 2024
1 parent 04f7c52 commit 64b33d2
Show file tree
Hide file tree
Showing 5 changed files with 180 additions and 491 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export declare function getFederatedWorkloadIdentityCredentials(serviceConnectionName: string, tenantId?: string) : Promise<string | undefined>
export declare function getFeedTenantId(feedUrl: string) : Promise<string | undefined>
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import path = require("path");
import * as tl from 'azure-pipelines-task-lib/task';
import { getSystemAccessToken } from "./webapi";
import fetch from "node-fetch";

tl.setResourcePath(path.join(__dirname, 'module.json'), true);

const ADO_RESOURCE : string = "499b84ac-1321-427f-aa17-267ca6975798/.default";
const CLIENT_ASSERTION_TYPE : string = "urn:ietf:params:oauth:client-assertion-type:jwt-bearer";
const GRANT_TYPE = "client_credentials";

export async function getFederatedWorkloadIdentityCredentials(serviceConnectionName: string, tenantId?: string) : Promise<string | undefined>
{
try {
let tenant = tenantId ?? tl.getEndpointAuthorizationParameterRequired(serviceConnectionName, "TenantId");
tl.debug(tl.loc('Info_UsingTenantId', tenantId));
const systemAccessToken = getSystemAccessToken();
const url = process.env["SYSTEM_OIDCREQUESTURI"]+"?api-version=7.1&serviceConnectionId="+serviceConnectionName;

const ADOResponse: {oidcToken: string} = await (await fetch(url,
{
method: 'POST',
headers:
{
'Content-Type': 'application/json',
'Authorization': 'Bearer '+ systemAccessToken
}
})).json() as {oidcToken: string};

tl.setSecret(ADOResponse.oidcToken);
let entraURI = "https://login.windows.net/"+tenant+"/oauth2/v2.0/token";
let clientId = tl.getEndpointAuthorizationParameterRequired(serviceConnectionName, "ServicePrincipalId");

let body = {
'scope': ADO_RESOURCE,
'client_id': clientId,
'client_assertion_type': CLIENT_ASSERTION_TYPE,
'client_assertion': ADOResponse.oidcToken,
'grant_type': GRANT_TYPE
};

let formBody = Object.keys(body)
.map(key => encodeURIComponent(key) + '=' + encodeURIComponent(body[key]))
.join('&');

const entraResponse: {access_token: string} = await (await fetch(entraURI,
{
method: 'POST',
body: formBody,
headers:
{
'Content-Type': 'application/x-www-form-urlencoded'
}
})).json() as {access_token: string};
tl.setSecret(entraResponse.access_token);
return entraResponse.access_token;
}
catch (error)
{
tl.error(tl.loc("Error_FederatedTokenAquisitionFailed", error));
return undefined;
}
}

export async function getFeedTenantId(feedUrl: string) : Promise<string | undefined>
{
try
{
const feedResponse = await fetch(feedUrl);
return feedResponse?.headers?.get('X-VSS-ResourceTenant');
}
catch (error)
{
tl.warning(tl.loc("Error_GetFeedTenantIdFailed", error));
return undefined;
}
}
5 changes: 4 additions & 1 deletion common-npm-packages/artifacts-common/module.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,14 @@
"CredProvider_SettingUpForOrgFeeds": "Setting up the credential provider to use the identity '%s' for feeds in your organization/collection starting with:",
"CredProvider_SettingUpForServiceConnections": "Setting up the credential provider for these service connections:",
"ErrorInSettingUpSubscription": "Error in setting up subscription",
"Error_FederatedTokenAquisitionFailed": "Failed to aquire federated token. %s",
"Error_GetFeedTenantIdFailed": "Failed to find tenantId for feedUrl. %s",
"LoginFailed": "Azure login failed",
"MSILoginFailed": "Azure login failed using Managed Service Identity",
"ServiceConnections_Error_FailedToParseServiceEndpoint_MissingParameter": "Failed to parse the service endpoint '%s' because it was missing the parameter '%s'",
"ServiceConnections_Error_FailedToParseServiceEndpoint_BadScheme": "Failed to parse the service endpoint '%s' because the auth scheme '%s' was invalid",
"SettingAzureCloud": "Setting active cloud to: %s",
"Info_GotAndMaskAuth":"Got auth token, setting it as secret so it does not print in console log"
"Info_GotAndMaskAuth":"Got auth token, setting it as secret so it does not print in console log",
"Info_UsingTenantId" : "Using tenant id: %s"
}
}
Loading

0 comments on commit 64b33d2

Please sign in to comment.