Files
rustfs/crates/ecstore/src/config/audit.rs
T
Zhengchao An 0fe41da688 fix(ecstore): document audit/notify KVS divergence and fix auth_token redaction (#6816)
Triages the three divergences backlog#2054 found between the audit and
notify default KVS tables, cross-checked against MinIO upstream
(internal/logger/config.go, internal/config/notify/parse.go):

- webhook: audit's extra batch_size/max_retry/retry_interval/http_timeout
  keys match MinIO's DefaultAuditWebhookKVS byte-for-byte, while notify's
  table matches MinIO's notify DefaultWebhookKVS (which lacks them).
  Intentional, not a copy/paste gap — documented with a doc comment on
  each table instead of changed.
- mqtt: audit's stronger QoS/keep-alive/reconnect defaults have no MinIO
  precedent (MinIO's audit logging has no MQTT target at all), while
  notify's 0/0s/0s defaults match MinIO's DefaultMQTTKVS exactly.
  Documented as an intentional RustFS-original choice, not changed.
- auth_token hidden_if_empty: audit had false, notify had true, with no
  MinIO precedent either way (this KVS version has no per-key hidden
  flag upstream). Fixed audit to true, matching notify and every other
  sensitive key in both files (MQTT_PASSWORD, *_TLS_*). Non-empty tokens
  were already redacted identically on both sides via ends_with("_token")
  pattern matching in config_admin.rs — this only changes how an *unset*
  audit webhook auth_token renders in admin config output (omitted
  instead of shown as an empty value).

Refs rustfs/backlog#2054
2026-08-28 17:34:04 +00:00

228 lines
8.2 KiB
Rust

// Copyright 2024 RustFS Team
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use super::target_defaults::{amqp_kvs, kafka_kvs, mysql_kvs, nats_kvs, postgres_kvs, pulsar_kvs, redis_kvs};
use rustfs_config::audit::AUDIT_REDIS_DEFAULT_CHANNEL;
use rustfs_config::server_config::{KV, KVS};
use rustfs_config::{
COMMENT_KEY, DEFAULT_LIMIT, ENABLE_KEY, EVENT_DEFAULT_DIR, EnableState, MQTT_BROKER, MQTT_KEEP_ALIVE_INTERVAL, MQTT_PASSWORD,
MQTT_QOS, MQTT_QUEUE_DIR, MQTT_QUEUE_LIMIT, MQTT_RECONNECT_INTERVAL, MQTT_TLS_CA, MQTT_TLS_CLIENT_CERT, MQTT_TLS_CLIENT_KEY,
MQTT_TLS_POLICY, MQTT_TLS_TRUST_LEAF_AS_CA, MQTT_TOPIC, MQTT_USERNAME, MQTT_WS_PATH_ALLOWLIST, WEBHOOK_AUTH_TOKEN,
WEBHOOK_BATCH_SIZE, WEBHOOK_CLIENT_CA, WEBHOOK_CLIENT_CERT, WEBHOOK_CLIENT_KEY, WEBHOOK_ENDPOINT, WEBHOOK_HTTP_TIMEOUT,
WEBHOOK_MAX_RETRY, WEBHOOK_QUEUE_DIR, WEBHOOK_QUEUE_LIMIT, WEBHOOK_RETRY_INTERVAL, WEBHOOK_SKIP_TLS_VERIFY,
};
use std::sync::LazyLock;
#[allow(clippy::declare_interior_mutable_const)]
/// Default KVS for audit webhook settings.
///
/// `WEBHOOK_BATCH_SIZE`/`WEBHOOK_MAX_RETRY`/`WEBHOOK_RETRY_INTERVAL`/`WEBHOOK_HTTP_TIMEOUT`
/// exist here but not in [`crate::config::notify::DEFAULT_NOTIFY_WEBHOOK_KVS`]. This mirrors
/// MinIO upstream: `internal/logger/config.go`'s `DefaultAuditWebhookKVS` carries the same
/// four keys with the same defaults (`"1"`/`"0"`/`"3s"`/`"5s"`), while
/// `internal/config/notify/parse.go`'s `DefaultWebhookKVS` (bucket event notifications) does
/// not — the notify webhook delivery path never supported them. Not a copy/paste gap
/// (backlog#2054).
pub static DEFAULT_AUDIT_WEBHOOK_KVS: LazyLock<KVS> = LazyLock::new(|| {
KVS(vec![
KV {
key: ENABLE_KEY.to_owned(),
value: EnableState::Off.to_string(),
hidden_if_empty: false,
},
KV {
key: WEBHOOK_ENDPOINT.to_owned(),
value: "".to_owned(),
hidden_if_empty: false,
},
KV {
key: WEBHOOK_AUTH_TOKEN.to_owned(),
value: "".to_owned(),
hidden_if_empty: true, // Sensitive field; matches notify's webhook auth_token (backlog#2054)
},
KV {
key: WEBHOOK_CLIENT_CERT.to_owned(),
value: "".to_owned(),
hidden_if_empty: false,
},
KV {
key: WEBHOOK_CLIENT_KEY.to_owned(),
value: "".to_owned(),
hidden_if_empty: false,
},
KV {
key: WEBHOOK_CLIENT_CA.to_owned(),
value: "".to_owned(),
hidden_if_empty: false,
},
KV {
key: WEBHOOK_SKIP_TLS_VERIFY.to_owned(),
value: EnableState::Off.to_string(),
hidden_if_empty: false,
},
KV {
key: WEBHOOK_BATCH_SIZE.to_owned(),
value: "1".to_owned(),
hidden_if_empty: false,
},
KV {
key: WEBHOOK_QUEUE_LIMIT.to_owned(),
value: DEFAULT_LIMIT.to_string(),
hidden_if_empty: false,
},
KV {
key: WEBHOOK_QUEUE_DIR.to_owned(),
value: EVENT_DEFAULT_DIR.to_owned(),
hidden_if_empty: false,
},
KV {
key: WEBHOOK_MAX_RETRY.to_owned(),
value: "0".to_owned(),
hidden_if_empty: false,
},
KV {
key: WEBHOOK_RETRY_INTERVAL.to_owned(),
value: "3s".to_owned(),
hidden_if_empty: false,
},
KV {
key: WEBHOOK_HTTP_TIMEOUT.to_owned(),
value: "5s".to_owned(),
hidden_if_empty: false,
},
KV {
key: COMMENT_KEY.to_owned(),
value: "".to_owned(),
hidden_if_empty: false,
},
])
});
#[allow(clippy::declare_interior_mutable_const)]
/// Default KVS for audit MQTT settings.
///
/// `MQTT_QOS`/`MQTT_KEEP_ALIVE_INTERVAL`/`MQTT_RECONNECT_INTERVAL` default to a stronger
/// delivery posture here (`"1"`/`"60s"`/`"5s"`) than
/// [`crate::config::notify::DEFAULT_NOTIFY_MQTT_KVS`] (`"0"`/`"0s"`/`"0s"`, which matches
/// MinIO's own `DefaultMQTTKVS` in `internal/config/notify/parse.go` byte-for-byte). MinIO has
/// no MQTT audit target to compare against — audit-over-MQTT is a RustFS-original addition —
/// so this divergence cannot be checked against upstream; it is intentional (audit favors
/// at-least-once delivery and faster reconnect over notify's opt-in defaults), not a
/// copy/paste gap (backlog#2054).
pub static DEFAULT_AUDIT_MQTT_KVS: LazyLock<KVS> = LazyLock::new(|| {
KVS(vec![
KV {
key: ENABLE_KEY.to_owned(),
value: EnableState::Off.to_string(),
hidden_if_empty: false,
},
KV {
key: MQTT_BROKER.to_owned(),
value: "".to_owned(),
hidden_if_empty: false,
},
KV {
key: MQTT_TOPIC.to_owned(),
value: "".to_owned(),
hidden_if_empty: false,
},
KV {
key: MQTT_USERNAME.to_owned(),
value: "".to_owned(),
hidden_if_empty: false,
},
KV {
key: MQTT_PASSWORD.to_owned(),
value: "".to_owned(),
hidden_if_empty: true, // Sensitive field
},
KV {
key: MQTT_QOS.to_owned(),
value: "1".to_owned(),
hidden_if_empty: false,
},
KV {
key: MQTT_KEEP_ALIVE_INTERVAL.to_owned(),
value: "60s".to_owned(),
hidden_if_empty: false,
},
KV {
key: MQTT_RECONNECT_INTERVAL.to_owned(),
value: "5s".to_owned(),
hidden_if_empty: false,
},
KV {
key: MQTT_QUEUE_DIR.to_owned(),
value: EVENT_DEFAULT_DIR.to_owned(),
hidden_if_empty: false,
},
KV {
key: MQTT_QUEUE_LIMIT.to_owned(),
value: DEFAULT_LIMIT.to_string(),
hidden_if_empty: false,
},
KV {
key: MQTT_TLS_POLICY.to_owned(),
value: "".to_owned(),
hidden_if_empty: true,
},
KV {
key: MQTT_TLS_CA.to_owned(),
value: "".to_owned(),
hidden_if_empty: true,
},
KV {
key: MQTT_TLS_CLIENT_CERT.to_owned(),
value: "".to_owned(),
hidden_if_empty: true,
},
KV {
key: MQTT_TLS_CLIENT_KEY.to_owned(),
value: "".to_owned(),
hidden_if_empty: true,
},
KV {
key: MQTT_TLS_TRUST_LEAF_AS_CA.to_owned(),
value: "".to_owned(),
hidden_if_empty: true,
},
KV {
key: MQTT_WS_PATH_ALLOWLIST.to_owned(),
value: "".to_owned(),
hidden_if_empty: true,
},
KV {
key: COMMENT_KEY.to_owned(),
value: "".to_owned(),
hidden_if_empty: false,
},
])
});
// The remaining targets declare the same defaults as notify, so both sides build them from
// `target_defaults`. Redis and mysql pass in the single default that audit and notify disagree on.
pub static DEFAULT_AUDIT_AMQP_KVS: LazyLock<KVS> = LazyLock::new(amqp_kvs);
pub static DEFAULT_AUDIT_NATS_KVS: LazyLock<KVS> = LazyLock::new(nats_kvs);
pub static DEFAULT_AUDIT_PULSAR_KVS: LazyLock<KVS> = LazyLock::new(pulsar_kvs);
pub static DEFAULT_AUDIT_REDIS_KVS: LazyLock<KVS> = LazyLock::new(|| redis_kvs(AUDIT_REDIS_DEFAULT_CHANNEL));
pub static DEFAULT_AUDIT_POSTGRES_KVS: LazyLock<KVS> = LazyLock::new(postgres_kvs);
pub static DEFAULT_AUDIT_KAFKA_KVS: LazyLock<KVS> = LazyLock::new(kafka_kvs);
pub static DEFAULT_AUDIT_MYSQL_KVS: LazyLock<KVS> = LazyLock::new(|| mysql_kvs("rustfs_audit_logs"));