diff --git a/operator/controller/src/main/java/io/apicurio/registry/operator/Constants.java b/operator/controller/src/main/java/io/apicurio/registry/operator/Constants.java index b94115433e..630ec0c182 100644 --- a/operator/controller/src/main/java/io/apicurio/registry/operator/Constants.java +++ b/operator/controller/src/main/java/io/apicurio/registry/operator/Constants.java @@ -36,6 +36,16 @@ public class Constants { .withInitialDelaySeconds(15).withTimeoutSeconds(5).withPeriodSeconds(10).withSuccessThreshold(1) .withFailureThreshold(3).build(); + public static final Probe TLS_DEFAULT_READINESS_PROBE = new ProbeBuilder().withNewHttpGet() + .withScheme("HTTPS").withPath("/health/ready").withNewPort().withValue(8443).endPort().endHttpGet() + .withInitialDelaySeconds(15).withTimeoutSeconds(5).withPeriodSeconds(10).withSuccessThreshold(1) + .withFailureThreshold(3).build(); + + public static final Probe TLS_DEFAULT_LIVENESS_PROBE = new ProbeBuilder().withNewHttpGet() + .withScheme("HTTPS").withPath("/health/live").withNewPort().withValue(8443).endPort().endHttpGet() + .withInitialDelaySeconds(15).withTimeoutSeconds(5).withPeriodSeconds(10).withSuccessThreshold(1) + .withFailureThreshold(3).build(); + public static final Map BASIC_LABELS = Map.of(MANAGED_BY_LABEL, MANAGED_BY_VALUE, LABEL_SELECTOR_KEY, LABEL_SELECTOR_VALUE); diff --git a/operator/controller/src/main/java/io/apicurio/registry/operator/EnvironmentVariables.java b/operator/controller/src/main/java/io/apicurio/registry/operator/EnvironmentVariables.java index 2496fbfe97..b98c620a42 100644 --- a/operator/controller/src/main/java/io/apicurio/registry/operator/EnvironmentVariables.java +++ b/operator/controller/src/main/java/io/apicurio/registry/operator/EnvironmentVariables.java @@ -6,10 +6,14 @@ public class EnvironmentVariables { public static final String QUARKUS_HTTP_ACCESS_LOG_ENABLED = "QUARKUS_HTTP_ACCESS_LOG_ENABLED"; public static final String QUARKUS_HTTP_CORS_ORIGINS = "QUARKUS_HTTP_CORS_ORIGINS"; + public static final String QUARKUS_HTTP_INSECURE_REQUESTS = "QUARKUS_HTTP_INSECURE_REQUESTS"; + public static final String QUARKUS_TLS_KEY_STORE_P12_PATH = "QUARKUS_TLS_KEY_STORE_P12_PATH"; + public static final String QUARKUS_TLS_KEY_STORE_P12_PASSWORD = "QUARKUS_TLS_KEY_STORE_P12_PASSWORD"; + public static final String QUARKUS_TLS_TRUST_STORE_P12_PATH = "QUARKUS_TLS_TRUST_STORE_P12_PATH"; + public static final String QUARKUS_TLS_TRUST_STORE_P12_PASSWORD = "QUARKUS_TLS_TRUST_STORE_P12_PASSWORD"; public static final String APICURIO_REST_DELETION_ARTIFACT_VERSION_ENABLED = "APICURIO_REST_DELETION_ARTIFACT-VERSION_ENABLED"; public static final String APICURIO_REST_DELETION_ARTIFACT_ENABLED = "APICURIO_REST_DELETION_ARTIFACT_ENABLED"; public static final String APICURIO_REST_DELETION_GROUP_ENABLED = "APICURIO_REST_DELETION_GROUP_ENABLED"; - public static final String APICURIO_REST_MUTABILITY_ARTIFACT_VERSION_CONTENT_ENABLED = "APICURIO_REST_MUTABILITY_ARTIFACT-VERSION-CONTENT_ENABLED"; private static final String KAFKA_PREFIX = "APICURIO_KAFKA_COMMON_"; @@ -29,8 +33,6 @@ public class EnvironmentVariables { public static final String APICURIO_UI_AUTH_OIDC_LOGOUT_URL = "APICURIO_UI_AUTH_OIDC_LOGOUT_URL"; public static final String APICURIO_REGISTRY_AUTH_SERVER_URL = "QUARKUS_OIDC_AUTH_SERVER_URL"; public static final String OIDC_TLS_VERIFICATION = "QUARKUS_OIDC_TLS_VERIFICATION"; - public static final String OIDC_TLS_TRUSTSTORE_LOCATION = "QUARKUS_OIDC_TLS_TRUST_STORE_FILE"; - public static final String OIDC_TLS_TRUSTSTORE_PASSWORD = "QUARKUS_OIDC_TLS_TRUST_STORE_PASSWORD"; public static final String APICURIO_AUTHN_BASIC_CLIENT_CREDENTIALS_ENABLED = "APICURIO_AUTHN_BASIC_CLIENT_CREDENTIALS_ENABLED"; public static final String APICURIO_AUTHN_BASIC_CLIENT_CREDENTIALS_CACHE_EXPIRATION = "APICURIO_AUTHN_BASIC_CLIENT_CREDENTIALS_CACHE_EXPIRATION"; diff --git a/operator/controller/src/main/java/io/apicurio/registry/operator/feat/TLS.java b/operator/controller/src/main/java/io/apicurio/registry/operator/feat/TLS.java new file mode 100644 index 0000000000..c6982bceb8 --- /dev/null +++ b/operator/controller/src/main/java/io/apicurio/registry/operator/feat/TLS.java @@ -0,0 +1,67 @@ +package io.apicurio.registry.operator.feat; + +import io.apicurio.registry.operator.api.v1.ApicurioRegistry3; +import io.apicurio.registry.operator.api.v1.ApicurioRegistry3Spec; +import io.apicurio.registry.operator.api.v1.spec.AppSpec; +import io.apicurio.registry.operator.api.v1.spec.TLSSpec; +import io.apicurio.registry.operator.utils.SecretKeyRefTool; +import io.fabric8.kubernetes.api.model.EnvVar; +import io.fabric8.kubernetes.api.model.apps.Deployment; + +import java.util.Map; +import java.util.Optional; + +import static io.apicurio.registry.operator.EnvironmentVariables.*; +import static io.apicurio.registry.operator.resource.app.AppDeploymentResource.addEnvVar; +import static java.util.Optional.ofNullable; + +public class TLS { + + public static void configureTLS(ApicurioRegistry3 primary, Deployment deployment, + String containerName, Map env) { + + addEnvVar(env, QUARKUS_HTTP_INSECURE_REQUESTS, Optional.ofNullable(primary.getSpec()) + .map(ApicurioRegistry3Spec::getApp) + .map(AppSpec::getTls) + .map(TLSSpec::getInsecureRequests) + .orElse("enabled")); + + var keystore = new SecretKeyRefTool(getTlsSpec(primary) + .map(TLSSpec::getKeystoreSecretRef) + .orElse(null), "user.p12"); + + var keystorePassword = new SecretKeyRefTool(getTlsSpec(primary) + .map(TLSSpec::getKeystorePasswordSecretRef) + .orElse(null), "user.password"); + + var truststore = new SecretKeyRefTool(getTlsSpec(primary) + .map(TLSSpec::getTruststoreSecretRef) + .orElse(null), "ca.p12"); + + var truststorePassword = new SecretKeyRefTool(getTlsSpec(primary) + .map(TLSSpec::getTruststorePasswordSecretRef) + .orElse(null), "ca.password"); + + if (truststore.isValid() && truststorePassword.isValid()) { + // ===== Truststore + truststore.applySecretVolume(deployment, containerName); + addEnvVar(env, QUARKUS_TLS_TRUST_STORE_P12_PATH, truststore.getSecretVolumeKeyPath()); + truststorePassword.applySecretEnvVar(env, QUARKUS_TLS_TRUST_STORE_P12_PASSWORD); + } + + if (keystore.isValid() + && keystorePassword.isValid()) { + // ===== Keystore + keystore.applySecretVolume(deployment, containerName); + addEnvVar(env, QUARKUS_TLS_KEY_STORE_P12_PATH, keystore.getSecretVolumeKeyPath()); + keystorePassword.applySecretEnvVar(env, QUARKUS_TLS_KEY_STORE_P12_PASSWORD); + } + } + + private static Optional getTlsSpec(ApicurioRegistry3 primary) { + return ofNullable(primary) + .map(ApicurioRegistry3::getSpec) + .map(ApicurioRegistry3Spec::getApp) + .map(AppSpec::getTls); + } +} diff --git a/operator/controller/src/main/java/io/apicurio/registry/operator/feat/security/Auth.java b/operator/controller/src/main/java/io/apicurio/registry/operator/feat/security/Auth.java index c57a993a2d..473a4a2f27 100644 --- a/operator/controller/src/main/java/io/apicurio/registry/operator/feat/security/Auth.java +++ b/operator/controller/src/main/java/io/apicurio/registry/operator/feat/security/Auth.java @@ -3,7 +3,6 @@ import io.apicurio.registry.operator.EnvironmentVariables; import io.apicurio.registry.operator.api.v1.spec.auth.AuthSpec; import io.fabric8.kubernetes.api.model.EnvVar; -import io.fabric8.kubernetes.api.model.apps.Deployment; import java.util.Map; import java.util.Optional; @@ -20,11 +19,10 @@ public class Auth { * Configures authentication-related environment variables for the Apicurio Registry. * * @param env The map of environment variables to be configured. - * @param deployment The application deployment to configure TLS. * @param authSpec The authentication specification containing required auth settings. If null, no changes * will be made to envVars. */ - public static void configureAuth(AuthSpec authSpec, Deployment deployment, Map env) { + public static void configureAuth(AuthSpec authSpec, Map env) { if (authSpec == null) { return; } @@ -53,7 +51,9 @@ public static void configureAuth(AuthSpec authSpec, Deployment deployment, Map env) { - - putIfNotBlank(env, EnvironmentVariables.OIDC_TLS_VERIFICATION, - authSpec.getTls().getTlsVerificationType()); - - // spotless:off - var truststore = new SecretKeyRefTool(getAuthTLSSpec(authSpec) - .map(AuthTLSSpec::getTruststoreSecretRef) - .orElse(null), "ca.p12"); - - var truststorePassword = new SecretKeyRefTool(getAuthTLSSpec(authSpec) - .map(AuthTLSSpec::getTruststorePasswordSecretRef) - .orElse(null), "ca.password"); - // spotless:on - if (truststore.isValid() && truststorePassword.isValid()) { - truststore.applySecretVolume(deployment, REGISTRY_APP_CONTAINER_NAME); - addEnvVar(env, OIDC_TLS_TRUSTSTORE_LOCATION, truststore.getSecretVolumeKeyPath()); - truststorePassword.applySecretEnvVar(env, OIDC_TLS_TRUSTSTORE_PASSWORD); - } - } - - private static Optional getAuthTLSSpec(AuthSpec primary) { - // spotless:off - return ofNullable(primary) - .map(AuthSpec::getTls); - // spotless:on - } -} diff --git a/operator/controller/src/main/java/io/apicurio/registry/operator/resource/ResourceFactory.java b/operator/controller/src/main/java/io/apicurio/registry/operator/resource/ResourceFactory.java index 7aba6f7614..4b53cbc1c1 100644 --- a/operator/controller/src/main/java/io/apicurio/registry/operator/resource/ResourceFactory.java +++ b/operator/controller/src/main/java/io/apicurio/registry/operator/resource/ResourceFactory.java @@ -7,6 +7,7 @@ import io.apicurio.registry.operator.api.v1.ApicurioRegistry3Spec; import io.apicurio.registry.operator.api.v1.spec.AppSpec; import io.apicurio.registry.operator.api.v1.spec.StudioUiSpec; +import io.apicurio.registry.operator.api.v1.spec.TLSSpec; import io.apicurio.registry.operator.api.v1.spec.UiSpec; import io.apicurio.registry.operator.status.ValidationErrorConditionManager; import io.apicurio.registry.operator.status.StatusManager; @@ -23,7 +24,7 @@ import java.util.Map; import java.util.Optional; -import static io.apicurio.registry.operator.Constants.DEFAULT_REPLICAS; +import static io.apicurio.registry.operator.Constants.*; import static io.apicurio.registry.operator.api.v1.ContainerNames.*; import static io.apicurio.registry.operator.resource.Labels.getSelectorLabels; import static io.apicurio.registry.operator.resource.app.AppDeploymentResource.getContainerFromPodTemplateSpec; @@ -56,6 +57,19 @@ public Deployment getDefaultAppDeployment(ApicurioRegistry3 primary) { .map(AppSpec::getReplicas).orElse(DEFAULT_REPLICAS), ofNullable(primary.getSpec()).map(ApicurioRegistry3Spec::getApp) .map(AppSpec::getPodTemplateSpec).orElse(null)); // TODO: + + var readinessProbe = DEFAULT_READINESS_PROBE; + var livenessProbe = DEFAULT_LIVENESS_PROBE; + + Optional tlsSpec = ofNullable(primary.getSpec()) + .map(ApicurioRegistry3Spec::getApp) + .map(AppSpec::getTls); + + if (tlsSpec.isPresent()) { + readinessProbe = TLS_DEFAULT_READINESS_PROBE; + livenessProbe = TLS_DEFAULT_LIVENESS_PROBE; + } + // Replicas mergeDeploymentPodTemplateSpec( COMPONENT_APP_SPEC_FIELD_NAME, @@ -64,11 +78,12 @@ public Deployment getDefaultAppDeployment(ApicurioRegistry3 primary) { REGISTRY_APP_CONTAINER_NAME, Configuration.getAppImage(), List.of(new ContainerPortBuilder().withName("http").withProtocol("TCP").withContainerPort(8080).build()), - new ProbeBuilder().withHttpGet(new HTTPGetActionBuilder().withPath("/health/ready").withPort(new IntOrString(8080)).withScheme("HTTP").build()).build(), - new ProbeBuilder().withHttpGet(new HTTPGetActionBuilder().withPath("/health/live").withPort(new IntOrString(8080)).withScheme("HTTP").build()).build(), + readinessProbe, + livenessProbe, Map.of("cpu", new Quantity("500m"), "memory", new Quantity("512Mi")), Map.of("cpu", new Quantity("1"), "memory", new Quantity("1Gi")) ); + addDefaultLabels(r.getMetadata().getLabels(), primary, COMPONENT_APP); addSelectorLabels(r.getSpec().getSelector().getMatchLabels(), primary, COMPONENT_APP); addDefaultLabels(r.getSpec().getTemplate().getMetadata().getLabels(), primary, COMPONENT_APP); diff --git a/operator/controller/src/main/java/io/apicurio/registry/operator/resource/app/AppDeploymentResource.java b/operator/controller/src/main/java/io/apicurio/registry/operator/resource/app/AppDeploymentResource.java index 888213ff0e..eade75c5cd 100644 --- a/operator/controller/src/main/java/io/apicurio/registry/operator/resource/app/AppDeploymentResource.java +++ b/operator/controller/src/main/java/io/apicurio/registry/operator/resource/app/AppDeploymentResource.java @@ -11,6 +11,7 @@ import io.apicurio.registry.operator.feat.Cors; import io.apicurio.registry.operator.feat.KafkaSql; import io.apicurio.registry.operator.feat.PostgresSql; +import io.apicurio.registry.operator.feat.TLS; import io.apicurio.registry.operator.feat.security.Auth; import io.apicurio.registry.operator.status.ReadyConditionManager; import io.apicurio.registry.operator.status.StatusManager; @@ -81,12 +82,15 @@ protected Deployment desired(ApicurioRegistry3 primary, Context context) { var networkPolicy = APP_NETWORK_POLICY_KEY.getFactory().apply(primary); + + Optional.ofNullable(primary.getSpec()) + .map(ApicurioRegistry3Spec::getApp) + .map(AppSpec::getTls) + .ifPresent(tls -> { + + var httpsPolicy = new io.fabric8.kubernetes.api.model.networking.v1.NetworkPolicyPortBuilder() + .withPort(new IntOrStringBuilder().withValue(8443).build()).build(); + + var httpPolicy = new io.fabric8.kubernetes.api.model.networking.v1.NetworkPolicyPortBuilder() + .withPort(new IntOrStringBuilder().withValue(8080).build()).build(); + + if (tls.getInsecureRequests() != null && !tls.getInsecureRequests().equals("enabled")) { + networkPolicy.getSpec().setIngress(List.of(new NetworkPolicyIngressRuleBuilder() + .withPorts(httpsPolicy) + .build())); + } + else { + networkPolicy.getSpec().setIngress(List.of(new NetworkPolicyIngressRuleBuilder() + .withPorts(httpsPolicy, httpPolicy) + .build())); + } + }); + log.trace("Desired {} is {}", APP_NETWORK_POLICY_KEY.getId(), toYAML(networkPolicy)); return networkPolicy; } diff --git a/operator/controller/src/main/java/io/apicurio/registry/operator/resource/app/AppServiceResource.java b/operator/controller/src/main/java/io/apicurio/registry/operator/resource/app/AppServiceResource.java index 09b103bf08..2b1d86d866 100644 --- a/operator/controller/src/main/java/io/apicurio/registry/operator/resource/app/AppServiceResource.java +++ b/operator/controller/src/main/java/io/apicurio/registry/operator/resource/app/AppServiceResource.java @@ -1,13 +1,20 @@ package io.apicurio.registry.operator.resource.app; import io.apicurio.registry.operator.api.v1.ApicurioRegistry3; +import io.apicurio.registry.operator.api.v1.ApicurioRegistry3Spec; +import io.apicurio.registry.operator.api.v1.spec.AppSpec; +import io.fabric8.kubernetes.api.model.IntOrStringBuilder; import io.fabric8.kubernetes.api.model.Service; +import io.fabric8.kubernetes.api.model.ServicePortBuilder; import io.javaoperatorsdk.operator.api.reconciler.Context; import io.javaoperatorsdk.operator.processing.dependent.kubernetes.CRUDKubernetesDependentResource; import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependent; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.List; +import java.util.Optional; + import static io.apicurio.registry.operator.resource.LabelDiscriminators.AppServiceDiscriminator; import static io.apicurio.registry.operator.resource.ResourceKey.APP_SERVICE_KEY; import static io.apicurio.registry.operator.utils.Mapper.toYAML; @@ -24,6 +31,31 @@ public AppServiceResource() { @Override protected Service desired(ApicurioRegistry3 primary, Context context) { var s = APP_SERVICE_KEY.getFactory().apply(primary); + + Optional.ofNullable(primary.getSpec()) + .map(ApicurioRegistry3Spec::getApp) + .map(AppSpec::getTls) + .ifPresent(tls -> { + var httpPort = new ServicePortBuilder() + .withName("http") + .withPort(8080) + .withTargetPort(new IntOrStringBuilder().withValue(8080).build()) + .build(); + + var httpsPort = new ServicePortBuilder() + .withName("https") + .withPort(443) + .withTargetPort(new IntOrStringBuilder().withValue(8443).build()) + .build(); + + if (tls.getInsecureRequests() != null && tls.getInsecureRequests().equals("enabled")) { + s.getSpec().setPorts(List.of(httpsPort, httpPort)); + } + else { + s.getSpec().setPorts(List.of(httpsPort)); + } + }); + log.trace("Desired {} is {}", APP_SERVICE_KEY.getId(), toYAML(s)); return s; } diff --git a/operator/controller/src/test/java/io/apicurio/registry/operator/it/TlsITTest.java b/operator/controller/src/test/java/io/apicurio/registry/operator/it/TlsITTest.java new file mode 100644 index 0000000000..b867402d02 --- /dev/null +++ b/operator/controller/src/test/java/io/apicurio/registry/operator/it/TlsITTest.java @@ -0,0 +1,162 @@ +package io.apicurio.registry.operator.it; + +import io.apicurio.registry.operator.EnvironmentVariables; +import io.apicurio.registry.operator.api.v1.ApicurioRegistry3; +import io.apicurio.registry.operator.resource.ResourceFactory; +import io.fabric8.kubernetes.api.model.HasMetadata; +import io.fabric8.kubernetes.api.model.networking.v1.NetworkPolicyIngressRule; +import io.fabric8.kubernetes.client.utils.Serialization; +import io.quarkus.test.junit.QuarkusTest; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static io.apicurio.registry.operator.api.v1.ContainerNames.REGISTRY_APP_CONTAINER_NAME; +import static io.apicurio.registry.operator.resource.app.AppDeploymentResource.getContainerFromDeployment; +import static org.assertj.core.api.Assertions.assertThat; +import static org.awaitility.Awaitility.await; + +@QuarkusTest +public class TlsITTest extends ITBase { + + @BeforeAll + public static void setup() { + List resources = Serialization + .unmarshal(AuthITTest.class.getResourceAsStream("/k8s/examples/tls/secrets.yaml")); + + createResources(resources, "tls-secrets"); + } + + /** + * In this test, the server uses a Keystore in PCKS format that identifies itself to the client. + */ + @Test + void testTLS() { + var registry = ResourceFactory.deserialize("/k8s/examples/tls/simple-with_tls.apicurioregistry3.yaml", + ApicurioRegistry3.class); + registry.getMetadata().setNamespace(namespace); + registry.getSpec().getApp().getIngress().setHost(ingressManager.getIngressHost("app")); + registry.getSpec().getUi().getIngress().setHost(ingressManager.getIngressHost("ui")); + + client.resource(registry).create(); + + // Deployments + await().ignoreExceptions().until(() -> { + assertThat(client.apps().deployments().inNamespace(namespace) + .withName(registry.getMetadata().getName() + "-app-deployment").get().getStatus() + .getReadyReplicas()).isEqualTo(1); + assertThat(client.apps().deployments().inNamespace(namespace) + .withName(registry.getMetadata().getName() + "-ui-deployment").get().getStatus() + .getReadyReplicas()).isEqualTo(1); + + var appEnv = getContainerFromDeployment( + client.apps().deployments().inNamespace(namespace) + .withName(registry.getMetadata().getName() + "-app-deployment").get(), + REGISTRY_APP_CONTAINER_NAME).getEnv(); + + assertThat(appEnv).map(ev -> ev.getName() + "=" + ev.getValue()) + .contains(EnvironmentVariables.QUARKUS_HTTP_INSECURE_REQUESTS + "=" + "disabled"); + + return true; + }); + + // Services + await().ignoreExceptions().until(() -> { + + var service = client.services().inNamespace(namespace) + .withName(registry.getMetadata().getName() + "-app-service").get().getSpec(); + + assertThat(service.getClusterIP()).isNotBlank(); + assertThat(service.getPorts().get(0).getPort()).isEqualTo(443); + assertThat(service.getClusterIP()).isNotBlank(); + return true; + }); + + // Ingresses + await().ignoreExceptions().until(() -> { + assertThat(client.network().v1().ingresses().inNamespace(namespace) + .withName(registry.getMetadata().getName() + "-app-ingress").get().getSpec().getRules() + .get(0).getHost()).isEqualTo(registry.getSpec().getApp().getIngress().getHost()); + assertThat(client.network().v1().ingresses().inNamespace(namespace) + .withName(registry.getMetadata().getName() + "-ui-ingress").get().getSpec().getRules() + .get(0).getHost()).isEqualTo(registry.getSpec().getUi().getIngress().getHost()); + return true; + }); + + // Network Policy + await().ignoreExceptions().until(() -> { + assertThat(client.network().v1().networkPolicies().inNamespace(namespace) + .withName("simple-app-networkpolicy").get().getSpec().getIngress() + .get(0).getPorts().get(0).getPort().getIntVal()).isEqualTo(8443); + return true; + }); + } + + /** + * In this test, the server uses a Keystore in PCKS format that identifies itself to the client. + */ + @Test + void testTLSInsecureTrafficEnabled() { + var registry = ResourceFactory.deserialize("/k8s/examples/tls/insecure-traffic-with_tls.apicurioregistry3.yaml", + ApicurioRegistry3.class); + registry.getMetadata().setNamespace(namespace); + registry.getSpec().getApp().getIngress().setHost(ingressManager.getIngressHost("app")); + registry.getSpec().getUi().getIngress().setHost(ingressManager.getIngressHost("ui")); + + client.resource(registry).create(); + + // Deployments + await().ignoreExceptions().until(() -> { + assertThat(client.apps().deployments().inNamespace(namespace) + .withName(registry.getMetadata().getName() + "-app-deployment").get().getStatus() + .getReadyReplicas()).isEqualTo(1); + assertThat(client.apps().deployments().inNamespace(namespace) + .withName(registry.getMetadata().getName() + "-ui-deployment").get().getStatus() + .getReadyReplicas()).isEqualTo(1); + + var appEnv = getContainerFromDeployment( + client.apps().deployments().inNamespace(namespace) + .withName(registry.getMetadata().getName() + "-app-deployment").get(), + REGISTRY_APP_CONTAINER_NAME).getEnv(); + + assertThat(appEnv).map(ev -> ev.getName() + "=" + ev.getValue()) + .contains(EnvironmentVariables.QUARKUS_HTTP_INSECURE_REQUESTS + "=" + "enabled"); + + return true; + }); + + // Services + await().ignoreExceptions().until(() -> { + var service = client.services().inNamespace(namespace) + .withName(registry.getMetadata().getName() + "-app-service").get().getSpec(); + + assertThat(service.getClusterIP()).isNotBlank(); + assertThat(service.getPorts().get(0).getPort()).isEqualTo(443); + assertThat(service.getPorts().get(1).getPort()).isEqualTo(8080); + assertThat(service.getClusterIP()).isNotBlank(); + return true; + }); + + // Ingresses + await().ignoreExceptions().until(() -> { + assertThat(client.network().v1().ingresses().inNamespace(namespace) + .withName(registry.getMetadata().getName() + "-app-ingress").get().getSpec().getRules() + .get(0).getHost()).isEqualTo(registry.getSpec().getApp().getIngress().getHost()); + assertThat(client.network().v1().ingresses().inNamespace(namespace) + .withName(registry.getMetadata().getName() + "-ui-ingress").get().getSpec().getRules() + .get(0).getHost()).isEqualTo(registry.getSpec().getUi().getIngress().getHost()); + return true; + }); + + // Network Policy + await().ignoreExceptions().until(() -> { + NetworkPolicyIngressRule networkPolicyIngressRule = client.network().v1().networkPolicies().inNamespace(namespace) + .withName("simple-app-networkpolicy").get().getSpec().getIngress() + .get(0); + assertThat(networkPolicyIngressRule.getPorts().get(0).getPort().getIntVal()).isEqualTo(8443); + assertThat(networkPolicyIngressRule.getPorts().get(1).getPort().getIntVal()).isEqualTo(8080); + return true; + }); + } +} diff --git a/operator/controller/src/test/resources/k8s/examples/auth/authz-with_keycloak.apicurioregistry3.yaml b/operator/controller/src/test/resources/k8s/examples/auth/authz-with_keycloak.apicurioregistry3.yaml index 9c4313a96c..43dc8d91aa 100644 --- a/operator/controller/src/test/resources/k8s/examples/auth/authz-with_keycloak.apicurioregistry3.yaml +++ b/operator/controller/src/test/resources/k8s/examples/auth/authz-with_keycloak.apicurioregistry3.yaml @@ -6,6 +6,13 @@ spec: app: ingress: host: simple-app.apps.cluster.example + tls: + truststoreSecretRef: + name: keycloak-truststore + key: truststore + truststorePasswordSecretRef: + name: keycloak-truststore + key: password auth: enabled: true appClientId: registry-api @@ -29,14 +36,7 @@ spec: role: admin claimName: test claimValue: test - tls: - tlsVerificationType: required - truststoreSecretRef: - name: keycloak-truststore - key: truststore - truststorePasswordSecretRef: - name: keycloak-truststore - key: password + tlsVerificationType: required ui: ingress: host: simple-ui.apps.cluster.example diff --git a/operator/controller/src/test/resources/k8s/examples/auth/simple-with_keycloak.apicurioregistry3.yaml b/operator/controller/src/test/resources/k8s/examples/auth/simple-with_keycloak.apicurioregistry3.yaml index 81a2d74418..7e1b5c4bf0 100644 --- a/operator/controller/src/test/resources/k8s/examples/auth/simple-with_keycloak.apicurioregistry3.yaml +++ b/operator/controller/src/test/resources/k8s/examples/auth/simple-with_keycloak.apicurioregistry3.yaml @@ -17,8 +17,7 @@ spec: basicAuth: enabled: true cacheExpiration: 25 - tls: - tlsVerificationType: none + tlsVerificationType: none ui: ingress: host: simple-ui.apps.cluster.example diff --git a/operator/controller/src/test/resources/k8s/examples/auth/tls/simple-with_keycloak.apicurioregistry3.yaml b/operator/controller/src/test/resources/k8s/examples/auth/tls/simple-with_keycloak.apicurioregistry3.yaml index fc5a4b0d9c..b712a3f532 100644 --- a/operator/controller/src/test/resources/k8s/examples/auth/tls/simple-with_keycloak.apicurioregistry3.yaml +++ b/operator/controller/src/test/resources/k8s/examples/auth/tls/simple-with_keycloak.apicurioregistry3.yaml @@ -6,6 +6,13 @@ spec: app: ingress: host: simple-app.apps.cluster.example + tls: + truststoreSecretRef: + name: keycloak-truststore + key: truststore + truststorePasswordSecretRef: + name: keycloak-truststore + key: password auth: enabled: true appClientId: registry-api @@ -13,14 +20,7 @@ spec: authServerUrl: https://simple-keycloak.apps.cluster.example/realms/registry redirectURI: https://simple-ui.apps.cluster.example logoutURL: https://simple-ui.apps.cluster.example - tls: - tlsVerificationType: required - truststoreSecretRef: - name: keycloak-truststore - key: truststore - truststorePasswordSecretRef: - name: keycloak-truststore - key: password + tlsVerificationType: required ui: ingress: host: simple-ui.apps.cluster.example diff --git a/operator/controller/src/test/resources/k8s/examples/tls/insecure-traffic-with_tls.apicurioregistry3.yaml b/operator/controller/src/test/resources/k8s/examples/tls/insecure-traffic-with_tls.apicurioregistry3.yaml new file mode 100644 index 0000000000..8ab05044dd --- /dev/null +++ b/operator/controller/src/test/resources/k8s/examples/tls/insecure-traffic-with_tls.apicurioregistry3.yaml @@ -0,0 +1,29 @@ +apiVersion: registry.apicur.io/v1 +kind: ApicurioRegistry3 +metadata: + name: simple +spec: + app: + env: + ingress: + host: simple-app.apps.cluster.example + tls: + insecureRequests: enabled + truststoreSecretRef: + name: truststore + key: truststore + truststorePasswordSecretRef: + name: truststore + key: password + keystoreSecretRef: + name: keystore + key: keystore + keystorePasswordSecretRef: + name: keystore + key: password + ui: + ingress: + host: simple-ui.apps.cluster.example + env: + - name: REGISTRY_API_URL + value: https://simple-app.apps.cluster.example/apis/registry/v3 diff --git a/operator/controller/src/test/resources/k8s/examples/tls/secrets.yaml b/operator/controller/src/test/resources/k8s/examples/tls/secrets.yaml new file mode 100644 index 0000000000..c2d96f4704 --- /dev/null +++ b/operator/controller/src/test/resources/k8s/examples/tls/secrets.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Secret +metadata: + name: truststore +data: + truststore: MIIFcgIBAzCCBRwGCSqGSIb3DQEHAaCCBQ0EggUJMIIFBTCCBQEGCSqGSIb3DQEHBqCCBPIwggTuAgEAMIIE5wYJKoZIhvcNAQcBMGYGCSqGSIb3DQEFDTBZMDgGCSqGSIb3DQEFDDArBBSlyEcqpo4m0AQA/+hur/q8btwLwQICJxACASAwDAYIKoZIhvcNAgkFADAdBglghkgBZQMEASoEEPSOQmxOp8AnVrNnXSGB0JeAggRwtGXgtgCdCMjH69rDh8Uwt0KG3++xVD/E+2Vi25fMZnfS3/f8xdis33Tfe4l2BVLN57r2/9nxb1pGGYMwMGndlYo27ulDvkQ2TsSABqtoIsfIyxJX/rT8sfLcQ0Yx3wDISJN2ofEXdRZXnHKZdNhLtsiC9tqITVL1tSpe8/uJLrIpuR9Rlc8msrhRHU+5S7irAgMMsEiaT/8UvDR4ABARmd649uSpI0rYu2sHA/MIc0MzMpR4fpgbdDWR88bHyG21KE5G86X3mqtFAxZ6v86m1L39YI/T5iTbLhUiWdUAOoeLvMbBz8MFToh8OoH07Xfy6HPojm8c5AKNajfaElQpW7XeeRo1tT2jS+FN7Wl3Wa6Um9XFpsYUpETQ3CgZF6H57H96tw/MvKAWgVPAbFbe4kQG4jlsDrTfnP0mIVP+fQKdMVJZWBAj9QryoABNmMZZreHrb9hHJ6sE+FU0NEC1o0fI/MfFycDGvJaOvqKYsUQ3/EiOcaLY9mCxHQRrAoWpo2gMmAzeZznrmkFiH5n44cq6bElmi23KLbuNFsz6Dy3V4idIPx5QYdNe/KNElBIEH3lq10Ih6XC87MIBAJg6K9rsO6MkeAsTrF77HXom5gYEW6sMzfB1fUWZdUWFaPJS089CMYlfaFdFv2CnqDpyG7kcuxdwCirw4l1uqB+Tz8xZhPYKL/Y+r6nl6k8oU9CAPoXGEEa+5mjPIJtStowTh4fvyGVuKJb1rXb+DzEM3l/PxZbEb9Ah0nVzttzrzt/EV9hHJzidAGxj1xaUWWEXFRBZ57c1nn24YFPuZZP2DisXf34vwJbGrs2x5Q/Y7V3gC4N0nC6HavTuVoYVLE5DfqKd6kIAkAspan7jmaczxSGQAh0Fh2sTveIJB6t5ODGXffEJ+1jSo4UqPUZoK643uOQEAPdKa9jDZTZUqUqYjjdmTMdllfc9R40djhIO7LsmR/O/R3ExDy+9rKKyhhZf3JC0AQVwoWwp2W78vCY3RO9VebPFofeHq9CrFaDpzjr5lQ3XYgJUGS4qTixukx+Y9n9HphKUn3SDzH5W+PdM7pMK9nIlAFtvoaxJP4MJLr0nlbrtIjPMpwDYKWreF2fbPGWdev9CHiQuVy9bpT5NUJ3IONJZBZ9pgs5FfMLYSFIAJahPPbqSo4KskGF6CzXpSboej8qFrIL48tPT4LQNNUk4zx0M/03Cc7AzcqJGe2Sbmyk8l4LMsnxg/aLPrDSRtmoR/e+bfz0Qr6WHol5Ptc7YaNfhktVcHYxM3OfBX9PS9/4Cqt8yOPVnbCwnTwzcHqwCxGr2nTPALFC8G2n01Sxzhuv+hRG0x3IticrBuC5DWgHNCfGVRRGI3tPhn2B41lkwKnkyl+UKff53KtyOtpmOZGZR7noERt6gAwvILQ1vk/a7kYMM6mGn0Vevvim0l4/FS2abLYiAZsEVxQ4Crpt4vp+WfR+jc0DykozMIS96FYwLn8bBmV12Md9OuzHRkFNTDtNIPYatE67piLQmH64wTTAxMA0GCWCGSAFlAwQCAQUABCDKrSt4bELwoaGUTpgJ2SkDgrekm+u3J/HhS53chWqycgQUh27kRpNBYLFcje1G0ADnHLWlBZkCAicQ + password: YXBpY3VyaW8= +--- +apiVersion: v1 +kind: Secret +metadata: + name: keystore +data: + keystore: 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 + password: YXBpY3VyaW8= \ No newline at end of file diff --git a/operator/controller/src/test/resources/k8s/examples/tls/simple-with_tls.apicurioregistry3.yaml b/operator/controller/src/test/resources/k8s/examples/tls/simple-with_tls.apicurioregistry3.yaml new file mode 100644 index 0000000000..060b2bdf69 --- /dev/null +++ b/operator/controller/src/test/resources/k8s/examples/tls/simple-with_tls.apicurioregistry3.yaml @@ -0,0 +1,29 @@ +apiVersion: registry.apicur.io/v1 +kind: ApicurioRegistry3 +metadata: + name: simple +spec: + app: + env: + ingress: + host: simple-app.apps.cluster.example + tls: + insecureRequests: disabled + truststoreSecretRef: + name: truststore + key: truststore + truststorePasswordSecretRef: + name: truststore + key: password + keystoreSecretRef: + name: keystore + key: keystore + keystorePasswordSecretRef: + name: keystore + key: password + ui: + ingress: + host: simple-ui.apps.cluster.example + env: + - name: REGISTRY_API_URL + value: https://simple-app.apps.cluster.example/apis/registry/v3 diff --git a/operator/model/src/main/java/io/apicurio/registry/operator/api/v1/spec/AppSpec.java b/operator/model/src/main/java/io/apicurio/registry/operator/api/v1/spec/AppSpec.java index d98e1a0565..0691202da2 100644 --- a/operator/model/src/main/java/io/apicurio/registry/operator/api/v1/spec/AppSpec.java +++ b/operator/model/src/main/java/io/apicurio/registry/operator/api/v1/spec/AppSpec.java @@ -13,7 +13,7 @@ @JsonDeserialize(using = None.class) @JsonInclude(NON_NULL) -@JsonPropertyOrder({ "env", "ingress", "podTemplateSpec", "storage", "sql", "kafkasql", "features", "auth" }) +@JsonPropertyOrder({ "env", "ingress", "podTemplateSpec", "storage", "sql", "kafkasql", "features", "auth", "tls" }) @NoArgsConstructor @AllArgsConstructor(access = PRIVATE) @SuperBuilder(toBuilder = true) @@ -53,6 +53,16 @@ Configure features of the Apicurio Registry backend (app). @JsonSetter(nulls = SKIP) private AuthSpec auth; + /** + * Configure features of the Apicurio Registry application. + */ + @JsonProperty("tls") + @JsonPropertyDescription(""" + Configure tls of Apicurio Registry. + """) + @JsonSetter(nulls = SKIP) + private TLSSpec tls; + /** * DEPRECATED: Use the `app.storage.type` and `app.storage.sql` fields instead. The operator will attempt * to update the fields automatically. diff --git a/operator/model/src/main/java/io/apicurio/registry/operator/api/v1/spec/auth/AuthTLSSpec.java b/operator/model/src/main/java/io/apicurio/registry/operator/api/v1/spec/TLSSpec.java similarity index 53% rename from operator/model/src/main/java/io/apicurio/registry/operator/api/v1/spec/auth/AuthTLSSpec.java rename to operator/model/src/main/java/io/apicurio/registry/operator/api/v1/spec/TLSSpec.java index 4a21d864c1..bbbdb27a9f 100644 --- a/operator/model/src/main/java/io/apicurio/registry/operator/api/v1/spec/auth/AuthTLSSpec.java +++ b/operator/model/src/main/java/io/apicurio/registry/operator/api/v1/spec/TLSSpec.java @@ -1,10 +1,9 @@ -package io.apicurio.registry.operator.api.v1.spec.auth; +package io.apicurio.registry.operator.api.v1.spec; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.databind.JsonDeserializer.None; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; -import io.apicurio.registry.operator.api.v1.spec.SecretKeyRef; import lombok.*; import lombok.experimental.SuperBuilder; @@ -12,7 +11,7 @@ @JsonDeserialize(using = None.class) @JsonInclude(Include.NON_NULL) -@JsonPropertyOrder({ "tlsVerificationType", "truststoreSecretRef", "truststorePasswordSecretRef" }) +@JsonPropertyOrder({ "insecureRequests", "truststoreSecretRef", "truststorePasswordSecretRef", "keystoreSecretRef", "keystorePasswordSecretRef" }) @NoArgsConstructor @AllArgsConstructor(access = PRIVATE) @SuperBuilder(toBuilder = true) @@ -20,16 +19,16 @@ @Setter @EqualsAndHashCode @ToString -public class AuthTLSSpec { +public class TLSSpec { /** - * Type of TLS verification. + * Whether insecure requests are allowed. Default is enabled. */ - @JsonProperty("tlsVerificationType") + @JsonProperty("insecureRequests") @JsonPropertyDescription(""" - Verify the identity server certificate.""") + Whether insecure requests are allowed. Default is enabled.""") @JsonSetter(nulls = Nulls.SKIP) - private String tlsVerificationType; + private String insecureRequests; /** * Name of a Secret that contains the TLS truststore (in PKCS12 format). Key ca.p12 is @@ -52,4 +51,26 @@ Name of a Secret that contains the TLS truststore (in PKCS12 format). \ Key `ca.password` is assumed by default.""") @JsonSetter(nulls = Nulls.SKIP) private SecretKeyRef truststorePasswordSecretRef; + + /** + * Name of a Secret that contains the TLS keystore (in PKCS12 format). Key ca.p12 is + * assumed by default. + */ + @JsonProperty("keystoreSecretRef") + @JsonPropertyDescription(""" + Name of a Secret that contains the TLS keystore (in PKCS12 format). \ + Key `ca.p12` is assumed by default.""") + @JsonSetter(nulls = Nulls.SKIP) + private SecretKeyRef keystoreSecretRef; + + /** + * Name of a Secret that contains the TLS keystore password. Key ca.password is assumed by + * default. + */ + @JsonProperty("keystorePasswordSecretRef") + @JsonPropertyDescription(""" + Name of a Secret that contains the TLS keystore password. \ + Key `ca.password` is assumed by default.""") + @JsonSetter(nulls = Nulls.SKIP) + private SecretKeyRef keystorePasswordSecretRef; } diff --git a/operator/model/src/main/java/io/apicurio/registry/operator/api/v1/spec/auth/AuthSpec.java b/operator/model/src/main/java/io/apicurio/registry/operator/api/v1/spec/auth/AuthSpec.java index 5e16f6b07e..fc4912c28d 100644 --- a/operator/model/src/main/java/io/apicurio/registry/operator/api/v1/spec/auth/AuthSpec.java +++ b/operator/model/src/main/java/io/apicurio/registry/operator/api/v1/spec/auth/AuthSpec.java @@ -22,7 +22,7 @@ @JsonDeserialize(using = JsonDeserializer.None.class) @JsonInclude(NON_NULL) @JsonPropertyOrder({ "enabled", "appClientId", "uiClientId", "redirectURI", "authServerUrl", "logoutURL", - "anonymousReads", "basicAuth", "tls", "authz" }) + "anonymousReads", "basicAuth", "tlsVerificationType", "authz" }) @NoArgsConstructor @AllArgsConstructor(access = PRIVATE) @SuperBuilder(toBuilder = true) @@ -83,12 +83,14 @@ public class AuthSpec { @JsonSetter(nulls = Nulls.SKIP) private BasicAuthSpec basicAuth; - @JsonProperty("tls") + /** + * Type of TLS verification for authentication. + */ + @JsonProperty("tlsVerificationType") @JsonPropertyDescription(""" - OIDC TLS configuration. - When custom certificates are used, this is the field to be used to configure the trustore""") + Verify the identity server certificate.""") @JsonSetter(nulls = Nulls.SKIP) - private AuthTLSSpec tls; + private String tlsVerificationType; @JsonProperty("authz") @JsonPropertyDescription("""