Module: Immunio::Context
- Defined in:
- lib/immunio/context.rb
Constant Summary collapse
- RAILS_TEMPLATE_FILTER =
Regexp.new("(.*(_erb|_haml))__+\\d+_\\d+(.*)")
- @@hash_cache =
Cache for contexts (named in tribute to our buddy Adam Back who invented proof of work)
{}
Class Method Summary collapse
-
.context(additional_data = nil) ⇒ Object
Calculate context hashes and a stack trace.
Class Method Details
.context(additional_data = nil) ⇒ Object
Calculate context hashes and a stack trace. Additional data, in the form of a String, may be provided to mix into the strict context hash.
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 |
# File 'lib/immunio/context.rb', line 9 def self.context(additional_data=nil) # We can filter out at least the top two frames cache_key = Digest::SHA1.hexdigest(caller(2).join()) if @@hash_cache.has_key?(cache_key) then loose_context = @@hash_cache[cache_key]["loose_context"] strict_context = @@hash_cache[cache_key]["strict_context"] stack = @@hash_cache[cache_key]["stack"] loose_stack = @@hash_cache[cache_key]["stack"] if Immunio.agent.config.log_context_data Immunio.logger.info {"Stack contexts from cache"} end else # Use ropes as they're faster than string concatenation loose_stack_rope = [] loose_context_rope = [] stack_rope = [] strict_context_rope = [] # drop the top frame as it's us, but retain the rest. Immunio frames # are filtered by the Gem regex. locations = caller(1).map do |frame| frame = frame.split(":", 3) {path: frame[0], line: frame[1], label: frame[2]} end locations.each do |frame| # Filter frame names from template rendering to remove generated random bits matchdata = RAILS_TEMPLATE_FILTER.match(frame[:label]) if matchdata != nil then frame[:label] = matchdata[1] + matchdata[3] end # Reduce paths to be relative to root if possible, to allow # relocation. If there's no rails root, or the path doesn't start with # the rails root, just use the filename part. if defined?(Rails) && defined?(Rails.root) && Rails.root && frame[:path].start_with?(Rails.root.to_s) strict_path = frame[:path].sub(Rails.root.to_s, '') else strict_path = File.basename(frame[:path]) end stack_rope << "\n" unless stack_rope.empty? stack_rope << frame[:path] stack_rope << ":" stack_rope << frame[:line] stack_rope << ":" stack_rope << frame[:label] strict_context_rope << "\n" unless strict_context_rope.empty? strict_context_rope << strict_path strict_context_rope << ":" strict_context_rope << frame[:line] strict_context_rope << ":" strict_context_rope << frame[:label] # Remove pathname from the loose context. The goal here is to prevent # upgrading gem versions from changing the loose context key, so for instance # users don't have to rebuild their whitelists every time they update a gem loose_context_rope << "\n" unless loose_context_rope.empty? loose_context_rope << File.basename(frame[:path]) loose_context_rope << ":" loose_context_rope << frame[:label] # build a second seperate rope for the stack that determines ou loose context key # This includes filenames for usability -- just method names not being very good # for display purposes... loose_stack_rope << "\n" unless loose_stack_rope.empty? loose_stack_rope << frame[:path] loose_stack_rope << ":" loose_stack_rope << frame[:label] end stack = stack_rope.join() strict_stack = strict_context_rope.join() loose_stack = loose_stack_rope.join() if Immunio.agent.config.log_context_data Immunio.logger.info {"Strict context stack:\n#{strict_stack}"} Immunio.logger.info {"Loose context stack:\n#{loose_stack}"} end strict_context = Digest::SHA1.hexdigest(strict_stack) loose_context = Digest::SHA1.hexdigest(loose_context_rope.join()) @@hash_cache[cache_key] = { "strict_context" => strict_context, "loose_context" => loose_context, "stack" => stack, "loose_stack" => loose_stack } end # Mix in additional context data unless additional_data.nil? if Immunio.agent.config.log_context_data Immunio.logger.info {"Additional context data:\n#{additional_data}"} end strict_context = Digest::SHA1.hexdigest(strict_context + additional_data) end return strict_context, loose_context, stack, loose_stack end |