Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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,11 @@ All notable changes to this project will be documented in this file.

## [Unreleased]

### Added

- The lifetime of auto generated TLS certificates is now configurable with the role and roleGroup
config property `requestedSecretLifetime`. This helps reducing frequent Pod restarts ([#722]).

### Fixed

- Fix OIDC endpoint construction in case the `rootPath` does not have a trailing slash ([#718]).
Expand All @@ -13,6 +18,7 @@ All notable changes to this project will be documented in this file.

[#717]: https://github.com/stackabletech/nifi-operator/pull/717
[#718]: https://github.com/stackabletech/nifi-operator/pull/718
[#722]: https://github.com/stackabletech/nifi-operator/pull/722

## [24.11.0] - 2024-11-18

Expand Down
25 changes: 7 additions & 18 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,13 @@ serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
serde_yaml = "0.9"
snafu = "0.8"
stackable-operator = { git = "https://github.com/stackabletech/operator-rs.git", tag = "stackable-operator-0.82.0" }
stackable-operator = { git = "https://github.com/stackabletech/operator-rs.git", tag = "stackable-operator-0.83.0" }
strum = { version = "0.26", features = ["derive"] }
tokio = { version = "1.40", features = ["full"] }
tracing = "0.1"
url = { version = "2.5.2" }
xml-rs = "0.8"

# [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 = "main" }
# stackable-operator = { path = "../operator-rs/crates/stackable-operator" }
8 changes: 8 additions & 0 deletions deploy/helm/nifi-operator/crds/crds.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,10 @@ spec:
nullable: true
type: boolean
type: object
requestedSecretLifetime:
description: Request secret (currently only autoTls certificates) lifetime from the secret operator, e.g. `7d`, or `30d`. Please note that this can be shortened by the `maxCertificateLifetime` setting on the SecretClass issuing the TLS certificate.
nullable: true
type: string
resources:
default:
cpu:
Expand Down Expand Up @@ -815,6 +819,10 @@ spec:
nullable: true
type: boolean
type: object
requestedSecretLifetime:
description: Request secret (currently only autoTls certificates) lifetime from the secret operator, e.g. `7d`, or `30d`. Please note that this can be shortened by the `maxCertificateLifetime` setting on the SecretClass issuing the TLS certificate.
nullable: true
type: string
resources:
default:
cpu:
Expand Down
9 changes: 8 additions & 1 deletion rust/crd/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -411,10 +411,16 @@ pub struct NifiConfig {
/// Time period Pods have to gracefully shut down, e.g. `30m`, `1h` or `2d`. Consult the operator documentation for details.
#[fragment_attrs(serde(default))]
pub graceful_shutdown_timeout: Option<Duration>,

/// Request secret (currently only autoTls certificates) lifetime from the secret operator, e.g. `7d`, or `30d`.
/// Please note that this can be shortened by the `maxCertificateLifetime` setting on the SecretClass issuing the TLS certificate.
#[fragment_attrs(serde(default))]
pub requested_secret_lifetime: Option<Duration>,
}

impl NifiConfig {
pub const NIFI_SENSITIVE_PROPS_KEY: &'static str = "NIFI_SENSITIVE_PROPS_KEY";
// Auto TLS certificate lifetime
const DEFAULT_NODE_SECRET_LIFETIME: Duration = Duration::from_days_unchecked(7);

pub fn default_config(cluster_name: &str, role: &NifiRole) -> NifiConfigFragment {
NifiConfigFragment {
Expand Down Expand Up @@ -458,6 +464,7 @@ impl NifiConfig {
},
affinity: get_affinity(cluster_name, role),
graceful_shutdown_timeout: Some(DEFAULT_NODE_GRACEFUL_SHUTDOWN_TIMEOUT),
requested_secret_lifetime: Some(Self::DEFAULT_NODE_SECRET_LIFETIME),
}
}
}
Expand Down
7 changes: 7 additions & 0 deletions rust/operator-binary/src/controller.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,9 @@ pub struct Ctx {
#[strum_discriminants(derive(IntoStaticStr))]
#[allow(clippy::enum_variant_names)]
pub enum Error {
#[snafu(display("missing secret lifetime"))]
MissingSecretLifetime,

#[snafu(display("NifiCluster object is invalid"))]
InvalidNifiCluster {
source: error_boundary::InvalidObject,
Expand Down Expand Up @@ -1253,6 +1256,9 @@ async fn build_node_rolegroup_statefulset(
.context(MetadataBuildSnafu)?
.build();

let requested_secret_lifetime = merged_config
.requested_secret_lifetime
.context(MissingSecretLifetimeSnafu)?;
let nifi_cluster_name = nifi.name_any();
pod_builder
.metadata(metadata)
Expand Down Expand Up @@ -1301,6 +1307,7 @@ async fn build_node_rolegroup_statefulset(
&build_reporting_task_service_name(&nifi_cluster_name),
],
SecretFormat::TlsPkcs12,
&requested_secret_lifetime,
)
.context(SecuritySnafu)?,
)
Expand Down
14 changes: 9 additions & 5 deletions rust/operator-binary/src/reporting_task/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,15 @@
//!
use std::collections::BTreeMap;

use crate::security::{
authentication::{NifiAuthenticationConfig, STACKABLE_ADMIN_USERNAME},
build_tls_volume,
};
use snafu::{OptionExt, ResultExt, Snafu};
use stackable_nifi_crd::{
NifiCluster, NifiRole, APP_NAME, HTTPS_PORT, HTTPS_PORT_NAME, METRICS_PORT,
};
use stackable_operator::time::Duration;
use stackable_operator::{
builder::{
self,
Expand All @@ -50,11 +55,6 @@ use stackable_operator::{
utils::cluster_info::KubernetesClusterInfo,
};

use crate::security::{
authentication::{NifiAuthenticationConfig, STACKABLE_ADMIN_USERNAME},
build_tls_volume,
};

use super::controller::{build_recommended_labels, NIFI_UID};

const REPORTING_TASK_CERT_VOLUME_NAME: &str = "tls";
Expand Down Expand Up @@ -359,6 +359,10 @@ fn build_reporting_task_job(
REPORTING_TASK_CERT_VOLUME_NAME,
vec![],
SecretFormat::TlsPem,
// The certificate is only used for the REST API call, so a short lifetime is sufficient.
// There is no correct way to configure this job since it's an implementation detail.
// Also it will be dropped when support for 1.x is removed.
&Duration::from_days_unchecked(1),
)
.context(SecretVolumeBuildFailureSnafu)?,
)
Expand Down
11 changes: 10 additions & 1 deletion rust/operator-binary/src/security/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use snafu::{ResultExt, Snafu};
use stackable_nifi_crd::NifiCluster;
use stackable_operator::client::Client;
use stackable_operator::time::Duration;
use stackable_operator::{builder::pod::volume::SecretFormat, k8s_openapi::api::core::v1::Volume};

pub mod authentication;
Expand Down Expand Up @@ -42,6 +43,14 @@ pub fn build_tls_volume(
volume_name: &str,
service_scopes: Vec<&str>,
secret_format: SecretFormat,
requested_secret_lifetime: &Duration,
) -> Result<Volume> {
tls::build_tls_volume(nifi, volume_name, service_scopes, secret_format).context(TlsSnafu)
tls::build_tls_volume(
nifi,
volume_name,
service_scopes,
secret_format,
requested_secret_lifetime,
)
.context(TlsSnafu)
}
6 changes: 4 additions & 2 deletions rust/operator-binary/src/security/tls.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
use crate::security::authentication::STACKABLE_TLS_STORE_PASSWORD;
use snafu::{ResultExt, Snafu};
use stackable_nifi_crd::NifiCluster;
use stackable_operator::time::Duration;
use stackable_operator::{
builder::pod::volume::{SecretFormat, SecretOperatorVolumeSourceBuilder, VolumeBuilder},
k8s_openapi::api::core::v1::Volume,
};

use crate::security::authentication::STACKABLE_TLS_STORE_PASSWORD;

pub const KEYSTORE_VOLUME_NAME: &str = "keystore";
pub const KEYSTORE_NIFI_CONTAINER_MOUNT: &str = "/stackable/keystore";
pub const TRUSTSTORE_VOLUME_NAME: &str = "truststore";
Expand All @@ -26,6 +26,7 @@ pub(crate) fn build_tls_volume(
volume_name: &str,
service_scopes: Vec<&str>,
secret_format: SecretFormat,
requested_secret_lifetime: &Duration,
) -> Result<Volume> {
let mut secret_volume_source_builder =
SecretOperatorVolumeSourceBuilder::new(nifi.server_tls_secret_class());
Expand All @@ -44,6 +45,7 @@ pub(crate) fn build_tls_volume(
.with_node_scope()
.with_pod_scope()
.with_format(secret_format)
.with_auto_tls_cert_lifetime(*requested_secret_lifetime)
.build()
.context(TlsCertSecretClassVolumeBuildSnafu)?,
)
Expand Down
Loading