1
1
import * as gcp from "@pulumi/gcp" ;
2
+ import * as pulumi from "@pulumi/pulumi" ;
3
+
4
+ const gcpConfig = new pulumi . Config ( "gcp" ) ;
5
+ const projectId = gcpConfig . require ( "project" )
2
6
3
7
const secret = new gcp . secretmanager . Secret ( "test-secret" , {
4
8
secretId : "novops-test-secret" ,
@@ -10,4 +14,91 @@ const secret = new gcp.secretmanager.Secret("test-secret", {
10
14
const secretVersion = new gcp . secretmanager . SecretVersion ( "test-secret-version" , {
11
15
secret : secret . id ,
12
16
secretData : "very!S3cret" ,
13
- } )
17
+ } )
18
+
19
+ // Workload Identity Federation config to allow Azure authentication and test of Google WIF
20
+ // Retrieve outputs from Azure setup stack
21
+ // As documented on https://cloud.google.com/iam/docs/workload-identity-federation-with-other-clouds#azure_2
22
+
23
+ const azStackRef = new pulumi . StackReference ( "az-stack-ref" , { name : "pierrebeucher/novops-test-infra-azure/test" } )
24
+ const azServicePrincipalObjectId = azStackRef . requireOutput ( "servicePrincipalObjectId" ) as pulumi . Output < string >
25
+ const azTenantId = azStackRef . requireOutput ( "tenantId" ) as pulumi . Output < string >
26
+ const azAppIdentifierUri = azStackRef . requireOutput ( "identifierUri" ) as pulumi . Output < string >
27
+
28
+ const poolId = "novops-test-identity-pool"
29
+ const providerId = "azure"
30
+
31
+ // Use an import-if-exists and retain pattern to avoid deletion on stack down and re-import on stack up
32
+ // Otherwise, as resources are soft-deleted, Google API would consider them already existing if Pulumi tried to recreate them
33
+ // See https://github.com/pulumi/pulumi-gcp/issues/1149
34
+ const identityPool = pulumi . output ( gcp . iam . getWorkloadIdentityPool ( {
35
+ workloadIdentityPoolId : poolId ,
36
+ } ) . then ( existingPool =>
37
+ new gcp . iam . WorkloadIdentityPool ( "workload-identity-pool" , {
38
+ workloadIdentityPoolId : poolId ,
39
+ } , {
40
+ import : existingPool . workloadIdentityPoolId ,
41
+ retainOnDelete : true ,
42
+ } )
43
+ ) . catch ( e =>
44
+ new gcp . iam . WorkloadIdentityPool ( "workload-identity-pool" , {
45
+ workloadIdentityPoolId : poolId ,
46
+ } , {
47
+ retainOnDelete : true ,
48
+ } )
49
+ ) )
50
+
51
+ const workloadIdentityProvider = pulumi . output ( gcp . iam . getWorkloadIdentityPoolProvider ( {
52
+ workloadIdentityPoolProviderId : providerId ,
53
+ workloadIdentityPoolId : poolId
54
+ } ) . then ( existingWifProvider =>
55
+ new gcp . iam . WorkloadIdentityPoolProvider ( "workload-identity-pool-provider" , {
56
+ workloadIdentityPoolProviderId : providerId ,
57
+ workloadIdentityPoolId : poolId ,
58
+ oidc : {
59
+ issuerUri : pulumi . interpolate `https://sts.windows.net/${ azTenantId } /` ,
60
+ allowedAudiences : [ azAppIdentifierUri ] ,
61
+ } ,
62
+ attributeMapping : {
63
+ "google.subject" : "assertion.sub" ,
64
+ } ,
65
+ } , {
66
+ import : existingWifProvider . name ,
67
+ retainOnDelete : true ,
68
+ } )
69
+ ) . catch ( e =>
70
+ new gcp . iam . WorkloadIdentityPoolProvider ( "workload-identity-pool-provider" , {
71
+ workloadIdentityPoolProviderId : providerId ,
72
+ workloadIdentityPoolId : poolId ,
73
+ oidc : {
74
+ issuerUri : pulumi . interpolate `https://sts.windows.net/${ azTenantId } /` ,
75
+ allowedAudiences : [ azAppIdentifierUri ] ,
76
+ } ,
77
+ attributeMapping : {
78
+ "google.subject" : "assertion.sub" ,
79
+ } ,
80
+ } , {
81
+ retainOnDelete : true ,
82
+ } )
83
+ ) )
84
+
85
+ const secretManagerIamBinding = new gcp . projects . IAMMember ( "secret-manager-iam-binding" , {
86
+ project : projectId ,
87
+ role : "roles/secretmanager.secretAccessor" ,
88
+ // Service Principal Object ID is the ID Google uses to identify or Azure user
89
+ member : pulumi . interpolate `principal://iam.googleapis.com/projects/${ projectId } /locations/global/workloadIdentityPools/${ poolId } /subject/${ azServicePrincipalObjectId } ` ,
90
+ } , {
91
+ dependsOn : [ workloadIdentityProvider ]
92
+ } )
93
+
94
+ const viewerIamBinding = new gcp . projects . IAMMember ( "viewer-iam-binding" , {
95
+ project : projectId ,
96
+ role : "roles/viewer" ,
97
+ member : pulumi . interpolate `principal://iam.googleapis.com/projects/${ projectId } /locations/global/workloadIdentityPools/${ poolId } /subject/${ azServicePrincipalObjectId } ` ,
98
+ } , {
99
+ dependsOn : [ workloadIdentityProvider ]
100
+ } )
101
+
102
+ export const workloadIdentityPoolName = identityPool . name
103
+ export const workloadIdentityPoolProviderName = workloadIdentityProvider . name
104
+ export const providerResourceName = workloadIdentityProvider . id
0 commit comments