mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-20 03:22:18 +00:00
0bd53becb5
* feat(s3-types): add KMS service-control audit events Configuration changes and service start/stop are management-plane actions with no event name of their own, so they could not reach the audit pipeline at all. Append three variants for them, following the existing rule that KMS events are audit-only and live outside the `s3:` namespace, so no bucket notification selector can expand to them. * feat(admin): audit KMS management operations Every KMS admin endpoint now builds an OperationContext from the authenticated caller and hands it to the KMS layer, so the record the manager already produces carries the principal, source address and canonical request id instead of the internal placeholder. A new adapter maps those records onto the server's existing AuditEntry format and installs itself as the KMS audit sink at service assembly, so KMS activity reaches the targets a deployment already operates. The handlers emit directly for what the KMS layer cannot see: a request the authorization gate rejects, and the endpoints with no context-aware KMS entry point (data-key derivation and service control). Only the failure class is recorded, never the error message, and the new module joins the logging guardrail's checked files alongside the handlers it serves.
108 lines
3.5 KiB
Rust
108 lines
3.5 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.
|
|
|
|
//! Regressions for rule matching against the KMS event namespace.
|
|
//!
|
|
//! KMS events (backlog#1583) are appended to `EventName` for the audit sink,
|
|
//! but they must stay invisible to bucket notification rules: a subscriber
|
|
//! asking for `s3:ObjectCreated:*` — or for everything — must never receive
|
|
//! key management activity.
|
|
|
|
use super::RulesMap;
|
|
use rustfs_s3_types::EventName;
|
|
use rustfs_targets::arn::TargetID;
|
|
|
|
const KMS_EVENTS: &[EventName] = &[
|
|
EventName::KmsKeyCreated,
|
|
EventName::KmsKeyRotated,
|
|
EventName::KmsKeyEnabled,
|
|
EventName::KmsKeyDisabled,
|
|
EventName::KmsKeyDeletionScheduled,
|
|
EventName::KmsKeyDeletionCancelled,
|
|
EventName::KmsKeyDeleted,
|
|
EventName::KmsKeyAccessed,
|
|
EventName::KmsServiceConfigured,
|
|
EventName::KmsServiceStarted,
|
|
EventName::KmsServiceStopped,
|
|
];
|
|
|
|
fn test_target() -> TargetID {
|
|
TargetID::new("primary".to_string(), "webhook".to_string())
|
|
}
|
|
|
|
fn rules_for(events: &[EventName]) -> RulesMap {
|
|
let mut rules = RulesMap::new();
|
|
rules.add_rule_config(events, String::new(), test_target());
|
|
rules
|
|
}
|
|
|
|
#[test]
|
|
fn s3_wildcard_subscriptions_do_not_match_kms_events() {
|
|
let rules = rules_for(&[
|
|
EventName::ObjectCreatedAll,
|
|
EventName::ObjectAccessedAll,
|
|
EventName::ObjectRemovedAll,
|
|
EventName::ObjectTaggingAll,
|
|
EventName::ObjectReplicationAll,
|
|
EventName::ObjectRestoreAll,
|
|
EventName::ObjectTransitionAll,
|
|
EventName::LifecycleExpirationAll,
|
|
EventName::ObjectScannerAll,
|
|
]);
|
|
|
|
for event in KMS_EVENTS {
|
|
assert!(!rules.has_subscriber(event), "{event} must not have an S3 wildcard subscriber");
|
|
assert!(
|
|
rules.match_rules(*event, "any/object").is_empty(),
|
|
"{event} must not match any S3 wildcard rule"
|
|
);
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn everything_subscription_does_not_match_kms_events() {
|
|
let rules = rules_for(&[EventName::Everything]);
|
|
|
|
// Sanity: the catch-all really is subscribed to the S3 surface.
|
|
assert!(rules.has_subscriber(&EventName::ObjectCreatedPut));
|
|
|
|
for event in KMS_EVENTS {
|
|
assert!(!rules.has_subscriber(event), "{event} must stay outside the s3 catch-all");
|
|
assert!(
|
|
rules.match_rules(*event, "any/object").is_empty(),
|
|
"{event} must not match the s3 catch-all rule"
|
|
);
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn kms_subscription_does_not_leak_into_s3_matching() {
|
|
// The inverse direction: even an explicit KMS subscription must not widen
|
|
// the mask so that S3 events start matching a KMS-only rule.
|
|
let rules = rules_for(KMS_EVENTS);
|
|
|
|
for event in [
|
|
EventName::ObjectCreatedPut,
|
|
EventName::ObjectRemovedDelete,
|
|
EventName::ObjectAccessedGet,
|
|
EventName::BucketCreated,
|
|
] {
|
|
assert!(!rules.has_subscriber(&event), "{event} must not match a KMS-only rule");
|
|
assert!(
|
|
rules.match_rules(event, "any/object").is_empty(),
|
|
"{event} must not match a KMS-only rule"
|
|
);
|
|
}
|
|
}
|