redhat-cop / cert-utils-operator

Set of functionalities around certificates packaged in a Kubernetes operator
Apache License 2.0
95 stars 35 forks source link

Ability to create truststore from Operator controlled Secrets #120

Closed ocpvkb closed 2 years ago

ocpvkb commented 2 years ago

In Openshift several operators are able to generate certificate and key in PEM format, stored in tls.crt and tls.key respectively, within a created secret.

e.g. service serving certificates are intended to support complex middleware applications that require encryption. (These certificates are issued as TLS web server certificates. The certificate and key are automatically replaced when they get close to expiration. The service CA certificate, which issues the service certificates, is valid for 26 months and is automatically rotated when there is less than 13 months validity left. After rotation, the previous service CA configuration is still trusted until its expiration. This allows a grace period for all affected services to refresh their key material before the expiration.) This can be done by annotate the service with "service.beta.openshift.io/" annotation.

Goal: For java applications it would be nice to have these certificate and key as truststore by using the cert-utils-operator.

Problem: When you annotate the secret to proceed by the cert-utils-operator the truststore is created. But within the next reconciling loop of the Service CA Operator the trustore is removed. --> Changing the secret by adding the truststore leads to endless loops for the operators involved.

Possible Solution: Generate the truststore in an new Secret....

By implement such a solution, the encryption of java applications would be very easy out-of-the-box. :-)

e.g. This would simplify this architecture:

https://developers.redhat.com/blog/2017/11/22/dynamically-creating-java-keystores-openshift#consuming_dynamically_generated_certificates_from_java_applications

raffaelespazzoli commented 2 years ago

maybe you can find another operator that replicates the content of a secret to another secret. Something like the reflector operator. And then you can inject the jks in the secret that does not get overwritten. This is really an OCP issue, in particular of the service serving certificate controller. It does not have to rewrite the entire secret if some fields are added. Closing for now, there isn't much I can do to fix this issue in this operator.

ocpvkb commented 2 years ago

Hello, I can't agree with you on this argument. This is not an openshift issue.

When creating a Secret, you can specify its type using the type field of a Secret resource, or certain equivalent kubectl command line flags (if available). The type of a Secret is used to facilitate programmatic handling of different kinds of confidential data. Kubernetes provides several builtin types for some common usage scenarios. These types vary in terms of the validations performed and the constraints Kubernetes imposes on them. Kubernetes provides a builtin Secret type kubernetes.io/tls for storing a certificate and its associated key that are typically used for TLS . This data is primarily used with TLS termination of the Ingress resource, but may be used with other resources or directly by a workload. When using this type of Secret, the tls.key and the tls.crt key must be provided in the data (or stringData) field of the Secret configuration, although the API server doesn't actually validate the values for each key. The TLS Secret type is provided for user's convenience. You can create an Opaque for credentials used for TLS server and/or client. However, using the builtin Secret type helps ensure the consistency of Secret format in your project; the API server does verify if the required keys are provided in a Secret configuration.

By injecting the kubernetes.io/tls secret type to hold a truststore you change the "RFC" of this type. --> The service serving certificate controller in openshift defines the secret in a correct deklariative way! (by removing the truststore from the secret)

Basically the modification, adding the truststore to a secret of type kubernetes.io/tls by the cert-utils-operator you move away from the standard....

Generating the truststore in an new Secret of type Opaque would be the best solution or at least the configuration option.

felixkrohn commented 1 year ago

+1 for this - cert-utils-operator and OCP serving-cert-controller would be a match made in heaven were it not for this issue. Could it be an idea to add an annotation with a target secretname in which to save the JKS? Something like cert-utils-operator.redhat-cop.io/java-keystore-secret: "foo-jks"