mirror of
https://github.com/google/nomulus.git
synced 2025-05-19 18:59:35 +02:00
Add the ability to provide credential JSON file to the nomulus tool
This allows us to run nomulus tool programmatically on environments that do not allow the 3-legged OAuth authentication flow. The provided JSON file corresponds to a service account, which must have GAE admin permission and whose client ID must be whitelisted in the config file. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=226008337
This commit is contained in:
parent
40b05ffb3c
commit
27b6231053
5 changed files with 76 additions and 20 deletions
|
@ -33,6 +33,7 @@ import com.google.common.collect.ImmutableMap;
|
|||
import com.google.common.collect.Ordering;
|
||||
import com.google.gson.Gson;
|
||||
import dagger.Binds;
|
||||
import dagger.Lazy;
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
import google.registry.config.CredentialModule.DefaultCredential;
|
||||
|
@ -45,12 +46,14 @@ import java.io.IOException;
|
|||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Qualifier;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
/**
|
||||
* Module providing the dependency graph for authorization credentials.
|
||||
*/
|
||||
/** Module providing the dependency graph for authorization credentials. */
|
||||
@Module
|
||||
public class AuthModule {
|
||||
|
||||
|
@ -84,9 +87,15 @@ public class AuthModule {
|
|||
@Provides
|
||||
@LocalCredential
|
||||
public static GoogleCredential provideLocalCredential(
|
||||
@LocalCredentialJson String credentialJson) {
|
||||
@LocalCredentialJson String credentialJson,
|
||||
@Config("localCredentialOauthScopes") ImmutableList<String> scopes) {
|
||||
try {
|
||||
return GoogleCredential.fromStream(new ByteArrayInputStream(credentialJson.getBytes(UTF_8)));
|
||||
GoogleCredential credential =
|
||||
GoogleCredential.fromStream(new ByteArrayInputStream(credentialJson.getBytes(UTF_8)));
|
||||
if (credential.createScopedRequired()) {
|
||||
credential = credential.createScoped(scopes);
|
||||
}
|
||||
return credential;
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
@ -133,16 +142,26 @@ public class AuthModule {
|
|||
@Provides
|
||||
@LocalCredentialJson
|
||||
public static String provideLocalCredentialJson(
|
||||
GoogleClientSecrets clientSecrets, @StoredCredential Credential credential) {
|
||||
Lazy<GoogleClientSecrets> clientSecrets,
|
||||
@StoredCredential Lazy<Credential> credential,
|
||||
@Nullable @Named("credentialFileName") String credentialFilename) {
|
||||
try {
|
||||
if (credentialFilename != null) {
|
||||
return new String(Files.readAllBytes(Paths.get(credentialFilename)), UTF_8);
|
||||
} else {
|
||||
return new Gson()
|
||||
.toJson(
|
||||
ImmutableMap.<String, String>builder()
|
||||
.put("type", "authorized_user")
|
||||
.put("client_id", clientSecrets.getDetails().getClientId())
|
||||
.put("client_secret", clientSecrets.getDetails().getClientSecret())
|
||||
.put("refresh_token", credential.getRefreshToken())
|
||||
.put("client_id", clientSecrets.get().getDetails().getClientId())
|
||||
.put("client_secret", clientSecrets.get().getDetails().getClientSecret())
|
||||
.put("refresh_token", credential.get().getRefreshToken())
|
||||
.build());
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Provides
|
||||
@OAuthClientId
|
||||
|
|
|
@ -58,6 +58,13 @@ final class RegistryCli implements AutoCloseable, CommandRunner {
|
|||
description = "Returns all command names.")
|
||||
private boolean showAllCommands;
|
||||
|
||||
@Parameter(
|
||||
names = {"--credential"},
|
||||
description =
|
||||
"Name of a JSON file containing credential information used by the tool. "
|
||||
+ "If not set, credentials saved by running `nomulus login' will be used.")
|
||||
private String credentialJson = null;
|
||||
|
||||
// Do not make this final - compile-time constant inlining may interfere with JCommander.
|
||||
@ParametersDelegate
|
||||
private LoggingParameters loggingParams = new LoggingParameters();
|
||||
|
@ -81,8 +88,6 @@ final class RegistryCli implements AutoCloseable, CommandRunner {
|
|||
this.commands = commands;
|
||||
|
||||
Security.addProvider(new BouncyCastleProvider());
|
||||
|
||||
component = DaggerRegistryToolComponent.create();
|
||||
}
|
||||
|
||||
// The <? extends Class<? extends Command>> wildcard looks a little funny, but is needed so that
|
||||
|
@ -146,6 +151,9 @@ final class RegistryCli implements AutoCloseable, CommandRunner {
|
|||
checkState(RegistryToolEnvironment.get() == environment,
|
||||
"RegistryToolEnvironment argument pre-processing kludge failed.");
|
||||
|
||||
component =
|
||||
DaggerRegistryToolComponent.builder().credentialFilename(credentialJson).build();
|
||||
|
||||
// JCommander stores sub-commands as nested JCommander objects containing a list of user objects
|
||||
// to be populated. Extract the subcommand by getting the JCommander wrapper and then
|
||||
// retrieving the first (and, by virtue of our usage, only) object from it.
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
package google.registry.tools;
|
||||
|
||||
import dagger.BindsInstance;
|
||||
import dagger.Component;
|
||||
import google.registry.bigquery.BigqueryModule;
|
||||
import google.registry.config.CredentialModule.LocalCredentialJson;
|
||||
|
@ -36,6 +37,8 @@ import google.registry.util.AppEngineServiceUtilsImpl.AppEngineServiceUtilsModul
|
|||
import google.registry.util.SystemClock.SystemClockModule;
|
||||
import google.registry.util.SystemSleeper.SystemSleeperModule;
|
||||
import google.registry.whois.WhoisModule;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
/**
|
||||
|
@ -113,5 +116,12 @@ interface RegistryToolComponent {
|
|||
|
||||
@LocalCredentialJson
|
||||
String googleCredentialJson();
|
||||
}
|
||||
|
||||
@Component.Builder
|
||||
interface Builder {
|
||||
@BindsInstance
|
||||
Builder credentialFilename(@Nullable @Named("credentialFileName") String credentialFilename);
|
||||
|
||||
RegistryToolComponent build();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ import com.google.api.client.http.HttpRequestFactory;
|
|||
import com.google.api.client.http.javanet.NetHttpTransport;
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
import google.registry.config.CredentialModule.LocalCredential;
|
||||
import google.registry.config.CredentialModule.DefaultCredential;
|
||||
import google.registry.config.RegistryConfig;
|
||||
|
||||
/**
|
||||
|
@ -35,7 +35,7 @@ class RequestFactoryModule {
|
|||
|
||||
@Provides
|
||||
static HttpRequestFactory provideHttpRequestFactory(
|
||||
@LocalCredential GoogleCredential credential) {
|
||||
@DefaultCredential GoogleCredential credential) {
|
||||
if (RegistryConfig.areServersLocal()) {
|
||||
return new NetHttpTransport()
|
||||
.createRequestFactory(
|
||||
|
|
|
@ -16,6 +16,7 @@ package google.registry.tools;
|
|||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static google.registry.testing.JUnitBackports.assertThrows;
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
|
@ -32,11 +33,15 @@ import com.google.api.client.util.store.DataStore;
|
|||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
import java.nio.file.Files;
|
||||
import java.util.Map;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.JUnit4;
|
||||
|
||||
|
@ -49,6 +54,9 @@ public class AuthModuleTest {
|
|||
private static final String ACCESS_TOKEN = "FakeAccessToken";
|
||||
private static final String REFRESH_TOKEN = "FakeReFreshToken";
|
||||
|
||||
@Rule
|
||||
public final TemporaryFolder folder = new TemporaryFolder();
|
||||
|
||||
private final Credential fakeCredential =
|
||||
new Credential.Builder(
|
||||
new Credential.AccessMethod() {
|
||||
|
@ -154,7 +162,8 @@ public class AuthModuleTest {
|
|||
|
||||
@Test
|
||||
public void test_provideLocalCredentialJson() {
|
||||
String credentialJson = AuthModule.provideLocalCredentialJson(getSecrets(), getCredential());
|
||||
String credentialJson =
|
||||
AuthModule.provideLocalCredentialJson(this::getSecrets, this::getCredential, null);
|
||||
Map<String, String> jsonMap =
|
||||
new Gson().fromJson(credentialJson, new TypeToken<Map<String, String>>() {}.getType());
|
||||
assertThat(jsonMap.get("type")).isEqualTo("authorized_user");
|
||||
|
@ -163,6 +172,16 @@ public class AuthModuleTest {
|
|||
assertThat(jsonMap.get("refresh_token")).isEqualTo(REFRESH_TOKEN);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_provideExternalCredentialJson() throws Exception {
|
||||
File credentialFile = folder.newFile("credential.json");
|
||||
Files.write(credentialFile.toPath(), "{some_field: some_value}".getBytes(UTF_8));
|
||||
String credentialJson =
|
||||
AuthModule.provideLocalCredentialJson(
|
||||
this::getSecrets, this::getCredential, credentialFile.getCanonicalPath());
|
||||
assertThat(credentialJson).isEqualTo("{some_field: some_value}");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_provideCredential() {
|
||||
Credential cred = getCredential();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue