class TCellAgent::Policies::DataLossPolicy

Attributes

database_actions[RW]
database_discovery_enabled[RW]
database_filter_actions[RW]
enabled[RW]
field_alerts[RW]
field_redact_body[RW]
policy_id[RW]
request_filter_actions[RW]
session_id_actions[RW]
session_id_filter_actions[RW]
table_field_actions[RW]

Public Class Methods

actions_from_json(options) click to toggle source
# File lib/tcell_agent/policies/dataloss_policy.rb, line 170
def self.actions_from_json(options)
  actions = nil
  if options.key?('log')
    if options['log'].include? 'redact'
      actions ||= FilterActions.new
      actions.log_redact = true
    end
    if options['log'].include? 'event'
      actions ||= FilterActions.new
      actions.log_event = true
    end
    if options['log'].include? 'hash'
      actions ||= FilterActions.new
      actions.log_hash = true
    end
  end
  if options.key?('body')
    if options['body'].include? 'redact'
      actions ||= FilterActions.new
      actions.body_redact = true
    end
    if options['body'].include? 'event'
      actions ||= FilterActions.new
      actions.body_event = true
    end
    if options['body'].include? 'hash'
      actions ||= FilterActions.new
      actions.body_hash = true
    end
  end
  actions
end
api_identifier() click to toggle source
# File lib/tcell_agent/policies/dataloss_policy.rb, line 7
def self.api_identifier
  'dlp'
end
new(policies_json) click to toggle source
# File lib/tcell_agent/policies/dataloss_policy.rb, line 45
def initialize(policies_json)
  init_options
  from_json(policies_json) unless policies_json.nil? || policies_json.empty?
end

Public Instance Methods

actions_for_form_parameter?() click to toggle source
# File lib/tcell_agent/policies/dataloss_policy.rb, line 87
def actions_for_form_parameter?
  !@request_filter_actions[RequestProtectionManager::FORM].empty?
end
actions_for_headers?() click to toggle source
# File lib/tcell_agent/policies/dataloss_policy.rb, line 91
def actions_for_headers?
  !@request_filter_actions[RequestProtectionManager::HEADER].empty?
end
from_json(policy_json) click to toggle source
# File lib/tcell_agent/policies/dataloss_policy.rb, line 203
def from_json(policy_json)
  return unless policy_json

  @policy_id = policy_json['policy_id']
  raise 'Policy ID missing' unless @policy_id

  data_json = (policy_json['data'] || {})

  if data_json.key?('data_discovery')
    data_discovery_json = data_json['data_discovery']
    @database_discovery_enabled = data_discovery_json.fetch('database_enabled', false)
    @enabled = @database_discovery_enabled
  end

  if data_json.key?('session_id_protections')
    session_id_protection = data_json['session_id_protections']
    rule_id = session_id_protection.fetch('id', nil)
    filter_actions = DataLossPolicy.actions_from_json(session_id_protection)
    unless filter_actions.nil?
      @enabled = true
      filter_actions.action_id = rule_id
      @session_id_filter_actions = filter_actions
    end
  end

  if data_json.key?('request_protections')
    data_json['request_protections'].each do |protection|
      context = protection.fetch('variable_context', nil)
      variables = protection.fetch('variables', nil)
      scope = protection.fetch('scope', 'global')
      rule_id = protection.fetch('id', nil)
      options = protection.fetch('actions', nil)
      route_ids = []

      if scope == 'global'
        route_ids = ['*']
      elsif scope == 'route'
        route_ids = protection.fetch('route_ids', [])
      else
        next
      end

      next unless context && @request_filter_actions.key?(context) && variables && options

      filter_actions = DataLossPolicy.actions_from_json(options)
      next if filter_actions.nil?

      @enabled = true
      filter_actions.action_id = rule_id
      variables.each do |variable|
        route_ids.each  do |route_id|
          if context == RequestProtectionManager::COOKIE
            # Case sensitive variable name
            @request_filter_actions[context][route_id][variable].add(filter_actions)
          else
            @request_filter_actions[context][route_id][variable.downcase].add(filter_actions)
          end
        end
      end
    end
  end

  return unless data_json.key?('db_protections')

  protections = data_json['db_protections']
  return unless protections

  protections.each do |protection_json|
    scope = protection_json.fetch('scope', nil)
    databases = protection_json.fetch('databases', ['*'])
    schemas = protection_json.fetch('schemas', ['*'])
    tables = protection_json.fetch('tables', ['*'])
    fields = protection_json.fetch('fields', nil)
    rule_id = protection_json.fetch('id', nil)
    actions = protection_json.fetch('actions', {})
    filter_actions = DataLossPolicy.actions_from_json(actions)
    route_ids = ['*']

    if !scope.nil? && scope != 'global' && scope == 'route'
      route_ids = protection_json.fetch('route_ids', [])
    end

    next if fields.nil? || filter_actions.nil?

    @enabled = true
    filter_actions.action_id = rule_id
    databases.each do |database|
      schemas.each do |schema|
        tables.each do |table|
          fields.each do |field|
            route_ids.each do |route_id|
              @database_actions[database][schema][table][field][route_id].add(filter_actions)
            end
          end
        end
      end
    end
  end
end
get_actions_for(table, field) click to toggle source
# File lib/tcell_agent/policies/dataloss_policy.rb, line 163
def get_actions_for(table, field)
  actions = Set.new
  key = "#{table}.#{field}"
  actions.merge(@table_field_actions.fetch(key, [].to_set))
  actions
end
get_actions_for_form_parameter(parameter_name, route_id = nil) click to toggle source
# File lib/tcell_agent/policies/dataloss_policy.rb, line 107
def get_actions_for_form_parameter(parameter_name, route_id = nil)
  get_actions_for_request(RequestProtectionManager::FORM, parameter_name.downcase, route_id)
end
get_actions_for_header(header_name, route_id = nil) click to toggle source
# File lib/tcell_agent/policies/dataloss_policy.rb, line 103
def get_actions_for_header(header_name, route_id = nil)
  get_actions_for_request(RequestProtectionManager::HEADER, header_name.downcase, route_id)
end
get_actions_for_request(context, variable, route_id = nil) click to toggle source
# File lib/tcell_agent/policies/dataloss_policy.rb, line 111
def get_actions_for_request(context, variable, route_id = nil)
  return nil if context.nil? || variable.nil?

  route_id = '*' if route_id.nil?
  if context != RequestProtectionManager::COOKIE
    variable = variable.downcase
  end
  actions = Set.new
  if @request_filter_actions.key?(context)
    if @request_filter_actions[context].key?(route_id) && @request_filter_actions[context][route_id].key?(variable)
      actions.merge(@request_filter_actions[context][route_id][variable])
    end
    if route_id != '*' && @request_filter_actions[context].key?('*') && @request_filter_actions[context]['*'].key?(variable)
      actions.merge(@request_filter_actions[context]['*'][variable])
    end
  end
  return nil if actions.size <= 0

  actions
end
get_actions_for_session_id(_route_id = nil) click to toggle source
# File lib/tcell_agent/policies/dataloss_policy.rb, line 83
def get_actions_for_session_id(_route_id = nil)
  @session_id_filter_actions
end
get_actions_for_table(database, schema, table, field, route_id = '*') click to toggle source
# File lib/tcell_agent/policies/dataloss_policy.rb, line 132
def get_actions_for_table(database, schema, table, field, route_id = '*')
  route_id = '*' if route_id.nil?
  actions = Set.new
  [database, '*'].each do |d|
    next if @database_actions.key?(d) == false

    [schema, '*'].each do |s|
      next if @database_actions[d].key?(s) == false

      [table, '*'].each do |t|
        next if @database_actions[d][s].key?(t) == false

        [field, '*'].each do |f|
          next if @database_actions[d][s][t].key?(f) == false

          route_id_rules = @database_actions[d][s][t][f]
          if route_id_rules.key?(route_id)
            actions.merge(@database_actions[d][s][t][f][route_id])
          end
          if route_id != '*' && route_id_rules.key?('*')
            actions.merge(@database_actions[d][s][t][f]['*'])
          end
        end
      end
    end
  end
  return nil if actions.empty?

  actions
end
init_options() click to toggle source
# File lib/tcell_agent/policies/dataloss_policy.rb, line 50
def init_options
  @enabled = false
  @policy_id = nil

  @table_field_actions = {}
  @session_id_actions = []

  @database_discovery_enabled = false

  @field_redact_body = Set.new # ["work_infos.SSN"].to_set #
  @field_alerts = Set.new

  @session_id_filter_actions = nil
  @request_filter_actions = {
    RequestProtectionManager::FORM => Hash.new { |h, k| h[k] = Hash.new { |i_h, i_k| i_h[i_k] = Set.new } },
    RequestProtectionManager::COOKIE => Hash.new { |h, k| h[k] = Hash.new { |i_h, i_k| i_h[i_k] = Set.new } },
    RequestProtectionManager::HEADER => Hash.new { |h, k| h[k] = Hash.new { |i_h, i_k| i_h[i_k] = Set.new } }
  }
  @database_actions = Hash.new do |h, k|
    h[k] = Hash.new do |d_h, d_k|
      d_h[d_k] = Hash.new do |s_h, s_k|
        s_h[s_k] = Hash.new do |t_h, t_k|
          t_h[t_k] = Hash.new do |f_h, f_k|
            f_h[f_k] = Set.new
          end
        end
      end
    end
  end

  @log_actions = nil
end
log_enforce(tcell_context, sanitize_string) click to toggle source
# File lib/tcell_agent/rails/dlp.rb, line 303
def log_enforce(tcell_context, sanitize_string)
  if TCellAgent.configuration.should_instrument? &&
     TCellAgent.configuration.should_intercept_requests?
    session_id_actions = get_actions_for_session_id
    if tcell_context && tcell_context.session_id && session_id_actions
      send_event = false
      sanitize_string.gsub!(tcell_context.session_id) do |m|
        if session_id_actions.log_redact
          send_event = true
          m = '[session_id]'
        elsif session_id_actions.log_hash
          send_event = true
          m = '[hash]'
        elsif session_id_actions.log_event
          send_event = true
        end
        m
      end
      if send_event
        TCellAgent.send_event(
          TCellAgent::SensorEvents::DlpEvent.new(
            tcell_context.route_id,
            tcell_context.uri,
            TCellAgent::SensorEvents::DlpEvent::FOUND_IN_LOG
          ).for_framework(TCellAgent::SensorEvents::DlpEvent::FRAMEWORK_VARIABLE_SESSION_ID)
        )
      end
    end
  end

  sanitize_string
end
response_body_enforce(tcell_context, sanitize_string) click to toggle source
# File lib/tcell_agent/rails/dlp.rb, line 336
def response_body_enforce(tcell_context, sanitize_string)
  if TCellAgent.configuration.should_instrument? &&
     TCellAgent.configuration.should_intercept_requests?
    session_id_actions = get_actions_for_session_id
    if tcell_context && tcell_context.session_id && session_id_actions
      send_event = false
      sanitize_string.gsub!(tcell_context.session_id) do |m|
        # rubocop:disable Lint/DuplicateBranch
        if session_id_actions.body_redact
          # m = "[session_id]"
          send_event = true
        elsif session_id_actions.body_hash
          # m = "[hash]"
          send_event = true
        elsif session_id_actions.body_event
          send_event = true
        end
        # rubocop:enable Lint/DuplicateBranch
        m
      end
    end
    if send_event
      TCellAgent.send_event(
        TCellAgent::SensorEvents::DlpEvent.new(
          tcell_context.route_id,
          tcell_context.uri,
          TCellAgent::SensorEvents::DlpEvent::FOUND_IN_BODY
        ).for_framework(TCellAgent::SensorEvents::DlpEvent::FRAMEWORK_VARIABLE_SESSION_ID)
      )
    end
  end

  sanitize_string
end