Module: Legion::Logging::SIEMExporter

Defined in:
lib/legion/logging/siem_exporter.rb

Constant Summary collapse

PHI_PATTERNS =
[
  [/\b\d{3}-\d{2}-\d{4}\b/, '[SSN-REDACTED]'],
  [/\b\d{3}-\d{3}-\d{4}\b/, '[PHONE-REDACTED]'],
  [/\b[A-Z]{2}\d{7}\b/, '[MRN-REDACTED]'],
  [%r{\b\d{2}/\d{2}/\d{4}\b}, '[DOB-REDACTED]']
].freeze

Class Method Summary collapse

Class Method Details

.export_to_splunk(event, hec_url:, token:) ⇒ Object



24
25
26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/legion/logging/siem_exporter.rb', line 24

def export_to_splunk(event, hec_url:, token:)
  uri = URI(hec_url)
  req = Net::HTTP::Post.new(uri)
  req['Authorization'] = "Splunk #{token}"
  req['Content-Type'] = 'application/json'
  req.body = ::JSON.dump({ event: redact_phi(event.to_s), time: Time.now.to_f })

  Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == 'https') do |http|
    http.request(req)
  end
rescue StandardError => e
  warn("Legion::Logging::SIEMExporter#export_to_splunk failed: #{e.message}")
  { error: e.message }
end

.format_for_elk(event, index: 'legion') ⇒ Object



39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/legion/logging/siem_exporter.rb', line 39

def format_for_elk(event, index: 'legion')
  result = {
    '@timestamp' => Time.now.utc.iso8601,
    'index'      => index,
    'message'    => redact_phi(event.to_s),
    'source'     => 'legion'
  }
  if event.is_a?(Hash)
    category = event[:category] || event['category']
    result['category'] = category.to_s if category
  end
  result
end

.redact_phi(text) ⇒ Object



18
19
20
21
22
# File 'lib/legion/logging/siem_exporter.rb', line 18

def redact_phi(text)
  result = text.to_s.dup
  PHI_PATTERNS.each { |pattern, replacement| result.gsub!(pattern, replacement) }
  result
end