1- package com .google .cloud .auth .samples ;
2-
31/*
42 * Copyright 2025 Google LLC
53 *
1614 * limitations under the License.
1715 */
1816
17+ package com .google .cloud .auth .samples ;
18+
1919// [START auth_custom_credential_supplier_aws]
2020import com .google .auth .oauth2 .AwsCredentials ;
2121import com .google .auth .oauth2 .AwsSecurityCredentials ;
3131import software .amazon .awssdk .auth .credentials .DefaultCredentialsProvider ;
3232import software .amazon .awssdk .regions .Region ;
3333import software .amazon .awssdk .regions .providers .DefaultAwsRegionProviderChain ;
34+
3435// [END auth_custom_credential_supplier_aws]
3536
3637/**
3940 */
4041public class CustomCredentialSupplierAwsWorkload {
4142
42- public static void main (String [] args ) throws IOException {
43- // The audience for the workload identity federation.
44- // Format:
45- // //iam.googleapis.com/projects/<project-number>/locations/global/workloadIdentityPools/<pool-id>/providers/<provider-id>
46- String gcpWorkloadAudience = System .getenv ("GCP_WORKLOAD_AUDIENCE" );
47-
48- // The bucket to fetch data from.
49- String gcsBucketName = System .getenv ("GCS_BUCKET_NAME" );
43+ public static void main (String [] args ) throws IOException {
44+ // The audience for the workload identity federation.
45+ // Format: //iam.googleapis.com/projects/<project-number>/locations/global/
46+ // workloadIdentityPools/<pool-id>/providers/<provider-id>
47+ String gcpWorkloadAudience = System .getenv ("GCP_WORKLOAD_AUDIENCE" );
5048
51- // (Optional) The service account impersonation URL .
52- String saImpersonationUrl = System .getenv ("GCP_SERVICE_ACCOUNT_IMPERSONATION_URL " );
49+ // The bucket to fetch data from .
50+ String gcsBucketName = System .getenv ("GCS_BUCKET_NAME " );
5351
54- if (gcpWorkloadAudience == null || gcsBucketName == null ) {
55- System .err .println (
56- "Error: GCP_WORKLOAD_AUDIENCE and GCS_BUCKET_NAME environment variables are required." );
57- return ;
58- }
52+ // (Optional) The service account impersonation URL.
53+ String saImpersonationUrl = System .getenv ("GCP_SERVICE_ACCOUNT_IMPERSONATION_URL" );
5954
60- System .out .println ("Getting metadata for bucket: " + gcsBucketName + "..." );
61- Bucket bucket =
62- authenticateWithAwsCredentials (gcpWorkloadAudience , saImpersonationUrl , gcsBucketName );
55+ if (gcpWorkloadAudience == null || gcsBucketName == null ) {
56+ System .err .println (
57+ "Error: GCP_WORKLOAD_AUDIENCE and GCS_BUCKET_NAME environment variables are required." );
58+ return ;
59+ }
6360
64- System .out .println (" --- SUCCESS! ---" );
65- System .out .printf ("Bucket Name: %s%n" , bucket .getName ());
66- System .out .printf ("Bucket Location: %s%n" , bucket .getLocation ());
61+ System .out .println ("Getting metadata for bucket: " + gcsBucketName + "..." );
62+ Bucket bucket =
63+ authenticateWithAwsCredentials (gcpWorkloadAudience , saImpersonationUrl , gcsBucketName );
64+
65+ System .out .println (" --- SUCCESS! ---" );
66+ System .out .printf ("Bucket Name: %s%n" , bucket .getName ());
67+ System .out .printf ("Bucket Location: %s%n" , bucket .getLocation ());
68+ }
69+
70+ /**
71+ * Authenticates using a custom AWS credential supplier and retrieves bucket metadata.
72+ *
73+ * @param gcpWorkloadAudience The WIF provider audience.
74+ * @param saImpersonationUrl Optional service account impersonation URL.
75+ * @param gcsBucketName The GCS bucket name.
76+ * @return The Bucket object containing metadata.
77+ * @throws IOException If authentication fails.
78+ */
79+ // [START auth_custom_credential_supplier_aws]
80+ public static Bucket authenticateWithAwsCredentials (
81+ String gcpWorkloadAudience , String saImpersonationUrl , String gcsBucketName )
82+ throws IOException {
83+
84+ // 1. Instantiate the custom supplier.
85+ CustomAwsSupplier customSupplier = new CustomAwsSupplier ();
86+
87+ // 2. Configure the AwsCredentials options.
88+ AwsCredentials .Builder credentialsBuilder =
89+ AwsCredentials .newBuilder ()
90+ .setAudience (gcpWorkloadAudience )
91+ // This token type indicates that the subject token is an AWS Signature Version 4 signed
92+ // request. This is required for AWS Workload Identity Federation.
93+ .setSubjectTokenType ("urn:ietf:params:aws:token-type:aws4_request" )
94+ .setAwsSecurityCredentialsSupplier (customSupplier );
95+
96+ if (saImpersonationUrl != null ) {
97+ credentialsBuilder .setServiceAccountImpersonationUrl (saImpersonationUrl );
6798 }
6899
69- /**
70- * Authenticates using a custom AWS credential supplier and retrieves bucket metadata.
71- *
72- * @param gcpWorkloadAudience The WIF provider audience.
73- * @param saImpersonationUrl Optional service account impersonation URL.
74- * @param gcsBucketName The GCS bucket name.
75- * @return The Bucket object containing metadata.
76- * @throws IOException If authentication fails.
77- */
78- // [START auth_custom_credential_supplier_aws]
79- public static Bucket authenticateWithAwsCredentials (
80- String gcpWorkloadAudience , String saImpersonationUrl , String gcsBucketName )
81- throws IOException {
82-
83- // 1. Instantiate the custom supplier.
84- CustomAwsSupplier customSupplier = new CustomAwsSupplier ();
85-
86- // 2. Configure the AwsCredentials options.
87- AwsCredentials .Builder credentialsBuilder =
88- AwsCredentials .newBuilder ()
89- .setAudience (gcpWorkloadAudience )
90- // This token type indicates that the subject token is an AWS Signature Version 4 signed
91- // request. This is required for AWS Workload Identity Federation.
92- .setSubjectTokenType ("urn:ietf:params:aws:token-type:aws4_request" )
93- .setAwsSecurityCredentialsSupplier (customSupplier );
94-
95- if (saImpersonationUrl != null ) {
96- credentialsBuilder .setServiceAccountImpersonationUrl (saImpersonationUrl );
97- }
100+ GoogleCredentials credentials = credentialsBuilder .build ();
98101
99- GoogleCredentials credentials = credentialsBuilder .build ();
102+ // 3. Use the credentials to make an authenticated request.
103+ Storage storage = StorageOptions .newBuilder ().setCredentials (credentials ).build ().getService ();
100104
101- // 3. Use the credentials to make an authenticated request.
102- Storage storage = StorageOptions . newBuilder (). setCredentials ( credentials ). build (). getService ();
105+ return storage . get ( gcsBucketName );
106+ }
103107
104- return storage .get (gcsBucketName );
105- }
108+ /**
109+ * Custom AWS Security Credentials Supplier.
110+ *
111+ * <p>This implementation resolves AWS credentials and regions using the default provider chains
112+ * from the AWS SDK (v2). This supports environment variables, ~/.aws/credentials, and EC2/EKS
113+ * metadata.
114+ */
115+ private static class CustomAwsSupplier implements AwsSecurityCredentialsSupplier {
116+ private final AwsCredentialsProvider awsCredentialsProvider ;
117+ private String region ;
106118
107- /**
108- * Custom AWS Security Credentials Supplier.
109- *
110- * <p>This implementation resolves AWS credentials and regions using the default provider chains
111- * from the AWS SDK (v2). This supports environment variables, ~/.aws/credentials, and EC2/EKS
112- * metadata.
113- */
114- private static class CustomAwsSupplier implements AwsSecurityCredentialsSupplier {
115- private final AwsCredentialsProvider awsCredentialsProvider ;
116- private String region ;
117-
118- public CustomAwsSupplier () {
119- // The AWS SDK handles memoization and refreshing internally.
120- this .awsCredentialsProvider = DefaultCredentialsProvider .create ();
121- }
119+ public CustomAwsSupplier () {
120+ // The AWS SDK handles memoization and refreshing internally.
121+ this .awsCredentialsProvider = DefaultCredentialsProvider .create ();
122+ }
122123
123- @ Override
124- public String getRegion (ExternalAccountSupplierContext context ) {
125- if (this .region == null ) {
126- Region awsRegion = new DefaultAwsRegionProviderChain ().getRegion ();
127- if (awsRegion == null ) {
128- throw new IllegalStateException (
129- "Unable to resolve AWS region. Ensure AWS_REGION is set or configured." );
130- }
131- this .region = awsRegion .id ();
132- }
133- return this .region ;
124+ @ Override
125+ public String getRegion (ExternalAccountSupplierContext context ) {
126+ if (this .region == null ) {
127+ Region awsRegion = new DefaultAwsRegionProviderChain ().getRegion ();
128+ if (awsRegion == null ) {
129+ throw new IllegalStateException (
130+ "Unable to resolve AWS region. Ensure AWS_REGION is set or configured." );
134131 }
132+ this .region = awsRegion .id ();
133+ }
134+ return this .region ;
135+ }
135136
136- @ Override
137- public AwsSecurityCredentials getCredentials (ExternalAccountSupplierContext context ) {
138- software .amazon .awssdk .auth .credentials .AwsCredentials credentials =
139- this .awsCredentialsProvider .resolveCredentials ();
137+ @ Override
138+ public AwsSecurityCredentials getCredentials (ExternalAccountSupplierContext context ) {
139+ software .amazon .awssdk .auth .credentials .AwsCredentials credentials =
140+ this .awsCredentialsProvider .resolveCredentials ();
140141
141- if (credentials == null ) {
142- throw new IllegalStateException ("Unable to resolve AWS credentials." );
143- }
142+ if (credentials == null ) {
143+ throw new IllegalStateException ("Unable to resolve AWS credentials." );
144+ }
144145
145- String sessionToken = null ;
146- if (credentials instanceof AwsSessionCredentials ) {
147- sessionToken = ((AwsSessionCredentials ) credentials ).sessionToken ();
148- }
146+ String sessionToken = null ;
147+ if (credentials instanceof AwsSessionCredentials ) {
148+ sessionToken = ((AwsSessionCredentials ) credentials ).sessionToken ();
149+ }
149150
150- return new AwsSecurityCredentials (
151- credentials .accessKeyId (), credentials .secretAccessKey (), sessionToken );
152- }
151+ return new AwsSecurityCredentials (
152+ credentials .accessKeyId (), credentials .secretAccessKey (), sessionToken );
153153 }
154- // [END auth_custom_credential_supplier_aws]
155- }
154+ }
155+ // [END auth_custom_credential_supplier_aws]
156+ }
0 commit comments