mirror of https://github.com/grpc/grpc-java.git
auth: GoogleAuthLibraryCallCredentials uses Credentials Builder
This commit is contained in:
parent
f25fe1fe6a
commit
09d9c4a919
|
|
@ -28,12 +28,11 @@ import io.grpc.SecurityLevel;
|
|||
import io.grpc.Status;
|
||||
import io.grpc.StatusException;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.security.PrivateKey;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
|
@ -245,31 +244,75 @@ final class GoogleAuthLibraryCallCredentials extends io.grpc.CallCredentials2 {
|
|||
return rawGoogleCredentialsClass.asSubclass(Credentials.class);
|
||||
}
|
||||
|
||||
private static class MethodPair {
|
||||
private final Method getter;
|
||||
private final Method builderSetter;
|
||||
|
||||
private MethodPair(Method getter, Method builderSetter) {
|
||||
this.getter = getter;
|
||||
this.builderSetter = builderSetter;
|
||||
}
|
||||
|
||||
private void apply(Credentials credentials, Object builder)
|
||||
throws InvocationTargetException, IllegalAccessException {
|
||||
builderSetter.invoke(builder, getter.invoke(credentials));
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
static class JwtHelper {
|
||||
private final Class<? extends Credentials> serviceAccountClass;
|
||||
private final Constructor<? extends Credentials> jwtConstructor;
|
||||
private final Method newJwtBuilder;
|
||||
private final Method build;
|
||||
private final Method getScopes;
|
||||
private final Method getClientId;
|
||||
private final Method getClientEmail;
|
||||
private final Method getPrivateKey;
|
||||
private final Method getPrivateKeyId;
|
||||
private final List<MethodPair> methodPairs;
|
||||
|
||||
public JwtHelper(Class<?> rawServiceAccountClass, ClassLoader loader)
|
||||
throws ClassNotFoundException, NoSuchMethodException {
|
||||
serviceAccountClass = rawServiceAccountClass.asSubclass(Credentials.class);
|
||||
getScopes = serviceAccountClass.getMethod("getScopes");
|
||||
getClientId = serviceAccountClass.getMethod("getClientId");
|
||||
getClientEmail = serviceAccountClass.getMethod("getClientEmail");
|
||||
getPrivateKey = serviceAccountClass.getMethod("getPrivateKey");
|
||||
getPrivateKeyId = serviceAccountClass.getMethod("getPrivateKeyId");
|
||||
Class<? extends Credentials> jwtClass = Class.forName(
|
||||
"com.google.auth.oauth2.ServiceAccountJwtAccessCredentials", false, loader)
|
||||
.asSubclass(Credentials.class);
|
||||
jwtConstructor
|
||||
= jwtClass.getConstructor(String.class, String.class, PrivateKey.class, String.class);
|
||||
newJwtBuilder = jwtClass.getDeclaredMethod("newBuilder");
|
||||
Class<?> builderClass = newJwtBuilder.getReturnType();
|
||||
build = builderClass.getMethod("build");
|
||||
|
||||
methodPairs = new ArrayList<>();
|
||||
|
||||
{
|
||||
Method getter = serviceAccountClass.getMethod("getClientId");
|
||||
Method setter = builderClass.getMethod("setClientId", getter.getReturnType());
|
||||
methodPairs.add(new MethodPair(getter, setter));
|
||||
}
|
||||
{
|
||||
Method getter = serviceAccountClass.getMethod("getClientEmail");
|
||||
Method setter = builderClass.getMethod("setClientEmail", getter.getReturnType());
|
||||
methodPairs.add(new MethodPair(getter, setter));
|
||||
}
|
||||
{
|
||||
Method getter = serviceAccountClass.getMethod("getPrivateKey");
|
||||
Method setter = builderClass.getMethod("setPrivateKey", getter.getReturnType());
|
||||
methodPairs.add(new MethodPair(getter, setter));
|
||||
}
|
||||
{
|
||||
Method getter = serviceAccountClass.getMethod("getPrivateKey");
|
||||
Method setter = builderClass.getMethod("setPrivateKey", getter.getReturnType());
|
||||
methodPairs.add(new MethodPair(getter, setter));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method tries to convert a {@link Credentials} object to a
|
||||
* ServiceAccountJwtAccessCredentials. The original credentials will be returned if:
|
||||
* <ul>
|
||||
* <li> The Credentials is not a ServiceAccountCredentials</li>
|
||||
* <li> The ServiceAccountCredentials has scopes</li>
|
||||
* <li> Something unexpected happens </li>
|
||||
* </ul>
|
||||
* @param creds the Credentials to convert
|
||||
* @return either the original Credentials or a fully formed ServiceAccountJwtAccessCredentials.
|
||||
*/
|
||||
public Credentials tryServiceAccountToJwt(Credentials creds) {
|
||||
if (!serviceAccountClass.isInstance(creds)) {
|
||||
return creds;
|
||||
|
|
@ -282,17 +325,20 @@ final class GoogleAuthLibraryCallCredentials extends io.grpc.CallCredentials2 {
|
|||
// Leave as-is, since the scopes may limit access within the service.
|
||||
return creds;
|
||||
}
|
||||
return jwtConstructor.newInstance(
|
||||
getClientId.invoke(creds),
|
||||
getClientEmail.invoke(creds),
|
||||
getPrivateKey.invoke(creds),
|
||||
getPrivateKeyId.invoke(creds));
|
||||
// Create the JWT Credentials Builder
|
||||
Object builder = newJwtBuilder.invoke(null);
|
||||
|
||||
// Get things from the credentials, and set them on the builder.
|
||||
for (MethodPair pair : this.methodPairs) {
|
||||
pair.apply(creds, builder);
|
||||
}
|
||||
|
||||
// Call builder.build()
|
||||
return (Credentials) build.invoke(builder);
|
||||
} catch (IllegalAccessException ex) {
|
||||
caughtException = ex;
|
||||
} catch (InvocationTargetException ex) {
|
||||
caughtException = ex;
|
||||
} catch (InstantiationException ex) {
|
||||
caughtException = ex;
|
||||
}
|
||||
if (caughtException != null) {
|
||||
// Failure is a bug in this class, but we still choose to gracefully recover
|
||||
|
|
|
|||
Loading…
Reference in New Issue