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

feat: Allow the specification of additional trust roots #573

Merged
merged 13 commits into from
Mar 21, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ All notable changes to this project will be documented in this file.
- Made RSA key length configurable for certificates issued by cert-manager ([#528]).
- Kerberos principal backends now also provision principals for IP address, not just DNS hostnames ([#552]).
- OLM deployment helper ([#546]).
- Allow the specification of additional trust roots in autoTls SecretClasses ([#573]).

### Changed

Expand All @@ -38,6 +39,7 @@ All notable changes to this project will be documented in this file.
[#566]: https://github.com/stackabletech/secret-operator/pull/566
[#569]: https://github.com/stackabletech/secret-operator/pull/569
[#571]: https://github.com/stackabletech/secret-operator/pull/571
[#573]: https://github.com/stackabletech/secret-operator/pull/573

## [24.11.1] - 2025-01-10

Expand Down
38 changes: 38 additions & 0 deletions deploy/helm/secret-operator/crds/crds.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,44 @@ spec:

A new certificate and key pair will be generated and signed for each Pod, keys or certificates are never reused.
properties:
additionalTrustRoots:
default: []
description: Additional trust roots which are added to the provided `ca.crt` file.
items:
oneOf:
- required:
- configMap
- required:
- secret
properties:
configMap:
description: 'Reference (name and namespace) to a Kubernetes ConfigMap object where additional certificates are stored. The extensions of the keys denote its contents: A key suffixed with `.crt` contains a stack of base64 encoded DER certificates, a key suffixed with `.der` contains a binary DER certificate.'
properties:
name:
description: Name of the ConfigMap being referred to.
type: string
namespace:
description: Namespace of the ConfigMap being referred to.
type: string
required:
- name
- namespace
type: object
secret:
description: 'Reference (name and namespace) to a Kubernetes Secret object where additional certificates are stored. The extensions of the keys denote its contents: A key suffixed with `.crt` contains a stack of base64 encoded DER certificates, a key suffixed with `.der` contains a binary DER certificate.'
properties:
name:
description: Name of the Secret being referred to.
type: string
namespace:
description: Namespace of the Secret being referred to.
type: string
required:
- name
- namespace
type: object
type: object
type: array
ca:
description: Configures the certificate authority used to issue Pod certificates.
properties:
Expand Down
1 change: 1 addition & 0 deletions deploy/helm/secret-operator/templates/roles.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ rules:
- apiGroups:
- ""
resources:
- configmaps
- nodes
- persistentvolumeclaims
verbs:
Expand Down
10 changes: 10 additions & 0 deletions docs/modules/secret-operator/pages/secretclass.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,10 @@ spec:
keyGeneration:
rsa:
length: 4096
additionalTrustRoots:
- secret:
name: trust-roots
namespace: default
maxCertificateLifetime: 15d # optional
----

Expand All @@ -125,6 +129,12 @@ spec:
`autoTls.ca.keyGeneration`:: Configures how keys should be generated.
`autoTls.ca.keyGeneration.rsa`:: Declares that keys should be generated using the RSA algorithm.
`autoTls.ca.keyGeneration.rsa.length`:: The amount of bits used for generating the RSA key pair. Currently, `2048`, `3072` and `4096` are supported. Defaults to `2048` bits.
`additionalTrustRoots`:: Configures additional trust roots which are added to the CA files or truststores in the provisioned volume mounts.
`additionalTrustRoots.secret`::
Reference (`name` and `namespace`) to a K8s `Secret` object where the trusted certificates are stored.
The extension of a key defines its content:
* `.crt` denotes a stack of PEM (base64-encoded DER) certificates.
* `.der` denotes a a binary DER certificates.
`autoTls.maxCertificateLifetime`:: Maximum lifetime the created certificates are allowed to have. In case consumers request a longer lifetime than allowed by this setting, the lifetime will be the minimum of both.

[#backend-certmanager]
Expand Down
50 changes: 48 additions & 2 deletions rust/crd-utils/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,47 @@ use std::fmt::Display;

use serde::{Deserialize, Serialize};
use stackable_operator::{
k8s_openapi::api::core::v1::Secret,
kube::runtime::reflector::ObjectRef,
k8s_openapi::api::core::v1::{ConfigMap, Secret},
kube::{api::DynamicObject, runtime::reflector::ObjectRef},
schemars::{self, JsonSchema},
};

#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
#[serde(rename_all = "camelCase")]
pub struct ConfigMapReference {
/// Namespace of the ConfigMap being referred to.
pub namespace: String,
/// Name of the ConfigMap being referred to.
pub name: String,
}

// Use ObjectRef for logging/errors
impl Display for ConfigMapReference {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
ObjectRef::<ConfigMap>::from(self).fmt(f)
}
}
impl From<ConfigMapReference> for ObjectRef<ConfigMap> {
fn from(val: ConfigMapReference) -> Self {
ObjectRef::<ConfigMap>::from(&val)
}
}
impl From<&ConfigMapReference> for ObjectRef<ConfigMap> {
fn from(val: &ConfigMapReference) -> Self {
ObjectRef::<ConfigMap>::new(&val.name).within(&val.namespace)
}
}
impl From<ConfigMapReference> for ObjectRef<DynamicObject> {
fn from(val: ConfigMapReference) -> Self {
ObjectRef::<ConfigMap>::from(&val).erase()
}
}
impl From<&ConfigMapReference> for ObjectRef<DynamicObject> {
fn from(val: &ConfigMapReference) -> Self {
ObjectRef::<ConfigMap>::from(val).erase()
}
}

// Redefine SecretReference instead of reusing k8s-openapi's, in order to make name/namespace mandatory.
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
#[serde(rename_all = "camelCase")]
Expand All @@ -35,3 +71,13 @@ impl From<&SecretReference> for ObjectRef<Secret> {
ObjectRef::<Secret>::new(&val.name).within(&val.namespace)
}
}
impl From<SecretReference> for ObjectRef<DynamicObject> {
fn from(val: SecretReference) -> Self {
ObjectRef::<Secret>::from(&val).erase()
}
}
impl From<&SecretReference> for ObjectRef<DynamicObject> {
fn from(val: &SecretReference) -> Self {
ObjectRef::<Secret>::from(val).erase()
}
}
2 changes: 2 additions & 0 deletions rust/operator-binary/src/backend/dynamic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,11 +118,13 @@ pub async fn from_class(
}
crd::SecretClassBackend::AutoTls(crd::AutoTlsBackend {
ca,
additional_trust_roots,
max_certificate_lifetime,
}) => from(
super::TlsGenerate::get_or_create_k8s_certificate(
client,
&ca,
&additional_trust_roots,
max_certificate_lifetime,
)
.await?,
Expand Down
Loading