Skip to content

Commit

Permalink
feat: Redact anonymous attributes within feature events
Browse files Browse the repository at this point in the history
  • Loading branch information
keelerm84 committed Jan 9, 2024
1 parent cb5a84f commit a3bfde1
Show file tree
Hide file tree
Showing 4 changed files with 26 additions and 17 deletions.
1 change: 1 addition & 0 deletions contract-tests/service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
'event-sampling',
'context-comparison',
'inline-context',
'anonymous-redaction',
],
}.to_json
end
Expand Down
10 changes: 6 additions & 4 deletions lib/ldclient-rb/events.rb
Original file line number Diff line number Diff line change
Expand Up @@ -481,12 +481,14 @@ def make_output_events(events, summary)
key: event.key,
value: event.value,
}

out[:default] = event.default unless event.default.nil?
out[:variation] = event.variation unless event.variation.nil?
out[:version] = event.version unless event.version.nil?
out[:prereqOf] = event.prereq_of unless event.prereq_of.nil?
out[:context] = @context_filter.filter(event.context)
out[:context] = @context_filter.filter(event.context, true)
out[:reason] = event.reason unless event.reason.nil?

out

when LaunchDarkly::Impl::MigrationOpEvent
Expand Down Expand Up @@ -552,7 +554,7 @@ def make_output_events(events, summary)
kind: IDENTIFY_KIND,
creationDate: event.timestamp,
key: event.context.fully_qualified_key,
context: @context_filter.filter(event.context),
context: @context_filter.filter(event.context, false),
}

when LaunchDarkly::Impl::CustomEvent
Expand All @@ -570,7 +572,7 @@ def make_output_events(events, summary)
{
kind: INDEX_KIND,
creationDate: event.timestamp,
context: @context_filter.filter(event.context),
context: @context_filter.filter(event.context, false),
}

when LaunchDarkly::Impl::DebugEvent
Expand All @@ -579,7 +581,7 @@ def make_output_events(events, summary)
kind: DEBUG_KIND,
creationDate: original.timestamp,
key: original.key,
context: @context_filter.filter(original.context),
context: @context_filter.filter(original.context, false),
value: original.value,
}
out[:default] = original.default unless original.default.nil?
Expand Down
22 changes: 13 additions & 9 deletions lib/ldclient-rb/impl/context_filter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,18 @@ def initialize(all_attributes_private, private_attributes)
# redaction applied.
#
# @param context [LaunchDarkly::LDContext]
# @param redact_anonymous [Boolean]
# @return [Hash]
#
def filter(context)
return filter_single_context(context, true) unless context.multi_kind?
def filter(context, redact_anonymous)
return filter_single_context(context, true, redact_anonymous) unless context.multi_kind?

filtered = {kind: 'multi'}
(0...context.individual_context_count).each do |i|
c = context.individual_context(i)
next if c.nil?

filtered[c.kind] = filter_single_context(c, false)
filtered[c.kind] = filter_single_context(c, false, redact_anonymous)
end

filtered
Expand All @@ -43,22 +44,24 @@ def filter(context)
# @param include_kind [Boolean]
# @return [Hash]
#
private def filter_single_context(context, include_kind)
private def filter_single_context(context, include_kind, redact_anonymous)
filtered = {key: context.key}

filtered[:kind] = context.kind if include_kind
filtered[:anonymous] = true if context.get_value(:anonymous)

anonymous = context.get_value(:anonymous)
filtered[:anonymous] = true if anonymous

redacted = []
private_attributes = @private_attributes.concat(context.private_attributes)

name = context.get_value(:name)
if !name.nil? && !check_whole_attribute_private(:name, private_attributes, redacted)
if !name.nil? && !check_whole_attribute_private(:name, private_attributes, redacted, anonymous && redact_anonymous)
filtered[:name] = name
end

context.get_custom_attribute_names.each do |attribute|
unless check_whole_attribute_private(attribute, private_attributes, redacted)
unless check_whole_attribute_private(attribute, private_attributes, redacted, anonymous && redact_anonymous)
value = context.get_value(attribute)
filtered[attribute] = redact_json_value(nil, attribute, value, private_attributes, redacted)
end
Expand All @@ -75,10 +78,11 @@ def filter(context)
# @param attribute [Symbol]
# @param private_attributes [Array<Reference>]
# @param redacted [Array<Symbol>]
# @param redact_all [Boolean]
# @return [Boolean]
#
private def check_whole_attribute_private(attribute, private_attributes, redacted)
if @all_attributes_private
private def check_whole_attribute_private(attribute, private_attributes, redacted, redact_all)
if @all_attributes_private || redact_all
redacted << attribute
return true
end
Expand Down
10 changes: 6 additions & 4 deletions spec/events_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -601,7 +601,7 @@ def index_event(config, context, timestamp = starting_timestamp)
out = {
kind: "index",
creationDate: timestamp,
context: context_filter.filter(context),
context: context_filter.filter(context, false),
}
JSON.parse(out.to_json, symbolize_names: true)
end
Expand All @@ -618,7 +618,7 @@ def identify_event(config, context, timestamp = starting_timestamp)
kind: "identify",
creationDate: timestamp,
key: context.fully_qualified_key,
context: context_filter.filter(context),
context: context_filter.filter(context, false),
}
JSON.parse(out.to_json, symbolize_names: true)
end
Expand All @@ -634,10 +634,12 @@ def identify_event(config, context, timestamp = starting_timestamp)
#
def feature_event(config, flag, context, variation, value, timestamp = starting_timestamp)
context_filter = Impl::ContextFilter.new(config.all_attributes_private, config.private_attributes)
redacted_context = context_filter.filter(context, true)

out = {
kind: 'feature',
creationDate: timestamp,
context: context_filter.filter(context),
context: redacted_context,
key: flag[:key],
variation: variation,
version: flag[:version],
Expand Down Expand Up @@ -691,7 +693,7 @@ def debug_event(config, flag, context, variation, value, timestamp = starting_ti
variation: variation,
version: flag[:version],
value: value,
context: context_filter.filter(context),
context: context_filter.filter(context, false),
}
JSON.parse(out.to_json, symbolize_names: true)
end
Expand Down

0 comments on commit a3bfde1

Please sign in to comment.