Skip to content

Commit 826ee40

Browse files
feat: add code sample and test for getting an access token from an impersonated SA (#1289)
Co-authored-by: Tianzi Cai <[email protected]>
1 parent 104e2b3 commit 826ee40

File tree

2 files changed

+108
-13
lines changed

2 files changed

+108
-13
lines changed
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
/*
2+
* Copyright 2023 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
// [START auth_cloud_accesstoken_impersonated_credentials]
18+
19+
import com.google.auth.oauth2.GoogleCredentials;
20+
import com.google.auth.oauth2.ImpersonatedCredentials;
21+
import java.io.IOException;
22+
import java.util.Arrays;
23+
import java.util.List;
24+
25+
public class AccessTokenFromImpersonatedCredentials {
26+
27+
public static void main(String[] args) throws IOException {
28+
// TODO(Developer): Replace the below variables before running the code.
29+
30+
// Provide the scopes that you might need to request access to Google APIs,
31+
// depending on the level of access you need.
32+
// This example uses the cloud-wide scope and uses IAM to narrow the permissions.
33+
// https://cloud.google.com/docs/authentication/external/authorization-gcp
34+
// For more information, see: https://developers.google.com/identity/protocols/oauth2/scopes
35+
String scope = "https://www.googleapis.com/auth/cloud-platform";
36+
37+
// The name of the privilege-bearing service account for whom the credential is created.
38+
String impersonatedServiceAccount = "[email protected]";
39+
40+
getAccessToken(impersonatedServiceAccount, scope);
41+
}
42+
43+
// Use a service account (SA1) to impersonate as another service account (SA2) and obtain id token
44+
// for the impersonated account.
45+
// To obtain token for SA2, SA1 should have the "roles/iam.serviceAccountTokenCreator" permission
46+
// on SA2.
47+
public static void getAccessToken(
48+
String impersonatedServiceAccount, String scope) throws IOException {
49+
50+
// Construct the GoogleCredentials object which obtains the default configuration from your
51+
// working environment.
52+
GoogleCredentials googleCredentials = GoogleCredentials.getApplicationDefault();
53+
54+
// delegates: The chained list of delegates required to grant the final accessToken.
55+
// For more information, see:
56+
// https://cloud.google.com/iam/docs/create-short-lived-credentials-direct#sa-credentials-permissions
57+
// Delegate is NOT USED here.
58+
List<String> delegates = null;
59+
60+
// Create the impersonated credential.
61+
ImpersonatedCredentials impersonatedCredentials =
62+
ImpersonatedCredentials.newBuilder()
63+
.setSourceCredentials(googleCredentials)
64+
.setTargetPrincipal(impersonatedServiceAccount)
65+
.setScopes(Arrays.asList(scope))
66+
.setLifetime(300)
67+
.setDelegates(delegates)
68+
.build();
69+
70+
// Get the OAuth2 token.
71+
// Once you've obtained the OAuth2 token, you can use it to make an authenticated call.
72+
impersonatedCredentials.refresh();
73+
String accessToken = impersonatedCredentials.getAccessToken().getTokenValue();
74+
System.out.println("Generated access token.");
75+
}
76+
}
77+
// [END auth_cloud_accesstoken_impersonated_credentials]

samples/snippets/src/test/java/SnippetsIT.java

Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ public class SnippetsIT {
4040

4141
private static final String PROJECT_ID = System.getenv("GOOGLE_CLOUD_PROJECT");
4242
private static final String CREDENTIALS = System.getenv("GOOGLE_APPLICATION_CREDENTIALS");
43+
private static final String impersonatedServiceAccount = "TODO";
44+
private static final String scope = "https://www.googleapis.com/auth/cloud-platform";
4345
private ByteArrayOutputStream stdOut;
4446

4547
// Check if the required environment variables are set.
@@ -62,18 +64,7 @@ public static void setup() throws IOException {
6264
}
6365

6466
@AfterClass
65-
public static void cleanup() {}
66-
67-
@Before
68-
public void beforeEach() {
69-
stdOut = new ByteArrayOutputStream();
70-
System.setOut(new PrintStream(stdOut));
71-
}
72-
73-
@After
74-
public void afterEach() {
75-
stdOut = null;
76-
System.setOut(null);
67+
public static void cleanup() {
7768
}
7869

7970
// Get an id token from a Google service account.
@@ -93,6 +84,18 @@ private static String getIdTokenFromServiceAccount(
9384
return idToken.getTokenValue();
9485
}
9586

87+
@Before
88+
public void beforeEach() {
89+
stdOut = new ByteArrayOutputStream();
90+
System.setOut(new PrintStream(stdOut));
91+
}
92+
93+
@After
94+
public void afterEach() {
95+
stdOut = null;
96+
System.setOut(null);
97+
}
98+
9699
@Test
97100
public void testIdTokenFromServiceAccount() throws IOException {
98101
IdTokenFromServiceAccount.getIdTokenFromServiceAccount(CREDENTIALS, "https://example.com");
@@ -107,6 +110,21 @@ public void testVerifyGoogleIdToken() throws IOException {
107110
idToken, "https://example.com", "https://www.googleapis.com/oauth2/v3/certs");
108111
}
109112

113+
@Test
114+
public void testAccessTokenFromImpersonatedCredentials()
115+
throws GeneralSecurityException, IOException {
116+
AccessTokenFromImpersonatedCredentials.getAccessToken(impersonatedServiceAccount, scope);
117+
assertThat(stdOut.toString()).contains("Generated access token.");
118+
}
119+
120+
@Test
121+
public void testIdTokenFromImpersonatedCredentials()
122+
throws GeneralSecurityException, IOException {
123+
IdTokenFromImpersonatedCredentials.getIdTokenUsingOAuth2(impersonatedServiceAccount, scope,
124+
"https://example.com");
125+
assertThat(stdOut.toString()).contains("Generated ID token.");
126+
}
127+
110128
@Test
111129
public void testIdTokenFromMetadataServer() throws GeneralSecurityException, IOException {
112130
IdTokenFromMetadataServer.getIdTokenFromMetadataServer("https://www.google.com");
@@ -116,7 +134,7 @@ public void testIdTokenFromMetadataServer() throws GeneralSecurityException, IOE
116134
@Test
117135
public void testAuthenticateImplicitWithAdc() throws IOException {
118136
AuthenticateImplicitWithAdc.authenticateImplicitWithAdc(PROJECT_ID);
119-
assertThat(stdOut.toString()).contains("Listing instances complete");
137+
assertThat(stdOut.toString()).contains("Listed all storage buckets.");
120138
}
121139

122140
@Test

0 commit comments

Comments
 (0)