diff --git a/README.md b/README.md index d2434d7..61d63b1 100644 --- a/README.md +++ b/README.md @@ -5,10 +5,24 @@ Scalar Admin for Kubernetes is a tool that creates a paused state for ScalarDB o ## Usage of the CLI tool ```console -Usage: scalar-admin-for-kubernetes-cli [-h] [-d=] - [-n=] -r= +Usage: scalar-admin-for-kubernetes-cli [-h] [--tls] + [--ca-root-cert-path=] + [--ca-root-cert-pem=] + [-d=] [-n=] + [--override-authority= + ] -r= [-w=] [-z=] Scalar Admin pause tool for the Kubernetes environment + --ca-root-cert-path= + A path to a root certificate file for verifying + the server's certificate when wire encryption is + enabled. + --ca-root-cert-pem= + A PEM format string of a root certificate for + verifying the server's certificate when wire + encryption is enabled. This option is + prioritized when --ca-root-cert-path is + specified. -d, --pause-duration= The duration of the pause period by millisecond. 5000 (5 seconds) by default. @@ -16,11 +30,17 @@ Scalar Admin pause tool for the Kubernetes environment -n, --namespace= Namespace that Scalar products you want to pause are deployed. `default` by default. + --override-authority= + The value to be used as the expected authority in + the server's certificate when wire encryption is + enabled. -r, --release-name= Required. The helm release name that you specify when you run the `helm install ` command. You can see the by using the `helm list` command. + --tls Whether wire encryption (TLS) between scalar-admin + and the target is enabled. -w, --max-pause-wait-time= The max wait time (in milliseconds) until Scalar products drain outstanding requests before they diff --git a/build.gradle b/build.gradle index 704c694..206b89b 100644 --- a/build.gradle +++ b/build.gradle @@ -11,7 +11,7 @@ subprojects { project.version = project.findProperty('projVersion') ?: '2.0.0-SNAPSHOT' ext { - scalarAdminVersion = '2.1.2' + scalarAdminVersion = '2.2.0' guavaVersion = '31.1-jre' kubernetesClientVersion = '17.0.2' slf4jVersion = '1.7.36' diff --git a/cli/src/main/java/com/scalar/admin/kubernetes/Cli.java b/cli/src/main/java/com/scalar/admin/kubernetes/Cli.java index 720d88c..b541aa0 100644 --- a/cli/src/main/java/com/scalar/admin/kubernetes/Cli.java +++ b/cli/src/main/java/com/scalar/admin/kubernetes/Cli.java @@ -2,6 +2,11 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.File; +import java.io.IOException; +import java.io.UncheckedIOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; import java.time.ZoneId; import java.util.concurrent.Callable; import javax.annotation.Nullable; @@ -59,6 +64,33 @@ class Cli implements Callable { defaultValue = "Etc/UTC") private ZoneId zoneId; + @Option( + names = {"--tls"}, + description = "Whether wire encryption (TLS) between scalar-admin and the target is enabled.") + private boolean tlsEnabled; + + @Option( + names = {"--ca-root-cert-path"}, + description = + "A path to a root certificate file for verifying the server's certificate when wire" + + " encryption is enabled.") + private String caRootCertPath; + + @Option( + names = {"--ca-root-cert-pem"}, + description = + "A PEM format string of a root certificate for verifying the server's certificate when" + + " wire encryption is enabled. This option is prioritized when --ca-root-cert-path" + + " is specified.") + private String caRootCertPem; + + @Option( + names = {"--override-authority"}, + description = + "The value to be used as the expected authority in the server's certificate when wire" + + " encryption is enabled.") + private String overrideAuthority; + @Option( names = {"-h", "--help"}, usageHelp = true, @@ -76,7 +108,11 @@ public Integer call() { Result result = null; try { - Pauser pauser = new Pauser(namespace, helmReleaseName); + Pauser pauser = + tlsEnabled + ? new TlsPauser(namespace, helmReleaseName, getCaRootCert(), overrideAuthority) + : new Pauser(namespace, helmReleaseName); + PausedDuration duration = pauser.pause(pauseDuration, maxPauseWaitTime); result = new Result(namespace, helmReleaseName, duration, zoneId); @@ -98,4 +134,22 @@ public Integer call() { return 0; } + + private String getCaRootCert() { + String caRootCert = null; + + if (caRootCertPem != null) { + caRootCert = caRootCertPem.replace("\\n", System.lineSeparator()); + } else if (caRootCertPath != null) { + try { + caRootCert = + new String( + Files.readAllBytes(new File(caRootCertPath).toPath()), StandardCharsets.UTF_8); + } catch (IOException e) { + throw new UncheckedIOException("Couldn't read the file: " + caRootCertPath, e); + } + } + + return caRootCert; + } } diff --git a/lib/src/main/java/com/scalar/admin/kubernetes/Pauser.java b/lib/src/main/java/com/scalar/admin/kubernetes/Pauser.java index 51eccc1..0cda1a3 100644 --- a/lib/src/main/java/com/scalar/admin/kubernetes/Pauser.java +++ b/lib/src/main/java/com/scalar/admin/kubernetes/Pauser.java @@ -84,11 +84,7 @@ public PausedDuration pause(int pauseDuration, @Nullable Long maxPauseWaitTime) throw new PauserException("Failed to find the target pods to pause.", e); } - RequestCoordinator coordinator = - new RequestCoordinator( - target.getPods().stream() - .map(p -> new InetSocketAddress(p.getStatus().getPodIP(), target.getAdminPort())) - .collect(Collectors.toList())); + RequestCoordinator coordinator = getRequestCoordinator(target); coordinator.pause(true, maxPauseWaitTime); @@ -137,4 +133,11 @@ private void unpauseWithRetry( } } } + + RequestCoordinator getRequestCoordinator(TargetSnapshot target) { + return new RequestCoordinator( + target.getPods().stream() + .map(p -> new InetSocketAddress(p.getStatus().getPodIP(), target.getAdminPort())) + .collect(Collectors.toList())); + } } diff --git a/lib/src/main/java/com/scalar/admin/kubernetes/TlsPauser.java b/lib/src/main/java/com/scalar/admin/kubernetes/TlsPauser.java new file mode 100644 index 0000000..4d6fd48 --- /dev/null +++ b/lib/src/main/java/com/scalar/admin/kubernetes/TlsPauser.java @@ -0,0 +1,35 @@ +package com.scalar.admin.kubernetes; + +import com.scalar.admin.RequestCoordinator; +import com.scalar.admin.TlsRequestCoordinator; +import java.net.InetSocketAddress; +import java.util.stream.Collectors; +import javax.annotation.Nullable; + +public class TlsPauser extends Pauser { + + private final String caRootCert; + private final String overrideAuthority; + + public TlsPauser( + String namespace, + String helmReleaseName, + @Nullable String caRootCert, + @Nullable String overrideAuthority) + throws PauserException { + super(namespace, helmReleaseName); + + this.caRootCert = caRootCert; + this.overrideAuthority = overrideAuthority; + } + + @Override + RequestCoordinator getRequestCoordinator(TargetSnapshot target) { + return new TlsRequestCoordinator( + target.getPods().stream() + .map(p -> new InetSocketAddress(p.getStatus().getPodIP(), target.getAdminPort())) + .collect(Collectors.toList()), + caRootCert, + overrideAuthority); + } +}