Skip to content

Commit 2b00dbb

Browse files
authored
Merge pull request #9 from github/fix_message
fix: allow to pass messages as arrays or hashes
2 parents 61b641e + a9ada2a commit 2b00dbb

File tree

3 files changed

+90
-105
lines changed

3 files changed

+90
-105
lines changed

lib/redacting_logger.rb

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,26 @@ def initialize(
3535
# Adds a message to the log.
3636
#
3737
# @param severity [Integer] The severity level of the message.
38-
# @param message [String] The message to log.
38+
# @param message [String|Array|Hash] The message to log.
3939
# @param progname [String] The name of the program.
4040
def add(severity, message = nil, progname = nil)
4141
message, progname = yield if block_given?
4242

43-
if message
44-
@redact_patterns.each do |pattern|
43+
@redact_patterns.each do |pattern|
44+
case message
45+
46+
when String
4547
message = message.to_s.gsub(pattern, @redacted_msg)
48+
49+
when Array
50+
message = message.map do |m|
51+
m = m.to_s.gsub(pattern, @redacted_msg)
52+
end
53+
54+
when Hash
55+
message = message.map do |k, v|
56+
[k, v.to_s.gsub(pattern, @redacted_msg)]
57+
end.to_h
4658
end
4759
end
4860

lib/version.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@
22

33
module RedactingLogger
44
module Version
5-
VERSION = "1.0.0"
5+
VERSION = "1.1.0"
66
end
77
end

spec/lib/redacting_logger_spec.rb

Lines changed: 74 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -45,114 +45,87 @@
4545
let(:logdev) { StringIO.new }
4646
let(:logger) { RedactingLogger.new(logdev, redact_patterns: [/secret/, /password/, /token_[A-Z]{5}/]) }
4747

48-
it "ensures the message is redacted" do
49-
logger.info { ["This is a secret password", nil] }
50-
51-
logdev.rewind
52-
log_output = logdev.read
53-
54-
expect(log_output).to match(/This is a \[REDACTED\] \[REDACTED\]/)
55-
end
56-
57-
it "ensures the progname is redacted" do
58-
logger.info { ["This is a message", "secret"] }
59-
60-
logdev.rewind
61-
log_output = logdev.read
62-
63-
expect(log_output).to match(/\[REDACTED\]: This is a message/)
64-
end
65-
66-
it "redacts the message when it is a substring of the redact pattern" do
67-
logger.info("This is a supersecretmessage")
68-
69-
logdev.rewind
70-
log_output = logdev.read
71-
expect(log_output).to match(/This is a super\[REDACTED\]message/)
72-
end
73-
74-
it "redacts a GitHub Personal Access Token that is 40 characters" do
75-
token = "ghp_aBcdeFghIjklMnoPqRSTUvwXYZ1234567890"
76-
77-
logger.info("logging in with token #{token} ...")
78-
79-
logdev.rewind
80-
log_output = logdev.read
81-
expect(log_output).to match(/logging in with token \[REDACTED\] .../)
82-
end
83-
84-
it "redacts a GitHub Personal Access Token got mashed with another string" do
85-
token = "ghp_aBcdeFghIjklMnoPqRSTUvwXYZ1234567890ohnothisisnotgood"
86-
87-
logger.info("logging in with token #{token} ...")
88-
89-
logdev.rewind
90-
log_output = logdev.read
91-
expect(log_output).to match(/logging in with token \[REDACTED\] .../)
92-
end
93-
94-
it "redacts a fine-grained GitHub Personal Access Token" do
95-
# This token is not real, but it is the correct length and format
96-
token = "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"
97-
98-
logger.warn("oh no, I failed to login with that token: #{token}, try again")
99-
100-
logdev.rewind
101-
log_output = logdev.read
102-
expect(log_output).to match(/oh no, I failed to login with that token: \[REDACTED\], try again/)
103-
end
104-
105-
it "redacts a GitHub Actions temp token" do
106-
token = "ghs_1234567890abcdefghijklmnopqrstuvwxyz123456"
107-
108-
logger.debug("GitHub Actions token: #{token}")
109-
110-
logdev.rewind
111-
log_output = logdev.read
112-
expect(log_output).to match(/GitHub Actions token: \[REDACTED\]/)
113-
end
114-
115-
it "redacts a custom token" do
116-
token = "token_ABCDE"
117-
118-
logger.fatal("Custom token: #{token}")
119-
120-
logdev.rewind
121-
log_output = logdev.read
122-
expect(log_output).to match(/Custom token: \[REDACTED\]/)
48+
[
49+
{
50+
case: "secret message",
51+
message: "This is a secret password",
52+
expected_message: "This is a [REDACTED] [REDACTED]",
53+
},
54+
{
55+
case: "secret progname",
56+
progname: "secret progname",
57+
expected_progname: "[REDACTED] progname",
58+
},
59+
{
60+
case: "secret substring",
61+
message: "This is a supersecretmessage",
62+
expected_message: "This is a super[REDACTED]message",
63+
},
64+
{
65+
case: "github token",
66+
message: "token ghp_aBcdeFghIjklMnoPqRSTUvwXYZ1234567890",
67+
expected_message: "token [REDACTED]",
68+
},
69+
{
70+
case: "github token hidden in another string",
71+
message: "token ghp_aBcdeFghIjklMnoPqRSTUvwXYZ1234567890ohnothisisnotgood",
72+
expected_message: "token [REDACTED]",
73+
},
74+
{
75+
case: "fine-grained github pat",
76+
message: "token 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",
77+
expected_message: "token [REDACTED]",
78+
},
79+
{
80+
case: "github action pat",
81+
message: "token ghs_1234567890abcdefghijklmnopqrstuvwxyz123456",
82+
expected_message: "token [REDACTED]123456",
83+
},
84+
{
85+
case: "custom token",
86+
message: "token token_ABCDE",
87+
expected_message: "token [REDACTED]",
88+
},
89+
{
90+
case: "custom token only if long enough",
91+
message: "token token_ABCD",
92+
expected_message: "token token_ABCD",
93+
},
94+
{
95+
case: "JWT token",
96+
message: "token eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c",
97+
expected_message: "token [REDACTED]",
98+
},
99+
{
100+
case: "RSA private key",
101+
message: "token #{File.read("spec/fixtures/fake.private_key")}",
102+
expected_message: "token [REDACTED]-\n",
103+
},
104+
{
105+
case: "list of messages",
106+
message: ["this", "is", "a", "secret"],
107+
expected_message: ["this", "is", "a", "[REDACTED]"],
108+
},
109+
{
110+
case: "hash of messages",
111+
message: { this: "is", "a" => "secret" },
112+
expected_message: { this: "is", "a" => "[REDACTED]" },
113+
},
114+
].each do |test|
115+
it "redacts #{test[:case]}" do
116+
expect_any_instance_of(Logger).to receive(:add).with(0, test[:expected_message], test[:expected_progname])
117+
logger.add(0, test[:message], test[:progname])
118+
end
123119
end
124120

125-
it "does not remove a token that is too short" do
126-
token = "token_ABCD"
127-
128-
logger.fatal("Custom token: #{token}")
129-
130-
logdev.rewind
131-
log_output = logdev.read
132-
133-
expect(log_output).to match(/Custom token: token_ABCD/)
134-
end
135-
136-
it "redacts a JWT token" do
137-
# this is a dummy JWT token, but it is the correct length and format
138-
token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"
139-
140-
logger.info("JWT token: #{token}")
121+
it "redacts with given block" do
122+
logger.info { ["This is a secret password", nil] }
141123

142124
logdev.rewind
143125
log_output = logdev.read
144126

145-
expect(log_output).to match(/JWT token: \[REDACTED\]/)
127+
expect(log_output).to match(/This is a \[REDACTED\] \[REDACTED\]/)
146128
end
147129

148-
it "redacts a RSA private key" do
149-
fake_private_key = File.read("spec/fixtures/fake.private_key")
150-
151-
logger.info("RSA private key: #{fake_private_key}")
152-
153-
logdev.rewind
154-
log_output = logdev.read
155-
expect(log_output).to match(/RSA private key: \[REDACTED\]/)
156-
end
157130
end
158131
end

0 commit comments

Comments
 (0)