1
1
import * as taskLib from 'azure-pipelines-task-lib/task' ;
2
2
import * as fs from 'fs' ;
3
3
import * as path from 'path' ;
4
+ import { getSystemAccessToken } from 'azure-pipelines-tasks-artifacts-common/webapi' ;
5
+ import { getHandlerFromToken , WebApi } from "azure-devops-node-api" ;
6
+ import { ITaskApi } from "azure-devops-node-api/TaskApi" ;
4
7
5
- export async function getVaultCredentials ( ) : Promise < { [ key : string ] : string } > {
8
+ export async function getVaultCredentials ( ) : Promise < [ { [ key : string ] : string } , String ] > {
6
9
let connectedService = taskLib . getInput ( "azurekvServiceConection" , true ) ;
7
10
if ( ! connectedService ) {
8
11
console . log ( taskLib . loc ( 'NoServiceConnection' ) ) ;
9
- return { } ;
12
+ return [ { } , "" ] ;
10
13
}
14
+
11
15
var authScheme = taskLib . getEndpointAuthorizationScheme ( connectedService , true ) ;
12
16
if ( ! authScheme ) {
13
17
console . log ( taskLib . loc ( 'NoAuthScheme' ) ) ;
14
- return { } ;
18
+ return [ { } , "" ] ;
15
19
}
16
20
17
21
let envVariables = { } ;
22
+ let credentialType = "" ;
18
23
switch ( authScheme . toLocaleLowerCase ( ) ) {
19
24
case "managedserviceidentity" :
20
25
// azure key vault plugin will automatially try managed idenitty
21
- console . log ( taskLib . loc ( 'UseManagedIdentity' ) ) ;
26
+ console . log ( taskLib . loc ( 'UseAuthenticationMethod' , 'Managed Identity' ) ) ;
27
+ credentialType = "managedid" ;
22
28
break ;
23
29
case "serviceprincipal" :
30
+ console . log ( taskLib . loc ( 'UseAuthenticationMethod' , 'Service Principal' ) ) ;
24
31
let authType = taskLib . getEndpointAuthorizationParameter ( connectedService , 'authenticationType' , true ) ;
25
32
let cliPassword : string | undefined = "" ;
26
33
var servicePrincipalId = taskLib . getEndpointAuthorizationParameter ( connectedService , "serviceprincipalid" , false ) ;
27
34
var tenantId = taskLib . getEndpointAuthorizationParameter ( connectedService , "tenantid" , false ) ;
28
-
29
35
if ( authType == "spnCertificate" ) {
30
36
taskLib . debug ( 'certificate based endpoint' ) ;
31
37
let certificateContent = taskLib . getEndpointAuthorizationParameter ( connectedService , "servicePrincipalCertificate" , false ) ?? '' ;
@@ -50,9 +56,76 @@ export async function getVaultCredentials(): Promise<{ [key: string]: string }>
50
56
"AZURE_CLIENT_SECRET" : cliPassword ,
51
57
}
52
58
}
59
+ credentialType = "environment"
60
+ break ;
61
+ case "workloadidentityfederation" :
62
+ console . log ( taskLib . loc ( 'UseAuthenticationMethod' , 'Workload Identity Federation' ) ) ;
63
+ var servicePrincipalId = taskLib . getEndpointAuthorizationParameter ( connectedService , "serviceprincipalid" , false ) ;
64
+ var tenantId = taskLib . getEndpointAuthorizationParameter ( connectedService , "tenantid" , false ) ;
65
+ const federatedToken = await getWorkloadIdToken ( connectedService ) ;
66
+ const extractPath = taskLib . getVariable ( 'Agent.TempDirectory' ) ;
67
+ if ( ! extractPath ) {
68
+ throw new Error ( taskLib . loc ( 'TempDirectoryNotSet' ) ) ;
69
+ }
70
+
71
+ const tokenFile = path . join ( extractPath , 'oidcToken' ) ;
72
+ fs . writeFileSync ( tokenFile , federatedToken ) ;
73
+ envVariables = {
74
+ "AZURE_TENANT_ID" : tenantId ,
75
+ "AZURE_CLIENT_ID" : servicePrincipalId ,
76
+ "AZURE_FEDERATED_TOKEN_FILE" : tokenFile ,
77
+ }
78
+ credentialType = "workloadid"
53
79
break ;
54
80
default :
55
81
throw new Error ( taskLib . loc ( 'UnsupportedAuthScheme' , authScheme ) ) ;
56
82
}
57
- return envVariables ;
83
+
84
+ return [ envVariables , credentialType ] ;
58
85
}
86
+
87
+ async function getWorkloadIdToken ( connectedService : string ) : Promise < string > {
88
+ const jobId = taskLib . getVariable ( "System.JobId" ) ;
89
+ if ( ! jobId ) {
90
+ throw new Error ( taskLib . loc ( 'FailedToGetWorkloadIdToken' , 'JobId not set' ) ) ;
91
+ }
92
+
93
+ const planId = taskLib . getVariable ( "System.PlanId" ) ;
94
+ if ( ! planId ) {
95
+ throw new Error ( taskLib . loc ( 'FailedToGetWorkloadIdToken' , 'PlanId not set' ) ) ;
96
+ }
97
+
98
+ const projectId = taskLib . getVariable ( "System.TeamProjectId" ) ;
99
+ if ( ! projectId ) {
100
+ throw new Error ( taskLib . loc ( 'FailedToGetWorkloadIdToken' , 'ProjectId not set' ) ) ;
101
+ }
102
+
103
+ const hub = taskLib . getVariable ( "System.HostType" ) ;
104
+ if ( ! hub ) {
105
+ throw new Error ( taskLib . loc ( 'FailedToGetWorkloadIdToken' , 'Hub not set' ) ) ;
106
+ }
107
+
108
+ const uri = taskLib . getVariable ( "System.CollectionUri" ) ;
109
+ if ( ! uri ) {
110
+ throw new Error ( taskLib . loc ( 'FailedToGetWorkloadIdToken' , 'CollectionUri not set' ) ) ;
111
+ }
112
+
113
+ const token = getSystemAccessToken ( ) ;
114
+ if ( ! token ) {
115
+ throw new Error ( taskLib . loc ( 'FailedToGetWorkloadIdToken' , 'Token not set' ) ) ;
116
+ }
117
+
118
+ const authHandler = getHandlerFromToken ( token ) ;
119
+ const connection = new WebApi ( uri , authHandler ) ;
120
+ const api : ITaskApi = await connection . getTaskApi ( ) ;
121
+ const response = await api . createOidcToken ( { } , projectId , hub , planId , jobId , connectedService ) ;
122
+ if ( response == null ) {
123
+ throw new Error ( taskLib . loc ( 'FailedToGetWorkloadIdToken' , 'Response is null' ) ) ;
124
+ }
125
+
126
+ if ( ! response . oidcToken ) {
127
+ throw new Error ( taskLib . loc ( 'FailedToGetWorkloadIdToken' , 'Token not set' ) ) ;
128
+ }
129
+
130
+ return response . oidcToken ;
131
+ }
0 commit comments