|
51 | 51 | import java.io.FileInputStream;
|
52 | 52 | import java.io.IOException;
|
53 | 53 | import java.nio.charset.StandardCharsets;
|
| 54 | +import java.time.Instant; |
54 | 55 | import org.junit.jupiter.api.BeforeEach;
|
55 | 56 | import org.junit.jupiter.api.Test;
|
56 | 57 |
|
@@ -86,7 +87,7 @@ void setup() throws IOException {
|
86 | 87 | * using the iamcredentials generateIdToken API. This will use the service account client ID as
|
87 | 88 | * the sub field of the token. This OIDC token will be used as the external subject token to be
|
88 | 89 | * exchanged for a GCP access token via GCP STS endpoint and then to impersonate the original
|
89 |
| - * service account key. |
| 90 | + * service account key. Retrieves the OIDC token from a file. |
90 | 91 | */
|
91 | 92 | @Test
|
92 | 93 | void identityPoolCredentials() throws IOException {
|
@@ -150,6 +151,23 @@ void awsCredentials() throws Exception {
|
150 | 151 | callGcs(awsCredential);
|
151 | 152 | }
|
152 | 153 |
|
| 154 | + /** |
| 155 | + * PluggableCredential (OIDC provider): Uses the service account to generate a Google ID token |
| 156 | + * using the iamcredentials generateIdToken API. This will use the service account client ID as |
| 157 | + * the sub field of the token. This OIDC token will be used as the external subject token to be |
| 158 | + * exchanged for a GCP access token via GCP STS endpoint and then to impersonate the original |
| 159 | + * service account key. Runs an executable to get the OIDC token. |
| 160 | + */ |
| 161 | + @Test |
| 162 | + void pluggableAuthCredentials() throws IOException { |
| 163 | + PluggableAuthCredentials pluggableAuthCredentials = |
| 164 | + (PluggableAuthCredentials) |
| 165 | + ExternalAccountCredentials.fromJson( |
| 166 | + buildPluggableCredentialConfig(), OAuth2Utils.HTTP_TRANSPORT_FACTORY); |
| 167 | + |
| 168 | + callGcs(pluggableAuthCredentials); |
| 169 | + } |
| 170 | + |
153 | 171 | private GenericJson buildIdentityPoolCredentialConfig() throws IOException {
|
154 | 172 | String idToken = generateGoogleIdToken(OIDC_AUDIENCE);
|
155 | 173 |
|
@@ -178,6 +196,57 @@ private GenericJson buildIdentityPoolCredentialConfig() throws IOException {
|
178 | 196 | return config;
|
179 | 197 | }
|
180 | 198 |
|
| 199 | + private GenericJson buildPluggableCredentialConfig() throws IOException { |
| 200 | + String idToken = generateGoogleIdToken(OIDC_AUDIENCE); |
| 201 | + |
| 202 | + Instant expiration_time = Instant.now().plusSeconds(60 * 60); |
| 203 | + |
| 204 | + GenericJson executableJson = new GenericJson(); |
| 205 | + executableJson.setFactory(OAuth2Utils.JSON_FACTORY); |
| 206 | + executableJson.put("success", true); |
| 207 | + executableJson.put("version", 1); |
| 208 | + executableJson.put("expiration_time", expiration_time.toEpochMilli()); |
| 209 | + executableJson.put("token_type", "urn:ietf:params:oauth:token-type:jwt"); |
| 210 | + executableJson.put("id_token", idToken); |
| 211 | + |
| 212 | + String fileContents = |
| 213 | + "#!/bin/bash\n" |
| 214 | + + "echo \"" |
| 215 | + + executableJson.toPrettyString().replace("\"", "\\\"") |
| 216 | + + "\"\n"; |
| 217 | + |
| 218 | + File file = |
| 219 | + File.createTempFile( |
| 220 | + "ITWorkloadIdentityFederation", /* suffix= */ null, /* directory= */ null); |
| 221 | + file.deleteOnExit(); |
| 222 | + if (!file.setExecutable(true, true)) { |
| 223 | + throw new IOException("Unable to make script executable"); |
| 224 | + } |
| 225 | + OAuth2Utils.writeInputStreamToFile( |
| 226 | + new ByteArrayInputStream(fileContents.getBytes(StandardCharsets.UTF_8)), |
| 227 | + file.getAbsolutePath()); |
| 228 | + |
| 229 | + GenericJson config = new GenericJson(); |
| 230 | + config.put("type", "external_account"); |
| 231 | + config.put("audience", OIDC_AUDIENCE); |
| 232 | + config.put("subject_token_type", "urn:ietf:params:oauth:token-type:jwt"); |
| 233 | + config.put("token_url", "https://sts.googleapis.com/v1/token"); |
| 234 | + config.put( |
| 235 | + "service_account_impersonation_url", |
| 236 | + String.format( |
| 237 | + "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/%s:generateAccessToken", |
| 238 | + clientEmail)); |
| 239 | + |
| 240 | + GenericJson credentialSource = new GenericJson(); |
| 241 | + config.put("credential_source", credentialSource); |
| 242 | + |
| 243 | + GenericJson executableConfig = new GenericJson(); |
| 244 | + credentialSource.put("executable", executableConfig); |
| 245 | + executableConfig.put("command", file.getAbsolutePath()); |
| 246 | + |
| 247 | + return config; |
| 248 | + } |
| 249 | + |
181 | 250 | private GenericJson buildAwsCredentialConfig() {
|
182 | 251 | GenericJson config = new GenericJson();
|
183 | 252 | config.put("type", "external_account");
|
|
0 commit comments