diff --git a/CHANGELOG.md b/CHANGELOG.md index 5cb6f283..ad3c8a05 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file. ## [Unreleased] +### Added + +- Lifetime of auto generated certificates is configurable with the `requestedSecretLifetime` role group property ([#660]) + ### Fixed - Fix OIDC endpoint construction in case the `rootPath` does have a trailing slash ([#656]). @@ -13,6 +17,7 @@ All notable changes to this project will be documented in this file. [#656]: https://github.com/stackabletech/druid-operator/pull/656 [#657]: https://github.com/stackabletech/druid-operator/pull/657 +[#660]: https://github.com/stackabletech/druid-operator/pull/660 ## [24.11.0] - 2024-11-18 diff --git a/Cargo.lock b/Cargo.lock index 5014a2c7..fc2649fa 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -488,17 +488,6 @@ dependencies = [ "powerfmt", ] -[[package]] -name = "derivative" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "digest" version = "0.10.7" @@ -2444,14 +2433,14 @@ dependencies = [ [[package]] name = "stackable-operator" version = "0.82.0" -source = "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.82.0#415bbd031bd52e9c0c5392060235030e9930b46b" +source = "git+https://github.com/stackabletech//operator-rs.git?branch=feat/request-secret-lifetime#f6aa3c46948d4cb59f92c5daa08f685068a393ba" dependencies = [ "chrono", "clap", "const_format", "delegate", - "derivative", "dockerfile-parser", + "educe", "either", "futures 0.3.31", "indexmap", @@ -2482,7 +2471,7 @@ dependencies = [ [[package]] name = "stackable-operator-derive" version = "0.3.1" -source = "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.82.0#415bbd031bd52e9c0c5392060235030e9930b46b" +source = "git+https://github.com/stackabletech//operator-rs.git?branch=feat/request-secret-lifetime#f6aa3c46948d4cb59f92c5daa08f685068a393ba" dependencies = [ "darling", "proc-macro2", @@ -2493,7 +2482,7 @@ dependencies = [ [[package]] name = "stackable-shared" version = "0.0.1" -source = "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.82.0#415bbd031bd52e9c0c5392060235030e9930b46b" +source = "git+https://github.com/stackabletech//operator-rs.git?branch=feat/request-secret-lifetime#f6aa3c46948d4cb59f92c5daa08f685068a393ba" dependencies = [ "kube", "semver", diff --git a/Cargo.nix b/Cargo.nix index 5e3f89ad..4a3641ec 100644 --- a/Cargo.nix +++ b/Cargo.nix @@ -7557,12 +7557,7 @@ rec { crateName = "stackable-operator"; version = "0.82.0"; edition = "2021"; - workspace_member = null; - src = pkgs.fetchgit { - url = "https://github.com/stackabletech/operator-rs.git"; - rev = "415bbd031bd52e9c0c5392060235030e9930b46b"; - sha256 = "0phasjwb64rxgn5hs8vks92icmx9255bd5v9dms280clrfpcg4hy"; - }; + src = lib.cleanSourceWith { filter = sourceFilter; src = ../operator-rs/crates/stackable-operator; }; libName = "stackable_operator"; authors = [ "Stackable GmbH " @@ -7715,12 +7710,7 @@ rec { crateName = "stackable-operator-derive"; version = "0.3.1"; edition = "2021"; - workspace_member = null; - src = pkgs.fetchgit { - url = "https://github.com/stackabletech/operator-rs.git"; - rev = "415bbd031bd52e9c0c5392060235030e9930b46b"; - sha256 = "0phasjwb64rxgn5hs8vks92icmx9255bd5v9dms280clrfpcg4hy"; - }; + src = lib.cleanSourceWith { filter = sourceFilter; src = ../operator-rs/crates/stackable-operator-derive; }; procMacro = true; libName = "stackable_operator_derive"; authors = [ @@ -7750,12 +7740,7 @@ rec { crateName = "stackable-shared"; version = "0.0.1"; edition = "2021"; - workspace_member = null; - src = pkgs.fetchgit { - url = "https://github.com/stackabletech/operator-rs.git"; - rev = "415bbd031bd52e9c0c5392060235030e9930b46b"; - sha256 = "0phasjwb64rxgn5hs8vks92icmx9255bd5v9dms280clrfpcg4hy"; - }; + src = lib.cleanSourceWith { filter = sourceFilter; src = ../operator-rs/crates/stackable-shared; }; libName = "stackable_shared"; authors = [ "Stackable GmbH " diff --git a/Cargo.toml b/Cargo.toml index a66977b4..4da2f304 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,5 +30,5 @@ strum = { version = "0.26", features = ["derive"] } tokio = { version = "1.40", features = ["full"] } tracing = "0.1" -# [patch."https://github.com/stackabletech/operator-rs.git"] -# stackable-operator = { git = "https://github.com/stackabletech//operator-rs.git", branch = "main" } +[patch."https://github.com/stackabletech/operator-rs.git"] +stackable-operator = { git = "https://github.com/stackabletech//operator-rs.git", branch = "feat/request-secret-lifetime" } diff --git a/crate-hashes.json b/crate-hashes.json index 0ca37e6e..46c186b3 100644 --- a/crate-hashes.json +++ b/crate-hashes.json @@ -1,6 +1,3 @@ { - "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.82.0#stackable-operator-derive@0.3.1": "0phasjwb64rxgn5hs8vks92icmx9255bd5v9dms280clrfpcg4hy", - "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.82.0#stackable-operator@0.82.0": "0phasjwb64rxgn5hs8vks92icmx9255bd5v9dms280clrfpcg4hy", - "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.82.0#stackable-shared@0.0.1": "0phasjwb64rxgn5hs8vks92icmx9255bd5v9dms280clrfpcg4hy", "git+https://github.com/stackabletech/product-config.git?tag=0.7.0#product-config@0.7.0": "0gjsm80g6r75pm3824dcyiz4ysq1ka4c1if6k1mjm9cnd5ym0gny" } \ No newline at end of file diff --git a/deploy/helm/druid-operator/crds/crds.yaml b/deploy/helm/druid-operator/crds/crds.yaml index a1e148ad..3364092b 100644 --- a/deploy/helm/druid-operator/crds/crds.yaml +++ b/deploy/helm/druid-operator/crds/crds.yaml @@ -154,6 +154,10 @@ spec: nullable: true type: boolean type: object + requestedSecretLifetime: + description: Request secret (currently only auto certificates) lifetime from the secret operator. + nullable: true + type: string resources: default: cpu: @@ -372,6 +376,10 @@ spec: nullable: true type: boolean type: object + requestedSecretLifetime: + description: Request secret (currently only auto certificates) lifetime from the secret operator. + nullable: true + type: string resources: default: cpu: @@ -994,6 +1002,10 @@ spec: nullable: true type: boolean type: object + requestedSecretLifetime: + description: Request secret (currently only auto certificates) lifetime from the secret operator. + nullable: true + type: string resources: default: cpu: @@ -1212,6 +1224,10 @@ spec: nullable: true type: boolean type: object + requestedSecretLifetime: + description: Request secret (currently only auto certificates) lifetime from the secret operator. + nullable: true + type: string resources: default: cpu: @@ -1410,6 +1426,10 @@ spec: nullable: true type: boolean type: object + requestedSecretLifetime: + description: Request secret (currently only auto certificates) lifetime from the secret operator. + nullable: true + type: string resources: default: cpu: @@ -1659,6 +1679,10 @@ spec: nullable: true type: boolean type: object + requestedSecretLifetime: + description: Request secret (currently only auto certificates) lifetime from the secret operator. + nullable: true + type: string resources: default: cpu: @@ -1936,6 +1960,10 @@ spec: nullable: true type: boolean type: object + requestedSecretLifetime: + description: Request secret (currently only auto certificates) lifetime from the secret operator. + nullable: true + type: string resources: default: cpu: @@ -2154,6 +2182,10 @@ spec: nullable: true type: boolean type: object + requestedSecretLifetime: + description: Request secret (currently only auto certificates) lifetime from the secret operator. + nullable: true + type: string resources: default: cpu: @@ -2352,6 +2384,10 @@ spec: nullable: true type: boolean type: object + requestedSecretLifetime: + description: Request secret (currently only auto certificates) lifetime from the secret operator. + nullable: true + type: string resources: default: cpu: @@ -2570,6 +2606,10 @@ spec: nullable: true type: boolean type: object + requestedSecretLifetime: + description: Request secret (currently only auto certificates) lifetime from the secret operator. + nullable: true + type: string resources: default: cpu: diff --git a/rust/crd/src/lib.rs b/rust/crd/src/lib.rs index 0f164d52..ce2b77a8 100644 --- a/rust/crd/src/lib.rs +++ b/rust/crd/src/lib.rs @@ -152,6 +152,9 @@ const DEFAULT_MIDDLEMANAGER_GRACEFUL_SHUTDOWN_TIMEOUT: Duration = const DEFAULT_ROUTER_GRACEFUL_SHUTDOWN_TIMEOUT: Duration = Duration::from_minutes_unchecked(5); const DEFAULT_HISTORICAL_GRACEFUL_SHUTDOWN_TIMEOUT: Duration = Duration::from_minutes_unchecked(5); +// Auto TLS certificate lifetime +const DEFAULT_SECRET_LIFETIME: Duration = Duration::from_days_unchecked(7); + #[derive(Snafu, Debug, EnumDiscriminants)] #[strum_discriminants(derive(IntoStaticStr))] #[allow(clippy::enum_variant_names)] @@ -348,6 +351,7 @@ pub struct CommonRoleGroupConfig { pub replicas: Option, pub affinity: StackableAffinity, pub graceful_shutdown_timeout: Option, + pub requested_secret_lifetime: Duration, } /// Container for the merged and validated role group configurations @@ -387,6 +391,11 @@ impl MergedConfig { replicas: rolegroup.replicas, affinity: rolegroup.config.config.affinity.clone(), graceful_shutdown_timeout: rolegroup.config.config.graceful_shutdown_timeout, + requested_secret_lifetime: rolegroup + .config + .config + .requested_secret_lifetime + .unwrap_or(DEFAULT_SECRET_LIFETIME), }) } DruidRole::Coordinator => { @@ -400,6 +409,11 @@ impl MergedConfig { replicas: rolegroup.replicas, affinity: rolegroup.config.config.affinity.clone(), graceful_shutdown_timeout: rolegroup.config.config.graceful_shutdown_timeout, + requested_secret_lifetime: rolegroup + .config + .config + .requested_secret_lifetime + .unwrap_or(DEFAULT_SECRET_LIFETIME), }) } DruidRole::Historical => { @@ -415,6 +429,11 @@ impl MergedConfig { replicas: rolegroup.replicas, affinity: rolegroup.config.config.affinity.clone(), graceful_shutdown_timeout: rolegroup.config.config.graceful_shutdown_timeout, + requested_secret_lifetime: rolegroup + .config + .config + .requested_secret_lifetime + .unwrap_or(DEFAULT_SECRET_LIFETIME), }) } DruidRole::MiddleManager => { @@ -428,6 +447,11 @@ impl MergedConfig { replicas: rolegroup.replicas, affinity: rolegroup.config.config.affinity.clone(), graceful_shutdown_timeout: rolegroup.config.config.graceful_shutdown_timeout, + requested_secret_lifetime: rolegroup + .config + .config + .requested_secret_lifetime + .unwrap_or(DEFAULT_SECRET_LIFETIME), }) } DruidRole::Router => { @@ -441,6 +465,11 @@ impl MergedConfig { replicas: rolegroup.replicas, affinity: rolegroup.config.config.affinity.clone(), graceful_shutdown_timeout: rolegroup.config.config.graceful_shutdown_timeout, + requested_secret_lifetime: rolegroup + .config + .config + .requested_secret_lifetime + .unwrap_or(DEFAULT_SECRET_LIFETIME), }) } } @@ -1105,6 +1134,10 @@ pub struct BrokerConfig { /// [graceful shutdown documentation](DOCS_BASE_URL_PLACEHOLDER/druid/usage-guide/operations/graceful-shutdown). #[fragment_attrs(serde(default))] pub graceful_shutdown_timeout: Option, + + /// Request secret (currently only auto certificates) lifetime from the secret operator. + #[fragment_attrs(serde(default))] + pub requested_secret_lifetime: Option, } impl BrokerConfig { @@ -1118,6 +1151,7 @@ impl BrokerConfig { logging: product_logging::spec::default_logging(), affinity: get_affinity(cluster_name, role, deep_storage), graceful_shutdown_timeout: Some(role.default_graceful_shutdown_timeout()), + requested_secret_lifetime: Some(DEFAULT_SECRET_LIFETIME), } } } @@ -1148,6 +1182,9 @@ pub struct CoordinatorConfig { /// [graceful shutdown documentation](DOCS_BASE_URL_PLACEHOLDER/druid/usage-guide/operations/graceful-shutdown). #[fragment_attrs(serde(default))] pub graceful_shutdown_timeout: Option, + /// Request secret (currently only auto certificates) lifetime from the secret operator. + #[fragment_attrs(serde(default))] + pub requested_secret_lifetime: Option, } impl CoordinatorConfig { @@ -1161,6 +1198,7 @@ impl CoordinatorConfig { logging: product_logging::spec::default_logging(), affinity: get_affinity(cluster_name, role, deep_storage), graceful_shutdown_timeout: Some(role.default_graceful_shutdown_timeout()), + requested_secret_lifetime: Some(DEFAULT_SECRET_LIFETIME), } } } @@ -1191,6 +1229,9 @@ pub struct MiddleManagerConfig { /// [graceful shutdown documentation](DOCS_BASE_URL_PLACEHOLDER/druid/usage-guide/operations/graceful-shutdown). #[fragment_attrs(serde(default))] pub graceful_shutdown_timeout: Option, + /// Request secret (currently only auto certificates) lifetime from the secret operator. + #[fragment_attrs(serde(default))] + pub requested_secret_lifetime: Option, } impl MiddleManagerConfig { @@ -1204,6 +1245,7 @@ impl MiddleManagerConfig { logging: product_logging::spec::default_logging(), affinity: get_affinity(cluster_name, role, deep_storage), graceful_shutdown_timeout: Some(role.default_graceful_shutdown_timeout()), + requested_secret_lifetime: Some(DEFAULT_SECRET_LIFETIME), } } } @@ -1234,6 +1276,9 @@ pub struct RouterConfig { /// [graceful shutdown documentation](DOCS_BASE_URL_PLACEHOLDER/druid/usage-guide/operations/graceful-shutdown). #[fragment_attrs(serde(default))] pub graceful_shutdown_timeout: Option, + /// Request secret (currently only auto certificates) lifetime from the secret operator. + #[fragment_attrs(serde(default))] + pub requested_secret_lifetime: Option, } impl RouterConfig { @@ -1247,6 +1292,7 @@ impl RouterConfig { logging: product_logging::spec::default_logging(), affinity: get_affinity(cluster_name, role, deep_storage), graceful_shutdown_timeout: Some(role.default_graceful_shutdown_timeout()), + requested_secret_lifetime: Some(DEFAULT_SECRET_LIFETIME), } } } @@ -1277,6 +1323,9 @@ pub struct HistoricalConfig { /// [graceful shutdown documentation](DOCS_BASE_URL_PLACEHOLDER/druid/usage-guide/operations/graceful-shutdown). #[fragment_attrs(serde(default))] pub graceful_shutdown_timeout: Option, + /// Request secret (currently only auto certificates) lifetime from the secret operator. + #[fragment_attrs(serde(default))] + pub requested_secret_lifetime: Option, } impl HistoricalConfig { @@ -1290,6 +1339,7 @@ impl HistoricalConfig { logging: product_logging::spec::default_logging(), affinity: get_affinity(cluster_name, role, deep_storage), graceful_shutdown_timeout: Some(role.default_graceful_shutdown_timeout()), + requested_secret_lifetime: Some(DEFAULT_SECRET_LIFETIME), } } } diff --git a/rust/crd/src/security.rs b/rust/crd/src/security.rs index e4b74ad6..d1319b1a 100644 --- a/rust/crd/src/security.rs +++ b/rust/crd/src/security.rs @@ -20,6 +20,7 @@ use stackable_operator::{ api::core::v1::{ContainerPort, Probe, ServicePort, TCPSocketAction}, apimachinery::pkg::util::intstr::IntOrString, }, + time::Duration, }; use std::collections::BTreeMap; @@ -190,6 +191,7 @@ impl DruidTlsSecurity { prepare: &mut ContainerBuilder, druid: &mut ContainerBuilder, pod: &mut PodBuilder, + requested_secret_lifetime: Duration, ) -> Result<(), Error> { // `ResolvedAuthenticationClasses::validate` already checked that the tls AuthenticationClass // uses the same SecretClass as the Druid server itself. @@ -202,6 +204,7 @@ impl DruidTlsSecurity { .with_node_scope() .with_format(SecretFormat::TlsPkcs12) .with_tls_pkcs12_password(TLS_STORE_PASSWORD) + .with_auto_tls_cert_lifetime(requested_secret_lifetime) .build() .context(SecretVolumeBuildSnafu)?, ) diff --git a/rust/operator-binary/src/druid_controller.rs b/rust/operator-binary/src/druid_controller.rs index dad2e8f3..275946c6 100644 --- a/rust/operator-binary/src/druid_controller.rs +++ b/rust/operator-binary/src/druid_controller.rs @@ -981,7 +981,12 @@ fn build_rolegroup_statefulset( // volume and volume mounts druid_tls_security - .add_tls_volume_and_volume_mounts(&mut cb_prepare, &mut cb_druid, &mut pb) + .add_tls_volume_and_volume_mounts( + &mut cb_prepare, + &mut cb_druid, + &mut pb, + merged_rolegroup_config.requested_secret_lifetime, + ) .context(FailedToInitializeSecurityContextSnafu)?; if let Some(s3) = s3_conn {