use std::sync::Arc;
use std::sync::LazyLock;
use super::AllowRule;
use super::FieldClassification;
use super::FieldNameMatching;
use super::MaskingPolicy;
use super::RedactionFloor;
use super::RedactionPolicyBuilder;
use super::RedactionRules;
use super::SensitiveFieldRule;
use super::Sensitivity;
#[cfg(feature = "json")]
use super::UnkeyedJsonValuePolicy;
use super::UnknownFieldPolicy;
use super::internal::RedactionPolicyInner;
use super::redaction_limits::RedactionLimits;
pub(super) const STANDARD_EXTRA_FIELDS: &[(&str, Sensitivity)] = &[
("auth_app_token", Sensitivity::High),
("auth_user_token", Sensitivity::High),
("connection_string", Sensitivity::Secret),
("database_uri", Sensitivity::Secret),
("database_url", Sensitivity::Secret),
("license_key", Sensitivity::Medium),
("mysql_pwd", Sensitivity::Secret),
("rediscli_auth", Sensitivity::Secret),
("sig", Sensitivity::Secret),
("signature", Sensitivity::Secret),
];
static STANDARD_POLICY: LazyLock<RedactionPolicy> = LazyLock::new(|| {
RedactionPolicy::from_rules(
RedactionRules::new(
RedactionPolicyInner {
sensitive: Default::default(),
allow_exact: Default::default(),
allow_suffix: Default::default(),
matching: FieldNameMatching::ExactOrTokenSuffix,
unknown_field_policy: UnknownFieldPolicy::PassThrough,
},
Some(RedactionFloor::standard()),
),
MaskingPolicy::default(),
RedactionLimits::default(),
#[cfg(feature = "http")]
crate::formats::http::HttpPolicyBuilder::new()
.build()
.expect("the built-in HTTP policy must be valid"),
#[cfg(feature = "uri")]
crate::formats::uri::UriPolicyBuilder::new()
.build()
.expect("the built-in URI policy must be valid"),
#[cfg(feature = "json")]
UnkeyedJsonValuePolicy::PassThrough,
false,
)
});
static STRICT_POLICY: LazyLock<RedactionPolicy> = LazyLock::new(|| {
RedactionPolicy::from_rules(
RedactionRules::new(
RedactionPolicyInner {
sensitive: Default::default(),
allow_exact: Default::default(),
allow_suffix: Default::default(),
matching: FieldNameMatching::ExactOrTokenSuffix,
unknown_field_policy: UnknownFieldPolicy::Redact(Sensitivity::Secret),
},
Some(RedactionFloor::standard()),
),
MaskingPolicy::default(),
RedactionLimits::default(),
#[cfg(feature = "http")]
{
let mut http = crate::formats::http::HttpPolicyBuilder::new();
http.url_path_mut(crate::formats::http::UrlPathPolicy::Redact);
http.text_body_mut(crate::formats::http::TextBodyPolicy::Redact);
http.build().expect("the built-in HTTP policy must be valid")
},
#[cfg(feature = "uri")]
{
let mut uri = crate::formats::uri::UriPolicyBuilder::new();
uri.path_policy_mut(crate::formats::uri::UriPathPolicy::Redact);
uri.build().expect("the built-in URI policy must be valid")
},
#[cfg(feature = "json")]
UnkeyedJsonValuePolicy::Redact,
false,
)
});
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct RedactionPolicy {
disabled: bool,
rules: RedactionRules,
masking: Arc<MaskingPolicy>,
limits: RedactionLimits,
#[cfg(feature = "http")]
http: Arc<crate::formats::http::HttpPolicy>,
#[cfg(feature = "uri")]
uri: Arc<crate::formats::uri::UriPolicy>,
#[cfg(feature = "json")]
unkeyed_json_value_policy: UnkeyedJsonValuePolicy,
}
impl RedactionPolicy {
#[must_use]
#[inline(always)]
pub fn standard() -> Self {
STANDARD_POLICY.clone()
}
#[must_use]
#[inline(always)]
pub fn strict() -> Self {
STRICT_POLICY.clone()
}
#[must_use]
pub fn disabled() -> Self {
let mut policy = Self::standard();
policy.disabled = true;
policy
}
#[must_use]
#[inline(always)]
pub fn builder() -> RedactionPolicyBuilder {
RedactionPolicyBuilder::new()
}
#[must_use]
pub(crate) fn from_rules(
rules: RedactionRules,
masking: MaskingPolicy,
limits: RedactionLimits,
#[cfg(feature = "http")] http: crate::formats::http::HttpPolicy,
#[cfg(feature = "uri")] uri: crate::formats::uri::UriPolicy,
#[cfg(feature = "json")] unkeyed_json_value_policy: UnkeyedJsonValuePolicy,
disabled: bool,
) -> Self {
Self {
disabled,
rules,
masking: Arc::new(masking),
limits,
#[cfg(feature = "http")]
http: Arc::new(http),
#[cfg(feature = "uri")]
uri: Arc::new(uri),
#[cfg(feature = "json")]
unkeyed_json_value_policy,
}
}
#[must_use]
#[inline(always)]
pub const fn is_disabled(&self) -> bool {
self.disabled
}
#[must_use]
#[inline(always)]
pub const fn limits(&self) -> &RedactionLimits {
&self.limits
}
#[must_use]
#[cfg(feature = "http")]
#[inline(always)]
pub fn http(&self) -> &crate::formats::http::HttpPolicy {
self.http.as_ref()
}
#[must_use]
#[cfg(feature = "uri")]
#[inline(always)]
pub fn uri(&self) -> &crate::formats::uri::UriPolicy {
self.uri.as_ref()
}
#[must_use]
#[cfg(feature = "json")]
#[inline(always)]
pub const fn unkeyed_json_value_policy(&self) -> UnkeyedJsonValuePolicy {
self.unkeyed_json_value_policy
}
#[must_use]
#[inline(always)]
pub const fn rules(&self) -> &RedactionRules {
&self.rules
}
#[must_use]
#[inline(always)]
pub fn floor(&self) -> Option<&RedactionFloor> {
self.rules.floor()
}
#[must_use]
#[inline(always)]
pub fn sensitivity_for(&self, field: &str) -> Option<Sensitivity> {
self.rules.sensitivity_for(field)
}
#[must_use]
#[inline(always)]
pub fn matching(&self) -> FieldNameMatching {
self.rules.matching()
}
#[must_use]
#[inline(always)]
pub fn unknown_field_policy(&self) -> UnknownFieldPolicy {
self.rules.unknown_field_policy()
}
#[must_use]
#[inline(always)]
pub fn masking(&self) -> &MaskingPolicy {
self.masking.as_ref()
}
#[inline(always)]
pub fn application_sensitive_rules(&self) -> impl Iterator<Item = SensitiveFieldRule<'_>> {
self.rules.application_sensitive_rules()
}
#[inline(always)]
pub fn application_allow_rules(&self) -> impl Iterator<Item = AllowRule<'_>> {
self.rules.application_allow_rules()
}
#[must_use]
#[inline(always)]
pub fn set_disabled(&mut self, disabled: bool) -> &mut Self {
self.disabled = disabled;
self
}
#[must_use]
#[inline(always)]
pub fn to_builder(&self) -> RedactionPolicyBuilder {
RedactionPolicyBuilder::from_policy(self)
}
#[must_use]
#[inline(always)]
pub fn with_floor(mut self, floor: RedactionFloor) -> Self {
self.rules = self.rules.with_floor(floor);
self
}
#[must_use]
#[inline(always)]
pub fn add_floor(mut self, floor: RedactionFloor) -> Self {
self.rules = self.rules.add_floor(floor);
self
}
#[must_use]
#[inline(always)]
pub fn disable_floor(mut self) -> Self {
self.rules = self.rules.disable_floor();
self
}
#[inline(always)]
#[must_use]
pub fn classify_field<'a>(&'a self, field: &str) -> FieldClassification<'a> {
self.rules.classify_field(field)
}
#[must_use]
#[inline(always)]
pub(crate) fn sensitivity_for_exact(&self, field: &str) -> Option<Sensitivity> {
self.rules.sensitivity_for_exact(field)
}
#[inline(always)]
pub(crate) fn resolve_field_exact(&self, field: &str) -> super::ResolvedField {
self.rules.resolve_field_exact(field)
}
#[doc(hidden)]
#[cfg(feature = "uri")]
#[inline(always)]
pub(crate) fn with_masking(mut self, masking: MaskingPolicy) -> Self {
self.masking = Arc::new(masking);
self
}
#[inline(always)]
#[must_use]
pub(crate) fn resolve_field(&self, field: &str) -> super::ResolvedField {
self.rules.resolve_field(field)
}
}
impl Default for RedactionPolicy {
#[inline(always)]
fn default() -> Self {
STANDARD_POLICY.clone()
}
}