Module: Api2Convert::Support::Redactor
- Defined in:
- lib/api2convert/support/redactor.rb
Overview
Credential redaction for cloud connectors.
Cloud credentials ride in the plaintext request body, so they must never
surface where a value object or an SDK-emitted string could leak them. This
helper centralizes the masks the contract mandates:
- the whole
credentialsobject collapses to MARKER on every object-inspection path (#inspect/#to_s); - any
parametersleaf whose key contains a sensitive token (SENSITIVE_SUBSTRINGS, case-insensitive substring) collapses to MARKER; - the decoded error body is deep-walked (Redactor.redact_body) as belt-and- suspenders — the API only ever echoes field names, never a credential value, but a future server/proxy change must not be able to leak one.
Internal helper, not part of the public API.
Constant Summary collapse
- MARKER =
The fixed, fleet-wide redaction marker (D9).
"[REDACTED]"- SENSITIVE_SUBSTRINGS =
Case-insensitive substrings that mark a key as carrying a secret. A key containing any of these has its whole value masked.
%w[ token password passwd secret key keyfile credential passphrase sas sig signature ].freeze
- SENSITIVE_PATTERN =
Precompiled union: a key is sensitive iff it contains any substring above. Equivalent to
SENSITIVE_SUBSTRINGS.any? { |s| key.include?(s) }but written as a regex so Style/ArrayIntersect can't rewrite the String#include? substring test into Array#intersect? (which would need an array argument and change the semantics). Regexp.union(SENSITIVE_SUBSTRINGS).freeze
Class Method Summary collapse
-
.parameters(params) ⇒ Object
Mask sensitive leaves of a
parametersmap: any key matching Redactor.sensitive_key? has its value replaced by MARKER; nested Hashes are walked recursively. -
.redact_body(body) ⇒ Object
Deep-walk a decoded error body and mask the value of every sensitive key (including a flattened/dotted key like
input.0.credentials.secretaccesskey) to MARKER. -
.sensitive_key?(key) ⇒ Boolean
Whether a key name marks its value as sensitive (case-insensitive substring match).
Class Method Details
.parameters(params) ⇒ Object
Mask sensitive leaves of a parameters map: any key matching
sensitive_key? has its value replaced by MARKER; nested Hashes are
walked recursively. Non-secret keys (bucket, host, file,
container, projectid, …) are left untouched.
50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
# File 'lib/api2convert/support/redactor.rb', line 50 def parameters(params) return params unless params.is_a?(Hash) params.each_with_object({}) do |(key, value), out| out[key] = if sensitive_key?(key) MARKER elsif value.is_a?(Hash) parameters(value) else value end end end |
.redact_body(body) ⇒ Object
Deep-walk a decoded error body and mask the value of every sensitive key
(including a flattened/dotted key like
input.0.credentials.secretaccesskey) to MARKER. Nested Hashes and
Arrays are walked; scalars pass through.
69 70 71 72 73 74 75 76 77 78 79 80 |
# File 'lib/api2convert/support/redactor.rb', line 69 def redact_body(body) case body when Hash body.each_with_object({}) do |(key, value), out| out[key] = sensitive_key?(key) ? MARKER : redact_body(value) end when Array body.map { |value| redact_body(value) } else body end end |
.sensitive_key?(key) ⇒ Boolean
Whether a key name marks its value as sensitive (case-insensitive substring match). Accepts String or Symbol keys.
42 43 44 |
# File 'lib/api2convert/support/redactor.rb', line 42 def sensitive_key?(key) SENSITIVE_PATTERN.match?(key.to_s.downcase) end |