Class ::nsmcp::LogRedactor (public)
::nx::Class ::nsmcp::LogRedactor
Defined in /usr/local/ns/tcl/nsmcp/lib/log-redaction.tcl
- Testcases:
- No testcase defined.
Source code: :property {queryParameters {__csrf_token csrf_token token access_token refresh_token id_token password passwd secret api_key apikey}} :property {headerNames {authorization proxy-authorization cookie set-cookie x-api-key}} :property {maskPeerAddresses:boolean true} :property {maskUserIdentifiers:boolean true} :property {replacement {[REDACTED]}} :method sensitive {name names} { foreach candidate $names { if {[string equal -nocase $name $candidate]} {return true} } return false } :public method queryValues {text} { set start 0 # Match literal query separators. Decode names, never values, for policy # comparison; retain the original URL spelling and nonsensitive values. while {[regexp -indices -start $start {[?&]([^=&#\s"<>]+)=([^&#\s"<>]*)} $text match key value]} { lassign $key a b set name [string range $text $a $b] if {[catch {ns_urldecode -charset utf-8 -- $name} decoded]} { set decoded $name } lassign $value a b if {[:sensitive $decoded ${:queryParameters}]} { set text "[string range $text 0 [expr {$a-1}]]${:replacement}[string range $text [expr {$b+1}] end]" set start [expr {$a+[string length ${:replacement}]}] } else {set start [expr {[lindex $match 1]+1}]} } return $text } :method identifiers {text pattern} { set start 0 while {[regexp -indices -nocase -start $start $pattern $text match prefix value]} { lassign $value a b set text [string replace $text $a $b ${:replacement}] set start [expr {$a+[string length ${:replacement}]}] } return $text } :public method message {text} { set lines {} foreach line [split $text \n] { if {[regexp {^([ \t]*(?::[ \t]*)?)([^:\s]+)[ \t]*:[ \t]*(.*)$} $line -> prefix name value] && [:sensitive $name ${:headerNames}]} { set line "${prefix}${name}: ${:replacement}" } else {set line [:queryValues $line]} if {${:maskPeerAddresses}} { if {[regexp -indices {^(\S+)[ \t]+\S+[ \t]+\S+[ \t]+\[[0-9]{2}/[A-Za-z]{3}/[0-9]{4}:} $line match peer]} { lassign $peer a b set line [string replace $line $a $b ${:replacement}] } set line [:identifiers $line {(peer(?:address|addr)?[ \t]*[:=]?[ \t]+)([0-9A-Fa-f:.]+)(?:[ \t,;]|$)}] } if {${:maskUserIdentifiers}} { set line [:identifiers $line {(user_id[ \t]*[:=]?[ \t]+)([0-9]+)(?:[ \t,;]|$)}] # The third field in the recognized access header is the user. if {[regexp -indices {^\S+[ \t]+\S+[ \t]+(\S+)[ \t]+\[[0-9]{2}/[A-Za-z]{3}/[0-9]{4}:} $line match user]} { lassign $user a b if {[string range $line $a $b] ne "-"} { set line [string replace $line $a $b ${:replacement}] } } } lappend lines $line } return [join $lines \n] } :public method record {entry} { set original $entry if {[dict exists $entry message]} { dict set entry message [:message [dict get $entry message]] } if {[dict exists $entry url]} { dict set entry url [:queryValues [dict get $entry url]] } if {${:maskPeerAddresses} && [dict exists $entry peerAddress] && [dict get $entry peerAddress] ne ""} { set peer [dict get $entry peerAddress] if {[dict exists $entry message]} { dict set entry message [string map [list $peer ${:replacement}] [dict get $entry message]] } dict set entry peerAddress ${:replacement} } dict set entry redacted [expr {$entry ne $original}] return $entry } :public method page {page} { set records {} foreach entry [dict get $page records] {lappend records [:record $entry]} dict set page records $records return $page }XQL Not present: Generic, PostgreSQL, Oracle
![[i]](/resources/acs-subsite/ZoomIn16.gif)