4343import com .google .auth .ServiceAccountSigner ;
4444import com .google .auth .http .HttpTransportFactory ;
4545import com .google .common .annotations .Beta ;
46+ import com .google .common .base .Joiner ;
4647import com .google .common .base .MoreObjects ;
48+ import com .google .common .collect .ImmutableSet ;
4749import java .io .IOException ;
4850import java .io .InputStream ;
4951import java .io .ObjectInputStream ;
5052import java .net .SocketTimeoutException ;
5153import java .net .UnknownHostException ;
54+ import java .util .ArrayList ;
55+ import java .util .Arrays ;
56+ import java .util .Collection ;
5257import java .util .Collections ;
5358import java .util .Date ;
5459import java .util .List ;
@@ -94,6 +99,8 @@ public class ComputeEngineCredentials extends GoogleCredentials
9499
95100 private final String transportFactoryClassName ;
96101
102+ private final Collection <String > scopes ;
103+
97104 private transient HttpTransportFactory transportFactory ;
98105 private transient String serviceAccountEmail ;
99106
@@ -102,13 +109,28 @@ public class ComputeEngineCredentials extends GoogleCredentials
102109 *
103110 * @param transportFactory HTTP transport factory, creates the transport used to get access
104111 * tokens.
112+ * @param scopes scope strings for the APIs to be called. May be null or an empty collection.
105113 */
106- private ComputeEngineCredentials (HttpTransportFactory transportFactory ) {
114+ private ComputeEngineCredentials (
115+ HttpTransportFactory transportFactory , Collection <String > scopes ) {
107116 this .transportFactory =
108117 firstNonNull (
109118 transportFactory ,
110119 getFromServiceLoader (HttpTransportFactory .class , OAuth2Utils .HTTP_TRANSPORT_FACTORY ));
111120 this .transportFactoryClassName = this .transportFactory .getClass ().getName ();
121+ if (scopes == null ) {
122+ this .scopes = ImmutableSet .<String >of ();
123+ } else {
124+ List <String > scopeList = new ArrayList <String >(scopes );
125+ scopeList .removeAll (Arrays .asList ("" , null ));
126+ this .scopes = ImmutableSet .<String >copyOf (scopeList );
127+ }
128+ }
129+
130+ /** Clones the compute engine account with the specified scopes. */
131+ @ Override
132+ public GoogleCredentials createScoped (Collection <String > newScopes ) {
133+ return new ComputeEngineCredentials (this .transportFactory , newScopes );
112134 }
113135
114136 /**
@@ -117,13 +139,30 @@ private ComputeEngineCredentials(HttpTransportFactory transportFactory) {
117139 * @return new ComputeEngineCredentials
118140 */
119141 public static ComputeEngineCredentials create () {
120- return new ComputeEngineCredentials (null );
142+ return new ComputeEngineCredentials (null , null );
143+ }
144+
145+ public final Collection <String > getScopes () {
146+ return scopes ;
147+ }
148+
149+ /**
150+ * If scopes is specified, add "?scopes=comma-separated-list-of-scopes" to the token url.
151+ *
152+ * @return token url with the given scopes
153+ */
154+ String createTokenUrlWithScopes () {
155+ GenericUrl tokenUrl = new GenericUrl (getTokenServerEncodedUrl ());
156+ if (!scopes .isEmpty ()) {
157+ tokenUrl .set ("scopes" , Joiner .on (',' ).join (scopes ));
158+ }
159+ return tokenUrl .toString ();
121160 }
122161
123162 /** Refresh the access token by getting it from the GCE metadata server */
124163 @ Override
125164 public AccessToken refreshAccessToken () throws IOException {
126- HttpResponse response = getMetadataResponse (getTokenServerEncodedUrl ());
165+ HttpResponse response = getMetadataResponse (createTokenUrlWithScopes ());
127166 int statusCode = response .getStatusCode ();
128167 if (statusCode == HttpStatusCodes .STATUS_CODE_NOT_FOUND ) {
129168 throw new IOException (
@@ -307,7 +346,8 @@ public boolean equals(Object obj) {
307346 return false ;
308347 }
309348 ComputeEngineCredentials other = (ComputeEngineCredentials ) obj ;
310- return Objects .equals (this .transportFactoryClassName , other .transportFactoryClassName );
349+ return Objects .equals (this .transportFactoryClassName , other .transportFactoryClassName )
350+ && Objects .equals (this .scopes , other .scopes );
311351 }
312352
313353 private void readObject (ObjectInputStream input ) throws IOException , ClassNotFoundException {
@@ -399,24 +439,35 @@ private String getDefaultServiceAccount() throws IOException {
399439
400440 public static class Builder extends GoogleCredentials .Builder {
401441 private HttpTransportFactory transportFactory ;
442+ private Collection <String > scopes ;
402443
403444 protected Builder () {}
404445
405446 protected Builder (ComputeEngineCredentials credentials ) {
406447 this .transportFactory = credentials .transportFactory ;
448+ this .scopes = credentials .scopes ;
407449 }
408450
409451 public Builder setHttpTransportFactory (HttpTransportFactory transportFactory ) {
410452 this .transportFactory = transportFactory ;
411453 return this ;
412454 }
413455
456+ public Builder setScopes (Collection <String > scopes ) {
457+ this .scopes = scopes ;
458+ return this ;
459+ }
460+
414461 public HttpTransportFactory getHttpTransportFactory () {
415462 return transportFactory ;
416463 }
417464
465+ public Collection <String > getScopes () {
466+ return scopes ;
467+ }
468+
418469 public ComputeEngineCredentials build () {
419- return new ComputeEngineCredentials (transportFactory );
470+ return new ComputeEngineCredentials (transportFactory , scopes );
420471 }
421472 }
422473}
0 commit comments