@@ -4,10 +4,10 @@ import (
4
4
"context"
5
5
"fmt"
6
6
"os"
7
- "strings"
8
7
9
8
"cloud.google.com/go/compute/metadata"
10
9
"github.com/alecthomas/kingpin"
10
+ "golang.org/x/oauth2"
11
11
"golang.org/x/oauth2/google"
12
12
directoryv1 "google.golang.org/api/admin/directory/v1"
13
13
"google.golang.org/api/impersonate"
@@ -112,6 +112,8 @@ func createGoogleDirectory(ctx context.Context, subject string) (*directoryv1.Se
112
112
return nil , err
113
113
}
114
114
115
+ var ts oauth2.TokenSource
116
+
115
117
// If the found credential doesn't contain JSON, try to fallback to workload identity
116
118
if len (creds .JSON ) == 0 {
117
119
// Get the email address associated with the service account. The account may be empty
@@ -128,21 +130,25 @@ func createGoogleDirectory(ctx context.Context, subject string) (*directoryv1.Se
128
130
Subject : subject ,
129
131
}
130
132
131
- ts , err := impersonate .CredentialsTokenSource (ctx , config , option .WithCredentials (creds ))
133
+ // Impersonation (as itself) is required as the federated access token obtained from the GCE
134
+ // metadata server is not sufficient for acting as the subject via domain-wide delegation.
135
+ // For delegation to work, we need to sign a JWT with the the "sub" claim set to subject -
136
+ // this happens implicitly through impersonation.
137
+ ts , err = impersonate .CredentialsTokenSource (ctx , config )
138
+ if err != nil {
139
+ return nil , err
140
+ }
141
+ } else {
142
+ conf , err := google .JWTConfigFromJSON (creds .JSON , scopes ... )
132
143
if err != nil {
133
144
return nil , err
134
145
}
135
146
136
- return directoryv1 . NewService ( ctx , option . WithTokenSource ( ts ))
137
- }
147
+ // Access to the directory API must be signed with a Subject to enable domain selection.
148
+ conf . Subject = subject
138
149
139
- conf , err := google .JWTConfigFromJSON (creds .JSON , strings .Join (scopes , " " ))
140
- if err != nil {
141
- return nil , err
150
+ ts = conf .TokenSource (ctx )
142
151
}
143
152
144
- // Access to the directory API must be signed with a Subject to enable domain selection.
145
- conf .Subject = subject
146
-
147
- return directoryv1 .NewService (ctx , option .WithHTTPClient (conf .Client (ctx )))
153
+ return directoryv1 .NewService (ctx , option .WithTokenSource (ts ))
148
154
}
0 commit comments