-
Notifications
You must be signed in to change notification settings - Fork 79
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Let VMDBLogger.log_hashes filter out the sensitive value. #135
Conversation
@Fryguy @jrafanie @bdunne I think the biggest change here is that the password lines would still be logged, so you could see the key exists, but the value would be marked as "[FILTERED]". Additionally any encrypted values would also be filtered out. |
lib/gems/pending/util/vmdb-logger.rb
Outdated
logger.send(level, " #{l}") unless filter.any? { |f| l.include?(f) } | ||
if key = filter.detect { |f| l.include?(f) } | ||
l.gsub!(/#{key}.*: (.+)/) { |m| m.gsub!($1, "[FILTERED]") } | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks like it is changing behavior in an interesting way.
Before this, the entire line which contained a key in options[:filter]
was not logged, but now the line has to match a regex and the key name is logged. Why make that change in addition to the filtering for MiqPassword::REGEXP
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah I see @gmcculloug mentioned this:
I think the biggest change here is that the password lines would still be logged, so you could see the key exists,
lib/gems/pending/util/vmdb-logger.rb
Outdated
@@ -108,9 +108,13 @@ def self.log_hashes(logger, h, options = {}) | |||
filter = Array(options[:filter]).flatten.compact.map(&:to_s) << "password" | |||
filter.uniq! | |||
|
|||
YAML.dump(h).split("\n").each do |l| | |||
values = YAML.dump(h).gsub(MiqPassword::REGEXP) { |m| m.gsub($2, "FILTERED") } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a reason this is "FILTERED" and the other is "[FILTERED]" (with square brackets)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The substitution here ends up looking like v2:{FILTERED}
where the braces come from the encrypted string. Adding [...]
into the mix seemed useless.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh weird, so if we remove the capture groups from that regex then this will probably break. Couldn't we just not even print the v2 part? Is that really that important?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is based on an existing regex constant from MiqPassword
. Would just need to create a new constant there that captures the entire string. Wasn't sure if it was worth it initially.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this would still work with the existing regex:
irb(main):002:0> "stuff...v2:{asbvawerfab}..morestuff".gsub(MiqPassword::REGEXP, "[FILTERED]")
=> "stuff...[FILTERED]..morestuff"
lib/gems/pending/util/vmdb-logger.rb
Outdated
next if l[0...3] == '---' | ||
logger.send(level, " #{l}") unless filter.any? { |f| l.include?(f) } | ||
if key = filter.detect { |f| l.include?(f) } | ||
l.gsub!(/#{key}.*: (.+)/) { |m| m.gsub!($1, "[FILTERED]") } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of doing string manipulation here, why not just dup the hash passed in and alter the value before doing the YAML.dump
? That seems like it would be much more reliable than this regex dance.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unless of course you're intentionally trying to match keys like "password-but-not-really-a-password"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The method was doing a YAML.dump before which means we do not have to be concerned with the depth of embedded objects.
If we stick with the YAML string I think we could do a gsub!
for any filters over the whole string outside of the .each
loop. Also, would .each_line
work here instead of .split("\n")
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So this would match password_for_important_things: s3cr3t
, but not root_password: s3cr3t
If we want it to match both we should test for that.
EDIT:
Nevermind, just tested this:
irb(main):008:0> l = "root_password: s3cret"
=> "root_password: s3cret"
irb(main):009:0> l.gsub!(/password.*: (.+)/) { |m| m.gsub!($1, "[FILTERED]") }
=> "root_password: [FILTERED]"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@gmcculloug .each_line
would preserve the \n
at the end of each line which would print out an extra blank line for each message in the log.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A few things after talking to @gmcculloug
lib/gems/pending/util/vmdb-logger.rb
Outdated
next if l[0...3] == '---' | ||
logger.send(level, " #{l}") unless filter.any? { |f| l.include?(f) } | ||
if key = filter.detect { |f| l.include?(f) } | ||
l.gsub!(/#{key}.*: (.+)/) { |m| m.gsub!($1, "[FILTERED]") } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So this would match password_for_important_things: s3cr3t
, but not root_password: s3cr3t
If we want it to match both we should test for that.
EDIT:
Nevermind, just tested this:
irb(main):008:0> l = "root_password: s3cret"
=> "root_password: s3cret"
irb(main):009:0> l.gsub!(/password.*: (.+)/) { |m| m.gsub!($1, "[FILTERED]") }
=> "root_password: [FILTERED]"
spec/util/vmdb-logger_spec.rb
Outdated
expect(buffer.read).to_not include("pa$$w0rd") | ||
message = buffer.read | ||
expect(message).to_not include("pa$$w0rd") | ||
expect(message).to include("FILTERED") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we change these specs to all compare against the expected message value directly?
That would make what log_hashes
is doing a whole lot more clear.
lib/gems/pending/util/vmdb-logger.rb
Outdated
if key = filter.detect { |f| l.include?(f) } | ||
l.gsub!(/#{key}.*: (.+)/) { |m| m.gsub!($1, "[FILTERED]") } | ||
end | ||
logger.send(level, " #{l}") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know this isn't changed in this PR, but what is the value of writing a bunch of individual log lines rather than a single multi-line message?
bc76743
to
80a59c3
Compare
My concern is that previously, this was intentionally a pretty blunt object. We filtered line by line and did a |
@Fryguy Updated. |
I'm good with this, but I don't know why the bot is not kicking a rubocop check here. |
lib/gems/pending/util/vmdb-logger.rb
Outdated
next if l[0...3] == '---' | ||
logger.send(level, " #{l}") unless filter.any? { |f| l.include?(f) } | ||
if key = filter.detect { |f| l.include?(f) } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@lfu Can you fix the bot warning...to solve it, just use parens around your if conditional...
if (key = filter.detect { |f| l.include?(f) })
Checked commit lfu@d5ae4de with ruby 2.2.6, rubocop 0.47.1, and haml-lint 0.20.0 |
Let VMDBLogger.log_hashes filter out the sensitive value. (cherry picked from commit 799ba56) https://bugzilla.redhat.com/show_bug.cgi?id=1458434
Fine backport details:
|
VMDBLogger.log_hashes would log the sensitive value as FILTERED.
Blocks #manageiq/pull/14878.
@miq-bot assign @gmcculloug
@miq-bot add_label fine/yes, enhancement