diff --git a/CHANGELOG.md b/CHANGELOG.md index 0e01f404..50e777c9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,7 +12,9 @@ All notable changes to this project will be documented in this file. - `vector` `0.26.0` -> `0.31.0` ([#709]). - `operator-rs` `0.44.0` -> `0.45.1` ([#711]). +- Let secret-operator handle certificate conversion ([#695]). +[#695]: https://github.com/stackabletech/zookeeper-operator/pull/695 [#709]: https://github.com/stackabletech/zookeeper-operator/pull/709 [#711]: https://github.com/stackabletech/zookeeper-operator/pull/711 diff --git a/Cargo.toml b/Cargo.toml index 3b999d13..603ea295 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,8 +1,9 @@ [workspace] members = ["rust/crd", "rust/operator-binary"] -#[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 = { path = "../operator-rs" } +# stackable-operator = { git = "https://github.com/stackabletech//operator-rs.git", branch = "main" } #[patch.crates-io] # tokio-zookeeper = { git = "https://github.com/stackabletech/tokio-zookeeper.git", branch = "feature/tokio-modernize" } diff --git a/rust/crd/src/security.rs b/rust/crd/src/security.rs index 3f117605..5899439e 100644 --- a/rust/crd/src/security.rs +++ b/rust/crd/src/security.rs @@ -5,14 +5,14 @@ //! //! This is required due to overlaps between TLS encryption and e.g. mTLS authentication or Kerberos -use crate::{ - authentication, authentication::ResolvedAuthenticationClasses, tls, ZookeeperCluster, - STACKABLE_RW_CONFIG_DIR, ZOOKEEPER_PROPERTIES_FILE, -}; +use crate::{authentication, authentication::ResolvedAuthenticationClasses, tls, ZookeeperCluster}; use snafu::{ResultExt, Snafu}; use stackable_operator::{ - builder::{ContainerBuilder, PodBuilder, SecretOperatorVolumeSourceBuilder, VolumeBuilder}, + builder::{ + ContainerBuilder, PodBuilder, SecretFormat, SecretOperatorVolumeSourceBuilder, + VolumeBuilder, + }, client::Client, commons::authentication::AuthenticationClassProvider, k8s_openapi::api::core::v1::Volume, @@ -117,100 +117,26 @@ impl ZookeeperSecurity { } } - /// Returns required (init) container commands to generate keystores and truststores - /// depending on the tls and authentication settings. - pub fn commands(&self) -> Vec { - let mut args = vec![]; - // Quorum - args.push(Self::generate_password(Self::STORE_PASSWORD_ENV)); - args.extend(Self::create_key_and_trust_store_cmd( - Self::QUORUM_TLS_MOUNT_DIR, - Self::QUORUM_TLS_DIR, - "quorum-tls", - Self::STORE_PASSWORD_ENV, - )); - args.extend(vec![ - Self::write_store_password_to_config( - Self::SSL_QUORUM_KEY_STORE_PASSWORD, - STACKABLE_RW_CONFIG_DIR, - Self::STORE_PASSWORD_ENV, - ), - Self::write_store_password_to_config( - Self::SSL_QUORUM_TRUST_STORE_PASSWORD, - STACKABLE_RW_CONFIG_DIR, - Self::STORE_PASSWORD_ENV, - ), - ]); - - // server-tls or client-auth-tls (only the certificates specified are accepted) - if self.tls_enabled() { - args.push(Self::generate_password(Self::STORE_PASSWORD_ENV)); - - args.extend(Self::create_key_and_trust_store_cmd( - Self::SERVER_TLS_MOUNT_DIR, - Self::SERVER_TLS_DIR, - "server-tls", - Self::STORE_PASSWORD_ENV, - )); - - args.extend(vec![ - Self::write_store_password_to_config( - Self::SSL_KEY_STORE_PASSWORD, - STACKABLE_RW_CONFIG_DIR, - Self::STORE_PASSWORD_ENV, - ), - Self::write_store_password_to_config( - Self::SSL_TRUST_STORE_PASSWORD, - STACKABLE_RW_CONFIG_DIR, - Self::STORE_PASSWORD_ENV, - ), - ]); - } - - args - } - /// Adds required volumes and volume mounts to the pod and container builders /// depending on the tls and authentication settings. pub fn add_volume_mounts( &self, pod_builder: &mut PodBuilder, - cb_prepare: &mut ContainerBuilder, cb_zookeeper: &mut ContainerBuilder, ) { let tls_secret_class = self.get_tls_secret_class(); if let Some(secret_class) = tls_secret_class { - // mounts for secret volume - cb_prepare.add_volume_mount("server-tls-mount", Self::SERVER_TLS_MOUNT_DIR); - cb_zookeeper.add_volume_mount("server-tls-mount", Self::SERVER_TLS_MOUNT_DIR); - pod_builder.add_volume(Self::create_tls_volume("server-tls-mount", secret_class)); - // empty mount for trust and keystore - cb_prepare.add_volume_mount("server-tls", Self::SERVER_TLS_DIR); cb_zookeeper.add_volume_mount("server-tls", Self::SERVER_TLS_DIR); - pod_builder.add_volume( - VolumeBuilder::new("server-tls") - .with_empty_dir(Some(""), None) - .build(), - ); + pod_builder.add_volume(Self::create_tls_volume("server-tls", secret_class)); } // quorum - // mounts for secret volume - cb_prepare.add_volume_mount("quorum-tls-mount", Self::QUORUM_TLS_MOUNT_DIR); - cb_zookeeper.add_volume_mount("quorum-tls-mount", Self::QUORUM_TLS_MOUNT_DIR); + cb_zookeeper.add_volume_mount("quorum-tls", Self::QUORUM_TLS_DIR); pod_builder.add_volume(Self::create_tls_volume( - "quorum-tls-mount", + "quorum-tls", &self.quorum_secret_class, )); - // empty mount for trust and keystore - cb_prepare.add_volume_mount("quorum-tls", Self::QUORUM_TLS_DIR); - cb_zookeeper.add_volume_mount("quorum-tls", Self::QUORUM_TLS_DIR); - pod_builder.add_volume( - VolumeBuilder::new("quorum-tls") - .with_empty_dir(Some(""), None) - .build(), - ); } /// Returns required ZooKeeper configuration settings for the `zoo.cfg` properties file @@ -331,47 +257,9 @@ impl ZookeeperSecurity { SecretOperatorVolumeSourceBuilder::new(secret_class_name) .with_pod_scope() .with_node_scope() + .with_format(SecretFormat::TlsPkcs12) .build(), ) .build() } - - /// Generates the shell script to retrieve a random 20 character password - fn generate_password(store_password_env_var: &str) -> String { - format!( - "export {store_password_env_var}=$(tr -dc A-Za-z0-9 String { - format!( - "echo {property}=${store_password_env_var} >> {rw_conf_dir}/{ZOOKEEPER_PROPERTIES_FILE}", - ) - } - - /// Generates the shell script to create key and trust stores from the certificates provided - /// by the secret operator - fn create_key_and_trust_store_cmd( - mount_directory: &str, - stackable_directory: &str, - alias_name: &str, - store_password_env_var: &str, - ) -> Vec { - vec![ - format!("echo [{stackable_directory}] Cleaning up truststore - just in case"), - format!("rm -f {stackable_directory}/truststore.p12"), - format!("echo [{stackable_directory}] Creating truststore"), - format!("keytool -importcert -file {mount_directory}/ca.crt -keystore {stackable_directory}/truststore.p12 -storetype pkcs12 -noprompt -alias {alias_name} -storepass ${store_password_env_var}"), - format!("echo [{stackable_directory}] Creating certificate chain"), - format!("cat {mount_directory}/ca.crt {mount_directory}/tls.crt > {stackable_directory}/chain.crt"), - format!("echo [{stackable_directory}] Creating keystore"), - format!("openssl pkcs12 -export -in {stackable_directory}/chain.crt -inkey {mount_directory}/tls.key -out {stackable_directory}/keystore.p12 --passout pass:${store_password_env_var}"), - ] - } } diff --git a/rust/operator-binary/src/zk_controller.rs b/rust/operator-binary/src/zk_controller.rs index 82af505c..e370c47e 100644 --- a/rust/operator-binary/src/zk_controller.rs +++ b/rust/operator-binary/src/zk_controller.rs @@ -640,7 +640,7 @@ fn build_server_rolegroup_statefulset( let mut pod_builder = PodBuilder::new(); // add volumes and mounts depending on tls / auth settings - zookeeper_security.add_volume_mounts(&mut pod_builder, &mut cb_prepare, &mut cb_zookeeper); + zookeeper_security.add_volume_mounts(&mut pod_builder, &mut cb_zookeeper); let mut args = Vec::new(); @@ -655,7 +655,6 @@ fn build_server_rolegroup_statefulset( )); } args.extend(create_init_container_command_args()); - args.extend(zookeeper_security.commands()); let container_prepare = cb_prepare .image_from_product_image(resolved_product_image)