Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 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
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file.

## [Unreleased]

### Added

- Made RSA key length configurable for certificates issued by cert-manager ([#528]).

[#528]: https://github.com/stackabletech/secret-operator/pull/528

## [24.11.0] - 2024-11-18

### Added
Expand Down
22 changes: 22 additions & 0 deletions deploy/helm/secret-operator/crds/crds.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,28 @@ spec:
- kind
- name
type: object
keyGeneration:
default:
rsa:
length: 2048
description: The algorithm used to generate a key pair and required configuration settings. Currently only RSA and a key length of 2048, 3072 or 4096 bits can be configured.
oneOf:
- required:
- rsa
properties:
rsa:
properties:
length:
description: The amount of bits used for generating the RSA keypair. Currently, `2048`, `3072` and `4096` are supported. Defaults to `2048` bits.
enum:
- 2048
- 3072
- 4096
type: integer
required:
- length
type: object
type: object
required:
- issuer
type: object
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
apiVersion: secrets.stackable.tech/v1alpha1
kind: SecretClass
metadata:
name: tls
spec:
backend:
experimentalCertManager:
issuer:
kind: Issuer
name: secret-operator-demonstration
keyGeneration: # <1>
rsa: # <2>
length: 4096 # <3>
35 changes: 35 additions & 0 deletions docs/modules/secret-operator/pages/secretclass.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,9 @@ spec:
namespace: default
autoGenerate: true
caCertificateLifetime: 700d
keyGeneration:
rsa:
length: 4096
maxCertificateLifetime: 15d # optional
----

Expand All @@ -119,6 +122,9 @@ spec:
and `ca.key` respectively.
`autoTls.ca.autoGenerate`:: Whether the certificate authority should be provisioned and managed by the Secret Operator.
`autoTls.ca.caCertificateLifetime` :: The lifetime of the certificate authority's root certificate.
`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.
`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 All @@ -136,6 +142,29 @@ A new certificate will be requested the first time it is used by a Pod, it will

Node-scoped requests will cause a Pod to become "sticky" to the Node that it was first scheduled to (like xref:#backend-k8ssearch[], but unlike xref:#backend-autotls[]).

[#backend-certmanager-certificate-key-pair-generation]
==== `TLS certificate key pair generation`

Currently, only RSA is supported in the `experimentalCertManager` backend.
You can however configure the key length for generated private keys. If not specified it will default to `2048` bits.

----
include::example$secretclass-certmanager-key-length.yaml[]
----
<1> `experimentalCertManager.ca.keyGeneration` specifies which algorithm and additional parameters are used
<2> `experimentalCertManager.ca.keyGeneration.rsa` specifies the RSA key pair algorithm (RSA currently is the only one supported)
<3> `experimentalCertManager.ca.keyGeneration.rsa.length` specifies the amount of bits used for generating the RSA key pair. Currently, `2048`, `3072` and `4096` are supported. Defaults to `2048` bits.

CAUTION
====
Using more than `2048` bits will significantly increase the computation time to create new key pairs.
The SSL Labs https://github.com/ssllabs/research/wiki/SSL-and-TLS-Deployment-Best-Practices[SSL and TLS Deployment Best Practices] as of 2024-10-01 recommend

> For most websites, using RSA keys stronger than 2,048 bits and ECDSA keys stronger than 256 bits is a waste of CPU power and might impair user experience

If options higher than `2048` are chosen, the CPU resources for the issuer may need to be increased in order to avoid Pods being stuck in `Pending` waiting for the computation of their key pair.
====

==== Reference

[source,yaml]
Expand All @@ -147,13 +176,19 @@ spec:
kind: Issuer
name: secret-operator-demonstration
defaultCertificateLifetime: 1d
keyGeneration:
rsa:
length: 4096
----

`experimentalCertManager`:: Declares that the `experimentalCertManager` backend is used.
`experimentalCertManager.issuer`:: The reference to the Cert-Manager issuer that should issue the certificates.
`experimentalCertManager.issuer.kind`:: The kind of the Cert-Manager issuer, either Issuer or ClusterIssuer. Note that Issuer must be in the same namespace as the Pod requesting the secret.
`experimentalCertManager.issuer.name`:: The name of the Issuer or ClusterIssuer to be used.
`experimentalCertManager.defaultCertificateLifetime`:: The default duration of the certificates. This may need to be increased for backends that impose stricter rate limits, such as https://letsencrypt.org/[Let's Encrypt].
`experimentalCertManager.keyGeneration`:: Configures how keys should be generated.
`experimentalCertManager.keyGeneration.rsa`:: Declares that keys should be generated using the RSA algorithm.
`experimentalCertManager.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.

[#backend-kerberoskeytab]
=== `kerberosKeytab`
Expand Down
22 changes: 16 additions & 6 deletions rust/operator-binary/src/backend/cert_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,12 @@ use stackable_operator::{
time::Duration,
};

use crate::{crd::CertManagerIssuer, external_crd, format::SecretData, utils::Unloggable};
use crate::{
crd::{self, CertificateKeyGeneration},
external_crd::{self, cert_manager::CertificatePrivateKey},
format::SecretData,
utils::Unloggable,
};

use super::{
k8s_search::LABEL_SCOPE_NODE,
Expand Down Expand Up @@ -73,8 +78,7 @@ impl SecretBackendError for Error {
pub struct CertManager {
// Not secret per se, but Client isn't Debug: https://github.com/stackabletech/secret-operator/issues/411
pub client: Unloggable<stackable_operator::client::Client>,
pub issuer: CertManagerIssuer,
pub default_certificate_lifetime: Duration,
pub config: crd::CertManagerBackend,
}

#[async_trait]
Expand Down Expand Up @@ -125,14 +129,20 @@ impl SecretBackend for CertManager {
"{}s",
selector
.cert_manager_cert_lifetime
.unwrap_or(self.default_certificate_lifetime)
.unwrap_or(self.config.default_certificate_lifetime)
.as_secs()
)),
dns_names,
ip_addresses,
issuer_ref: external_crd::cert_manager::ObjectReference {
name: self.issuer.name.clone(),
kind: Some(self.issuer.kind.to_string()),
name: self.config.issuer.name.clone(),
kind: Some(self.config.issuer.kind.to_string()),
},
private_key: match self.config.key_generation {
CertificateKeyGeneration::Rsa { length } => CertificatePrivateKey {
algorithm: "RSA".to_string(),
size: length,
},
},
},
};
Expand Down
8 changes: 2 additions & 6 deletions rust/operator-binary/src/backend/dynamic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,13 +128,9 @@ pub async fn from_class(
)
.await?,
),
crd::SecretClassBackend::CertManager(crd::CertManagerBackend {
issuer,
default_certificate_lifetime,
}) => from(super::CertManager {
crd::SecretClassBackend::CertManager(config) => from(super::CertManager {
client: Unloggable(client.clone()),
issuer,
default_certificate_lifetime,
config,
}),
crd::SecretClassBackend::KerberosKeytab(crd::KerberosKeytabBackend {
realm_name,
Expand Down
5 changes: 5 additions & 0 deletions rust/operator-binary/src/crd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,11 @@ pub struct CertManagerBackend {
/// Defaults to 1 day. This may need to be increased for external issuers that impose rate limits (such as Let's Encrypt).
#[serde(default = "CertManagerBackend::default_certificate_lifetime")]
pub default_certificate_lifetime: Duration,

/// The algorithm used to generate a key pair and required configuration settings.
/// Currently only RSA and a key length of 2048, 3072 or 4096 bits can be configured.
#[serde(default)]
pub key_generation: CertificateKeyGeneration,
}

impl CertManagerBackend {
Expand Down
9 changes: 9 additions & 0 deletions rust/operator-binary/src/external_crd/cert_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,15 @@ pub struct CertificateSpec {
#[serde(default)]
pub ip_addresses: Vec<String>,
pub issuer_ref: ObjectReference,
pub private_key: CertificatePrivateKey,
}

/// See <https://cert-manager.io/docs/reference/api-docs/#cert-manager.io/v1.CertificatePrivateKey>.
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
#[serde(rename_all = "camelCase")]
pub struct CertificatePrivateKey {
pub algorithm: String,
pub size: u32,
}

/// See <https://cert-manager.io/docs/reference/api-docs/#meta.cert-manager.io/v1.ObjectReference>.
Expand Down
Loading