PipelineSecretRegistry
Namespace: Meshmakers.Octo.Sdk.Common.EtlDataPipeline
The plaintext values one pipeline execution must never show in its diagnostics (AB#5528 / AB#5538):
the plaintext RevealSecret@1 wrote into the data context and the credentials nodes resolved
from configuration. The values themselves still flow through the data context unchanged — a node
that needs the plaintext (an HTTP call, an SMTP login) gets it — but every diagnostic surface
replaces them with PipelineSecretRegistry.Mask: debug snapshots and dry-run intents
(DefaultPipelineDebugger), the execution log written through
INodeContext and the persisted execution result
(SetPipelineExecutionResult@1).
public sealed class PipelineSecretRegistry
Inheritance Object → PipelineSecretRegistry
Remarks:
Redaction is by value, not by path: a revealed secret copied to another path, concatenated
into a header (Bearer …) or carried into a child context of a loop is masked as well, which a
path marker could not follow. A string that equals a registered value becomes PipelineSecretRegistry.Mask;
a string that contains one has each occurrence replaced, but only for values of at least
PipelineSecretRegistry.MinimumSubstringLength characters — a one-character "secret" masked inside every
string would make every snapshot unreadable and tells an attacker nothing anyway.
One instance belongs to one execution: the root NodeContext creates it and
every child context shares it, so nothing registered in one run is masked (or remembered) in the
next. Thread-safe — parallel ForEach@1 iterations register concurrently.
Fields
Mask
Text that replaces a registered value in every diagnostic output.
public static string Mask;
MinimumSubstringLength
Shortest value that is also masked inside longer strings; shorter values are masked only where a string equals them.
public static int MinimumSubstringLength;
Properties
HasSecrets
True when at least one value is registered; every redaction is a no-op otherwise.
public bool HasSecrets { get; }
Property Value
Constructors
PipelineSecretRegistry()
public PipelineSecretRegistry()
Methods
Register(String)
Registers a plaintext that must not appear in diagnostics of this execution. Null, empty and whitespace-only values are ignored.
public void Register(string plaintext)
Parameters
plaintext String
The value
Redact(String)
Returns text with every registered value masked (see the class remarks).
public string Redact(string text)
Parameters
text String
The text
Returns
String
The redacted text; the same instance when nothing had to be masked
RedactArgument(Object)
Redacts a log argument: strings are masked, a is redacted like a snapshot, anything else is returned unchanged.
public object RedactArgument(object argument)
Parameters
argument Object
The argument
Returns
Object
The redacted argument
RedactException(Exception)
Returns exception unchanged when no registered value appears in it (its
messages and those of every inner exception), otherwise a copy whose messages are masked: a
DataPipelineException stays one, anything else becomes a
PipelineExecutionException. The copy has no stack trace and does not reference the
original, so neither the execution log nor the error message persisted on the pipeline execution
(ReportExecutionEndAsync) can carry the plaintext — e.g. a conversion error that quotes a
revealed value (AB#5538).
public Exception RedactException(Exception exception)
Parameters
exception Exception
The exception
Returns
Exception
The same exception, or a redacted copy
Redact(JsonNode)
Returns node with every string value masked (see the class remarks). The
input is never modified: when something has to be masked a redacted deep clone is returned,
otherwise the same instance — so the common case (no secret in the document) allocates nothing.
public JsonNode Redact(JsonNode node)
Parameters
node JsonNode
The JSON tree
Returns
JsonNode
The redacted tree
Redact(JsonNode, String, ICollection<String>)
Same as PipelineSecretRegistry.Redact(String), and additionally adds the JSONPath of every string that
was masked to redactedPaths (handover §11, Q12): rooted at
rootPath (e.g. $.output), properties as .name (or
['name'] when the name is not a plain identifier), array items as [index]. A string
in which a secret was masked as a substring (Bearer ***) is reported with its own path;
a bare string root with rootPath itself.
public JsonNode Redact(JsonNode node, string rootPath, ICollection<string> redactedPaths)
Parameters
node JsonNode
The JSON tree
rootPath String
The JSONPath of node
redactedPaths ICollection<String>
Receives the paths of the masked strings; may be null
Returns
JsonNode
The redacted tree
AppendProperty(String, String)
Appends a property segment to a JSONPath: .name for plain identifiers, bracket notation
with single quotes otherwise.
internal static string AppendProperty(string path, string propertyName)
Parameters
path String
The parent path
propertyName String
The property name
Returns
String
The child path