-
Notifications
You must be signed in to change notification settings - Fork 273
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement tls support for the app #6007
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
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<String, EnvVar> env) { | ||
|
||
addEnvVar(env, QUARKUS_HTTP_INSECURE_REQUESTS, Optional.ofNullable(primary.getSpec()) | ||
.map(ApicurioRegistry3Spec::getApp) | ||
.map(AppSpec::getTls) | ||
.map(TLSSpec::getInsecureRequests) | ||
.orElse("enabled")); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we use boolean for There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No, the possible values are enabled, disabled and redirect, so I don't think boolean makes sense here. |
||
|
||
var keystore = new SecretKeyRefTool(getTlsSpec(primary) | ||
.map(TLSSpec::getKeystoreSecretRef) | ||
.orElse(null), "user.p12"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe a constructor that takes Optional would be useful here. We've got this pattern elsewhere, e.g. in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't have a strong opinion, I was just following the pattern from KafkaSqlTLS. I'll let you decide if you want to do it in a separate PR. |
||
|
||
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); | ||
} | ||
Comment on lines
+45
to
+50
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. what if I will use just PEM cert as truststore? Like
wouldn't it cause failure? I would more expect that keystore password will be required There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. At the operator level we're supporting P12 (since it's usually a better practice than just specifying cert by cert). You will still be able to use PEM files using Quarkus own env vars. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I see, thanks. |
||
|
||
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<TLSSpec> getTlsSpec(ApicurioRegistry3 primary) { | ||
return ofNullable(primary) | ||
.map(ApicurioRegistry3::getSpec) | ||
.map(ApicurioRegistry3Spec::getApp) | ||
.map(AppSpec::getTls); | ||
} | ||
|
||
public static boolean insecureRequestsEnabled(TLSSpec tlsSpec) { | ||
return "enabled".equals(tlsSpec.getInsecureRequests()); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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,19 +57,35 @@ 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; | ||
var containerPort = List.of(new ContainerPortBuilder().withName("http").withProtocol("TCP").withContainerPort(8080).build()); | ||
|
||
Optional<TLSSpec> tlsSpec = ofNullable(primary.getSpec()) | ||
.map(ApicurioRegistry3Spec::getApp) | ||
.map(AppSpec::getTls); | ||
|
||
if (tlsSpec.isPresent()) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Assuming TLS is enabled only by the presence of the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. True, but, if it's misconfigured, the application won't even start, which, if you tried to configure TLS, might be even better than a "healthy" application and then having to look at the logs, wdyt? |
||
readinessProbe = TLS_DEFAULT_READINESS_PROBE; | ||
livenessProbe = TLS_DEFAULT_LIVENESS_PROBE; | ||
containerPort = List.of(new ContainerPortBuilder().withName("https").withProtocol("TCP").withContainerPort(8443).build()); | ||
} | ||
|
||
// Replicas | ||
mergeDeploymentPodTemplateSpec( | ||
COMPONENT_APP_SPEC_FIELD_NAME, | ||
primary, | ||
r.getSpec().getTemplate(), | ||
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(), | ||
containerPort, | ||
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); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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; | ||
|
@@ -87,6 +88,9 @@ protected Deployment desired(ApicurioRegistry3 primary, Context<ApicurioRegistry | |
// Configure the CORS_ALLOWED_ORIGINS env var based on the ingress host | ||
Cors.configureAllowedOrigins(primary, envVars); | ||
|
||
// Configure the TLS env vars | ||
TLS.configureTLS(primary, deployment, REGISTRY_APP_CONTAINER_NAME, envVars); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think TLS only makes sense for Registry container at the moment, so There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The same value is also used in line 114 in this class, so I think it makes more sense to import the constant (easier refactor later if needed). |
||
|
||
// Enable the "mutability" feature in Registry, but only if Studio is deployed. It is based on Service | ||
// in case a custom Ingress is used. | ||
var sOpt = context.getSecondaryResource(STUDIO_UI_SERVICE_KEY.getKlass(), | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a nit, but
*
is not much good practice form my pov (different projects, different standards) :)