Skip to content

Commit a6bfd48

Browse files
author
Ajay Kannan
committed
Make AppEngineAuthCredentials Restorable
1 parent b5c1cae commit a6bfd48

File tree

2 files changed

+57
-39
lines changed

2 files changed

+57
-39
lines changed

gcloud-java-core/src/main/java/com/google/gcloud/AuthCredentials.java

Lines changed: 46 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import com.google.auth.oauth2.AccessToken;
2222
import com.google.auth.oauth2.GoogleCredentials;
2323
import com.google.auth.oauth2.ServiceAccountCredentials;
24+
import com.google.common.collect.ImmutableSet;
2425

2526
import java.io.IOException;
2627
import java.io.InputStream;
@@ -37,12 +38,14 @@ public abstract class AuthCredentials implements Restorable<AuthCredentials> {
3738

3839
private static class AppEngineAuthCredentials extends AuthCredentials {
3940

40-
private static final AuthCredentials INSTANCE = new AppEngineAuthCredentials();
41-
private static final AppEngineAuthCredentialsState STATE = new AppEngineAuthCredentialsState();
41+
private final Collection<String> scopes;
42+
private final boolean scopesRequired;
4243

4344
private static class AppEngineCredentials extends GoogleCredentials {
4445

4546
private final Object appIdentityService;
47+
private final Method getAccessToken;
48+
private final Method getAccessTokenResult;
4649
private final Collection<String> scopes;
4750
private final boolean scopesRequired;
4851

@@ -52,17 +55,26 @@ private static class AppEngineCredentials extends GoogleCredentials {
5255
Class.forName("com.google.appengine.api.appidentity.AppIdentityServiceFactory");
5356
Method method = factoryClass.getMethod("getAppIdentityService");
5457
this.appIdentityService = method.invoke(null);
58+
Class<?> serviceClass =
59+
Class.forName("com.google.appengine.api.appidentity.AppIdentityService");
60+
Class<?> tokenResultClass = Class.forName(
61+
"com.google.appengine.api.appidentity.AppIdentityService$GetAccessTokenResult");
62+
this.getAccessTokenResult = serviceClass.getMethod("getAccessToken", Iterable.class);
63+
this.getAccessToken = tokenResultClass.getMethod("getAccessToken");
5564
this.scopes = null;
5665
this.scopesRequired = true;
5766
} catch (Exception e) {
5867
throw new RuntimeException("Could not create AppEngineCredentials using reflection.");
5968
}
6069
}
6170

62-
AppEngineCredentials(Collection<String> scopes, Object appIdentityService) {
63-
this.appIdentityService = appIdentityService;
64-
this.scopes = scopes;
65-
this.scopesRequired = (scopes == null || scopes.isEmpty());
71+
AppEngineCredentials(Collection<String> scopes, Object appIdentityService,
72+
Method getAccessToken, Method getAccessTokenResult) {
73+
this.appIdentityService = appIdentityService;
74+
this.getAccessToken = getAccessToken;
75+
this.getAccessTokenResult = getAccessTokenResult;
76+
this.scopes = scopes;
77+
this.scopesRequired = (scopes == null || scopes.isEmpty());
6678
}
6779

6880
/**
@@ -74,13 +86,7 @@ public AccessToken refreshAccessToken() throws IOException {
7486
throw new IOException("AppEngineCredentials requires createScoped call before use.");
7587
}
7688
try {
77-
Class<?> serviceClass =
78-
Class.forName("com.google.appengine.api.appidentity.AppIdentityService");
79-
Class<?> tokenResultClass = Class.forName(
80-
"com.google.appengine.api.appidentity.AppIdentityService$GetAccessTokenResult");
81-
Method getAccessTokenResult = serviceClass.getMethod("getAccessToken", Iterable.class);
8289
Object accessTokenResult = getAccessTokenResult.invoke(appIdentityService, scopes);
83-
Method getAccessToken = tokenResultClass.getMethod("getAccessToken");
8490
String accessToken = (String) getAccessToken.invoke(accessTokenResult);
8591
return new AccessToken(accessToken, null);
8692
} catch (Exception e) {
@@ -95,7 +101,8 @@ public boolean createScopedRequired() {
95101

96102
@Override
97103
public GoogleCredentials createScoped(Collection<String> scopes) {
98-
return new AppEngineCredentials(scopes, appIdentityService);
104+
return new AppEngineCredentials(
105+
scopes, appIdentityService, getAccessToken, getAccessTokenResult);
99106
}
100107
}
101108

@@ -104,9 +111,17 @@ private static class AppEngineAuthCredentialsState
104111

105112
private static final long serialVersionUID = 3558563960848658928L;
106113

114+
private final boolean scopesRequired;
115+
private final Collection<String> scopes;
116+
117+
private AppEngineAuthCredentialsState(Collection<String> scopes, boolean scopesRequired) {
118+
this.scopes = scopes;
119+
this.scopesRequired = scopesRequired;
120+
}
121+
107122
@Override
108123
public AuthCredentials restore() {
109-
return INSTANCE;
124+
return new AppEngineAuthCredentials(scopes, scopesRequired);
110125
}
111126

112127
@Override
@@ -120,14 +135,19 @@ public boolean equals(Object obj) {
120135
}
121136
}
122137

138+
AppEngineAuthCredentials(Collection<String> scopes, boolean scopesRequired) {
139+
this.scopes = scopes != null ? ImmutableSet.copyOf(checkNotNull(scopes)) : null;
140+
this.scopesRequired = scopesRequired;
141+
}
142+
123143
@Override
124-
protected GoogleCredentials credentials() {
144+
public GoogleCredentials credentials() {
125145
return new AppEngineCredentials();
126146
}
127147

128148
@Override
129149
public RestorableState<AuthCredentials> capture() {
130-
return STATE;
150+
return new AppEngineAuthCredentialsState(scopes, scopesRequired);
131151
}
132152
}
133153

@@ -176,7 +196,7 @@ public boolean equals(Object obj) {
176196
}
177197

178198
@Override
179-
protected GoogleCredentials credentials() {
199+
public GoogleCredentials credentials() {
180200
return new ServiceAccountCredentials(null, account, privateKey, null, null);
181201
}
182202

@@ -232,7 +252,7 @@ public boolean equals(Object obj) {
232252
}
233253

234254
@Override
235-
protected GoogleCredentials credentials() {
255+
public GoogleCredentials credentials() {
236256
return googleCredentials;
237257
}
238258

@@ -251,10 +271,10 @@ public RestorableState<AuthCredentials> capture() {
251271
}
252272
}
253273

254-
protected abstract GoogleCredentials credentials();
274+
public abstract GoogleCredentials credentials();
255275

256276
public static AuthCredentials createForAppEngine() {
257-
return AppEngineAuthCredentials.INSTANCE;
277+
return new AppEngineAuthCredentials(null, true);
258278
}
259279

260280
/**
@@ -297,11 +317,12 @@ public static ServiceAccountAuthCredentials createFor(String account, PrivateKey
297317
* Account Authentication</a>.
298318
* </p>
299319
*
300-
* @param jsonCredentialStream stream for Service Account Credentials in JSON format
320+
* @param jsonCredentialStream stream for Service Account Credentials or User Credentials in JSON
321+
* format
301322
* @return the credentials instance.
302323
* @throws IOException if the credentials cannot be created from the stream.
303324
*/
304-
public static ServiceAccountAuthCredentials createForJson(InputStream jsonCredentialStream)
325+
public static AuthCredentials createForJson(InputStream jsonCredentialStream)
305326
throws IOException {
306327
GoogleCredentials tempCredentials = GoogleCredentials.fromStream(jsonCredentialStream);
307328
if (tempCredentials instanceof ServiceAccountCredentials) {
@@ -310,9 +331,9 @@ public static ServiceAccountAuthCredentials createForJson(InputStream jsonCreden
310331
return new ServiceAccountAuthCredentials(
311332
tempServiceAccountCredentials.getClientEmail(),
312333
tempServiceAccountCredentials.getPrivateKey());
313-
} else {
314-
throw new IOException(
315-
"The given JSON Credentials Stream is not a service account credential.");
316334
}
335+
throw new IOException(
336+
"The given JSON credentials stream could not be parsed as service account credentials or"
337+
+ " user credentials.");
317338
}
318339
}

gcloud-java-storage/src/main/java/com/google/gcloud/storage/StorageImpl.java

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -31,26 +31,26 @@
3131
import static java.nio.charset.StandardCharsets.UTF_8;
3232

3333
import com.google.api.services.storage.model.StorageObject;
34+
import com.google.auth.oauth2.GoogleCredentials;
35+
import com.google.auth.oauth2.ServiceAccountCredentials;
3436
import com.google.common.base.Function;
3537
import com.google.common.base.Functions;
3638
import com.google.common.collect.ImmutableList;
3739
import com.google.common.collect.ImmutableMap;
3840
import com.google.common.collect.Iterables;
3941
import com.google.common.collect.Lists;
4042
import com.google.common.collect.Maps;
41-
import com.google.common.collect.Sets;
4243
import com.google.common.hash.Hashing;
4344
import com.google.common.io.BaseEncoding;
4445
import com.google.common.primitives.Ints;
4546
import com.google.gcloud.AuthCredentials;
46-
import com.google.gcloud.AuthCredentials.ApplicationDefaultAuthCredentials;
4747
import com.google.gcloud.AuthCredentials.ServiceAccountAuthCredentials;
48-
import com.google.gcloud.PageImpl;
4948
import com.google.gcloud.BaseService;
5049
import com.google.gcloud.ExceptionHandler;
5150
import com.google.gcloud.ExceptionHandler.Interceptor;
52-
import com.google.gcloud.RetryHelper.RetryHelperException;
5351
import com.google.gcloud.Page;
52+
import com.google.gcloud.PageImpl;
53+
import com.google.gcloud.RetryHelper.RetryHelperException;
5454
import com.google.gcloud.spi.StorageRpc;
5555
import com.google.gcloud.spi.StorageRpc.RewriteResponse;
5656
import com.google.gcloud.spi.StorageRpc.Tuple;
@@ -71,7 +71,6 @@
7171
import java.util.EnumMap;
7272
import java.util.List;
7373
import java.util.Map;
74-
import java.util.Set;
7574
import java.util.concurrent.Callable;
7675
import java.util.concurrent.TimeUnit;
7776

@@ -566,15 +565,13 @@ public URL signUrl(BlobInfo blobInfo, long duration, TimeUnit unit, SignUrlOptio
566565
ServiceAccountAuthCredentials cred =
567566
(ServiceAccountAuthCredentials) optionMap.get(SignUrlOption.Option.SERVICE_ACCOUNT_CRED);
568567
if (cred == null) {
569-
AuthCredentials serviceCred = this.options().authCredentials();
570-
if (serviceCred instanceof ServiceAccountAuthCredentials) {
571-
cred = (ServiceAccountAuthCredentials) serviceCred;
572-
} else {
573-
if (serviceCred instanceof ApplicationDefaultAuthCredentials) {
574-
cred = ((ApplicationDefaultAuthCredentials) serviceCred).toServiceAccountCredentials();
575-
}
576-
}
577-
checkArgument(cred != null, "Signing key was not provided and could not be derived");
568+
AuthCredentials authCredentials = this.options().authCredentials();
569+
GoogleCredentials serviceCred =
570+
authCredentials != null ? authCredentials.credentials() : null;
571+
checkArgument(
572+
serviceCred instanceof ServiceAccountCredentials,
573+
"Signing key was not provided and could not be derived");
574+
cred = (ServiceAccountAuthCredentials) authCredentials;
578575
}
579576
// construct signature - see https://cloud.google.com/storage/docs/access-control#Signed-URLs
580577
StringBuilder stBuilder = new StringBuilder();

0 commit comments

Comments
 (0)