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.Status;
|
||||||
import io.grpc.StatusException;
|
import io.grpc.StatusException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.lang.reflect.Constructor;
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
import java.security.PrivateKey;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
@ -245,31 +244,75 @@ final class GoogleAuthLibraryCallCredentials extends io.grpc.CallCredentials2 {
|
||||||
return rawGoogleCredentialsClass.asSubclass(Credentials.class);
|
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
|
@VisibleForTesting
|
||||||
static class JwtHelper {
|
static class JwtHelper {
|
||||||
private final Class<? extends Credentials> serviceAccountClass;
|
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 getScopes;
|
||||||
private final Method getClientId;
|
private final List<MethodPair> methodPairs;
|
||||||
private final Method getClientEmail;
|
|
||||||
private final Method getPrivateKey;
|
|
||||||
private final Method getPrivateKeyId;
|
|
||||||
|
|
||||||
public JwtHelper(Class<?> rawServiceAccountClass, ClassLoader loader)
|
public JwtHelper(Class<?> rawServiceAccountClass, ClassLoader loader)
|
||||||
throws ClassNotFoundException, NoSuchMethodException {
|
throws ClassNotFoundException, NoSuchMethodException {
|
||||||
serviceAccountClass = rawServiceAccountClass.asSubclass(Credentials.class);
|
serviceAccountClass = rawServiceAccountClass.asSubclass(Credentials.class);
|
||||||
getScopes = serviceAccountClass.getMethod("getScopes");
|
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(
|
Class<? extends Credentials> jwtClass = Class.forName(
|
||||||
"com.google.auth.oauth2.ServiceAccountJwtAccessCredentials", false, loader)
|
"com.google.auth.oauth2.ServiceAccountJwtAccessCredentials", false, loader)
|
||||||
.asSubclass(Credentials.class);
|
.asSubclass(Credentials.class);
|
||||||
jwtConstructor
|
newJwtBuilder = jwtClass.getDeclaredMethod("newBuilder");
|
||||||
= jwtClass.getConstructor(String.class, String.class, PrivateKey.class, String.class);
|
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) {
|
public Credentials tryServiceAccountToJwt(Credentials creds) {
|
||||||
if (!serviceAccountClass.isInstance(creds)) {
|
if (!serviceAccountClass.isInstance(creds)) {
|
||||||
return 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.
|
// Leave as-is, since the scopes may limit access within the service.
|
||||||
return creds;
|
return creds;
|
||||||
}
|
}
|
||||||
return jwtConstructor.newInstance(
|
// Create the JWT Credentials Builder
|
||||||
getClientId.invoke(creds),
|
Object builder = newJwtBuilder.invoke(null);
|
||||||
getClientEmail.invoke(creds),
|
|
||||||
getPrivateKey.invoke(creds),
|
// Get things from the credentials, and set them on the builder.
|
||||||
getPrivateKeyId.invoke(creds));
|
for (MethodPair pair : this.methodPairs) {
|
||||||
|
pair.apply(creds, builder);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call builder.build()
|
||||||
|
return (Credentials) build.invoke(builder);
|
||||||
} catch (IllegalAccessException ex) {
|
} catch (IllegalAccessException ex) {
|
||||||
caughtException = ex;
|
caughtException = ex;
|
||||||
} catch (InvocationTargetException ex) {
|
} catch (InvocationTargetException ex) {
|
||||||
caughtException = ex;
|
caughtException = ex;
|
||||||
} catch (InstantiationException ex) {
|
|
||||||
caughtException = ex;
|
|
||||||
}
|
}
|
||||||
if (caughtException != null) {
|
if (caughtException != null) {
|
||||||
// Failure is a bug in this class, but we still choose to gracefully recover
|
// Failure is a bug in this class, but we still choose to gracefully recover
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue