diff --git a/core/src/main/java/google/registry/config/files/default-config.yaml b/core/src/main/java/google/registry/config/files/default-config.yaml index e432edc35fd..9472dbdecd6 100644 --- a/core/src/main/java/google/registry/config/files/default-config.yaml +++ b/core/src/main/java/google/registry/config/files/default-config.yaml @@ -29,9 +29,13 @@ gcpProject: # See: https://cloud.google.com/iap/docs/signed-headers-howto#verifying_the_jwt_payload backendServiceIds: frontend: 12345 + frontend-canary: 12345 backend: 12345 + backend-canary: 12345 pubapi: 12345 + pubapi-canary: 12345 console: 12345 + console-canary: 12345 # The base domain name of the registry service. Services are reachable at [service].baseDomain. baseDomain: registry.test diff --git a/core/src/main/java/google/registry/request/auth/OidcTokenAuthenticationMechanism.java b/core/src/main/java/google/registry/request/auth/OidcTokenAuthenticationMechanism.java index c206f1fdd15..672653d9df6 100644 --- a/core/src/main/java/google/registry/request/auth/OidcTokenAuthenticationMechanism.java +++ b/core/src/main/java/google/registry/request/auth/OidcTokenAuthenticationMechanism.java @@ -87,6 +87,9 @@ public AuthResult authenticate(HttpServletRequest request) { if (RegistryEnvironment.isOnJetty()) { String hostname = request.getServerName(); service = Splitter.on('.').split(hostname).iterator().next(); + if (request.getHeader("canary") != null) { + service += "-canary"; + } } token = tokenVerifier.verify(service, rawIdToken); } catch (Exception e) { diff --git a/core/src/main/java/google/registry/tools/CurlCommand.java b/core/src/main/java/google/registry/tools/CurlCommand.java index df3be3d13a5..9c2f4039899 100644 --- a/core/src/main/java/google/registry/tools/CurlCommand.java +++ b/core/src/main/java/google/registry/tools/CurlCommand.java @@ -80,15 +80,14 @@ public enum Method { required = true) private String serviceName; - @Parameter( - names = {"--canary"}, - description = "If set, use the canary end-point; otherwise use the regular end-point.") - private Boolean canary = Boolean.FALSE; - @Inject @Config("useGke") boolean useGke; + @Inject + @Config("useCanary") + boolean useCanary; + @Override public void setConnection(ServiceConnection connection) { this.connection = connection; @@ -109,7 +108,7 @@ public void run() throws Exception { ? GkeService.valueOf(Ascii.toUpperCase(serviceName)) : GaeService.valueOf(Ascii.toUpperCase(serviceName)); - ServiceConnection connectionToService = connection.withService(service, canary); + ServiceConnection connectionToService = connection.withService(service, useCanary); String response = (method == Method.GET) ? connectionToService.sendGetRequest(path, ImmutableMap.of()) diff --git a/core/src/main/java/google/registry/tools/RegistryCli.java b/core/src/main/java/google/registry/tools/RegistryCli.java index 3ce447dea10..8f28edc6296 100644 --- a/core/src/main/java/google/registry/tools/RegistryCli.java +++ b/core/src/main/java/google/registry/tools/RegistryCli.java @@ -73,6 +73,9 @@ final class RegistryCli implements CommandRunner { @Parameter(names = "--gke", description = "Whether to use GKE runtime, instead of GAE") private boolean useGke = false; + @Parameter(names = "--canary", description = "Whether to connect to the canary instances") + private boolean useCanary = false; + // Do not make this final - compile-time constant inlining may interfere with JCommander. @ParametersDelegate private LoggingParameters loggingParams = new LoggingParameters(); @@ -166,6 +169,7 @@ public void run(String[] args) throws Exception { .credentialFilePath(credentialJson) .sqlAccessInfoFile(sqlAccessInfoFile) .useGke(useGke) + .useCanary(useCanary) .build(); // JCommander stores sub-commands as nested JCommander objects containing a list of user objects @@ -196,9 +200,9 @@ public void run(String[] args) throws Exception { System.err.println("==================================================================="); System.err.println( """ - This error is likely the result of having another instance of - nomulus running at the same time. Check your system, shut down - the other instance, and try again."""); + This error is likely the result of having another instance of + nomulus running at the same time. Check your system, shut down + the other instance, and try again."""); System.err.println("==================================================================="); } else { throw e; diff --git a/core/src/main/java/google/registry/tools/RegistryToolComponent.java b/core/src/main/java/google/registry/tools/RegistryToolComponent.java index 40b093c18d6..7e68a6d71b6 100644 --- a/core/src/main/java/google/registry/tools/RegistryToolComponent.java +++ b/core/src/main/java/google/registry/tools/RegistryToolComponent.java @@ -195,6 +195,9 @@ interface Builder { @BindsInstance Builder useGke(@Config("useGke") boolean useGke); + @BindsInstance + Builder useCanary(@Config("useCanary") boolean useCanary); + RegistryToolComponent build(); } } diff --git a/core/src/main/java/google/registry/tools/ServiceConnection.java b/core/src/main/java/google/registry/tools/ServiceConnection.java index 961ccd94d39..c8ee62f034b 100644 --- a/core/src/main/java/google/registry/tools/ServiceConnection.java +++ b/core/src/main/java/google/registry/tools/ServiceConnection.java @@ -65,8 +65,11 @@ public class ServiceConnection { private final HttpRequestFactory requestFactory; @Inject - ServiceConnection(@Config("useGke") boolean useGke, HttpRequestFactory requestFactory) { - this(useGke ? GkeService.BACKEND : GaeService.TOOLS, requestFactory, false); + ServiceConnection( + @Config("useGke") boolean useGke, + @Config("useCanary") boolean useCanary, + HttpRequestFactory requestFactory) { + this(useGke ? GkeService.BACKEND : GaeService.TOOLS, requestFactory, useCanary); } private ServiceConnection(Service service, HttpRequestFactory requestFactory, boolean useCanary) { diff --git a/core/src/test/java/google/registry/tools/CurlCommandTest.java b/core/src/test/java/google/registry/tools/CurlCommandTest.java index d1593c0f48b..ea0823bf0da 100644 --- a/core/src/test/java/google/registry/tools/CurlCommandTest.java +++ b/core/src/test/java/google/registry/tools/CurlCommandTest.java @@ -157,19 +157,6 @@ void testExplicitPostInvocation() throws Exception { eq("".getBytes(UTF_8))); } - @Test - void testCanaryInvocation() throws Exception { - runCommand("--path=/foo/bar?a=1&b=2", "--request=POST", "--service=TOOLS", "--canary"); - verify(connection).withService(eq(TOOLS), eq(true)); - verifyNoMoreInteractions(connection); - verify(connectionForService) - .sendPostRequest( - eq("/foo/bar?a=1&b=2"), - eq(ImmutableMap.of()), - eq(MediaType.PLAIN_TEXT_UTF_8), - eq("".getBytes(UTF_8))); - } - @Test @MockitoSettings(strictness = Strictness.LENIENT) void testGetWithBody() { diff --git a/core/src/test/java/google/registry/tools/GcpProjectConnectionTest.java b/core/src/test/java/google/registry/tools/GcpProjectConnectionTest.java index 2e655ea6824..d29259b1e60 100644 --- a/core/src/test/java/google/registry/tools/GcpProjectConnectionTest.java +++ b/core/src/test/java/google/registry/tools/GcpProjectConnectionTest.java @@ -85,7 +85,7 @@ void beforeEach() throws Exception { when(lowLevelHttpResponse.getStatusCode()).thenReturn(200); httpTransport = new TestHttpTransport(); - connection = new ServiceConnection(false, httpTransport.createRequestFactory()); + connection = new ServiceConnection(false, false, httpTransport.createRequestFactory()); } @Test diff --git a/core/src/test/java/google/registry/tools/ServiceConnectionTest.java b/core/src/test/java/google/registry/tools/ServiceConnectionTest.java index 87e65be38ac..bde677c8f67 100644 --- a/core/src/test/java/google/registry/tools/ServiceConnectionTest.java +++ b/core/src/test/java/google/registry/tools/ServiceConnectionTest.java @@ -37,7 +37,8 @@ public class ServiceConnectionTest { @Test void testSuccess_serverUrl_notCanary() { - ServiceConnection connection = new ServiceConnection(false, null).withService(DEFAULT, false); + ServiceConnection connection = + new ServiceConnection(false, false, null).withService(DEFAULT, false); String serverUrl = connection.getServer().toString(); assertThat(serverUrl).isEqualTo("https://default.example.com"); // See default-config.yaml } @@ -48,14 +49,15 @@ void testFailure_mixedService() throws Exception { assertThrows( IllegalArgumentException.class, () -> { - new ServiceConnection(true, null).withService(DEFAULT, true); + new ServiceConnection(true, false, null).withService(DEFAULT, true); }); assertThat(thrown).hasMessageThat().contains("Cannot switch from GkeService to GaeService"); } @Test void testSuccess_serverUrl_gae_canary() { - ServiceConnection connection = new ServiceConnection(false, null).withService(DEFAULT, true); + ServiceConnection connection = + new ServiceConnection(false, false, null).withService(DEFAULT, true); String serverUrl = connection.getServer().toString(); assertThat(serverUrl).isEqualTo("https://nomulus-dot-default.example.com"); } @@ -71,7 +73,7 @@ void testSuccess_serverUrl_gke_canary() throws Exception { when(request.execute()).thenReturn(response); when(response.getContent()).thenReturn(ByteArrayInputStream.nullInputStream()); ServiceConnection connection = - new ServiceConnection(true, factory).withService(GkeService.PUBAPI, true); + new ServiceConnection(true, false, factory).withService(GkeService.PUBAPI, true); String serverUrl = connection.getServer().toString(); assertThat(serverUrl).isEqualTo("https://pubapi.registry.test"); connection.sendGetRequest("/path", ImmutableMap.of()); diff --git a/jetty/deploy-nomulus-for-env.sh b/jetty/deploy-nomulus-for-env.sh index 22154657ec4..bc21d05f9a1 100755 --- a/jetty/deploy-nomulus-for-env.sh +++ b/jetty/deploy-nomulus-for-env.sh @@ -49,12 +49,19 @@ do if [[ "${parts[1]}" == us-* ]] then kubectl apply -f "./kubernetes/gateway/nomulus-gateway.yaml" - for service in frontend backend pubapi console + for service in frontend backend console pubapi do sed s/BASE_DOMAIN/"${base_domain}"/g "./kubernetes/gateway/nomulus-route-${service}.yaml" | \ kubectl apply -f - + # Don't enable IAP on pubapi. + if [[ "${service}" == pubapi ]] + then + continue + fi sed s/SERVICE/"${service}"/g "./kubernetes/gateway/nomulus-iap-${environment}.yaml" | \ kubectl apply -f - + sed s/SERVICE/"${service}-canary"/g "./kubernetes/gateway/nomulus-iap-${environment}.yaml" | \ + kubectl apply -f - done fi done < <(gcloud container clusters list --project "${project}" | grep nomulus) diff --git a/jetty/kubernetes/nomulus-frontend.yaml b/jetty/kubernetes/nomulus-frontend.yaml index 995e2bdccbb..8381850ee9f 100644 --- a/jetty/kubernetes/nomulus-frontend.yaml +++ b/jetty/kubernetes/nomulus-frontend.yaml @@ -45,6 +45,14 @@ spec: - name: CONTAINER_NAME value: proxy --- +# Only need to define the service account once per cluster. +apiVersion: v1 +kind: ServiceAccount +metadata: + name: nomulus + annotations: + iam.gke.io/gcp-service-account: "nomulus-service-account@GCP_PROJECT.iam.gserviceaccount.com" +--- apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler metadata: