-
Notifications
You must be signed in to change notification settings - Fork 780
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
[RFC] Diags scrubbing mechanism #1567
Conversation
Please squash the commits. |
clang format successful! https://ci.trafficserver.apache.org/job/clang-format-github/34/ |
RAT check successful! https://ci.trafficserver.apache.org/job/RAT-github/47/ |
Diagnostic log scrubbing is intended an extra security measure to prevent sensitive strings from leaking to diagnostic logs. This is provided via a config option proxy.config.diags.scrubs. For each line that is to be written to diagnostic logs, a regular expression(s) is applied to the line. If there are any matches, the matched substring is replaced with the replacement string.
|
||
.. note:: | ||
|
||
Multiple captures are not supported. (ie. ``s/foo/bar/g`` is not suppored while ``s/foo/bar/`` is). Furthermore, |
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.
"Multiple replacements"? That is, can I have capture groups? More than one capture group? Also, "suppored".
FreeBSD11 build failed! https://ci.trafficserver.apache.org/job/freebsd-github/1729/ |
clang format successful! https://ci.trafficserver.apache.org/job/clang-format-github/35/ |
RAT check successful! https://ci.trafficserver.apache.org/job/RAT-github/48/ |
FreeBSD11 build failed! https://ci.trafficserver.apache.org/job/freebsd-github/1730/ |
lib/ts/Diags.h
Outdated
struct Scrub { | ||
~Scrub() | ||
{ | ||
if (pattern) { |
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.
ats_scoped_str
might be useful here.
AU check failed! https://ci.trafficserver.apache.org/job/autest-github/33/ |
Lots of allocation to be removed. This should be done without any allocation. |
clang format successful! https://ci.trafficserver.apache.org/job/clang-format-github/36/ |
RAT check successful! https://ci.trafficserver.apache.org/job/RAT-github/49/ |
FreeBSD11 build failed! https://ci.trafficserver.apache.org/job/freebsd-github/1731/ |
Intel CC build successful! https://ci.trafficserver.apache.org/job/icc-github/159/ |
AU check failed! https://ci.trafficserver.apache.org/job/autest-github/34/ |
Linux build successful! https://ci.trafficserver.apache.org/job/linux-github/1624/ |
Intel CC build successful! https://ci.trafficserver.apache.org/job/icc-github/160/ |
Linux build successful! https://ci.trafficserver.apache.org/job/linux-github/1625/ |
Spoke with Dan, we'll get the allocations cleaned up before Leif has a stroke. |
clang-analyzer build failed! https://ci.trafficserver.apache.org/job/clang-analyzer-github/291/ |
clang-analyzer build failed! https://ci.trafficserver.apache.org/job/clang-analyzer-github/292/ |
The last commit gets error.log scrubbed too. I'll fix the allocation stuff on Tuesday. Nobody tell Leif. |
FreeBSD11 build successful! https://ci.trafficserver.apache.org/job/freebsd-github/1757/ |
Intel CC build successful! https://ci.trafficserver.apache.org/job/icc-github/188/ |
clang-analyzer build successful! https://ci.trafficserver.apache.org/job/clang-analyzer-github/320/ |
@@ -226,6 +242,10 @@ class Diags | |||
mutable ink_mutex tag_table_lock; // prevents reconfig/read races | |||
DFA *activated_tags[2]; // 1 table for debug, 1 for action | |||
|
|||
// Scrubbing variables -- replaces predefined regexp matches with the replacement string | |||
bool scrub_enabled = false; | |||
Scrubber *scrubber = nullptr; |
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 a good place to use std::unique_ptr
.
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.
As discussed, due to namespace issues in Vec.h
, using unique_ptr
is more trouble than it's worth.
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.
My long range plan is KIWF on Vec.h
so we'll live with this for now.
lib/ts/Scrubber.cc
Outdated
Scrubber::Scrubber(const char *config) | ||
{ | ||
bool state_expecting_regex = true; | ||
const ts::StringView delimiters("->;,", ts::StringView::literal); |
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.
Make this static
also, so that it's constructed at process start.
lib/ts/Scrubber.cc
Outdated
const ts::StringView delimiters("->;,", ts::StringView::literal); | ||
ts::StringView regex; | ||
ts::StringView replacement; | ||
ts::StringView text(config); |
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 problematic, because the StringView
will be pointing in to external memory. This needs to point to the local memory in this->config
.
lib/ts/Scrubber.cc
Outdated
|
||
// This means that there was some kind of config or parse error. | ||
// This doesn't catch *all* errors, and is just a heuristic so we can't actually print any meaningful message. | ||
if ((regex && !replacement) || (!regex && replacement)) { |
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.
Why check this, if nothing is done?
lib/ts/Scrubber.cc
Outdated
memmove(buffer_ptr, buffer + scrub->ovector[1], buffer_len - scrub->ovector[1] + 1); | ||
|
||
// the last char should ALWAYS be a '\0' otherwise we did our math wrong | ||
ink_assert(buffer[strlen(buffer)] == '\0'); |
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 expensive and pointless - by definition, strlen
will find a null so this will always be true, unless it segfaults. The index should be computed from the other lengths, not searched for, if you want to verify your math.
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 must have been asleep at the wheel here.
lib/ts/Scrubber.cc
Outdated
int n_slide = buffer_len - scrub->ovector[0] - replacement_len; | ||
if (n_slide < 0) { | ||
// replacement string is too long, we need to shorten it | ||
replacement_len -= -n_slide; |
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 +=
?
lib/ts/Scrubber.h
Outdated
pcre_free(const_cast<pcre *>(compiled_re)); | ||
} | ||
} | ||
static const int OVECCOUNT = 30; |
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.
Where does 30
come from? POOMA?
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.
It was used in the PCRE example documentation. Really this could be any value >= 3.
lib/ts/Scrubber.h
Outdated
*/ | ||
void scrub_buffer(char *buffer, Scrub *scrub) const; | ||
|
||
char *config = nullptr; |
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 recommend using ats_scoped_str
here, to avoid having to explicitly clean up.
@@ -299,6 +299,10 @@ class LogObject : public RefCountObj | |||
unsigned m_buffer_manager_idx; | |||
LogBufferManager *m_buffer_manager; | |||
|
|||
// scrubbing data -- helps us scrub buffers of sensitive data | |||
bool scrub_enabled = false; |
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.
Are both of these needed? Does not scubber
suffice by being null or not null?
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.
Maybe. Depends on if we want to let users toggle scrubbing at runtime.
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.
Hmmm, I'd need to think about if that make sense.
Looking better. |
Personally, I don't think this feature has much use in open source. If nothing else, it probably encourages poor security practices. Even with this patch, someone could still do a |
[approve ci] |
What's the future of this PR? Are we planning on landing this? Is it still WIP? |
[approve ci] |
IIRC this patch is ready to merge. There are no performance penalties for not using this feature (other than a few branch mispredicts, if that). It's a nifty feature to have in my opinion. If anyone else is +1 on this I'm willing to merge this and potentially apply fixes if it breaks in the future. |
I really think this should be done on post processing and this adds more complexity to the proxy. |
Since diagnostics is something you generally do not run as part of a production environment (due to performance), it feels to me that a better approach is an external tool (perl or python script) that scrubs the logs. That would be a lot easier to maintain and add features to, and could have a lot more features as well. |
This should be the squashed commit message:
Diagnostic log scrubbing is intended an extra security measure to prevent sensitive strings from leaking to diagnostic logs. This is provided via a config option
proxy.config.diags.scrubs
.For each line that is to be written to diagnostic logs, a regular expression(s) is applied to the line. If there are any matches, the matched substring is replaced with the replacement string.