diff --git a/CHANGELOG.md b/CHANGELOG.md index eae1743b8..3e2001314 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,14 @@ All notable changes to this project will be documented in this file. - Bump stackable-operator to 0.109.0 ([#877]). - Warn when an unsupported OIDC client authentication method is configured ([#877]). +### Fixed + +- Previously, the shared secret as well as the client spooling secret have been placed in immutable Kubernetes Secrets. + This caused problems, as they have been cached by Kubernetes, so re-creations of the mentioned Secrets (e.g. by deleting and re-creating the stacklet) + could cause Trino Pods to have different shared secrets, causing workers failing to join the coordinator. + This fix places the secrets in mutable Kubernetes Secrets going forward and migrates existing immutable Secrets to mutable by re-creating them ([#876]). + +[#876]: https://github.com/stackabletech/trino-operator/pull/876 [#877]: https://github.com/stackabletech/trino-operator/pull/877 ## [26.3.0] - 2026-03-16 diff --git a/Cargo.lock b/Cargo.lock index bba8debb9..34ab88907 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -835,21 +835,6 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" -[[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -dependencies = [ - "foreign-types-shared", -] - -[[package]] -name = "foreign-types-shared" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" - [[package]] name = "form_urlencoded" version = "1.2.2" @@ -1831,50 +1816,12 @@ version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" -[[package]] -name = "openssl" -version = "0.10.76" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "951c002c75e16ea2c65b8c7e4d3d51d5530d8dfa7d060b4776828c88cfb18ecf" -dependencies = [ - "bitflags", - "cfg-if", - "foreign-types", - "libc", - "once_cell", - "openssl-macros", - "openssl-sys", -] - -[[package]] -name = "openssl-macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - [[package]] name = "openssl-probe" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" -[[package]] -name = "openssl-sys" -version = "0.9.112" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57d55af3b3e226502be1526dfdba67ab0e9c96fc293004e79576b2b9edb0dbdb" -dependencies = [ - "cc", - "libc", - "pkg-config", - "vcpkg", -] - [[package]] name = "opentelemetry" version = "0.31.0" @@ -3049,7 +2996,6 @@ dependencies = [ "const_format", "futures 0.3.32", "indoc", - "openssl", "product-config", "rstest", "serde", diff --git a/Cargo.nix b/Cargo.nix index 53d7611cc..9ff9d3455 100644 --- a/Cargo.nix +++ b/Cargo.nix @@ -2596,34 +2596,6 @@ rec { "default" = [ "std" ]; }; }; - "foreign-types" = rec { - crateName = "foreign-types"; - version = "0.3.2"; - edition = "2015"; - sha256 = "1cgk0vyd7r45cj769jym4a6s7vwshvd0z4bqrb92q1fwibmkkwzn"; - libName = "foreign_types"; - authors = [ - "Steven Fackler " - ]; - dependencies = [ - { - name = "foreign-types-shared"; - packageId = "foreign-types-shared"; - } - ]; - - }; - "foreign-types-shared" = rec { - crateName = "foreign-types-shared"; - version = "0.1.1"; - edition = "2015"; - sha256 = "0jxgzd04ra4imjv8jgkmdq59kj8fsz6w4zxsbmlai34h26225c00"; - libName = "foreign_types_shared"; - authors = [ - "Steven Fackler " - ]; - - }; "form_urlencoded" = rec { crateName = "form_urlencoded"; version = "1.2.2"; @@ -6039,78 +6011,6 @@ rec { }; resolvedDefaultFeatures = [ "default" ]; }; - "openssl" = rec { - crateName = "openssl"; - version = "0.10.76"; - edition = "2021"; - sha256 = "1kwfn77qi342fr3hn1kxza6hslyma4ylszlcbg3a4vp1fln0074m"; - authors = [ - "Steven Fackler " - ]; - dependencies = [ - { - name = "bitflags"; - packageId = "bitflags"; - } - { - name = "cfg-if"; - packageId = "cfg-if"; - } - { - name = "foreign-types"; - packageId = "foreign-types"; - } - { - name = "libc"; - packageId = "libc"; - } - { - name = "once_cell"; - packageId = "once_cell"; - } - { - name = "openssl-macros"; - packageId = "openssl-macros"; - } - { - name = "openssl-sys"; - packageId = "openssl-sys"; - rename = "ffi"; - } - ]; - features = { - "aws-lc" = [ "ffi/aws-lc" ]; - "aws-lc-fips" = [ "ffi/aws-lc-fips" ]; - "bindgen" = [ "ffi/bindgen" ]; - "unstable_boringssl" = [ "ffi/unstable_boringssl" ]; - "vendored" = [ "ffi/vendored" ]; - }; - resolvedDefaultFeatures = [ "default" ]; - }; - "openssl-macros" = rec { - crateName = "openssl-macros"; - version = "0.1.1"; - edition = "2018"; - sha256 = "173xxvfc63rr5ybwqwylsir0vq6xsj4kxiv4hmg4c3vscdmncj59"; - procMacro = true; - libName = "openssl_macros"; - dependencies = [ - { - name = "proc-macro2"; - packageId = "proc-macro2"; - } - { - name = "quote"; - packageId = "quote"; - } - { - name = "syn"; - packageId = "syn 2.0.117"; - features = [ "full" ]; - } - ]; - - }; "openssl-probe" = rec { crateName = "openssl-probe"; version = "0.2.1"; @@ -6122,48 +6022,6 @@ rec { ]; }; - "openssl-sys" = rec { - crateName = "openssl-sys"; - version = "0.9.112"; - edition = "2021"; - links = "openssl"; - sha256 = "1nyvn3nvkcknjpkh8c19zjb9q3mbcyxgsvajw4mm09p2ngrmmmap"; - build = "build/main.rs"; - libName = "openssl_sys"; - authors = [ - "Alex Crichton " - "Steven Fackler " - ]; - dependencies = [ - { - name = "libc"; - packageId = "libc"; - } - ]; - buildDependencies = [ - { - name = "cc"; - packageId = "cc"; - } - { - name = "pkg-config"; - packageId = "pkg-config"; - } - { - name = "vcpkg"; - packageId = "vcpkg"; - } - ]; - features = { - "aws-lc" = [ "dep:aws-lc-sys" ]; - "aws-lc-fips" = [ "dep:aws-lc-fips-sys" ]; - "bindgen" = [ "dep:bindgen" ]; - "bssl-sys" = [ "dep:bssl-sys" ]; - "openssl-src" = [ "dep:openssl-src" ]; - "unstable_boringssl" = [ "bssl-sys" ]; - "vendored" = [ "openssl-src" ]; - }; - }; "opentelemetry" = rec { crateName = "opentelemetry"; version = "0.31.0"; @@ -10186,10 +10044,6 @@ rec { name = "indoc"; packageId = "indoc"; } - { - name = "openssl"; - packageId = "openssl"; - } { name = "product-config"; packageId = "product-config"; diff --git a/Cargo.toml b/Cargo.toml index ea026ccbe..9a87b0bef 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,7 +20,6 @@ clap = "4.5" const_format = "0.2" futures = { version = "0.3", features = ["compat"] } indoc = "2.0" -openssl = "0.10" rstest = "0.26" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" diff --git a/rust/operator-binary/Cargo.toml b/rust/operator-binary/Cargo.toml index 07438665e..efa9d3472 100644 --- a/rust/operator-binary/Cargo.toml +++ b/rust/operator-binary/Cargo.toml @@ -19,7 +19,6 @@ clap.workspace = true const_format.workspace = true futures.workspace = true indoc.workspace = true -openssl.workspace = true snafu.workspace = true strum.workspace = true tokio.workspace = true diff --git a/rust/operator-binary/src/controller.rs b/rust/operator-binary/src/controller.rs index 14be2badc..9dab0a053 100644 --- a/rust/operator-binary/src/controller.rs +++ b/rust/operator-binary/src/controller.rs @@ -27,10 +27,10 @@ use stackable_operator::{ volume::{SecretFormat, SecretOperatorVolumeSourceBuilder, VolumeBuilder}, }, }, - client::Client, cluster_resources::{ClusterResourceApplyStrategy, ClusterResources}, commons::{ product_image_selection::{self, ResolvedProductImage}, + random_secret_creation, rbac::build_rbac_resources, secret_class::SecretClassVolumeProvisionParts, }, @@ -41,7 +41,7 @@ use stackable_operator::{ apps::v1::{StatefulSet, StatefulSetSpec}, core::v1::{ ConfigMap, ConfigMapVolumeSource, ContainerPort, EnvVar, EnvVarSource, ExecAction, - HTTPGetAction, Probe, Secret, SecretKeySelector, Volume, + HTTPGetAction, Probe, SecretKeySelector, Volume, }, }, apimachinery::pkg::{apis::meta::v1::LabelSelector, util::intstr::IntOrString}, @@ -182,11 +182,6 @@ pub enum Error { rolegroup: RoleGroupRef, }, - #[snafu(display("failed to apply internal secret"))] - ApplyInternalSecret { - source: stackable_operator::client::Error, - }, - #[snafu(display("invalid product config"))] InvalidProductConfig { source: stackable_operator::product_config_utils::Error, @@ -386,6 +381,11 @@ pub enum Error { "client spooling protocol is not supported for Trino version {product_version}" ))] ClientSpoolingProtocolTrinoVersion { product_version: String }, + + #[snafu(display("failed to create internal secret"))] + InvalidInternalSecret { + source: random_secret_creation::Error, + }, } type Result = std::result::Result; @@ -538,25 +538,27 @@ pub async fn reconcile_trino( None => None, }; - create_random_secret( + random_secret_creation::create_random_secret_if_not_exists( &shared_internal_secret_name(trino), ENV_INTERNAL_SECRET, 512, trino, client, ) - .await?; + .await + .context(InvalidInternalSecretSnafu)?; // This secret is created even if spooling is not configured. // Trino currently requires the secret to be exactly 256 bits long. - create_random_secret( + random_secret_creation::create_random_secret_if_not_exists( &shared_spooling_secret_name(trino), ENV_SPOOLING_SECRET, 32, trino, client, ) - .await?; + .await + .context(InvalidInternalSecretSnafu)?; let mut sts_cond_builder = StatefulSetConditionBuilder::default(); @@ -1526,49 +1528,6 @@ fn build_recommended_labels<'a>( } } -async fn create_random_secret( - secret_name: &str, - secret_key: &str, - secret_byte_size: usize, - trino: &v1alpha1::TrinoCluster, - client: &Client, -) -> Result<()> { - let mut internal_secret = BTreeMap::new(); - internal_secret.insert(secret_key.to_string(), get_random_base64(secret_byte_size)); - - let secret = Secret { - immutable: Some(true), - metadata: ObjectMetaBuilder::new() - .name(secret_name) - .namespace_opt(trino.namespace()) - .ownerreference_from_resource(trino, None, Some(true)) - .context(ObjectMissingMetadataForOwnerRefSnafu)? - .build(), - string_data: Some(internal_secret), - ..Secret::default() - }; - - if client - .get_opt::( - &secret.name_any(), - secret - .namespace() - .as_deref() - .context(ObjectHasNoNamespaceSnafu)?, - ) - .await - .context(FailedToRetrieveInternalSecretSnafu)? - .is_none() - { - client - .apply_patch(CONTROLLER_NAME, &secret, &secret) - .await - .context(ApplyInternalSecretSnafu)?; - } - - Ok(()) -} - fn shared_internal_secret_name(trino: &v1alpha1::TrinoCluster) -> String { format!("{}-internal-secret", trino.name_any()) } @@ -1577,14 +1536,6 @@ fn shared_spooling_secret_name(trino: &v1alpha1::TrinoCluster) -> String { format!("{}-spooling-secret", trino.name_any()) } -// TODO: Maybe switch to something non-openssl. -// See https://github.com/stackabletech/airflow-operator/pull/686#discussion_r2348354468 (which is currently under discussion) -fn get_random_base64(byte_size: usize) -> String { - let mut buf: Vec = vec![0; byte_size]; - openssl::rand::rand_bytes(&mut buf).unwrap(); - openssl::base64::encode_block(&buf) -} - fn container_ports(trino: &v1alpha1::TrinoCluster) -> Vec { let mut ports = vec![ContainerPort { name: Some(METRICS_PORT_NAME.to_string()),