5959import com .google .common .collect .ImmutableMap ;
6060
6161/**
62- * ImpersonatedCredentials allowing credentials issued to a user or
63- * service account to impersonate another.
64- * <br/>
65- * The source project using ImpersonatedCredentials must enable the
66- * "IAMCredentials" API.<br/>
67- * Also, the target service account must grant the orginating principal the
68- * "Service Account Token Creator" IAM role.
69- * <br/>
70- * Usage:<br/>
62+ * ImpersonatedCredentials allowing credentials issued to a user or service account to impersonate
63+ * another. <br> The source project using ImpersonatedCredentials must enable the "IAMCredentials"
64+ * API.<br> Also, the target service account must grant the orginating principal the "Service
65+ * Account Token Creator" IAM role. <br> Usage:<br>
7166 * <pre>
7267 * String credPath = "/path/to/svc_account.json";
7368 * ServiceAccountCredentials sourceCredentials = ServiceAccountCredentials
@@ -92,7 +87,6 @@ public class ImpersonatedCredentials extends GoogleCredentials {
9287 private static final String RFC3339 = "yyyy-MM-dd'T'HH:mm:ss'Z'" ;
9388 private static final int ONE_HOUR_IN_SECONDS = 3600 ;
9489 private static final String CLOUD_PLATFORM_SCOPE = "https://www.googleapis.com/auth/cloud-platform" ;
95- private static final String ERROR_PREFIX = "Error processng IamCredentials generateAccessToken: " ;
9690 private static final String IAM_ENDPOINT = "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/%s:generateAccessToken" ;
9791
9892 private static final String SCOPE_EMPTY_ERROR = "Scopes cannot be null" ;
@@ -108,74 +102,64 @@ public class ImpersonatedCredentials extends GoogleCredentials {
108102 private transient HttpTransportFactory transportFactory ;
109103
110104 /**
111- * @param sourceCredentials The source credential used as to acquire the
112- * impersonated credentials
113- * @param targetPrincipal The service account to impersonate.
114- * @param delegates The chained list of delegates required to grant
115- * the final access_token. <br/>If set, the sequence of identities must
116- * have "Service Account Token Creator" capability granted to the
117- * prceeding identity. <br/>For example, if set to
118- * [serviceAccountB, serviceAccountC], the sourceCredential
119- * must have the Token Creator role on serviceAccountB. serviceAccountB must
120- * have the Token Creator on serviceAccountC. <br/>Finally, C must have
121- * Token Creator on target_principal. If left unset, sourceCredential
122- * must have that role on targetPrincipal.
123- * @param scopes Scopes to request during the authorization grant.
124- * @param lifetime Number of seconds the delegated credential should
125- * be valid for (upto 3600).
126- * @param transportFactory HTTP transport factory, creates the transport used
127- * to get access tokens.
105+ * @param sourceCredentials The source credential used as to acquire the impersonated credentials
106+ * @param targetPrincipal The service account to impersonate.
107+ * @param delegates The chained list of delegates required to grant the final access_token. If
108+ * set, the sequence of identities must have "Service Account Token Creator" capability granted to
109+ * the preceding identity. For example, if set to [serviceAccountB, serviceAccountC], the
110+ * sourceCredential must have the Token Creator role on serviceAccountB. serviceAccountB must have
111+ * the Token Creator on serviceAccountC. Finally, C must have Token Creator on target_principal.
112+ * If left unset, sourceCredential must have that role on targetPrincipal.
113+ * @param scopes Scopes to request during the authorization grant.
114+ * @param lifetime Number of seconds the delegated credential should be valid for (up to 3600).
115+ * @param transportFactory HTTP transport factory, creates the transport used to get access
116+ * tokens.
128117 */
129- public static ImpersonatedCredentials create (GoogleCredentials sourceCredentials , String targetPrincipal ,
130- List <String > delegates , List <String > scopes , int lifetime , HttpTransportFactory transportFactory ) {
131- return ImpersonatedCredentials .newBuilder ().setSourceCredentials (sourceCredentials )
132- .setTargetPrincipal (targetPrincipal ).setDelegates (delegates ).setScopes (scopes ).setLifetime (lifetime )
133- .setHttpTransportFactory (transportFactory ).build ();
118+ public static ImpersonatedCredentials create (GoogleCredentials sourceCredentials ,
119+ String targetPrincipal ,
120+ List <String > delegates , List <String > scopes , int lifetime ,
121+ HttpTransportFactory transportFactory ) {
122+ return ImpersonatedCredentials .newBuilder ()
123+ .setSourceCredentials (sourceCredentials )
124+ .setTargetPrincipal (targetPrincipal )
125+ .setDelegates (delegates )
126+ .setScopes (scopes )
127+ .setLifetime (lifetime )
128+ .setHttpTransportFactory (transportFactory )
129+ .build ();
134130 }
135131
136132 /**
137- * @param sourceCredentials The source credential used as to acquire the
138- * impersonated credentials
139- * @param targetPrincipal The service account to impersonate.
140- * @param delegates The chained list of delegates required to grant
141- * the final access_token. <br/>If set, the sequence of identities must
142- * have "Service Account Token Creator" capability granted to the
143- * prceeding identity. <br/>For example, if set to
144- * [serviceAccountB, serviceAccountC], the sourceCredential
145- * must have the Token Creator role on serviceAccountB. serviceAccountB must
146- * have the Token Creator on serviceAccountC. <br/>Finally, C must have
147- * Token Creator on target_principal. If left unset, sourceCredential
148- * must have that role on targetPrincipal.
149- * @param scopes Scopes to request during the authorization grant.
150- * @param lifetime Number of seconds the delegated credential should
151- * be valid for (upto 3600).
152- */
153- public static ImpersonatedCredentials create (GoogleCredentials sourceCredentials , String targetPrincipal ,
133+ * @param sourceCredentials The source credential used as to acquire the impersonated credentials
134+ * @param targetPrincipal The service account to impersonate.
135+ * @param delegates The chained list of delegates required to grant the final access_token. If
136+ * set, the sequence of identities must have "Service Account Token Creator" capability granted to
137+ * the preceding identity. For example, if set to [serviceAccountB, serviceAccountC], the
138+ * sourceCredential must have the Token Creator role on serviceAccountB. serviceAccountB must have
139+ * the Token Creator on serviceAccountC. Finally, C must have Token Creator on target_principal.
140+ * If left unset, sourceCredential must have that role on targetPrincipal.
141+ * @param scopes Scopes to request during the authorization grant.
142+ * @param lifetime Number of seconds the delegated credential should be valid for (up to 3600).
143+ */
144+ public static ImpersonatedCredentials create (GoogleCredentials sourceCredentials ,
145+ String targetPrincipal ,
154146 List <String > delegates , List <String > scopes , int lifetime ) {
155- return ImpersonatedCredentials .newBuilder ().setSourceCredentials (sourceCredentials )
156- .setTargetPrincipal (targetPrincipal ).setDelegates (delegates ).setScopes (scopes ).setLifetime (lifetime ).build ();
147+ return ImpersonatedCredentials .newBuilder ()
148+ .setSourceCredentials (sourceCredentials )
149+ .setTargetPrincipal (targetPrincipal )
150+ .setDelegates (delegates )
151+ .setScopes (scopes )
152+ .setLifetime (lifetime )
153+ .build ();
157154 }
158155
159- /**
160- * @param sourceCredentials = Source Credentials.
161- * @param targetPrincipal = targetPrincipal;
162- * @param delegates = delegates;
163- * @param scopes = scopes;
164- * @param lifetime = lifetime;
165- * @param transportFactory = HTTP transport factory, creates the transport used
166- * to get access tokens.
167- * @deprecated Use {@link #create(ImpersonatedCredentials)} instead. This constructor
168- * will either be deleted or made private in a later version.
169- */
170- @ Deprecated
171- private ImpersonatedCredentials (GoogleCredentials sourceCredentials , String targetPrincipal , List <String > delegates ,
172- List <String > scopes , int lifetime , HttpTransportFactory transportFactory ) {
173- this .sourceCredentials = sourceCredentials ;
174- this .targetPrincipal = targetPrincipal ;
175- this .delegates = delegates ;
176- this .scopes = scopes ;
177- this .lifetime = lifetime ;
178- this .transportFactory = firstNonNull (transportFactory ,
156+ private ImpersonatedCredentials (Builder builder ) {
157+ this .sourceCredentials = builder .getSourceCredentials ();
158+ this .targetPrincipal = builder .getTargetPrincipal ();
159+ this .delegates = builder .getDelegates ();
160+ this .scopes = builder .getScopes ();
161+ this .lifetime = builder .getLifetime ();
162+ this .transportFactory = firstNonNull (builder .getHttpTransportFactory (),
179163 getFromServiceLoader (HttpTransportFactory .class , OAuth2Utils .HTTP_TRANSPORT_FACTORY ));
180164 this .transportFactoryClassName = this .transportFactory .getClass ().getName ();
181165 if (this .delegates == null ) {
@@ -189,47 +173,17 @@ private ImpersonatedCredentials(GoogleCredentials sourceCredentials, String targ
189173 }
190174 }
191175
192- /**
193- * @param sourceCredentials = Source Credentials.
194- * @param targetPrincipal = targetPrincipal;
195- * @param scopes = scopes;
196- * @param lifetime = lifetime;
197- * @param transportFactory = HTTP transport factory, creates the transport used
198- * to get access tokens.
199- * @deprecated Use {@link #create(ImpersonatedCredentials)} instead. This constructor
200- * will either be deleted or made private in a later version.
201- */
202- @ Deprecated
203- private ImpersonatedCredentials (GoogleCredentials sourceCredentials , String targetPrincipal , List <String > scopes ,
204- int lifetime , HttpTransportFactory transportFactory ) {
205- this (sourceCredentials , targetPrincipal , new ArrayList <String >(), scopes , lifetime , transportFactory );
206- }
207-
208- /**
209- * @param sourceCredentials = Source Credentials.
210- * @param targetPrincipal = targetPrincipal;
211- * @param delegates = delegates;
212- * @param scopes = scopes;
213- * @param lifetime = lifetime;
214- * @deprecated Use {@link #create(ImpersonatedCredentials)} instead. This constructor
215- * will either be deleted or made private in a later version.
216- */
217- @ Deprecated
218- private ImpersonatedCredentials (GoogleCredentials sourceCredentials , String targetPrincipal , List <String > scopes ,
219- int lifetime ) {
220- this (sourceCredentials , targetPrincipal , new ArrayList <String >(), scopes , lifetime , null );
221- }
222-
223176 @ Override
224177 public AccessToken refreshAccessToken () throws IOException {
225-
178+ if (this .sourceCredentials .getAccessToken () == null ) {
179+ this .sourceCredentials = this .sourceCredentials
180+ .createScoped (Arrays .asList (CLOUD_PLATFORM_SCOPE ));
181+ }
182+
226183 try {
227- if (this .sourceCredentials .getAccessToken () == null ) {
228- this .sourceCredentials = this .sourceCredentials .createScoped (Arrays .asList (CLOUD_PLATFORM_SCOPE ));
229- }
230184 this .sourceCredentials .refreshIfExpired ();
231185 } catch (IOException e ) {
232- throw new IOException (ERROR_PREFIX + "Unable to refresh sourceCredentials " + e . toString () );
186+ throw new IOException ("Unable to refresh sourceCredentials" , e );
233187 }
234188
235189 HttpTransport httpTransport = this .transportFactory .create ();
@@ -241,7 +195,8 @@ public AccessToken refreshAccessToken() throws IOException {
241195 String endpointUrl = String .format (IAM_ENDPOINT , this .targetPrincipal );
242196 GenericUrl url = new GenericUrl (endpointUrl );
243197
244- Map <String , Object > body = ImmutableMap .<String , Object >of ("delegates" , this .delegates , "scope" , this .scopes ,
198+ Map <String , Object > body = ImmutableMap .<String , Object >of ("delegates" , this .delegates , "scope" ,
199+ this .scopes ,
245200 "lifetime" , this .lifetime + "s" );
246201
247202 HttpContent requestContent = new JsonHttpContent (parser .getJsonFactory (), body );
@@ -253,21 +208,23 @@ public AccessToken refreshAccessToken() throws IOException {
253208 try {
254209 response = request .execute ();
255210 } catch (IOException e ) {
256- throw new IOException (ERROR_PREFIX + e . toString () );
211+ throw new IOException ("Error requesting access token" , e );
257212 }
258213
259214 GenericData responseData = response .parseAs (GenericData .class );
260215 response .disconnect ();
261216
262- String accessToken = OAuth2Utils .validateString (responseData , "accessToken" , ERROR_PREFIX );
263- String expireTime = OAuth2Utils .validateString (responseData , "expireTime" , ERROR_PREFIX );
217+ String accessToken = OAuth2Utils
218+ .validateString (responseData , "accessToken" , "Expected to find an accessToken" );
219+ String expireTime = OAuth2Utils
220+ .validateString (responseData , "expireTime" , "Expected to find an expireTime" );
264221
265222 DateFormat format = new SimpleDateFormat (RFC3339 );
266223 Date date ;
267224 try {
268225 date = format .parse (expireTime );
269226 } catch (ParseException pe ) {
270- throw new IOException (ERROR_PREFIX + pe .getMessage ());
227+ throw new IOException ("Error parsing expireTime: " + pe .getMessage ());
271228 }
272229 return new AccessToken (accessToken , date );
273230 }
@@ -383,8 +340,7 @@ public HttpTransportFactory getHttpTransportFactory() {
383340 }
384341
385342 public ImpersonatedCredentials build () {
386- return new ImpersonatedCredentials (this .sourceCredentials , this .targetPrincipal , this .delegates , this .scopes ,
387- this .lifetime , this .transportFactory );
343+ return new ImpersonatedCredentials (this );
388344 }
389345
390346 }
0 commit comments