diff --git a/CHANGELOG.md b/CHANGELOG.md index b0541532..52eda5ed 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,11 +4,16 @@ All notable changes to this project will be documented in this file. ## [Unreleased] +### Added + +- Support specifying the SecretClass that is used to obtain TLS certificates ([#662]). + ### Changed - Make it easy to test custom Nifi images ([#616]) [#616]: https://github.com/stackabletech/nifi-operator/pull/616 +[#662]: https://github.com/stackabletech/nifi-operator/pull/662 ## [24.3.0] - 2024-03-20 diff --git a/deploy/helm/nifi-operator/crds/crds.yaml b/deploy/helm/nifi-operator/crds/crds.yaml index 9917fd3b..9d87b0f7 100644 --- a/deploy/helm/nifi-operator/crds/crds.yaml +++ b/deploy/helm/nifi-operator/crds/crds.yaml @@ -1205,6 +1205,16 @@ spec: required: - keySecret type: object + tls: + default: + serverSecretClass: tls + description: TLS configuration options for the server. + properties: + serverSecretClass: + default: tls + description: This only affects client connections and is used to control which certificate the servers should use to authenticate themselves against the client. + type: string + type: object vectorAggregatorConfigMapName: description: Name of the Vector aggregator [discovery ConfigMap](https://docs.stackable.tech/home/nightly/concepts/service_discovery). It must contain the key `ADDRESS` with the address of the Vector aggregator. Follow the [logging tutorial](https://docs.stackable.tech/home/nightly/tutorials/logging-vector-aggregator) to learn how to configure log aggregation with Vector. nullable: true diff --git a/docs/modules/nifi/pages/usage_guide/security.adoc b/docs/modules/nifi/pages/usage_guide/security.adoc index 88beddf4..78dbe6dd 100644 --- a/docs/modules/nifi/pages/usage_guide/security.adoc +++ b/docs/modules/nifi/pages/usage_guide/security.adoc @@ -1,5 +1,25 @@ = Security +== TLS + +NiFi sets up TLS encryption for the http endpoints that serve the UI. +By default, this interface is secured using certificates generated to work with the default SecretClass `tls`. + +Nifi can be configured to use a different SecretClass as shown below: + +[source, yaml] +---- +apiVersion: nifi.stackable.tech/v1alpha1 +kind: NifiCluster +spec: + # ... + clusterConfig: + tls: + serverSecretClass: non-default-secret-class # <1> +---- + +<1> The name of the `SecretClass` that will be used for certificates for the NiFi UI. + == Authentication Every user has to authenticate themselves before using NiFI. diff --git a/rust/crd/src/lib.rs b/rust/crd/src/lib.rs index 47f9b92c..dc982b1e 100644 --- a/rust/crd/src/lib.rs +++ b/rust/crd/src/lib.rs @@ -1,5 +1,6 @@ pub mod affinity; pub mod authentication; +pub mod tls; use crate::authentication::NifiAuthenticationClassRef; @@ -33,6 +34,7 @@ use stackable_operator::{ }; use std::collections::BTreeMap; use strum::Display; +use tls::NifiTls; pub const APP_NAME: &str = "nifi"; @@ -114,6 +116,10 @@ pub struct NifiClusterConfig { // We don't add `#[serde(default)]` here, as we require authentication pub authentication: Vec, + /// TLS configuration options for the server. + #[serde(default)] + pub tls: NifiTls, + // no doc - docs in NifiSensitivePropertiesConfig struct. pub sensitive_properties: NifiSensitivePropertiesConfig, @@ -481,6 +487,11 @@ impl NifiCluster { } } + /// Return user provided server TLS settings + pub fn server_tls_secret_class(&self) -> &str { + &self.spec.cluster_config.tls.server_secret_class + } + /// List all pods expected to form the cluster /// /// We try to predict the pods here rather than looking at the current cluster state in order to diff --git a/rust/crd/src/tls.rs b/rust/crd/src/tls.rs new file mode 100644 index 00000000..25a5f3da --- /dev/null +++ b/rust/crd/src/tls.rs @@ -0,0 +1,26 @@ +use serde::{Deserialize, Serialize}; +use stackable_operator::schemars::{self, JsonSchema}; + +#[derive(Clone, Debug, Deserialize, Eq, JsonSchema, PartialEq, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct NifiTls { + /// This only affects client connections and is used to + /// control which certificate the servers should use to + /// authenticate themselves against the client. + #[serde(default = "NifiTls::default_server_secret_class")] + pub server_secret_class: String, +} + +impl Default for NifiTls { + fn default() -> Self { + Self { + server_secret_class: Self::default_server_secret_class(), + } + } +} + +impl NifiTls { + fn default_server_secret_class() -> String { + "tls".to_owned() + } +} diff --git a/rust/operator-binary/src/controller.rs b/rust/operator-binary/src/controller.rs index 982cc45b..361f7a74 100644 --- a/rust/operator-binary/src/controller.rs +++ b/rust/operator-binary/src/controller.rs @@ -1208,6 +1208,7 @@ async fn build_node_rolegroup_statefulset( // One volume for the keystore and truststore data configmap .add_volume( build_tls_volume( + nifi, KEYSTORE_VOLUME_NAME, vec![ &nifi_cluster_name, diff --git a/rust/operator-binary/src/reporting_task/mod.rs b/rust/operator-binary/src/reporting_task/mod.rs index ffa31e77..0dc38aa9 100644 --- a/rust/operator-binary/src/reporting_task/mod.rs +++ b/rust/operator-binary/src/reporting_task/mod.rs @@ -321,6 +321,7 @@ fn build_reporting_task_job( .add_container(cb.build()) .add_volume( build_tls_volume( + nifi, REPORTING_TASK_CERT_VOLUME_NAME, vec![], SecretFormat::TlsPem, diff --git a/rust/operator-binary/src/security/mod.rs b/rust/operator-binary/src/security/mod.rs index df2601de..5944e198 100644 --- a/rust/operator-binary/src/security/mod.rs +++ b/rust/operator-binary/src/security/mod.rs @@ -25,9 +25,10 @@ pub async fn check_or_generate_sensitive_key(client: &Client, nifi: &NifiCluster } pub fn build_tls_volume( + nifi: &NifiCluster, volume_name: &str, service_scopes: Vec<&str>, secret_format: SecretFormat, ) -> Result { - tls::build_tls_volume(volume_name, service_scopes, secret_format).context(TlsSnafu) + tls::build_tls_volume(nifi, volume_name, service_scopes, secret_format).context(TlsSnafu) } diff --git a/rust/operator-binary/src/security/tls.rs b/rust/operator-binary/src/security/tls.rs index 26f275b0..070241bb 100644 --- a/rust/operator-binary/src/security/tls.rs +++ b/rust/operator-binary/src/security/tls.rs @@ -1,4 +1,5 @@ use snafu::{ResultExt, Snafu}; +use stackable_nifi_crd::NifiCluster; use stackable_operator::{ builder::pod::volume::{SecretFormat, SecretOperatorVolumeSourceBuilder, VolumeBuilder}, k8s_openapi::api::core::v1::Volume, @@ -21,12 +22,13 @@ pub enum Error { } pub(crate) fn build_tls_volume( + nifi: &NifiCluster, volume_name: &str, service_scopes: Vec<&str>, secret_format: SecretFormat, ) -> Result { - // TODO: Make adaptable (https://github.com/stackabletech/nifi-operator/issues/499) - let mut secret_volume_source_builder = SecretOperatorVolumeSourceBuilder::new("tls"); + let mut secret_volume_source_builder = + SecretOperatorVolumeSourceBuilder::new(nifi.server_tls_secret_class()); if secret_format == SecretFormat::TlsPkcs12 { secret_volume_source_builder.with_tls_pkcs12_password(STACKABLE_TLS_STORE_PASSWORD);