logstash-filter-real_ip 0.1.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/lib/logstash/filters/real_ip.rb +35 -10
- data/logstash-filter-real_ip.gemspec +1 -1
- data/spec/filters/real_ip_spec.rb +82 -4
- metadata +2 -2
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: df7a4bbe848333419b6bd9cdddcb6396caa6469e1e80db081282c0ce3d6afe1a
         | 
| 4 | 
            +
              data.tar.gz: d56cd9f9f44694175f181777d3b25244236c80c97d129a8bd4eb90c42c8ad2c4
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: d2f799ae54fffe451882944901b007d426f6aaa2a9909ed339bf50f5112f38a186d49e48d667d4513eb0722035aea2f3a05b9da6ed0e2aa56444c5838e653d68
         | 
| 7 | 
            +
              data.tar.gz: 7df5f2176930a09f686bc63a2f5841a9b9985acef23d33ce0f461b0d23f002c866a2b141545323af6636b2369d7c85e442dce1c0c74ef26b549df541775f9e20
         | 
    
        data/CHANGELOG.md
    CHANGED
    
    
| @@ -98,6 +98,16 @@ class LogStash::Filters::RealIp < LogStash::Filters::Base | |
| 98 98 | 
             
              # address to.
         | 
| 99 99 | 
             
              config :target_field, :validate => :string, :default => "real_ip"
         | 
| 100 100 |  | 
| 101 | 
            +
              # writes all valid IPs found in the x_forwarded_for header to this field
         | 
| 102 | 
            +
              config :x_forwarded_for_target, :validate => :string, :default => ""
         | 
| 103 | 
            +
             | 
| 104 | 
            +
              # In case any IPs processed are invalid IP addresses,
         | 
| 105 | 
            +
              # write all of them as one string to the field specified.
         | 
| 106 | 
            +
              config :target_on_invalid_ip, :validate => :string, :default => ""
         | 
| 107 | 
            +
             | 
| 108 | 
            +
              # In case any IPs processed are invalid IP addresses, these tags will be set.
         | 
| 109 | 
            +
              config :tags_in_invalid_ip, :valudate => :array, :default => ["_real_ip_invalid_ip"]
         | 
| 110 | 
            +
             | 
| 101 111 | 
             
              # In case of error during evaluation, these tags will be set.
         | 
| 102 112 | 
             
              config :tags_on_failure, :validate => :array, :default => ["_real_ip_lookup_failure"]
         | 
| 103 113 |  | 
| @@ -122,6 +132,7 @@ class LogStash::Filters::RealIp < LogStash::Filters::Base | |
| 122 132 | 
             
                end
         | 
| 123 133 |  | 
| 124 134 | 
             
                @trusted_networks.map! {|e| IPAddr.new(e)}
         | 
| 135 | 
            +
                @need_all = x_forwarded_for_target.length > 0
         | 
| 125 136 | 
             
              end # def register
         | 
| 126 137 |  | 
| 127 138 | 
             
              private
         | 
| @@ -151,7 +162,7 @@ class LogStash::Filters::RealIp < LogStash::Filters::Base | |
| 151 162 |  | 
| 152 163 | 
             
                # check for presence of x_forwarded_for_field
         | 
| 153 164 | 
             
                if fwdfor == nil
         | 
| 154 | 
            -
                  @logger. | 
| 165 | 
            +
                  @logger.debug? and @logger.debug("x_forwarded_for_field missing from event", :event => event)
         | 
| 155 166 | 
             
                  event.set(@target_field, remote_addr)
         | 
| 156 167 | 
             
                  filter_matched(event)
         | 
| 157 168 | 
             
                  return
         | 
| @@ -206,29 +217,43 @@ class LogStash::Filters::RealIp < LogStash::Filters::Base | |
| 206 217 | 
             
                  return
         | 
| 207 218 | 
             
                end
         | 
| 208 219 |  | 
| 220 | 
            +
                found = false
         | 
| 221 | 
            +
                fatal = false
         | 
| 222 | 
            +
                target = []
         | 
| 209 223 | 
             
                # check each IP in x_forwarded_for_field from last to first
         | 
| 210 224 | 
             
                (fwdfor.length - 1).downto(0) do |i|
         | 
| 211 225 | 
             
                  begin
         | 
| 212 226 | 
             
                    ip = IPAddr.new(fwdfor[i])
         | 
| 213 227 | 
             
                  rescue ArgumentError => e
         | 
| 214 228 | 
             
                    @logger.warn("Invalid IP address", :address => fwdfor[i], :event => event)
         | 
| 215 | 
            -
                     | 
| 216 | 
            -
             | 
| 229 | 
            +
                    if not found
         | 
| 230 | 
            +
                      @tags_on_failure.each {|tag| event.tag(tag)}
         | 
| 231 | 
            +
                      fatal = true
         | 
| 232 | 
            +
                    end
         | 
| 233 | 
            +
                    @tags_in_invalid_ip.each {|tag| event.tag(tag)}
         | 
| 234 | 
            +
                    next
         | 
| 217 235 | 
             
                  end
         | 
| 218 236 |  | 
| 237 | 
            +
                  target.unshift(ip.to_s()) if @need_all
         | 
| 238 | 
            +
             | 
| 219 239 | 
             
                  # return on the first non-match against our trusted networks
         | 
| 220 | 
            -
                  if match(ip) == false
         | 
| 240 | 
            +
                  if found == false and fatal == false and match(ip) == false
         | 
| 221 241 | 
             
                    event.set(@target_field, fwdfor[i])
         | 
| 222 242 | 
             
                    filter_matched(event)
         | 
| 223 | 
            -
                    return
         | 
| 243 | 
            +
                    return if not @need_all
         | 
| 244 | 
            +
                    found = true
         | 
| 224 245 | 
             
                  end
         | 
| 225 246 | 
             
                end
         | 
| 226 247 |  | 
| 227 | 
            -
                 | 
| 228 | 
            -
             | 
| 229 | 
            -
                 | 
| 230 | 
            -
             | 
| 231 | 
            -
             | 
| 248 | 
            +
                event.set(@x_forwarded_for_target, target) if @need_all
         | 
| 249 | 
            +
             | 
| 250 | 
            +
                if found == false and fatal == false
         | 
| 251 | 
            +
                  # in case remote_addr and all x_forwarded_for IPs are trusted, use the
         | 
| 252 | 
            +
                  # left-most IP from x_forwarded_for
         | 
| 253 | 
            +
                  event.set(@target_field, fwdfor[0])
         | 
| 254 | 
            +
                  filter_matched(event)
         | 
| 255 | 
            +
                  return
         | 
| 256 | 
            +
                end
         | 
| 232 257 |  | 
| 233 258 | 
             
              end # def filter
         | 
| 234 259 | 
             
            end # class LogStash::Filters::RealIp
         | 
| @@ -1,6 +1,6 @@ | |
| 1 1 | 
             
            Gem::Specification.new do |s|
         | 
| 2 2 | 
             
              s.name          = 'logstash-filter-real_ip'
         | 
| 3 | 
            -
              s.version       = '0. | 
| 3 | 
            +
              s.version       = '0.2.0'
         | 
| 4 4 | 
             
              s.licenses      = ['Apache-2.0']
         | 
| 5 5 | 
             
              s.summary       = 'Evaluates real client IP from X-Forwarded-For header'
         | 
| 6 6 | 
             
              s.description   = 'See https://github.com/fholzer/logstash-filter-real_ip/blob/master/README.md for details.'
         | 
| @@ -10,57 +10,81 @@ describe LogStash::Filters::RealIp do | |
| 10 10 | 
             
                      remote_address_field => "remote_addr"
         | 
| 11 11 | 
             
                      x_forwarded_for_field => "xfwdfor"
         | 
| 12 12 | 
             
                      trusted_networks => ["10.0.0.0/8", "192.168.0.0/16"]
         | 
| 13 | 
            +
                      add_field => { "success" => "success" }
         | 
| 13 14 | 
             
                    }
         | 
| 14 15 | 
             
                  }
         | 
| 15 16 | 
             
                CONFIG
         | 
| 16 17 | 
             
                end
         | 
| 17 18 |  | 
| 18 19 | 
             
                sample("dummy") do
         | 
| 20 | 
            +
                  expect(subject).not_to include("success")
         | 
| 19 21 | 
             
                  expect(subject).to include("tags")
         | 
| 20 22 | 
             
                  expect(subject.get('tags')).to include("_real_ip_lookup_failure")
         | 
| 21 23 | 
             
                end
         | 
| 22 24 |  | 
| 23 25 | 
             
                sample("remote_addr" => "1.2.3.4") do
         | 
| 24 | 
            -
                   | 
| 26 | 
            +
                  expect(subject).to include("success")
         | 
| 27 | 
            +
                  expect(subject).not_to include("tags")
         | 
| 25 28 | 
             
                  expect(subject).to include("real_ip")
         | 
| 26 29 | 
             
                  expect(subject.get('real_ip')).to eq('1.2.3.4')
         | 
| 27 30 | 
             
                end
         | 
| 28 31 |  | 
| 29 32 | 
             
                sample("remote_addr" => "10.2.3.4") do
         | 
| 33 | 
            +
                  expect(subject).to include("success")
         | 
| 30 34 | 
             
                  expect(subject).not_to include("tags")
         | 
| 31 35 | 
             
                  expect(subject).to include("real_ip")
         | 
| 32 36 | 
             
                  expect(subject.get('real_ip')).to eq('10.2.3.4')
         | 
| 33 37 | 
             
                end
         | 
| 34 38 |  | 
| 35 39 | 
             
                sample("remote_addr" => "1.2.3.4", "xfwdfor" => "") do
         | 
| 40 | 
            +
                  expect(subject).to include("success")
         | 
| 36 41 | 
             
                  expect(subject).not_to include("tags")
         | 
| 37 42 | 
             
                  expect(subject).to include("real_ip")
         | 
| 38 43 | 
             
                  expect(subject.get('real_ip')).to eq('1.2.3.4')
         | 
| 39 44 | 
             
                end
         | 
| 40 45 |  | 
| 41 46 | 
             
                sample("remote_addr" => "10.2.3.4", "xfwdfor" => "1.2.3.4") do
         | 
| 42 | 
            -
                  expect(subject | 
| 47 | 
            +
                  expect(subject).to include("success")
         | 
| 48 | 
            +
                  expect(subject).not_to include("tags")
         | 
| 43 49 | 
             
                  expect(subject).to include("real_ip")
         | 
| 44 50 | 
             
                  expect(subject.get('real_ip')).to eq('1.2.3.4')
         | 
| 45 51 | 
             
                end
         | 
| 46 52 |  | 
| 47 53 | 
             
                sample("remote_addr" => "10.2.3.4", "xfwdfor" => ["1.2.3.4", "192.168.3.4"]) do
         | 
| 54 | 
            +
                  expect(subject).to include("success")
         | 
| 48 55 | 
             
                  expect(subject).not_to include("tags")
         | 
| 49 56 | 
             
                  expect(subject).to include("real_ip")
         | 
| 50 57 | 
             
                  expect(subject.get('real_ip')).to eq('1.2.3.4')
         | 
| 51 58 | 
             
                end
         | 
| 52 59 |  | 
| 53 60 | 
             
                sample("remote_addr" => "10.2.3.4", "xfwdfor" => ["192.168.5.6", "192.168.3.4"]) do
         | 
| 61 | 
            +
                  expect(subject).to include("success")
         | 
| 54 62 | 
             
                  expect(subject).not_to include("tags")
         | 
| 55 63 | 
             
                  expect(subject).to include("real_ip")
         | 
| 56 64 | 
             
                  expect(subject.get('real_ip')).to eq('192.168.5.6')
         | 
| 57 65 | 
             
                end
         | 
| 58 66 |  | 
| 59 67 | 
             
                sample("remote_addr" => "10.2.3.4", "xfwdfor" => []) do
         | 
| 68 | 
            +
                  expect(subject).to include("success")
         | 
| 60 69 | 
             
                  expect(subject).not_to include("tags")
         | 
| 61 70 | 
             
                  expect(subject).to include("real_ip")
         | 
| 62 71 | 
             
                  expect(subject.get('real_ip')).to eq('10.2.3.4')
         | 
| 63 72 | 
             
                end
         | 
| 73 | 
            +
             | 
| 74 | 
            +
                sample("remote_addr" => "10.2.3.4", "xfwdfor" => ["10.5", "1.2.3.4", "192.168.3.4"]) do
         | 
| 75 | 
            +
                  expect(subject).to include("success")
         | 
| 76 | 
            +
                  expect(subject).not_to include("tags")
         | 
| 77 | 
            +
                  expect(subject).to include("real_ip")
         | 
| 78 | 
            +
                  expect(subject.get('real_ip')).to eq('1.2.3.4')
         | 
| 79 | 
            +
                end
         | 
| 80 | 
            +
             | 
| 81 | 
            +
                sample("remote_addr" => "10.2.3.4", "xfwdfor" => ["10.5", "192.168.3.4"]) do
         | 
| 82 | 
            +
                  expect(subject).not_to include("success")
         | 
| 83 | 
            +
                  expect(subject).to include("tags")
         | 
| 84 | 
            +
                  expect(subject).not_to include("real_ip")
         | 
| 85 | 
            +
                  expect(subject.get('tags')).to include('_real_ip_invalid_ip')
         | 
| 86 | 
            +
                  expect(subject.get('tags')).to include('_real_ip_lookup_failure')
         | 
| 87 | 
            +
                end
         | 
| 64 88 | 
             
              end
         | 
| 65 89 |  | 
| 66 90 | 
             
              describe "Evaluates real IP correctly with flat string xfwfor" do
         | 
| @@ -71,24 +95,28 @@ describe LogStash::Filters::RealIp do | |
| 71 95 | 
             
                      x_forwarded_for_field => "xfwdfor"
         | 
| 72 96 | 
             
                      x_forwarded_for_is_string => true
         | 
| 73 97 | 
             
                      trusted_networks => ["10.0.0.0/8", "192.168.0.0/16"]
         | 
| 98 | 
            +
                      add_field => { "success" => "success" }
         | 
| 74 99 | 
             
                    }
         | 
| 75 100 | 
             
                  }
         | 
| 76 101 | 
             
                CONFIG
         | 
| 77 102 | 
             
                end
         | 
| 78 103 |  | 
| 79 104 | 
             
                sample("remote_addr" => "10.2.3.4", "xfwdfor" => "1.2.3.4") do
         | 
| 80 | 
            -
                  expect(subject | 
| 105 | 
            +
                  expect(subject).to include("success")
         | 
| 106 | 
            +
                  expect(subject).not_to include("tags")
         | 
| 81 107 | 
             
                  expect(subject).to include("real_ip")
         | 
| 82 108 | 
             
                  expect(subject.get('real_ip')).to eq('1.2.3.4')
         | 
| 83 109 | 
             
                end
         | 
| 84 110 |  | 
| 85 111 | 
             
                sample("remote_addr" => "10.2.3.4", "xfwdfor" => "1.2.3.4,+192.168.3.4") do
         | 
| 112 | 
            +
                  expect(subject).to include("success")
         | 
| 86 113 | 
             
                  expect(subject).not_to include("tags")
         | 
| 87 114 | 
             
                  expect(subject).to include("real_ip")
         | 
| 88 115 | 
             
                  expect(subject.get('real_ip')).to eq('1.2.3.4')
         | 
| 89 116 | 
             
                end
         | 
| 90 117 |  | 
| 91 118 | 
             
                sample("remote_addr" => "10.2.3.4", "xfwdfor" => "1.2.3.4, 192.168.3.4,+ 192.168.4.5") do
         | 
| 119 | 
            +
                  expect(subject).to include("success")
         | 
| 92 120 | 
             
                  expect(subject).not_to include("tags")
         | 
| 93 121 | 
             
                  expect(subject).to include("real_ip")
         | 
| 94 122 | 
             
                  expect(subject.get('real_ip')).to eq('1.2.3.4')
         | 
| @@ -103,30 +131,35 @@ describe LogStash::Filters::RealIp do | |
| 103 131 | 
             
                      x_forwarded_for_field => "xfwdfor"
         | 
| 104 132 | 
             
                      target_field => "evaluated_ip"
         | 
| 105 133 | 
             
                      trusted_networks => ["10.0.0.0/8", "192.168.0.0/16"]
         | 
| 134 | 
            +
                      add_field => { "success" => "success" }
         | 
| 106 135 | 
             
                    }
         | 
| 107 136 | 
             
                  }
         | 
| 108 137 | 
             
                CONFIG
         | 
| 109 138 | 
             
                end
         | 
| 110 139 |  | 
| 111 140 | 
             
                sample("remote_addr" => "1.2.3.4") do
         | 
| 141 | 
            +
                  expect(subject).to include("success")
         | 
| 112 142 | 
             
                  expect(subject).not_to include("tags")
         | 
| 113 143 | 
             
                  expect(subject).to include("evaluated_ip")
         | 
| 114 144 | 
             
                  expect(subject.get('evaluated_ip')).to eq('1.2.3.4')
         | 
| 115 145 | 
             
                end
         | 
| 116 146 |  | 
| 117 147 | 
             
                sample("remote_addr" => "10.2.3.4", "xfwdfor" => "") do
         | 
| 148 | 
            +
                  expect(subject).to include("success")
         | 
| 118 149 | 
             
                  expect(subject).not_to include("tags")
         | 
| 119 150 | 
             
                  expect(subject).to include("evaluated_ip")
         | 
| 120 151 | 
             
                  expect(subject.get('evaluated_ip')).to eq('10.2.3.4')
         | 
| 121 152 | 
             
                end
         | 
| 122 153 |  | 
| 123 154 | 
             
                sample("remote_addr" => "10.2.3.4", "xfwdfor" => "1.2.3.4") do
         | 
| 124 | 
            -
                  expect(subject | 
| 155 | 
            +
                  expect(subject).to include("success")
         | 
| 156 | 
            +
                  expect(subject).not_to include("tags")
         | 
| 125 157 | 
             
                  expect(subject).to include("evaluated_ip")
         | 
| 126 158 | 
             
                  expect(subject.get('evaluated_ip')).to eq('1.2.3.4')
         | 
| 127 159 | 
             
                end
         | 
| 128 160 |  | 
| 129 161 | 
             
                sample("remote_addr" => "10.2.3.4", "xfwdfor" => ["1.2.3.4", "192.168.3.4"]) do
         | 
| 162 | 
            +
                  expect(subject).to include("success")
         | 
| 130 163 | 
             
                  expect(subject).not_to include("tags")
         | 
| 131 164 | 
             
                  expect(subject).to include("evaluated_ip")
         | 
| 132 165 | 
             
                  expect(subject.get('evaluated_ip')).to eq('1.2.3.4')
         | 
| @@ -140,15 +173,60 @@ describe LogStash::Filters::RealIp do | |
| 140 173 | 
             
                      remote_address_field => "remote_addr"
         | 
| 141 174 | 
             
                      x_forwarded_for_field => "xfwdfor"
         | 
| 142 175 | 
             
                      trusted_networks => ["10.0.0.0/8", "2606:2800:220:1:248:1893:25c8:1946/120"]
         | 
| 176 | 
            +
                      add_field => { "success" => "success" }
         | 
| 143 177 | 
             
                    }
         | 
| 144 178 | 
             
                  }
         | 
| 145 179 | 
             
                CONFIG
         | 
| 146 180 | 
             
                end
         | 
| 147 181 |  | 
| 148 182 | 
             
                sample("remote_addr" => "10.2.3.4", "xfwdfor" => ["1.2.3.4", "2606:2800:220:1:248:1893:25c8:1946"]) do
         | 
| 183 | 
            +
                  expect(subject).to include("success")
         | 
| 184 | 
            +
                  expect(subject).not_to include("tags")
         | 
| 185 | 
            +
                  expect(subject).to include("real_ip")
         | 
| 186 | 
            +
                  expect(subject.get('real_ip')).to eq('1.2.3.4')
         | 
| 187 | 
            +
                end
         | 
| 188 | 
            +
              end
         | 
| 189 | 
            +
             | 
| 190 | 
            +
              describe "writes IPs to target array" do
         | 
| 191 | 
            +
                let(:config) do <<-CONFIG
         | 
| 192 | 
            +
                  filter {
         | 
| 193 | 
            +
                    real_ip {
         | 
| 194 | 
            +
                      remote_address_field => "remote_addr"
         | 
| 195 | 
            +
                      x_forwarded_for_field => "xfwdfor"
         | 
| 196 | 
            +
                      x_forwarded_for_target => "xtarget"
         | 
| 197 | 
            +
                      trusted_networks => ["10.0.0.0/8", "192.168.0.0/16"]
         | 
| 198 | 
            +
                      add_field => { "success" => "success" }
         | 
| 199 | 
            +
                    }
         | 
| 200 | 
            +
                  }
         | 
| 201 | 
            +
                CONFIG
         | 
| 202 | 
            +
                end
         | 
| 203 | 
            +
             | 
| 204 | 
            +
                sample("remote_addr" => "10.2.3.4", "xfwdfor" => ["5.6.7.8", "1.2.3.4", "192.168.3.4"]) do
         | 
| 205 | 
            +
                  expect(subject).to include("success")
         | 
| 149 206 | 
             
                  expect(subject).not_to include("tags")
         | 
| 150 207 | 
             
                  expect(subject).to include("real_ip")
         | 
| 151 208 | 
             
                  expect(subject.get('real_ip')).to eq('1.2.3.4')
         | 
| 209 | 
            +
                  expect(subject.get('xtarget')).to eq(["5.6.7.8", "1.2.3.4", "192.168.3.4"])
         | 
| 210 | 
            +
                end
         | 
| 211 | 
            +
             | 
| 212 | 
            +
                sample("remote_addr" => "10.2.3.4", "xfwdfor" => ["10.5", "1.2.3.4", "192.168.3.4"]) do
         | 
| 213 | 
            +
                  expect(subject).to include("success")
         | 
| 214 | 
            +
                  expect(subject).to include("tags")
         | 
| 215 | 
            +
                  expect(subject).to include("real_ip")
         | 
| 216 | 
            +
                  expect(subject.get('real_ip')).to eq('1.2.3.4')
         | 
| 217 | 
            +
                  expect(subject.get('xtarget')).to eq(["1.2.3.4", "192.168.3.4"])
         | 
| 218 | 
            +
                  expect(subject.get('tags')).to include('_real_ip_invalid_ip')
         | 
| 219 | 
            +
                  expect(subject.get('tags')).not_to include('_real_ip_lookup_failure')
         | 
| 220 | 
            +
                end
         | 
| 221 | 
            +
             | 
| 222 | 
            +
                sample("remote_addr" => "10.2.3.4", "xfwdfor" => ["10.5", "192.168.3.4"]) do
         | 
| 223 | 
            +
                  expect(subject).not_to include("success")
         | 
| 224 | 
            +
                  expect(subject).to include("tags")
         | 
| 225 | 
            +
                  expect(subject).not_to include("real_ip")
         | 
| 226 | 
            +
                  expect(subject.get('xtarget')).to eq(["192.168.3.4"])
         | 
| 227 | 
            +
                  expect(subject.get('tags')).to include('_real_ip_invalid_ip')
         | 
| 228 | 
            +
                  expect(subject.get('tags')).to include('_real_ip_lookup_failure')
         | 
| 152 229 | 
             
                end
         | 
| 153 230 | 
             
              end
         | 
| 231 | 
            +
             | 
| 154 232 | 
             
            end
         | 
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: logstash-filter-real_ip
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0. | 
| 4 | 
            +
              version: 0.2.0
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Ferdinand Holzer
         | 
| 8 8 | 
             
            autorequire:
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2018- | 
| 11 | 
            +
            date: 2018-07-11 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              requirement: !ruby/object:Gem::Requirement
         |