Skip to content
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

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

carlesarnal
Copy link
Member

No description provided.

Comment on lines +45 to +50
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);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what if I will use just PEM cert as truststore? Like

kind: ApicurioRegistry3
apiVersion: registry.apicur.io/v1
metadata:
  name: schema-registry
spec:
  app:
    storage:
      type: "kafkasql"
      kafkasql:
        bootstrapServers: anubis-kafka-bootstrap.strimzi-kafka.svc:9093
        tls:
          truststoreSecretRef:
            name: anubis-cluster-ca-cert
            key: ca.crt

wouldn't it cause failure? I would more expect that keystore password will be required

Copy link
Member Author

Choose a reason for hiding this comment

The 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.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see, thanks.

import java.util.Map;
import java.util.Optional;

import static io.apicurio.registry.operator.EnvironmentVariables.*;
Copy link
Contributor

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) :)

@carlesarnal carlesarnal force-pushed the tls-support branch 2 times, most recently from 6e93999 to 7fadf42 Compare March 4, 2025 12:27
@carlesarnal carlesarnal requested a review from jsenko March 4, 2025 12:30
Copy link
Member

@jsenko jsenko left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, but have some questions. Some of the comments are optional/can be done later.

.map(ApicurioRegistry3Spec::getApp)
.map(AppSpec::getTls)
.map(TLSSpec::getInsecureRequests)
.orElse("enabled"));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we use boolean for insecureRequests?

Copy link
Member Author

Choose a reason for hiding this comment

The 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.

.map(ApicurioRegistry3Spec::getApp)
.map(AppSpec::getTls);

if (tlsSpec.isPresent()) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Assuming TLS is enabled only by the presence of the tls object in the CR seems like it could cause user errors. I suggest we also check that the truststore/keystore is valid via io.apicurio.registry.operator.utils.SecretKeyRefTool#isValid before we assume user wants to enable TLS. Could be done by a static method in io.apicurio.registry.operator.feat.TLS.

Copy link
Member Author

Choose a reason for hiding this comment

The 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?

@@ -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 = new ProbeBuilder().withHttpGet(new HTTPGetActionBuilder().withPath("/health/ready").withPort(new IntOrString(8080)).withScheme("HTTP").build()).build();
var livenessProbe = new ProbeBuilder().withHttpGet(new HTTPGetActionBuilder().withPath("/health/live").withPort(new IntOrString(8080)).withScheme("HTTP").build()).build();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you merge the non-tls probes above into io.apicurio.registry.operator.Constants as well? Some of the values in that class are unused and will need to be removed, but now it's a bit confusing.

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 QUARKUS_OIDC_TLS_TLS_CONFIGURATION_NAME = "QUARKUS_OIDC_TLS_TLS_CONFIGURATION_NAME";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused in this PR


var keystore = new SecretKeyRefTool(getTlsSpec(primary)
.map(TLSSpec::getKeystoreSecretRef)
.orElse(null), "user.p12");
Copy link
Member

Choose a reason for hiding this comment

The 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 io.apicurio.registry.operator.feat.KafkaSqlTLS. Optional suggestion, could be done in a separate PR.

Copy link
Member Author

Choose a reason for hiding this comment

The 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.

@@ -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()),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we set the 8443 port in the container? The probes will succeed even if the connection can't be actually established. Do we make an actual connection in the tests?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a complete miss on my part, we must add the container to the port. No real connection is made in the tests, but that's expected, we only check for the needed resources to be created and for the deployment to become ready.

import static org.awaitility.Awaitility.await;

@QuarkusTest
public class TlsITTest extends ITBase {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should ping the REST API in the tests, port-forwarding should be enough since we do not support yet create HTTPS Ingresses.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If https is not properly configured at the application level, the pod won't even start, so I think checking whether the deployment is ready or not should be enough.

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);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also check for other ports.

return true;
});

// Ingresses
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we do not create https Ingresses automatically, this check is probably unnecessary?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is, yes.

host: simple-ui.apps.cluster.example
env:
- name: REGISTRY_API_URL
value: https://simple-app.apps.cluster.example/apis/registry/v3
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should add a note to this example that the feature is intended for TLS inside of the cluster for now, and they would have to create their own https reencrypt Ingress.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants