Skip to content
Draft
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
20 changes: 14 additions & 6 deletions deploy/rustfs-operator/crds/tenant-crd.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,10 @@ spec:
x-kubernetes-list-type: map
containerSecurityContext:
description: |-
Override the default RustFS container SecurityContext for every Pool in this Tenant.
Pool-level values take precedence.
RustFS container SecurityContext overrides for every Pool in this Tenant.
Non-empty values merge by field over operator defaults, with Pool-level values taking
precedence. Setting this and `securityContext` to explicit empty objects resets the
defaults and delegates unspecified values to platform admission.
nullable: true
properties:
allowPrivilegeEscalation:
Expand Down Expand Up @@ -1204,7 +1206,9 @@ spec:
containerSecurityContext:
description: |-
RustFS container SecurityContext overrides for this Pool.
Values are merged over Tenant-level container settings and operator defaults.
Non-empty values merge by field over Tenant-level settings and operator defaults. An
explicit empty object paired with an empty `securityContext` resets inherited values and
delegates unspecified values to platform admission.
nullable: true
properties:
allowPrivilegeEscalation:
Expand Down Expand Up @@ -1500,7 +1504,9 @@ spec:
securityContext:
description: |-
Pod SecurityContext overrides for this Pool.
Values override Tenant-level Pod SecurityContext settings.
Non-empty values merge by field over Tenant-level settings and operator defaults. An
explicit empty object paired with an empty `containerSecurityContext` resets inherited
values and delegates unspecified values to platform admission.
nullable: true
properties:
fsGroup:
Expand Down Expand Up @@ -1700,8 +1706,10 @@ spec:
type: string
securityContext:
description: |-
Override the default Pod SecurityContext for every Pool in this Tenant.
Pool-level values take precedence.
Pod SecurityContext overrides for every Pool in this Tenant.
Non-empty values merge by field over operator defaults, with Pool-level values taking
precedence. Setting this and `containerSecurityContext` to explicit empty objects resets
the defaults and delegates unspecified values to platform admission.
nullable: true
properties:
fsGroup:
Expand Down
8 changes: 6 additions & 2 deletions src/types/v1alpha1/pool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,16 @@ pub struct Pool {
pub persistence: PersistenceConfig,

/// Pod SecurityContext overrides for this Pool.
/// Values override Tenant-level Pod SecurityContext settings.
/// Non-empty values merge by field over Tenant-level settings and operator defaults. An
/// explicit empty object paired with an empty `containerSecurityContext` resets inherited
/// values and delegates unspecified values to platform admission.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub security_context: Option<PodSecurityContextOverride>,

/// RustFS container SecurityContext overrides for this Pool.
/// Values are merged over Tenant-level container settings and operator defaults.
/// Non-empty values merge by field over Tenant-level settings and operator defaults. An
/// explicit empty object paired with an empty `securityContext` resets inherited values and
/// delegates unspecified values to platform admission.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub container_security_context: Option<corev1::SecurityContext>,

Expand Down
30 changes: 26 additions & 4 deletions src/types/v1alpha1/security_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,12 @@ pub(crate) fn effective_run_as_non_root(run_as_user: Option<i64>, explicit: Opti

/// Pod SecurityContext overrides for RustFS pods.
///
/// Overrides the operator defaults (`runAsUser` / `runAsGroup` / `fsGroup` = 10001,
/// `runAsNonRoot` = true, and `seccompProfile.type` = `RuntimeDefault`).
#[derive(Deserialize, Serialize, Clone, Debug, KubeSchema, Default)]
/// A non-empty object overrides the operator defaults (`runAsUser` / `runAsGroup` /
/// `fsGroup` = 10001, `runAsNonRoot` = true, and `seccompProfile.type` =
/// `RuntimeDefault`). When both the Pod and container security contexts at the same scope are
/// explicit empty objects, those values are delegated to the platform, for example to an
/// OpenShift Security Context Constraint.
#[derive(Deserialize, Serialize, Clone, Debug, KubeSchema, Default, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct PodSecurityContextOverride {
/// UID to run the container process as.
Expand All @@ -58,9 +61,28 @@ pub struct PodSecurityContextOverride {
pub seccomp_profile: Option<corev1::SeccompProfile>,
}

impl PodSecurityContextOverride {
/// Returns whether the API object was explicitly supplied without any override fields.
pub(crate) fn is_empty(&self) -> bool {
self == &Self::default()
}
}

#[cfg(test)]
mod tests {
use super::effective_run_as_non_root;
use super::{PodSecurityContextOverride, effective_run_as_non_root};

#[test]
fn empty_override_is_distinct_from_a_partial_override() {
assert!(PodSecurityContextOverride::default().is_empty());
assert!(
!PodSecurityContextOverride {
run_as_non_root: Some(true),
..Default::default()
}
.is_empty()
);
}

#[test]
fn effective_run_as_non_root_preserves_legacy_uid_zero() {
Expand Down
12 changes: 8 additions & 4 deletions src/types/v1alpha1/tenant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -231,13 +231,17 @@ pub struct TenantSpec {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub encryption: Option<EncryptionConfig>,

/// Override the default Pod SecurityContext for every Pool in this Tenant.
/// Pool-level values take precedence.
/// Pod SecurityContext overrides for every Pool in this Tenant.
/// Non-empty values merge by field over operator defaults, with Pool-level values taking
/// precedence. Setting this and `containerSecurityContext` to explicit empty objects resets
/// the defaults and delegates unspecified values to platform admission.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub security_context: Option<PodSecurityContextOverride>,

/// Override the default RustFS container SecurityContext for every Pool in this Tenant.
/// Pool-level values take precedence.
/// RustFS container SecurityContext overrides for every Pool in this Tenant.
/// Non-empty values merge by field over operator defaults, with Pool-level values taking
/// precedence. Setting this and `securityContext` to explicit empty objects resets the
/// defaults and delegates unspecified values to platform admission.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub container_security_context: Option<corev1::SecurityContext>,
}
Expand Down
Loading
Loading