Skip to content

Commit

Permalink
feat: add code sample and test for getting an access token from an im…
Browse files Browse the repository at this point in the history
…personated SA (#1289)

Co-authored-by: Tianzi Cai <tianzi@google.com>
  • Loading branch information
irataxy and anguillanneuf committed Oct 5, 2023
1 parent 104e2b3 commit 826ee40
Show file tree
Hide file tree
Showing 2 changed files with 108 additions and 13 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/*
* Copyright 2023 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

// [START auth_cloud_accesstoken_impersonated_credentials]

import com.google.auth.oauth2.GoogleCredentials;
import com.google.auth.oauth2.ImpersonatedCredentials;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;

public class AccessTokenFromImpersonatedCredentials {

public static void main(String[] args) throws IOException {
// TODO(Developer): Replace the below variables before running the code.

// Provide the scopes that you might need to request access to Google APIs,
// depending on the level of access you need.
// This example uses the cloud-wide scope and uses IAM to narrow the permissions.
// https://cloud.google.com/docs/authentication/external/authorization-gcp
// For more information, see: https://developers.google.com/identity/protocols/oauth2/scopes
String scope = "https://www.googleapis.com/auth/cloud-platform";

// The name of the privilege-bearing service account for whom the credential is created.
String impersonatedServiceAccount = "name@project.service.gserviceaccount.com";

getAccessToken(impersonatedServiceAccount, scope);
}

// Use a service account (SA1) to impersonate as another service account (SA2) and obtain id token
// for the impersonated account.
// To obtain token for SA2, SA1 should have the "roles/iam.serviceAccountTokenCreator" permission
// on SA2.
public static void getAccessToken(
String impersonatedServiceAccount, String scope) throws IOException {

// Construct the GoogleCredentials object which obtains the default configuration from your
// working environment.
GoogleCredentials googleCredentials = GoogleCredentials.getApplicationDefault();

// delegates: The chained list of delegates required to grant the final accessToken.
// For more information, see:
// https://cloud.google.com/iam/docs/create-short-lived-credentials-direct#sa-credentials-permissions
// Delegate is NOT USED here.
List<String> delegates = null;

// Create the impersonated credential.
ImpersonatedCredentials impersonatedCredentials =
ImpersonatedCredentials.newBuilder()
.setSourceCredentials(googleCredentials)
.setTargetPrincipal(impersonatedServiceAccount)
.setScopes(Arrays.asList(scope))
.setLifetime(300)
.setDelegates(delegates)
.build();

// Get the OAuth2 token.
// Once you've obtained the OAuth2 token, you can use it to make an authenticated call.
impersonatedCredentials.refresh();
String accessToken = impersonatedCredentials.getAccessToken().getTokenValue();
System.out.println("Generated access token.");
}
}
// [END auth_cloud_accesstoken_impersonated_credentials]
44 changes: 31 additions & 13 deletions samples/snippets/src/test/java/SnippetsIT.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ public class SnippetsIT {

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

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

@AfterClass
public static void cleanup() {}

@Before
public void beforeEach() {
stdOut = new ByteArrayOutputStream();
System.setOut(new PrintStream(stdOut));
}

@After
public void afterEach() {
stdOut = null;
System.setOut(null);
public static void cleanup() {
}

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

@Before
public void beforeEach() {
stdOut = new ByteArrayOutputStream();
System.setOut(new PrintStream(stdOut));
}

@After
public void afterEach() {
stdOut = null;
System.setOut(null);
}

@Test
public void testIdTokenFromServiceAccount() throws IOException {
IdTokenFromServiceAccount.getIdTokenFromServiceAccount(CREDENTIALS, "https://example.com");
Expand All @@ -107,6 +110,21 @@ public void testVerifyGoogleIdToken() throws IOException {
idToken, "https://example.com", "https://www.googleapis.com/oauth2/v3/certs");
}

@Test
public void testAccessTokenFromImpersonatedCredentials()
throws GeneralSecurityException, IOException {
AccessTokenFromImpersonatedCredentials.getAccessToken(impersonatedServiceAccount, scope);
assertThat(stdOut.toString()).contains("Generated access token.");
}

@Test
public void testIdTokenFromImpersonatedCredentials()
throws GeneralSecurityException, IOException {
IdTokenFromImpersonatedCredentials.getIdTokenUsingOAuth2(impersonatedServiceAccount, scope,
"https://example.com");
assertThat(stdOut.toString()).contains("Generated ID token.");
}

@Test
public void testIdTokenFromMetadataServer() throws GeneralSecurityException, IOException {
IdTokenFromMetadataServer.getIdTokenFromMetadataServer("https://www.google.com");
Expand All @@ -116,7 +134,7 @@ public void testIdTokenFromMetadataServer() throws GeneralSecurityException, IOE
@Test
public void testAuthenticateImplicitWithAdc() throws IOException {
AuthenticateImplicitWithAdc.authenticateImplicitWithAdc(PROJECT_ID);
assertThat(stdOut.toString()).contains("Listing instances complete");
assertThat(stdOut.toString()).contains("Listed all storage buckets.");
}

@Test
Expand Down

0 comments on commit 826ee40

Please sign in to comment.