43
43
import com .google .auth .ServiceAccountSigner ;
44
44
import com .google .auth .http .HttpTransportFactory ;
45
45
import com .google .common .annotations .Beta ;
46
+ import com .google .common .base .Joiner ;
46
47
import com .google .common .base .MoreObjects ;
48
+ import com .google .common .collect .ImmutableSet ;
47
49
import java .io .IOException ;
48
50
import java .io .InputStream ;
49
51
import java .io .ObjectInputStream ;
50
52
import java .net .SocketTimeoutException ;
51
53
import java .net .UnknownHostException ;
54
+ import java .util .ArrayList ;
55
+ import java .util .Arrays ;
56
+ import java .util .Collection ;
52
57
import java .util .Collections ;
53
58
import java .util .Date ;
54
59
import java .util .List ;
@@ -94,6 +99,8 @@ public class ComputeEngineCredentials extends GoogleCredentials
94
99
95
100
private final String transportFactoryClassName ;
96
101
102
+ private final Collection <String > scopes ;
103
+
97
104
private transient HttpTransportFactory transportFactory ;
98
105
private transient String serviceAccountEmail ;
99
106
@@ -102,13 +109,28 @@ public class ComputeEngineCredentials extends GoogleCredentials
102
109
*
103
110
* @param transportFactory HTTP transport factory, creates the transport used to get access
104
111
* tokens.
112
+ * @param scopes scope strings for the APIs to be called. May be null or an empty collection.
105
113
*/
106
- private ComputeEngineCredentials (HttpTransportFactory transportFactory ) {
114
+ private ComputeEngineCredentials (
115
+ HttpTransportFactory transportFactory , Collection <String > scopes ) {
107
116
this .transportFactory =
108
117
firstNonNull (
109
118
transportFactory ,
110
119
getFromServiceLoader (HttpTransportFactory .class , OAuth2Utils .HTTP_TRANSPORT_FACTORY ));
111
120
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 );
112
134
}
113
135
114
136
/**
@@ -117,13 +139,30 @@ private ComputeEngineCredentials(HttpTransportFactory transportFactory) {
117
139
* @return new ComputeEngineCredentials
118
140
*/
119
141
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 ();
121
160
}
122
161
123
162
/** Refresh the access token by getting it from the GCE metadata server */
124
163
@ Override
125
164
public AccessToken refreshAccessToken () throws IOException {
126
- HttpResponse response = getMetadataResponse (getTokenServerEncodedUrl ());
165
+ HttpResponse response = getMetadataResponse (createTokenUrlWithScopes ());
127
166
int statusCode = response .getStatusCode ();
128
167
if (statusCode == HttpStatusCodes .STATUS_CODE_NOT_FOUND ) {
129
168
throw new IOException (
@@ -307,7 +346,8 @@ public boolean equals(Object obj) {
307
346
return false ;
308
347
}
309
348
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 );
311
351
}
312
352
313
353
private void readObject (ObjectInputStream input ) throws IOException , ClassNotFoundException {
@@ -399,24 +439,35 @@ private String getDefaultServiceAccount() throws IOException {
399
439
400
440
public static class Builder extends GoogleCredentials .Builder {
401
441
private HttpTransportFactory transportFactory ;
442
+ private Collection <String > scopes ;
402
443
403
444
protected Builder () {}
404
445
405
446
protected Builder (ComputeEngineCredentials credentials ) {
406
447
this .transportFactory = credentials .transportFactory ;
448
+ this .scopes = credentials .scopes ;
407
449
}
408
450
409
451
public Builder setHttpTransportFactory (HttpTransportFactory transportFactory ) {
410
452
this .transportFactory = transportFactory ;
411
453
return this ;
412
454
}
413
455
456
+ public Builder setScopes (Collection <String > scopes ) {
457
+ this .scopes = scopes ;
458
+ return this ;
459
+ }
460
+
414
461
public HttpTransportFactory getHttpTransportFactory () {
415
462
return transportFactory ;
416
463
}
417
464
465
+ public Collection <String > getScopes () {
466
+ return scopes ;
467
+ }
468
+
418
469
public ComputeEngineCredentials build () {
419
- return new ComputeEngineCredentials (transportFactory );
470
+ return new ComputeEngineCredentials (transportFactory , scopes );
420
471
}
421
472
}
422
473
}
0 commit comments