Skip to content

Commit 3d2ff26

Browse files
committed
fix: redact sensitive attributes
1 parent cb5f1c4 commit 3d2ff26

File tree

3 files changed

+86
-1
lines changed

3 files changed

+86
-1
lines changed
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# frozen_string_literal: true
2+
3+
# Copyright The OpenTelemetry Authors
4+
#
5+
# SPDX-License-Identifier: Apache-2.0
6+
7+
module OpenTelemetry
8+
module Instrumentation
9+
module Net
10+
module LDAP
11+
# attribute mapper to redact sensitive keys
12+
class AttributeMapper
13+
SENSITIVE_KEYS = %w[userPassword unicodePwd lmPassword ntPassword authPassword krbPrincipalKey sambaNTPassword sambaLMPassword].freeze
14+
15+
def self.redact(_value)
16+
'[REDACTED]'
17+
end
18+
19+
def self.map_json(json_string)
20+
begin
21+
parsed = JSON.parse(json_string)
22+
redacted = deep_map(parsed)
23+
JSON.generate(redacted)
24+
rescue JSON::ParserError
25+
json_string
26+
end
27+
end
28+
29+
def self.map(attributes)
30+
deep_map(attributes)
31+
end
32+
33+
def self.deep_map(obj)
34+
case obj
35+
when Hash
36+
obj.each_with_object({}) do |(k, v), result|
37+
key_str = k.to_s
38+
result[k] = SENSITIVE_KEYS.include?(key_str) ? redact(v) : deep_map(v)
39+
end
40+
when Array
41+
# Special case: LDAP operation tuple like ["replace", "unicodePwd", ["value"]]
42+
if obj.size == 3 && obj[1].is_a?(String) && SENSITIVE_KEYS.include?(obj[1])
43+
[obj[0], obj[1], ['[REDACTED]']]
44+
else
45+
obj.map { |item| deep_map(item) }
46+
end
47+
when String
48+
map_json(obj)
49+
else
50+
obj
51+
end
52+
end
53+
end
54+
end
55+
end
56+
end
57+
end

instrumentation/net_ldap/lib/opentelemetry/instrumentation/net/ldap/instrumentation_service.rb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
#
55
# SPDX-License-Identifier: Apache-2.0
66

7+
require_relative 'attribute_mapper'
8+
79
module OpenTelemetry
810
module Instrumentation
911
module Net
@@ -33,7 +35,7 @@ def instrument(event, payload)
3335

3436
tracer.in_span(
3537
event,
36-
attributes: attributes,
38+
attributes: AttributeMapper.map(attributes),
3739
kind: :client
3840
) do |span|
3941
yield(payload).tap do |response|

instrumentation/net_ldap/test/opentelemetry/instrumentation/net/ldap/instrumentation_test.rb

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ class FakeConnection
2929

3030
def initialize
3131
@bind_success = Result.new(true, Net::LDAP::ResultCodeSuccess)
32+
@modify_success = Result.new(true, Net::LDAP::ResultCodeSuccess)
3233
@search_success = Result.new(true, Net::LDAP::ResultCodeSizeLimitExceeded)
3334
end
3435

@@ -45,6 +46,11 @@ def search(*args)
4546
def add(args)
4647
raise Net::LDAP::Error, 'Connection timed out - user specified timeout'
4748
end
49+
50+
# for testing redaction
51+
def modify(args)
52+
@modify_success
53+
end
4854
end
4955

5056
before do
@@ -115,5 +121,25 @@ def add(args)
115121
_(span.attributes['net.peer.port']).must_equal 636
116122
end
117123
end
124+
125+
describe 'when modify happens' do
126+
it 'tracks the attributes with correct name & redacts sensitive information' do
127+
ldap.connection = FakeConnection.new
128+
ops = [
129+
[:replace, :unicodePwd, ['P@ssw0rd']],
130+
]
131+
assert ldap.modify(dn: 'CN=test,OU=test,DC=com', operations: ops)
132+
133+
_(exporter.finished_spans.size).must_equal 1
134+
_(span.name).must_equal 'modify.net_ldap'
135+
_(span.attributes['ldap.auth']).must_equal '{"method":"anonymous"}'
136+
_(span.attributes['ldap.base']).must_equal 'dc=com'
137+
_(span.attributes['ldap.encryption']).must_equal '{"method":"simple_tls","tls_options":{"foo":"bar"}}'
138+
_(span.attributes['ldap.payload']).must_equal '{"dn":"CN=test,OU=test,DC=com","operations":[["replace","unicodePwd",["[REDACTED]"]]]}'
139+
_(span.attributes['ldap.status_code']).must_equal 0
140+
_(span.attributes['net.peer.name']).must_equal 'test.mocked.com'
141+
_(span.attributes['net.peer.port']).must_equal 636
142+
end
143+
end
118144
end
119145
end

0 commit comments

Comments
 (0)