forked from apple/containerization
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSpec+Redaction.swift
More file actions
69 lines (64 loc) · 2.98 KB
/
Copy pathSpec+Redaction.swift
File metadata and controls
69 lines (64 loc) · 2.98 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
//===----------------------------------------------------------------------===//
// Copyright © 2026 Apple Inc. and the Containerization project authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//===----------------------------------------------------------------------===//
// Environment variables routinely carry secrets, so rendering a process or a
// hook as text must not expose their values. These conformances make the
// redacted form the *default* rendering rather than something a caller has to
// opt into: any `\(spec)` or `\(process)`, in this repo or downstream, is safe
// without the author knowing this file exists.
//
// Only the two types that own an `env` need conforming. Swift's reflection
// based description uses a nested value's own `description`, so `Spec` and
// `Hooks` inherit the redaction through the values they hold.
//
// This affects text rendering only. `Codable` is untouched, so an encoded spec
// still carries the real values, and the unredacted environment remains
// available to callers through `process.env`.
extension Process: CustomStringConvertible {
public var description: String {
var copy = self
copy.env = redactingEnvironmentValues(copy.env)
return describeFields(of: copy)
}
}
extension Hook: CustomStringConvertible {
public var description: String {
var copy = self
copy.env = redactingEnvironmentValues(copy.env)
return describeFields(of: copy)
}
}
/// Replaces the value of every `NAME=value` entry with `<redacted>`, keeping
/// the name, which is still useful for seeing *which* variables were set.
/// Entries without an `=` are kept as-is: they name a variable to inherit and
/// carry no value of their own.
private func redactingEnvironmentValues(_ env: [String]) -> [String] {
env.map { entry in
guard let separator = entry.firstIndex(of: "=") else {
return entry
}
return entry[..<separator] + "=<redacted>"
}
}
/// Renders `TypeName(label: value, ...)`, the shape Swift's own description
/// produces. Going through a mirror rather than listing the fields by hand
/// keeps every field in the log line, and means a field added later shows up
/// without anyone remembering to edit this file.
private func describeFields<T>(of value: T) -> String {
let fields = Mirror(reflecting: value).children.map { child in
"\(child.label ?? "_"): \(String(describing: child.value))"
}
return "\(T.self)(\(fields.joined(separator: ", ")))"
}