From d9df3afe3379a6edfc88f26eb971d94ca581bbff Mon Sep 17 00:00:00 2001 From: "mae.kasza" Date: Thu, 22 Sep 2022 13:55:51 +0200 Subject: [PATCH 01/15] Revert "Add redaction control based on environment variables (#7)" Due to the way cargo works .veil.toml can't impact other crates consistently. This reverts commit 69dd762f1ee01003c058a0b6b9dee2a19833b06e. --- Cargo.lock | 174 ------------- Cargo.toml | 16 +- README.md | 37 --- src/lib.rs | 37 --- src/private.rs | 37 +-- veil-macros/Cargo.toml | 9 +- veil-macros/src/enums.rs | 8 - veil-macros/src/env.rs | 235 ------------------ veil-macros/src/fmt.rs | 31 +-- veil-macros/src/lib.rs | 9 - .../environment-aware-disable/Cargo.toml | 9 - .../environment-aware-disable/src/lib.rs | 21 -- .../environment-aware-fallback-off/.veil.toml | 2 - .../environment-aware-fallback-off/Cargo.toml | 9 - .../environment-aware-fallback-off/src/lib.rs | 13 - .../environment-aware-fallback-on/.veil.toml | 2 - .../environment-aware-fallback-on/Cargo.toml | 9 - .../environment-aware-fallback-on/src/lib.rs | 13 - .../.veil.toml | 2 - .../Cargo.toml | 8 - .../src/lib.rs | 13 - veil-tests/environment-aware/.veil.toml | 3 - veil-tests/environment-aware/Cargo.toml | 10 - veil-tests/environment-aware/src/lib.rs | 53 ---- 24 files changed, 5 insertions(+), 755 deletions(-) delete mode 100644 veil-macros/src/env.rs delete mode 100644 veil-tests/environment-aware-disable/Cargo.toml delete mode 100644 veil-tests/environment-aware-disable/src/lib.rs delete mode 100644 veil-tests/environment-aware-fallback-off/.veil.toml delete mode 100644 veil-tests/environment-aware-fallback-off/Cargo.toml delete mode 100644 veil-tests/environment-aware-fallback-off/src/lib.rs delete mode 100644 veil-tests/environment-aware-fallback-on/.veil.toml delete mode 100644 veil-tests/environment-aware-fallback-on/Cargo.toml delete mode 100644 veil-tests/environment-aware-fallback-on/src/lib.rs delete mode 100644 veil-tests/environment-aware-fallback-panic/.veil.toml delete mode 100644 veil-tests/environment-aware-fallback-panic/Cargo.toml delete mode 100644 veil-tests/environment-aware-fallback-panic/src/lib.rs delete mode 100644 veil-tests/environment-aware/.veil.toml delete mode 100644 veil-tests/environment-aware/Cargo.toml delete mode 100644 veil-tests/environment-aware/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index a7d5d1b7..69d174ab 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11,24 +11,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "autocfg" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" - -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - [[package]] name = "glob" version = "0.3.0" @@ -41,28 +23,6 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c8af84674fe1f223a982c933a0ee1086ac4d4052aa0fb8060c12c6ad838e754" -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" - -[[package]] -name = "libc" -version = "0.2.132" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8371e4e5341c3a96db127eb2465ac681ced4c433e01dd0e938adbef26ba93ba5" - -[[package]] -name = "lock_api" -version = "0.4.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f80bf5aacaf25cbfc8210d1cfb718f2bf3b11c4c54e5afe36c236853a8ec390" -dependencies = [ - "autocfg", - "scopeguard", -] - [[package]] name = "memchr" version = "2.5.0" @@ -75,29 +35,6 @@ version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2f7254b99e31cad77da24b08ebf628882739a608578bb1bcdfc1f9c21260d7c0" -[[package]] -name = "parking_lot" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" -dependencies = [ - "lock_api", - "parking_lot_core", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09a279cbf25cb0757810394fbc1e359949b59e348145c643a939a525692e6929" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall", - "smallvec", - "windows-sys", -] - [[package]] name = "proc-macro2" version = "1.0.43" @@ -116,15 +53,6 @@ dependencies = [ "proc-macro2", ] -[[package]] -name = "redox_syscall" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" -dependencies = [ - "bitflags", -] - [[package]] name = "regex" version = "1.6.0" @@ -157,20 +85,11 @@ dependencies = [ "winapi-util", ] -[[package]] -name = "scopeguard" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" - [[package]] name = "serde" version = "1.0.144" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0f747710de3dcd43b88c9168773254e809d8ddbdf9653b84e2554ab219f17860" -dependencies = [ - "serde_derive", -] [[package]] name = "serde_derive" @@ -194,12 +113,6 @@ dependencies = [ "serde", ] -[[package]] -name = "smallvec" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1" - [[package]] name = "syn" version = "1.0.100" @@ -254,7 +167,6 @@ checksum = "c4f5b37a154999a8f3f98cc23a628d850e154479cd94decf3414696e12e31aaf" name = "veil" version = "0.1.0" dependencies = [ - "lazy_static", "veil-macros", ] @@ -262,12 +174,9 @@ dependencies = [ name = "veil-macros" version = "0.1.0" dependencies = [ - "lazy_static", "proc-macro2", "quote", - "serde", "syn", - "toml", ] [[package]] @@ -280,46 +189,6 @@ dependencies = [ "walkdir", ] -[[package]] -name = "veil-tests-environment-aware" -version = "0.1.0" -dependencies = [ - "parking_lot", - "veil", - "veil-tests", -] - -[[package]] -name = "veil-tests-environment-aware-disable" -version = "0.1.0" -dependencies = [ - "veil", - "veil-tests", -] - -[[package]] -name = "veil-tests-environment-aware-fallback-off" -version = "0.1.0" -dependencies = [ - "veil", - "veil-tests", -] - -[[package]] -name = "veil-tests-environment-aware-fallback-on" -version = "0.1.0" -dependencies = [ - "veil", - "veil-tests", -] - -[[package]] -name = "veil-tests-environment-aware-fallback-panic" -version = "0.1.0" -dependencies = [ - "veil", -] - [[package]] name = "walkdir" version = "2.3.2" @@ -361,46 +230,3 @@ name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - -[[package]] -name = "windows-sys" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" -dependencies = [ - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_msvc", -] - -[[package]] -name = "windows_aarch64_msvc" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" - -[[package]] -name = "windows_i686_gnu" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" - -[[package]] -name = "windows_i686_msvc" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" diff --git a/Cargo.toml b/Cargo.toml index 20ffee6b..3c7bb596 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,19 +7,7 @@ license = "MIT" repository = "https://github.com/primait/veil" [workspace] -members = [ - "veil-macros", - "veil-tests", - "veil-tests/environment-aware", - "veil-tests/environment-aware-fallback-on", - "veil-tests/environment-aware-fallback-off", - "veil-tests/environment-aware-fallback-panic", - "veil-tests/environment-aware-disable", -] - -[features] -environment-aware = ["veil-macros/environment-aware", "lazy_static"] +members = ["veil-macros", "veil-tests"] [dependencies] -veil-macros = { path = "veil-macros" } -lazy_static = { version = "1", optional = true } +veil-macros = { path = "veil-macros" } \ No newline at end of file diff --git a/README.md b/README.md index b28ba882..58b9a5b4 100644 --- a/README.md +++ b/README.md @@ -85,40 +85,3 @@ enum InsuranceStatus { }, } ``` - -# Environment Awareness - -You can configure Veil to redact or skip redacting data based on environment variables. Enable the `environment-aware` Cargo feature like so in your Cargo.toml: - -```toml -[dependencies] -veil = { version = "0.1", features = ["environment-aware"] } -``` - -## `VEIL_DISABLE_REDACTION` - -Redaction can be completely disabled by setting the `VEIL_DISABLE_REDACTION` environment variable. This is only checked once during the program lifetime for security purposes. - -## `.veil.toml` - -Redaction can also be configured on a per-project basis using a `.veil.toml` file. Put this file in your crate or workspace root and Veil will read it at compile time. - -**Please note, if you change the file, Veil won't see the changes until you do a clean build of your crate.** - -### Example - -`APP_ENV` is just an example here. You can match multiple environment variables with any UTF-8 name and value(s). - -```toml -[env.APP_ENV] -redact = ["production", "staging"] # redact data if "APP_ENV" is set to any of these values -skip-redact = ["dev", "qa"] # SKIP redacting data if "APP_ENV" is set to any of these values - -# If "APP_ENV" isn't set or isn't recognised... -[fallback] -redact = true # do redact data (default) -# OR -redact = false # don't redact data -# OR -redact = "panic" # panic at runtime -``` diff --git a/src/lib.rs b/src/lib.rs index 26fa337e..4b07ff21 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -204,43 +204,6 @@ //! } //! ``` //! -//! # Environment Awareness -//! -//! You can configure Veil to redact or skip redacting data based on environment variables. Enable the `environment-aware` Cargo feature like so in your Cargo.toml: -//! -//! ```toml -//! [dependencies] -//! veil = { version = "0.1", features = ["environment-aware"] } -//! ``` -//! -//! ## `VEIL_DISABLE_REDACTION` -//! -//! Redaction can be completely disabled by setting the `VEIL_DISABLE_REDACTION` environment variable. This is only checked once during the program lifetime for security purposes. -//! -//! ## `.veil.toml` -//! -//! Redaction can also be configured on a per-project basis using a `.veil.toml` file. Put this file in your crate or workspace root and Veil will read it at compile time. -//! -//! **Please note, if you change the file, Veil won't see the changes until you do a clean build of your crate.** -//! -//! ### Example -//! -//! `APP_ENV` is just an example here. You can match multiple environment variables with any UTF-8 name and value(s). -//! -//! ```toml -//! [env.APP_ENV] -//! redact = ["production", "staging"] # redact data if "APP_ENV" is set to any of these values -//! skip-redact = ["dev", "qa"] # SKIP redacting data if "APP_ENV" is set to any of these values -//! -//! ## If "APP_ENV" isn't set or isn't recognised... -//! [fallback] -//! redact = true # do redact data (default) -//! ## OR -//! redact = false # don't redact data -//! ## OR -//! redact = "panic" # panic at runtime -//! ``` -//! //! # Limitations //! //! Currently, this macro only supports [`std::fmt::Debug`] formatting with no modifiers (`{:?}`) or the "alternate" modifier (`{:#?}`). diff --git a/src/private.rs b/src/private.rs index e8ff231f..f9220aed 100644 --- a/src/private.rs +++ b/src/private.rs @@ -107,22 +107,9 @@ impl RedactFlags { } } -pub fn redact( - this: &dyn Debug, - flags: RedactFlags, - #[cfg(feature = "environment-aware")] env_is_redaction_enabled: bool, -) -> DisplayDebug { +pub fn redact(this: &dyn Debug, flags: RedactFlags) -> DisplayDebug { let mut redacted = String::new(); - #[cfg(feature = "environment-aware")] - if !env_is_redaction_enabled { - return DisplayDebug(if flags.debug_alternate { - format!("{:#?}", this) - } else { - format!("{:?}", this) - }); - } - (|| { if flags.fixed > 0 { flags.redact_fixed(flags.fixed as usize, &mut redacted); @@ -165,25 +152,3 @@ pub fn redact( DisplayDebug(redacted) } - -#[cfg(feature = "environment-aware")] -pub fn env_is_redaction_enabled() -> Option { - // First check VEIL_DISABLE_REDACTION, which overrides any config file - lazy_static::lazy_static! { - // We deliberately only look this up once. - // If an attacker somehow is able to change environment variables, we don't want to give them a way of revealing sensitive data. - static ref IS_REDACTION_DISABLED: bool = std::env::var("VEIL_DISABLE_REDACTION").is_ok(); - } - if *IS_REDACTION_DISABLED { - return Some(false); - } - - // We'll run the `env_is_redaction_enabled!` macro here - // This is handled by the `fmt` module - // This is needed because we need CARGO_MANIFEST_DIR to be set by the crate being built, - // rather than this crate itself! - None -} - -#[cfg(feature = "environment-aware")] -pub use veil_macros::env_is_redaction_enabled; diff --git a/veil-macros/Cargo.toml b/veil-macros/Cargo.toml index 6cf530ea..2d5573c8 100644 --- a/veil-macros/Cargo.toml +++ b/veil-macros/Cargo.toml @@ -3,17 +3,10 @@ name = "veil-macros" version = "0.1.0" edition = "2021" -[features] -environment-aware = ["lazy_static", "toml", "serde"] - [lib] proc-macro = true [dependencies] syn = { version = "1", features = ["full"] } quote = "1" -proc-macro2 = "1" - -lazy_static = { version = "1", optional = true } -toml = { version = "0.5", optional = true } -serde = { version = "1", features = ["derive"], optional = true } +proc-macro2 = "1" \ No newline at end of file diff --git a/veil-macros/src/enums.rs b/veil-macros/src/enums.rs index ee1909c3..d6aa52a5 100644 --- a/veil-macros/src/enums.rs +++ b/veil-macros/src/enums.rs @@ -178,21 +178,13 @@ pub(super) fn derive_redact( }); } - // Generate the `__veil_env_is_redaction_enabled` function - // Used by the `environment-aware` feature - // See the `env` module - let __veil_env_is_redaction_enabled = fmt::__veil_env_is_redaction_enabled(); - Ok(quote! { impl ::std::fmt::Debug for #name_ident { fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { - #__veil_env_is_redaction_enabled - let debug_alternate = f.alternate(); match self { #(Self::#variant_idents #variant_destructures => { #variant_bodies; },)* } - Ok(()) } } diff --git a/veil-macros/src/env.rs b/veil-macros/src/env.rs deleted file mode 100644 index 593883f0..00000000 --- a/veil-macros/src/env.rs +++ /dev/null @@ -1,235 +0,0 @@ -//! If the `environment-aware` feature is enabled, the user can configure Veil's behaviour in different environments. -//! -//! If the environment variable `VEIL_DISBALE_REDACTION` is set, Veil will not redact any data. -//! -//! If the user's project contains a `.veil.toml` file, Veil will use the configuration in that file to figure out whether to redact data. -//! This is done at compile time. Runtime changes to this file will have no effect. -//! -//! The configuration file allows the user to specify what environment variables and their values should enable or disable redaction. -//! -//! For example, I can configure the file to redact when APP_ENV="production", and not redact when APP_ENV="development". - -use lazy_static::lazy_static; -use proc_macro::TokenStream; -use quote::ToTokens; -use serde::Deserialize; -use std::{collections::BTreeMap, path::Path}; -use syn::spanned::Spanned; - -#[derive(Deserialize)] -#[serde(untagged)] -enum FallbackBehavior { - Redact(bool), - Panic(String), -} -impl ToTokens for FallbackBehavior { - fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) { - match self { - Self::Redact(redact) => redact.to_tokens(tokens), - Self::Panic(_) => quote! { panic!("Veil expected environment variables to be set that determine whether sensitive data should be redacted or not. Please refer to .veil.toml in the project files to see what Veil was expecting.") }.to_tokens(tokens) - } - } -} - -#[derive(Deserialize)] -/// Should we redact data based on the values of environment variables? -struct EnvRedactConfig { - #[serde(default)] - /// Redaction should be ON if the environment variable is set to one of these values. - redact: Vec, - - #[serde(default)] - #[serde(rename = "skip-redact")] - /// Redaction should be OFF if the environment variable is set to one of these values. - skip_redact: Vec, -} - -#[derive(Deserialize)] -/// If none of those environment variables are present... -struct FallbackRedactConfig { - /// ...then we should [redact|not redact] the data. - redact: FallbackBehavior, -} -impl Default for FallbackRedactConfig { - fn default() -> Self { - Self { - redact: FallbackBehavior::Redact(true), - } - } -} - -#[derive(Deserialize)] -struct TomlVeilConfig { - #[serde(default)] - fallback: FallbackRedactConfig, - env: Option>, -} - -#[derive(Default)] -pub struct VeilConfig { - fallback: FallbackRedactConfig, - env: BTreeMap, -} -impl VeilConfig { - pub fn read(path: &Path) -> Result { - let config = std::fs::read_to_string(path)?; - let config: TomlVeilConfig = toml::from_str(&config)?; - - // Ensure there are no duplicate key-value environment variable pairs. - if let Some(env) = &config.env { - let mut pairs = Vec::new(); - for (key, config) in env { - // Ensure there are no empty environment variable configs. - if config.redact.is_empty() && config.skip_redact.is_empty() { - return Err(VeilConfigError::Custom(format!( - "Environment variable {key:?} has an empty configuration" - ))); - } - - for value in [&config.redact, &config.skip_redact].into_iter().flatten() { - let pair = (key.as_str(), value.as_str()); - if pairs.contains(&pair) { - return Err(VeilConfigError::Custom(format!( - "duplicate key-value environment variable pair: {pair:?}" - ))); - } else { - pairs.push(pair); - } - } - } - } - - // Ensure the fallback is configured correctly. - if let FallbackBehavior::Panic(value) = &config.fallback.redact { - if value != "panic" { - return Err(VeilConfigError::Custom( - "fallback redaction behavior must be \"panic\"".to_string(), - )); - } - } - - Ok(Self { - env: config.env.unwrap_or_default(), - fallback: config.fallback, - }) - } -} - -#[derive(Debug)] -pub enum VeilConfigError { - IoError(std::io::Error), - TomlError(toml::de::Error), - Custom(String), -} -impl std::error::Error for VeilConfigError {} -impl std::fmt::Display for VeilConfigError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - Self::IoError(err) => write!(f, "I/O error reading .veil.toml: {err}"), - Self::TomlError(err) => write!(f, "TOML error reading .veil.toml: {err:#?}"), - Self::Custom(err) => write!(f, ".veil.toml error: {err}"), - } - } -} -impl From for VeilConfigError { - #[inline] - fn from(err: std::io::Error) -> Self { - Self::IoError(err) - } -} -impl From for VeilConfigError { - #[inline] - fn from(err: toml::de::Error) -> Self { - Self::TomlError(err) - } -} - -lazy_static! { - static ref CACHED_VEIL_CONFIG: Result = find_config(); -} -fn find_config() -> Result { - let manifest_dir = match std::env::var_os("CARGO_MANIFEST_DIR") { - Some(manifest_dir) => manifest_dir, - None => return Ok(Default::default()), - }; - - let mut manifest_dir = Path::new(&manifest_dir); - - // Walk up the directory tree until we find a .veil.toml file - // We should stop at the workspace root - let config_path = loop { - let config_path = manifest_dir.join(".veil.toml"); - if config_path.is_file() { - break Some(config_path); - } - - // HACK! We can detect the workspace root by looking for Cargo.lock - if manifest_dir.join("Cargo.lock").is_file() { - break None; - } - - manifest_dir = match manifest_dir.parent() { - Some(parent) => parent, - None => break None, - }; - }; - - let config_path = match config_path { - Some(config_path) => config_path, - None => return Ok(Default::default()), - }; - - VeilConfig::read(&config_path) -} - -/// This macro expands to a function that returns true or false depending on whether the -/// data should be redacted based on the values of environment variables, configured by -/// `.veil.toml` in the project's files, if present. -pub fn env_is_redaction_enabled(input: TokenStream) -> TokenStream { - let config = match &*CACHED_VEIL_CONFIG { - Ok(config) => config, - Err(err) => { - return syn::Error::new(proc_macro2::TokenStream::from(input).span(), err.to_string()) - .into_compile_error() - .into() - } - }; - - let env = config.env.iter().map(|(key, config)| { - let redacts = &config.redact; - let skips = &config.skip_redact; - quote! { - if let Ok(value) = ::std::env::var(#key) { - static REDACTS: &[&str] = &[#(#redacts),*]; - if REDACTS.contains(&value.as_str()) { - return true; - } - - static SKIPS: &[&str] = &[#(#skips),*]; - if SKIPS.contains(&value.as_str()) { - return false; - } - } - } - }); - - let fallback = config.fallback.redact.to_token_stream(); - if config.env.is_empty() { - quote! { - #[inline(always)] - fn __veil_env_is_redaction_enabled() -> bool { - #fallback - } - } - .into() - } else { - quote! { - #[inline(never)] - fn __veil_env_is_redaction_enabled() -> bool { - #(#env)* - #fallback - } - } - .into() - } -} diff --git a/veil-macros/src/fmt.rs b/veil-macros/src/fmt.rs index 24d6626b..ed1e6946 100644 --- a/veil-macros/src/fmt.rs +++ b/veil-macros/src/fmt.rs @@ -115,18 +115,11 @@ impl FormatData<'_> { } } - // Generate the `__veil_env_is_redaction_enabled` function - // Used by the `environment-aware` feature - // See the `env` module - let __veil_env_is_redaction_enabled = __veil_env_is_redaction_enabled(); - Ok(match self { Self::FieldsNamed(syn::FieldsNamed { named, .. }) => { let field_names = named.iter().map(|field| field.ident.as_ref().unwrap().to_string()); quote! { - #__veil_env_is_redaction_enabled - f.debug_struct(&#name.as_ref()) #( .field(#field_names, &#field_bodies) @@ -137,8 +130,6 @@ impl FormatData<'_> { Self::FieldsUnnamed(syn::FieldsUnnamed { .. }) => { quote! { - #__veil_env_is_redaction_enabled - f.debug_tuple(&#name.as_ref()) #( .field(&#field_bodies) @@ -161,34 +152,14 @@ pub(crate) fn generate_redact_call( // This is the one place where we actually track whether the derive macro had any effect! Nice. unused.redacted_something(); - // Environment awareness (we assume that we injected the `__veil_env_is_redaction_enabled` function earlier) - let env_is_redaction_enabled = if cfg!(feature = "environment-aware") { - quote! { - , ::veil::private::env_is_redaction_enabled().unwrap_or_else(__veil_env_is_redaction_enabled) - } - } else { - proc_macro2::TokenStream::default() - }; - quote! { ::veil::private::redact(#field_accessor, ::veil::private::RedactFlags { debug_alternate, is_option: #is_option, #field_flags - } #env_is_redaction_enabled) + }) } } else { field_accessor } } - -/// Generates the `__veil_env_is_redaction_enabled` function -pub fn __veil_env_is_redaction_enabled() -> proc_macro2::TokenStream { - if cfg!(feature = "environment-aware") { - // Generate a function that returns whether redaction is enabled based on the environment. - // The compiler will be able to deduplicate the function, so we won't be generating hundreds of copies of it in the final binary. - quote! { ::veil::private::env_is_redaction_enabled!(); } - } else { - proc_macro2::TokenStream::default() - } -} diff --git a/veil-macros/src/lib.rs b/veil-macros/src/lib.rs index bcc685f8..0d43f334 100644 --- a/veil-macros/src/lib.rs +++ b/veil-macros/src/lib.rs @@ -73,12 +73,3 @@ pub fn derive_redact(item: TokenStream) -> TokenStream { Err(err) => err.into_compile_error().into(), } } - -#[cfg(feature = "environment-aware")] -mod env; - -#[cfg(feature = "environment-aware")] -#[proc_macro] -pub fn env_is_redaction_enabled(input: TokenStream) -> TokenStream { - env::env_is_redaction_enabled(input) -} diff --git a/veil-tests/environment-aware-disable/Cargo.toml b/veil-tests/environment-aware-disable/Cargo.toml deleted file mode 100644 index 4d1c9411..00000000 --- a/veil-tests/environment-aware-disable/Cargo.toml +++ /dev/null @@ -1,9 +0,0 @@ -[package] -name = "veil-tests-environment-aware-disable" -version = "0.1.0" -edition = "2021" -publish = false - -[dependencies] -veil = { path = "../../", features = ["environment-aware"] } -veil-tests = { path = "../" } diff --git a/veil-tests/environment-aware-disable/src/lib.rs b/veil-tests/environment-aware-disable/src/lib.rs deleted file mode 100644 index db7096b4..00000000 --- a/veil-tests/environment-aware-disable/src/lib.rs +++ /dev/null @@ -1,21 +0,0 @@ -//! This needs its own crate because VEIL_DISABLE_REDACTION is only checked once -//! and another test in the other crates might run first, causing THIS test to fail. - -#![cfg_attr(not(test), allow(unused))] - -use veil::Redact; -use veil_tests::{assert_has_sensitive_data, SENSITIVE_DATA}; - -#[derive(Redact)] -#[redact(all, partial)] -struct Redactable(&'static str); - -#[test] -fn test_disable_redact_env_var() { - std::env::set_var("VEIL_DISABLE_REDACTION", "1"); - assert_has_sensitive_data(Redactable(SENSITIVE_DATA[1])); - - // Ensure it's only checked once - std::env::remove_var("VEIL_DISABLE_REDACTION"); - assert_has_sensitive_data(Redactable(SENSITIVE_DATA[1])); -} diff --git a/veil-tests/environment-aware-fallback-off/.veil.toml b/veil-tests/environment-aware-fallback-off/.veil.toml deleted file mode 100644 index d87ecc8c..00000000 --- a/veil-tests/environment-aware-fallback-off/.veil.toml +++ /dev/null @@ -1,2 +0,0 @@ -[fallback] -redact = false diff --git a/veil-tests/environment-aware-fallback-off/Cargo.toml b/veil-tests/environment-aware-fallback-off/Cargo.toml deleted file mode 100644 index ef56b5e8..00000000 --- a/veil-tests/environment-aware-fallback-off/Cargo.toml +++ /dev/null @@ -1,9 +0,0 @@ -[package] -name = "veil-tests-environment-aware-fallback-off" -version = "0.1.0" -edition = "2021" -publish = false - -[dependencies] -veil = { path = "../../", features = ["environment-aware"] } -veil-tests = { path = "../" } diff --git a/veil-tests/environment-aware-fallback-off/src/lib.rs b/veil-tests/environment-aware-fallback-off/src/lib.rs deleted file mode 100644 index b5ca97c8..00000000 --- a/veil-tests/environment-aware-fallback-off/src/lib.rs +++ /dev/null @@ -1,13 +0,0 @@ -#![cfg_attr(not(test), allow(unused))] - -use veil::Redact; -use veil_tests::{assert_has_sensitive_data, SENSITIVE_DATA}; - -#[derive(Redact)] -#[redact(all, partial)] -struct Redactable(&'static str); - -#[test] -fn test_fallback_redact_off() { - assert_has_sensitive_data(Redactable(SENSITIVE_DATA[1])); -} diff --git a/veil-tests/environment-aware-fallback-on/.veil.toml b/veil-tests/environment-aware-fallback-on/.veil.toml deleted file mode 100644 index 39ad76ac..00000000 --- a/veil-tests/environment-aware-fallback-on/.veil.toml +++ /dev/null @@ -1,2 +0,0 @@ -[fallback] -redact = true diff --git a/veil-tests/environment-aware-fallback-on/Cargo.toml b/veil-tests/environment-aware-fallback-on/Cargo.toml deleted file mode 100644 index d4bd71fc..00000000 --- a/veil-tests/environment-aware-fallback-on/Cargo.toml +++ /dev/null @@ -1,9 +0,0 @@ -[package] -name = "veil-tests-environment-aware-fallback-on" -version = "0.1.0" -edition = "2021" -publish = false - -[dependencies] -veil = { path = "../../", features = ["environment-aware"] } -veil-tests = { path = "../" } diff --git a/veil-tests/environment-aware-fallback-on/src/lib.rs b/veil-tests/environment-aware-fallback-on/src/lib.rs deleted file mode 100644 index 21b68719..00000000 --- a/veil-tests/environment-aware-fallback-on/src/lib.rs +++ /dev/null @@ -1,13 +0,0 @@ -#![cfg_attr(not(test), allow(unused))] - -use veil::Redact; -use veil_tests::{assert_no_sensitive_data, SENSITIVE_DATA}; - -#[derive(Redact)] -#[redact(all, partial)] -struct Redactable(&'static str); - -#[test] -fn test_fallback_redact_on() { - assert_no_sensitive_data(Redactable(SENSITIVE_DATA[1])); -} diff --git a/veil-tests/environment-aware-fallback-panic/.veil.toml b/veil-tests/environment-aware-fallback-panic/.veil.toml deleted file mode 100644 index 371629c0..00000000 --- a/veil-tests/environment-aware-fallback-panic/.veil.toml +++ /dev/null @@ -1,2 +0,0 @@ -[fallback] -redact = "panic" diff --git a/veil-tests/environment-aware-fallback-panic/Cargo.toml b/veil-tests/environment-aware-fallback-panic/Cargo.toml deleted file mode 100644 index 1371ba0b..00000000 --- a/veil-tests/environment-aware-fallback-panic/Cargo.toml +++ /dev/null @@ -1,8 +0,0 @@ -[package] -name = "veil-tests-environment-aware-fallback-panic" -version = "0.1.0" -edition = "2021" -publish = false - -[dependencies] -veil = { path = "../../", features = ["environment-aware"] } diff --git a/veil-tests/environment-aware-fallback-panic/src/lib.rs b/veil-tests/environment-aware-fallback-panic/src/lib.rs deleted file mode 100644 index cbd849f4..00000000 --- a/veil-tests/environment-aware-fallback-panic/src/lib.rs +++ /dev/null @@ -1,13 +0,0 @@ -#![cfg_attr(not(test), allow(unused))] - -use veil::Redact; - -#[derive(Redact)] -#[redact(all, partial)] -struct Redactable(&'static str); - -#[test] -#[should_panic] -fn test_fallback_redact_on() { - format!("{:?}", Redactable("")); -} diff --git a/veil-tests/environment-aware/.veil.toml b/veil-tests/environment-aware/.veil.toml deleted file mode 100644 index 352e18e5..00000000 --- a/veil-tests/environment-aware/.veil.toml +++ /dev/null @@ -1,3 +0,0 @@ -[env.APP_ENV] -skip-redact = ["dev", "qa"] -redact = ["production", "staging"] diff --git a/veil-tests/environment-aware/Cargo.toml b/veil-tests/environment-aware/Cargo.toml deleted file mode 100644 index f4b8e3b5..00000000 --- a/veil-tests/environment-aware/Cargo.toml +++ /dev/null @@ -1,10 +0,0 @@ -[package] -name = "veil-tests-environment-aware" -version = "0.1.0" -edition = "2021" -publish = false - -[dependencies] -parking_lot = "0.12" # needed for non-poisoning mutex -veil = { path = "../../", features = ["environment-aware"] } -veil-tests = { path = "../" } diff --git a/veil-tests/environment-aware/src/lib.rs b/veil-tests/environment-aware/src/lib.rs deleted file mode 100644 index 58483204..00000000 --- a/veil-tests/environment-aware/src/lib.rs +++ /dev/null @@ -1,53 +0,0 @@ -#![cfg_attr(not(test), allow(unused))] - -use parking_lot::Mutex; -use veil::Redact; -use veil_tests::{assert_has_sensitive_data, assert_no_sensitive_data}; - -const SENSITIVE_DATA: &str = veil_tests::SENSITIVE_DATA[1]; - -static ENVIRONMENT_LOCK: Mutex<()> = parking_lot::const_mutex(()); - -#[derive(Redact)] -#[redact(all, partial)] -struct Redactable(&'static str); - -#[test] -fn test_production() { - // We've set up redaction to happen when APP_ENV="production" - let _lock = ENVIRONMENT_LOCK.lock(); - - std::env::set_var("APP_ENV", "production"); - - assert_no_sensitive_data(Redactable(SENSITIVE_DATA)); -} - -#[test] -fn test_staging() { - // We've set up redaction to happen when APP_ENV="staging" - let _lock = ENVIRONMENT_LOCK.lock(); - - std::env::set_var("APP_ENV", "staging"); - - assert_no_sensitive_data(Redactable(SENSITIVE_DATA)); -} - -#[test] -fn test_dev() { - // We've set up redaction to NOT happen when APP_ENV="dev" - let _lock = ENVIRONMENT_LOCK.lock(); - - std::env::set_var("APP_ENV", "dev"); - - assert_has_sensitive_data(Redactable(SENSITIVE_DATA)); -} - -#[test] -fn test_qa() { - // We've set up redaction to NOT happen when APP_ENV="qa" - let _lock = ENVIRONMENT_LOCK.lock(); - - std::env::set_var("APP_ENV", "qa"); - - assert_has_sensitive_data(Redactable(SENSITIVE_DATA)); -} From 313501697e96762fdfbcacc75f57a348782fa97c Mon Sep 17 00:00:00 2001 From: "mae.kasza" Date: Thu, 22 Sep 2022 14:07:27 +0200 Subject: [PATCH 02/15] Remove all mentions of the environment aware feature --- .drone.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.drone.yml b/.drone.yml index 671eb7ea..c7b63f2b 100644 --- a/.drone.yml +++ b/.drone.yml @@ -36,7 +36,7 @@ steps: - name: cargo-clippy-ci image: rust:1.61 commands: - - cargo clippy -- -D warnings && cargo clippy --features environment-aware -- -D warnings + - cargo clippy -- -D warnings && cargo clippy -- -D warnings environment: BUILD_ENV: dev CARGO_HOME: /drone/src/.cargo @@ -46,7 +46,7 @@ steps: - name: cargo-test image: rust:1.61 commands: - - cargo test --all && cargo test --all --features environment-aware + - cargo test --all && cargo test --all environment: BUILD_ENV: dev CARGO_HOME: /drone/src/.cargo From 30520c0f8ff25d0768b7df19ed366a9045f86372 Mon Sep 17 00:00:00 2001 From: "mae.kasza" Date: Thu, 22 Sep 2022 15:02:39 +0200 Subject: [PATCH 03/15] Add a set_debug_format function This is a simpler replacement for the environmental awareness feature. --- Cargo.lock | 5 +-- Cargo.toml | 3 +- examples/disable_redaction.rs | 22 +++++++++++++ src/lib.rs | 4 +++ src/private.rs | 9 ++++++ src/toggle.rs | 51 +++++++++++++++++++++++++++++++ veil-tests/src/redaction_tests.rs | 8 +++++ 7 files changed, 99 insertions(+), 3 deletions(-) create mode 100644 examples/disable_redaction.rs create mode 100644 src/toggle.rs diff --git a/Cargo.lock b/Cargo.lock index 69d174ab..be37ebf9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -31,9 +31,9 @@ checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" [[package]] name = "once_cell" -version = "1.14.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f7254b99e31cad77da24b08ebf628882739a608578bb1bcdfc1f9c21260d7c0" +checksum = "e82dad04139b71a90c080c8463fe0dc7902db5192d939bd0950f074d014339e1" [[package]] name = "proc-macro2" @@ -167,6 +167,7 @@ checksum = "c4f5b37a154999a8f3f98cc23a628d850e154479cd94decf3414696e12e31aaf" name = "veil" version = "0.1.0" dependencies = [ + "once_cell", "veil-macros", ] diff --git a/Cargo.toml b/Cargo.toml index 3c7bb596..c865629d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,4 +10,5 @@ repository = "https://github.com/primait/veil" members = ["veil-macros", "veil-tests"] [dependencies] -veil-macros = { path = "veil-macros" } \ No newline at end of file +veil-macros = { path = "veil-macros" } +once_cell = "1.15.0" diff --git a/examples/disable_redaction.rs b/examples/disable_redaction.rs new file mode 100644 index 00000000..5a435c2e --- /dev/null +++ b/examples/disable_redaction.rs @@ -0,0 +1,22 @@ +use std::env; +use veil::Redact; + +#[derive(Redact)] +pub struct Customer { + #[redact(partial)] + first_name: String, +} + +fn main() { + // If the environment variable DISABLE_REDACTION is set veil will not redact anything + if let Ok(_) = env::var("DISABLE_REDACTION") { + veil::set_debug_format(veil::DebugFormat::Plaintext).ok(); + } + + println!( + "{:#?}", + Customer { + first_name: "John".to_string(), + } + ); +} diff --git a/src/lib.rs b/src/lib.rs index 4b07ff21..914c5571 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -218,5 +218,9 @@ pub use veil_macros::Redact; +mod toggle; +pub use toggle::*; + + #[doc(hidden)] pub mod private; diff --git a/src/private.rs b/src/private.rs index f9220aed..3229be24 100644 --- a/src/private.rs +++ b/src/private.rs @@ -1,5 +1,6 @@ use std::fmt::Debug; + #[repr(transparent)] pub struct DisplayDebug(String); impl std::fmt::Debug for DisplayDebug { @@ -110,6 +111,14 @@ impl RedactFlags { pub fn redact(this: &dyn Debug, flags: RedactFlags) -> DisplayDebug { let mut redacted = String::new(); + if crate::toggle::get_debug_format().is_plaintext() { + return DisplayDebug(if flags.debug_alternate { + format!("{:#?}", this) + } else { + format!("{:?}", this) + }); + } + (|| { if flags.fixed > 0 { flags.redact_fixed(flags.fixed as usize, &mut redacted); diff --git a/src/toggle.rs b/src/toggle.rs new file mode 100644 index 00000000..c9034a17 --- /dev/null +++ b/src/toggle.rs @@ -0,0 +1,51 @@ +//! Makes it possible to disable veil's redaction behaviour +//! +use once_cell::sync::OnceCell; +/// Enum describing the behaviour of veil +#[derive(Debug, Copy, Clone)] +pub enum DebugFormat { + /// Redact the fields as normal + Redacted, + /// Print the fields as plaintext + Plaintext, +} + +impl DebugFormat { + pub fn is_redacted(&self) -> bool { + matches!(self, &DebugFormat::Redacted) + } + + pub fn is_plaintext(&self) -> bool { + matches!(self, &DebugFormat::Plaintext) + } +} + +static DEBUG_FORMAT: OnceCell = OnceCell::new(); + +/// Sets the formatting of the debug logs +/// +/// Should only be called once, preferrably at the top of main, +/// before any calls to [`std::fmt::debug`] or [`get_debug_format`]. +/// +/// If sucessfuly set the value returns Ok(()), +/// otherwise returns Err with the current value. +pub fn set_debug_format(v: DebugFormat) -> Result<(), DebugFormat> { + DEBUG_FORMAT.set(v) +} + +/// Get the current debug format value +pub fn get_debug_format() -> DebugFormat { + *DEBUG_FORMAT.get_or_init(|| DebugFormat::Redacted) +} + +#[cfg(test)] +mod tests { + use super::*; + #[test] + fn debug_format_can_only_be_set_once() { + set_debug_format(DebugFormat::Redacted).unwrap(); + assert!(get_debug_format().is_redacted()); + set_debug_format(DebugFormat::Plaintext).unwrap_err(); + assert!(get_debug_format().is_redacted()); + } +} diff --git a/veil-tests/src/redaction_tests.rs b/veil-tests/src/redaction_tests.rs index eecc67f6..f686bb67 100644 --- a/veil-tests/src/redaction_tests.rs +++ b/veil-tests/src/redaction_tests.rs @@ -147,3 +147,11 @@ fn test_sensitive_tuple_structs() { SENSITIVE_DATA[3], )); } + +#[test] +fn test_veil_can_be_disabled() { + #[derive(Redact)] + struct SensitiveWrapper(#[redact] String); + veil::set_debug_format(veil::DebugFormat::Plaintext).ok(); + assert_has_sensitive_data(SensitiveWrapper(SENSITIVE_DATA[0].to_string())); +} From 9ee709637dbffa077710f6c85c1782e34608df8f Mon Sep 17 00:00:00 2001 From: "mae.kasza" Date: Thu, 22 Sep 2022 15:13:56 +0200 Subject: [PATCH 04/15] Mention being able to skip redacting data --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 58b9a5b4..df49ba70 100644 --- a/README.md +++ b/README.md @@ -85,3 +85,6 @@ enum InsuranceStatus { }, } ``` + +# Skip redacting data +In testing environments it may be useful not to censor your logs. You can configure Veil to redact or skip redacting data based during runtime using the `set_debug_format` function. See this [example](examples/disable_redaction.rs) From dd9c3eed9a7a3f785632280333725ae92fa4f996 Mon Sep 17 00:00:00 2001 From: "mae.kasza" Date: Thu, 22 Sep 2022 15:52:11 +0200 Subject: [PATCH 05/15] Move tests that disable redaction into a separate crate This is neccessary because rust runs all tests in the same process, leading to tests failing randomly, because of other tests modifying the global state. There is some proposal on the rust compiler-team github repo but until that gets stabilized we have to use this hack instead https://github.com/rust-lang/compiler-team/issues/508 --- Cargo.lock | 8 ++++++++ Cargo.toml | 7 ++++++- veil-tests/disable-redaction-test/Cargo.toml | 10 ++++++++++ veil-tests/disable-redaction-test/src/lib.rs | 12 ++++++++++++ veil-tests/src/redaction_tests.rs | 8 -------- 5 files changed, 36 insertions(+), 9 deletions(-) create mode 100644 veil-tests/disable-redaction-test/Cargo.toml create mode 100644 veil-tests/disable-redaction-test/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index be37ebf9..da6c1e35 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11,6 +11,14 @@ dependencies = [ "memchr", ] +[[package]] +name = "disable-redaction-test" +version = "0.1.0" +dependencies = [ + "veil", + "veil-tests", +] + [[package]] name = "glob" version = "0.3.0" diff --git a/Cargo.toml b/Cargo.toml index c865629d..219d3245 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,7 +7,12 @@ license = "MIT" repository = "https://github.com/primait/veil" [workspace] -members = ["veil-macros", "veil-tests"] +members = ["veil-macros", "veil-tests" +# Because those tests deal with global state we need to run them in a separate process. +# The easiest/only way to do this with the standard rust test harness is to put them in a +# separate crate +,"veil-tests/disable-redaction-test" +] [dependencies] veil-macros = { path = "veil-macros" } diff --git a/veil-tests/disable-redaction-test/Cargo.toml b/veil-tests/disable-redaction-test/Cargo.toml new file mode 100644 index 00000000..ed8b9d0c --- /dev/null +++ b/veil-tests/disable-redaction-test/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "disable-redaction-test" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +veil = { path = "../../" } +veil-tests = { path = "../" } diff --git a/veil-tests/disable-redaction-test/src/lib.rs b/veil-tests/disable-redaction-test/src/lib.rs new file mode 100644 index 00000000..f1892218 --- /dev/null +++ b/veil-tests/disable-redaction-test/src/lib.rs @@ -0,0 +1,12 @@ +#![cfg_attr(not(test), allow(unused))] +/// Simple test that ensures veil can actually be disabled + +use veil::Redact; +use veil_tests::{SENSITIVE_DATA, assert_has_sensitive_data}; +#[test] +fn test_veil_can_be_disabled() { + #[derive(Redact)] + struct SensitiveWrapper(#[redact] String); + veil::set_debug_format(veil::DebugFormat::Plaintext).ok(); + assert_has_sensitive_data(SensitiveWrapper(SENSITIVE_DATA[0].to_string())); +} diff --git a/veil-tests/src/redaction_tests.rs b/veil-tests/src/redaction_tests.rs index f686bb67..eecc67f6 100644 --- a/veil-tests/src/redaction_tests.rs +++ b/veil-tests/src/redaction_tests.rs @@ -147,11 +147,3 @@ fn test_sensitive_tuple_structs() { SENSITIVE_DATA[3], )); } - -#[test] -fn test_veil_can_be_disabled() { - #[derive(Redact)] - struct SensitiveWrapper(#[redact] String); - veil::set_debug_format(veil::DebugFormat::Plaintext).ok(); - assert_has_sensitive_data(SensitiveWrapper(SENSITIVE_DATA[0].to_string())); -} From 0efc7861abd7b84ee519e5965f2fc28a7e3cc00a Mon Sep 17 00:00:00 2001 From: MaeIsBad <26093674+MaeIsBad@users.noreply.github.com> Date: Thu, 22 Sep 2022 16:09:45 +0200 Subject: [PATCH 06/15] Loosen the version requirement of once_cell to 1.0.0 Co-authored-by: William --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 219d3245..2f735595 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,4 +16,4 @@ members = ["veil-macros", "veil-tests" [dependencies] veil-macros = { path = "veil-macros" } -once_cell = "1.15.0" +once_cell = "1" From 643c52880dd5f4b5fc82dd461d329c19b5a61b01 Mon Sep 17 00:00:00 2001 From: "mae.kasza" Date: Thu, 22 Sep 2022 17:12:05 +0200 Subject: [PATCH 07/15] Hide the disable feature behind a feature flag Ensure that the use of this feature requires a very explicit opt-in from the user. --- Cargo.toml | 3 ++ README.md | 2 +- examples/disable_redaction.rs | 7 +++- src/lib.rs | 2 + src/private.rs | 3 +- src/toggle.rs | 43 ++++++++++++-------- veil-tests/disable-redaction-test/Cargo.toml | 2 +- veil-tests/disable-redaction-test/src/lib.rs | 2 +- 8 files changed, 40 insertions(+), 24 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 2f735595..a8bb49a3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,3 +17,6 @@ members = ["veil-macros", "veil-tests" [dependencies] veil-macros = { path = "veil-macros" } once_cell = "1" + +[features] +toggle = [] diff --git a/README.md b/README.md index df49ba70..a5fb9268 100644 --- a/README.md +++ b/README.md @@ -87,4 +87,4 @@ enum InsuranceStatus { ``` # Skip redacting data -In testing environments it may be useful not to censor your logs. You can configure Veil to redact or skip redacting data based during runtime using the `set_debug_format` function. See this [example](examples/disable_redaction.rs) +In testing environments it may be useful not to censor your logs. You can globally disable Veil's redaction behavior at runtime by calling the `disable` function(locked behind the *non-default* `toggle` feature flag.) See this [example](examples/disable_redaction.rs) diff --git a/examples/disable_redaction.rs b/examples/disable_redaction.rs index 5a435c2e..0257f563 100644 --- a/examples/disable_redaction.rs +++ b/examples/disable_redaction.rs @@ -9,8 +9,11 @@ pub struct Customer { fn main() { // If the environment variable DISABLE_REDACTION is set veil will not redact anything - if let Ok(_) = env::var("DISABLE_REDACTION") { - veil::set_debug_format(veil::DebugFormat::Plaintext).ok(); + if let Ok(env) = env::var("APP_ENV") { + if env == "dev" { + // Note that veil::disable needs the `toggle` feature flag enabled + veil::disable().unwrap(); + } } println!( diff --git a/src/lib.rs b/src/lib.rs index 914c5571..030f01f4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -218,7 +218,9 @@ pub use veil_macros::Redact; +#[cfg(feature = "toggle")] mod toggle; +#[cfg(feature = "toggle")] pub use toggle::*; diff --git a/src/private.rs b/src/private.rs index 3229be24..2ea356de 100644 --- a/src/private.rs +++ b/src/private.rs @@ -111,7 +111,8 @@ impl RedactFlags { pub fn redact(this: &dyn Debug, flags: RedactFlags) -> DisplayDebug { let mut redacted = String::new(); - if crate::toggle::get_debug_format().is_plaintext() { + #[cfg(feature = "toggle")] + if crate::toggle::get_redaction_behavior().is_plaintext() { return DisplayDebug(if flags.debug_alternate { format!("{:#?}", this) } else { diff --git a/src/toggle.rs b/src/toggle.rs index c9034a17..a3f18319 100644 --- a/src/toggle.rs +++ b/src/toggle.rs @@ -3,49 +3,56 @@ use once_cell::sync::OnceCell; /// Enum describing the behaviour of veil #[derive(Debug, Copy, Clone)] -pub enum DebugFormat { +pub enum RedactionBehavior { /// Redact the fields as normal - Redacted, + Redact, /// Print the fields as plaintext Plaintext, } -impl DebugFormat { - pub fn is_redacted(&self) -> bool { - matches!(self, &DebugFormat::Redacted) +impl RedactionBehavior { + pub fn is_redact(&self) -> bool { + matches!(self, &RedactionBehavior::Redact) } pub fn is_plaintext(&self) -> bool { - matches!(self, &DebugFormat::Plaintext) + matches!(self, &RedactionBehavior::Plaintext) } } -static DEBUG_FORMAT: OnceCell = OnceCell::new(); +static DEBUG_FORMAT: OnceCell = OnceCell::new(); /// Sets the formatting of the debug logs /// /// Should only be called once, preferrably at the top of main, -/// before any calls to [`std::fmt::debug`] or [`get_debug_format`]. +/// before any calls to [`std::fmt::Debug`] or [`get_redaction_behavior`] /// /// If sucessfuly set the value returns Ok(()), -/// otherwise returns Err with the current value. -pub fn set_debug_format(v: DebugFormat) -> Result<(), DebugFormat> { - DEBUG_FORMAT.set(v) +/// otherwise returns Err +/// ``` +/// // If the environment variable DISABLE_REDACTION is set veil will not redact anything +/// if let Ok(env) = std::env::var("APP_ENV") { +/// if env == "dev" { +/// veil::disable().unwrap(); +/// } +/// } +/// ``` +pub fn disable() -> Result<(), RedactionBehavior> { + DEBUG_FORMAT.set(RedactionBehavior::Plaintext) } /// Get the current debug format value -pub fn get_debug_format() -> DebugFormat { - *DEBUG_FORMAT.get_or_init(|| DebugFormat::Redacted) +pub(crate) fn get_redaction_behavior() -> RedactionBehavior { + *DEBUG_FORMAT.get_or_init(|| RedactionBehavior::Redact) } #[cfg(test)] mod tests { use super::*; #[test] - fn debug_format_can_only_be_set_once() { - set_debug_format(DebugFormat::Redacted).unwrap(); - assert!(get_debug_format().is_redacted()); - set_debug_format(DebugFormat::Plaintext).unwrap_err(); - assert!(get_debug_format().is_redacted()); + fn redaction_cant_be_set_after_reading() { + assert!(get_redaction_behavior().is_redact()); + disable().unwrap_err(); + assert!(get_redaction_behavior().is_redact()); } } diff --git a/veil-tests/disable-redaction-test/Cargo.toml b/veil-tests/disable-redaction-test/Cargo.toml index ed8b9d0c..be93a30d 100644 --- a/veil-tests/disable-redaction-test/Cargo.toml +++ b/veil-tests/disable-redaction-test/Cargo.toml @@ -6,5 +6,5 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -veil = { path = "../../" } +veil = { path = "../../", features = ["toggle"] } veil-tests = { path = "../" } diff --git a/veil-tests/disable-redaction-test/src/lib.rs b/veil-tests/disable-redaction-test/src/lib.rs index f1892218..49a49227 100644 --- a/veil-tests/disable-redaction-test/src/lib.rs +++ b/veil-tests/disable-redaction-test/src/lib.rs @@ -7,6 +7,6 @@ use veil_tests::{SENSITIVE_DATA, assert_has_sensitive_data}; fn test_veil_can_be_disabled() { #[derive(Redact)] struct SensitiveWrapper(#[redact] String); - veil::set_debug_format(veil::DebugFormat::Plaintext).ok(); + veil::disable().ok(); assert_has_sensitive_data(SensitiveWrapper(SENSITIVE_DATA[0].to_string())); } From c1e9b724d15eae3ce6503923de48254d6cd9846a Mon Sep 17 00:00:00 2001 From: "mae.kasza" Date: Thu, 22 Sep 2022 17:28:39 +0200 Subject: [PATCH 08/15] Add support for disabling veil with VEIL_DISABLE_REDACTION --- README.md | 4 +++- src/toggle.rs | 6 +++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index a5fb9268..d7508705 100644 --- a/README.md +++ b/README.md @@ -87,4 +87,6 @@ enum InsuranceStatus { ``` # Skip redacting data -In testing environments it may be useful not to censor your logs. You can globally disable Veil's redaction behavior at runtime by calling the `disable` function(locked behind the *non-default* `toggle` feature flag.) See this [example](examples/disable_redaction.rs) +In testing environments it may be useful not to censor your logs.You can globally disable Veil's redaction behavior at runtime by enabling the *non-default* feature flag `toggle` and: +- Setting the VEIL_DISABLE_REDACTION environment variable. +- Calling the `disable` function(locked behind the *non-default* `toggle` feature flag). See this [example](examples/disable_redaction.rs). diff --git a/src/toggle.rs b/src/toggle.rs index a3f18319..de15780a 100644 --- a/src/toggle.rs +++ b/src/toggle.rs @@ -43,7 +43,11 @@ pub fn disable() -> Result<(), RedactionBehavior> { /// Get the current debug format value pub(crate) fn get_redaction_behavior() -> RedactionBehavior { - *DEBUG_FORMAT.get_or_init(|| RedactionBehavior::Redact) + if let "1" | "on" = std::env::var("VEIL_DISABLE_REDACTION").unwrap_or_default().as_str() { + *DEBUG_FORMAT.get_or_init(|| RedactionBehavior::Plaintext) + } else { + *DEBUG_FORMAT.get_or_init(|| RedactionBehavior::Redact) + } } #[cfg(test)] From 55db4385357edce617d189187883c1317e796c86 Mon Sep 17 00:00:00 2001 From: "mae.kasza" Date: Fri, 23 Sep 2022 14:37:42 +0200 Subject: [PATCH 09/15] Test the toggle feature with drone --- .drone.yml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/.drone.yml b/.drone.yml index c7b63f2b..bfea5026 100644 --- a/.drone.yml +++ b/.drone.yml @@ -1,5 +1,4 @@ ---- -kind: pipeline +--- kind: pipeline name: default platform: @@ -36,7 +35,7 @@ steps: - name: cargo-clippy-ci image: rust:1.61 commands: - - cargo clippy -- -D warnings && cargo clippy -- -D warnings + - cargo clippy -- -D warnings && cargo clippy --features toggle -- -D warnings environment: BUILD_ENV: dev CARGO_HOME: /drone/src/.cargo @@ -46,7 +45,7 @@ steps: - name: cargo-test image: rust:1.61 commands: - - cargo test --all && cargo test --all + - cargo test --all && cargo test --all --features toggle environment: BUILD_ENV: dev CARGO_HOME: /drone/src/.cargo From 01687e552887dbbc04f23939b929aa239698b5ba Mon Sep 17 00:00:00 2001 From: "mae.kasza" Date: Fri, 23 Sep 2022 14:39:27 +0200 Subject: [PATCH 10/15] Minor fixes to disable-redaction-test * Rename it to veil-tests-disable-redaction * Set publish = false * Change the outer line doc comment describing the test into a inner line doc comment --- Cargo.lock | 16 ++++++++-------- veil-tests/disable-redaction-test/Cargo.toml | 5 ++--- veil-tests/disable-redaction-test/src/lib.rs | 2 +- 3 files changed, 11 insertions(+), 12 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index da6c1e35..3c45f9b6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11,14 +11,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "disable-redaction-test" -version = "0.1.0" -dependencies = [ - "veil", - "veil-tests", -] - [[package]] name = "glob" version = "0.3.0" @@ -198,6 +190,14 @@ dependencies = [ "walkdir", ] +[[package]] +name = "veil-tests-disable-redaction" +version = "0.1.0" +dependencies = [ + "veil", + "veil-tests", +] + [[package]] name = "walkdir" version = "2.3.2" diff --git a/veil-tests/disable-redaction-test/Cargo.toml b/veil-tests/disable-redaction-test/Cargo.toml index be93a30d..8cea0630 100644 --- a/veil-tests/disable-redaction-test/Cargo.toml +++ b/veil-tests/disable-redaction-test/Cargo.toml @@ -1,9 +1,8 @@ [package] -name = "disable-redaction-test" +name = "veil-tests-disable-redaction" version = "0.1.0" edition = "2021" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +publish = false [dependencies] veil = { path = "../../", features = ["toggle"] } diff --git a/veil-tests/disable-redaction-test/src/lib.rs b/veil-tests/disable-redaction-test/src/lib.rs index 49a49227..41283a77 100644 --- a/veil-tests/disable-redaction-test/src/lib.rs +++ b/veil-tests/disable-redaction-test/src/lib.rs @@ -1,5 +1,5 @@ #![cfg_attr(not(test), allow(unused))] -/// Simple test that ensures veil can actually be disabled +//! Simple test that ensures veil can actually be disabled use veil::Redact; use veil_tests::{SENSITIVE_DATA, assert_has_sensitive_data}; From b820a32566030edce996a079433bed668f49d1e1 Mon Sep 17 00:00:00 2001 From: "mae.kasza" Date: Fri, 23 Sep 2022 14:47:01 +0200 Subject: [PATCH 11/15] Improve the disable veil redaction docs This avoids repeating that the disable function needs the toggle feature flag which makes it clearer that the VEIL_DISABLE_REDACTION envar also needs the feature flag --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d7508705..55a12e7e 100644 --- a/README.md +++ b/README.md @@ -89,4 +89,4 @@ enum InsuranceStatus { # Skip redacting data In testing environments it may be useful not to censor your logs.You can globally disable Veil's redaction behavior at runtime by enabling the *non-default* feature flag `toggle` and: - Setting the VEIL_DISABLE_REDACTION environment variable. -- Calling the `disable` function(locked behind the *non-default* `toggle` feature flag). See this [example](examples/disable_redaction.rs). +- Calling the `disable` function. See this [example](examples/disable_redaction.rs). From e9a5ff931b7744f1cf25bea5ef78107159ceb71d Mon Sep 17 00:00:00 2001 From: MaeIsBad <26093674+MaeIsBad@users.noreply.github.com> Date: Mon, 26 Sep 2022 09:27:37 +0200 Subject: [PATCH 12/15] Clarify RedactionBehavior doc comment Co-authored-by: William --- src/toggle.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/toggle.rs b/src/toggle.rs index de15780a..d0391ade 100644 --- a/src/toggle.rs +++ b/src/toggle.rs @@ -1,7 +1,7 @@ //! Makes it possible to disable veil's redaction behaviour //! use once_cell::sync::OnceCell; -/// Enum describing the behaviour of veil +/// Enum describing how Veil should behave when `std::fmt::Debug` is called on a `#[derive(Redact)]` item #[derive(Debug, Copy, Clone)] pub enum RedactionBehavior { /// Redact the fields as normal From b61b10a937168a23c4536e73da3ab196d33f1850 Mon Sep 17 00:00:00 2001 From: "mae.kasza" Date: Mon, 26 Sep 2022 09:31:37 +0200 Subject: [PATCH 13/15] Add missing space in README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 55a12e7e..a4173a5d 100644 --- a/README.md +++ b/README.md @@ -87,6 +87,6 @@ enum InsuranceStatus { ``` # Skip redacting data -In testing environments it may be useful not to censor your logs.You can globally disable Veil's redaction behavior at runtime by enabling the *non-default* feature flag `toggle` and: +In testing environments it may be useful not to censor your logs. You can globally disable Veil's redaction behavior at runtime by enabling the *non-default* feature flag `toggle` and: - Setting the VEIL_DISABLE_REDACTION environment variable. - Calling the `disable` function. See this [example](examples/disable_redaction.rs). From 2738c5c60f53d084d88372a59995ab81997ecc3f Mon Sep 17 00:00:00 2001 From: "mae.kasza" Date: Mon, 26 Sep 2022 09:31:59 +0200 Subject: [PATCH 14/15] Update README.md Make it clear that to skip redacting data the user needs to either call the disable function *or* set the VEIL_DISABLE_REDACTION variable, not both. --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index a4173a5d..fe6cd283 100644 --- a/README.md +++ b/README.md @@ -89,4 +89,5 @@ enum InsuranceStatus { # Skip redacting data In testing environments it may be useful not to censor your logs. You can globally disable Veil's redaction behavior at runtime by enabling the *non-default* feature flag `toggle` and: - Setting the VEIL_DISABLE_REDACTION environment variable. +or - Calling the `disable` function. See this [example](examples/disable_redaction.rs). From 1e073aa46991ebb8dd414a567423fdd6a4ef6cd0 Mon Sep 17 00:00:00 2001 From: "mae.kasza" Date: Mon, 26 Sep 2022 09:36:08 +0200 Subject: [PATCH 15/15] Update outdated comment in the disable_redaction example --- examples/disable_redaction.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/disable_redaction.rs b/examples/disable_redaction.rs index 0257f563..1edb2e3a 100644 --- a/examples/disable_redaction.rs +++ b/examples/disable_redaction.rs @@ -8,7 +8,7 @@ pub struct Customer { } fn main() { - // If the environment variable DISABLE_REDACTION is set veil will not redact anything + // If the environment variable APP_ENV is set to "dev" veil will not redact anything if let Ok(env) = env::var("APP_ENV") { if env == "dev" { // Note that veil::disable needs the `toggle` feature flag enabled