Skip to content

Commit 22f37aa

Browse files
feat: integration tests for pluggable auth (#939)
* feat: integration tests for pluggable auth * feat: integration tests for pluggable auth * feat: integration tests for pluggable auth * feat: integration tests for pluggable auth * fix: format Co-authored-by: Leo <[email protected]> Co-authored-by: lsirac <[email protected]>
1 parent ca1f7a6 commit 22f37aa

File tree

3 files changed

+81
-2
lines changed

3 files changed

+81
-2
lines changed

.kokoro/nightly/integration.cfg

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,8 @@ env_vars: {
4040
key: "GCS_BUCKET"
4141
value: "byoid-it-bucket"
4242
}
43+
44+
env_vars: {
45+
key: "GOOGLE_EXTERNAL_ACCOUNT_ALLOW_EXECUTABLES"
46+
value: "1"
47+
}

.kokoro/presubmit/integration.cfg

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,4 +35,9 @@ env_vars: {
3535
env_vars: {
3636
key: "GCS_BUCKET"
3737
value: "byoid-it-bucket"
38-
}
38+
}
39+
40+
env_vars: {
41+
key: "GOOGLE_EXTERNAL_ACCOUNT_ALLOW_EXECUTABLES"
42+
value: "1"
43+
}

oauth2_http/javatests/com/google/auth/oauth2/ITWorkloadIdentityFederationTest.java

Lines changed: 70 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
import java.io.FileInputStream;
5252
import java.io.IOException;
5353
import java.nio.charset.StandardCharsets;
54+
import java.time.Instant;
5455
import org.junit.jupiter.api.BeforeEach;
5556
import org.junit.jupiter.api.Test;
5657

@@ -86,7 +87,7 @@ void setup() throws IOException {
8687
* using the iamcredentials generateIdToken API. This will use the service account client ID as
8788
* the sub field of the token. This OIDC token will be used as the external subject token to be
8889
* 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.
9091
*/
9192
@Test
9293
void identityPoolCredentials() throws IOException {
@@ -150,6 +151,23 @@ void awsCredentials() throws Exception {
150151
callGcs(awsCredential);
151152
}
152153

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+
153171
private GenericJson buildIdentityPoolCredentialConfig() throws IOException {
154172
String idToken = generateGoogleIdToken(OIDC_AUDIENCE);
155173

@@ -178,6 +196,57 @@ private GenericJson buildIdentityPoolCredentialConfig() throws IOException {
178196
return config;
179197
}
180198

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+
181250
private GenericJson buildAwsCredentialConfig() {
182251
GenericJson config = new GenericJson();
183252
config.put("type", "external_account");

0 commit comments

Comments
 (0)