Skip to content
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

Change URL obfuscation behavior #145

Merged
merged 2 commits into from
Jul 9, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 12 additions & 4 deletions src/span.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,13 +60,14 @@ Span::Span(std::shared_ptr<const Tracer> tracer, std::shared_ptr<SpanBuffer> buf
TimeProvider get_time, uint64_t span_id, uint64_t trace_id, uint64_t parent_id,
SpanContext context, TimePoint start_time, std::string span_service,
std::string span_type, std::string span_name, std::string resource,
std::string operation_name_override)
std::string operation_name_override, bool legacy_obfuscation)
: tracer_(std::move(tracer)),
buffer_(std::move(buffer)),
get_time_(get_time),
context_(std::move(context)),
start_time_(start_time),
operation_name_override_(operation_name_override),
legacy_obfuscation_(legacy_obfuscation),
span_(makeSpanData(span_type, span_service, resource, span_name, trace_id, span_id,
parent_id,
std::chrono::duration_cast<std::chrono::nanoseconds>(
Expand Down Expand Up @@ -103,10 +104,17 @@ std::regex &PATH_MIXED_ALPHANUMERICS() {
// or cardinality issues.
// If you want to add any more steps to this function, we should use a more
// sophisticated architecture. For now, YAGNI.
void audit(SpanData *span) {
void audit(bool legacy_obfuscation, SpanData *span) {
auto http_tag = span->meta.find(ot::ext::http_url);
if (http_tag != span->meta.end()) {
http_tag->second = std::regex_replace(http_tag->second, PATH_MIXED_ALPHANUMERICS(), "$1$2?");
if (legacy_obfuscation) {
// Heavy-handed obfuscation that replaces hostname, runs of alphanumerics, fragments and
// parameters.
http_tag->second = std::regex_replace(http_tag->second, PATH_MIXED_ALPHANUMERICS(), "$1$2?");
} else {
// Just trim the parameter portion of the URL.
http_tag->second = http_tag->second.substr(0, http_tag->second.find_first_of('?'));
}
}
}

Expand Down Expand Up @@ -173,7 +181,7 @@ void Span::FinishWithOptions(
span_->meta.erase(tag);
}
// Audit and finish span.
audit(span_.get());
audit(legacy_obfuscation_, span_.get());
buffer_->finishSpan(std::move(span_));
// According to the OT lifecycle, no more methods should be called on this Span. But just in case
// let's make sure that span_ isn't nullptr. Fine line between defensive programming and voodoo.
Expand Down
4 changes: 3 additions & 1 deletion src/span.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,8 @@ class Span : public DatadogSpan {
Span(std::shared_ptr<const Tracer> tracer, std::shared_ptr<SpanBuffer> buffer,
TimeProvider get_time, uint64_t span_id, uint64_t trace_id, uint64_t parent_id,
SpanContext context, TimePoint start_time, std::string span_service, std::string span_type,
std::string span_name, std::string resource, std::string operation_name_override);
std::string span_name, std::string resource, std::string operation_name_override,
bool legacy_obfuscation = false);

Span() = delete;
~Span() override;
Expand Down Expand Up @@ -134,6 +135,7 @@ class Span : public DatadogSpan {
SpanContext context_;
TimePoint start_time_;
std::string operation_name_override_;
bool legacy_obfuscation_ = false;

// Set in constructor initializer, depends on previous constructor initializer-set members:
std::unique_ptr<SpanData> span_;
Expand Down
21 changes: 18 additions & 3 deletions src/tracer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,14 @@ double analyticsRate(TracerOptions options) {
return std::nan("");
}

bool legacyObfuscationEnabled() {
auto obfuscation = std::getenv("DD_TRACE_CPP_LEGACY_OBFUSCATION");
if (obfuscation != nullptr && std::string(obfuscation) == "1") {
return true;
}
return false;
}

void startupLog(TracerOptions &options) {
auto env_setting = std::getenv("DD_TRACE_STARTUP_LOGS");
if (env_setting != nullptr && std::string(env_setting) == "0") {
Expand Down Expand Up @@ -204,11 +212,18 @@ void logTracerOptions(std::chrono::time_point<std::chrono::system_clock> timesta

Tracer::Tracer(TracerOptions options, std::shared_ptr<SpanBuffer> buffer, TimeProvider get_time,
IdProvider get_id)
: opts_(options), buffer_(std::move(buffer)), get_time_(get_time), get_id_(get_id) {}
: opts_(options),
buffer_(std::move(buffer)),
get_time_(get_time),
get_id_(get_id),
legacy_obfuscation_(legacyObfuscationEnabled()) {}

Tracer::Tracer(TracerOptions options, std::shared_ptr<Writer> &writer,
std::shared_ptr<RulesSampler> sampler)
: opts_(options), get_time_(getRealTime), get_id_(getId) {
: opts_(options),
get_time_(getRealTime),
get_id_(getId),
legacy_obfuscation_(legacyObfuscationEnabled()) {
configureRulesSampler(sampler, options);
startupLog(options);
buffer_ = std::make_shared<WritingSpanBuffer>(
Expand Down Expand Up @@ -245,7 +260,7 @@ std::unique_ptr<ot::Span> Tracer::StartSpanWithOptions(ot::string_view operation
std::unique_ptr<Span> span{new Span{shared_from_this(), buffer_, get_time_, span_id, trace_id,
parent_id, std::move(span_context), get_time_(),
opts_.service, opts_.type, operation_name, operation_name,
opts_.operation_name_override}};
opts_.operation_name_override, legacy_obfuscation_}};

if (!opts_.environment.empty()) {
span->SetTag(datadog::tags::environment, opts_.environment);
Expand Down
1 change: 1 addition & 0 deletions src/tracer.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ class Tracer : public ot::Tracer, public std::enable_shared_from_this<Tracer> {
std::shared_ptr<SpanBuffer> buffer_;
TimeProvider get_time_;
IdProvider get_id_;
bool legacy_obfuscation_ = false;
};

} // namespace opentracing
Expand Down
5 changes: 3 additions & 2 deletions test/integration/nginx/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,10 @@ COPY ./test/integration/nginx/dd-config.json /etc/dd-config.json
RUN mkdir -p /var/www/
COPY ./test/integration/nginx/index.html /var/www/index.html

COPY ./test/integration/nginx/nginx_integration_test.sh ./
COPY ./test/integration/nginx/expected_*.json ./
# TODO(cgilmour): Hack to pin a dep of msgpack-cli
RUN git clone -b v1.1.2 https://github.com/ugorji/go /root/go/src/github.com/ugorji/go
RUN go get github.com/jakm/msgpack-cli
# Copy these last so that edits don't need as many image rebuild steps
COPY ./test/integration/nginx/nginx_integration_test.sh ./
COPY ./test/integration/nginx/expected_*.json ./
CMD [ "bash", "-x", "./nginx_integration_test.sh"]
2 changes: 1 addition & 1 deletion test/integration/nginx/expected_tc6.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"http.method": "GET",
"http.status_code": "200",
"http.status_line": "200 OK",
"http.url": "http://localhost/proxy/?",
"http.url": "http://localhost/proxy/",
"operation": "GET /proxy/"
},
"metrics": {
Expand Down
43 changes: 41 additions & 2 deletions test/span_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,45 @@ TEST_CASE("span") {
REQUIRE(result->duration == 10000000000);
}

SECTION("audits span data") {
SECTION("audits span data (just URL parameters)") {
std::list<std::pair<std::string, std::string>> test_cases{
// Should remove query params
{"/", "/"},
{"/?asdf", "/"},
{"/search", "/search"},
{"/search?", "/search"},
{"/search?id=100&private=true", "/search"},
{"/search?id=100&private=true?", "/search"},
{"http://i-012a3b45c6d78901e//api/v1/check_run?api_key=0abcdef1a23b4c5d67ef8a90b1cde234",
"http://i-012a3b45c6d78901e//api/v1/check_run"},
};

std::shared_ptr<SpanBuffer> buffer_ptr{buffer};
for (auto& test_case : test_cases) {
auto span_id = get_id();
Span span{nullptr,
buffer_ptr,
get_time,
span_id,
span_id,
0,
SpanContext{span_id, span_id, "", {}},
get_time(),
"",
"",
"",
"",
""};
span.SetTag(ot::ext::http_url, test_case.first);
const ot::FinishSpanOptions finish_options;
span.FinishWithOptions(finish_options);

auto& result = buffer->traces(span_id).finished_spans->back();
REQUIRE(result->meta.find(ot::ext::http_url)->second == test_case.second);
}
}

SECTION("audits span data (legacy)") {
std::list<std::pair<std::string, std::string>> test_cases{
// Should remove query params
{"/", "/"},
Expand Down Expand Up @@ -103,7 +141,8 @@ TEST_CASE("span") {
"",
"",
"",
""};
"",
true};
span.SetTag(ot::ext::http_url, test_case.first);
const ot::FinishSpanOptions finish_options;
span.FinishWithOptions(finish_options);
Expand Down