logstash-input-akamai-siem 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,142 @@
1
+ # frozen_string_literal: true
2
+
3
+ class LogStash::Inputs::AkamaiSiem::Headers < ::Hash
4
+ def self.from(value)
5
+ new(value)
6
+ end
7
+
8
+ def self.allocate
9
+ new_self = super
10
+ new_self.initialize_names
11
+ new_self
12
+ end
13
+
14
+ def initialize(hash = nil)
15
+ super()
16
+ @names = {}
17
+ update(hash || {})
18
+ end
19
+
20
+ def initialize_names
21
+ @names = {}
22
+ end
23
+
24
+ # on dup/clone, we need to duplicate @names hash
25
+ def initialize_copy(other)
26
+ super
27
+ @names = other.names.dup
28
+ end
29
+
30
+ # need to synchronize concurrent writes to the shared KeyMap
31
+ keymap_mutex = Mutex.new
32
+
33
+ # symbol -> string mapper + cache
34
+ KeyMap = Hash.new do |map, key|
35
+ value = if key.respond_to?(:to_str)
36
+ key
37
+ else
38
+ key.to_s.split('_') # user_agent: %w(user agent)
39
+ .each(&:capitalize!) # => %w(User Agent)
40
+ .join('-') # => "User-Agent"
41
+ end
42
+ keymap_mutex.synchronize { map[key] = value }
43
+ end
44
+ KeyMap[:etag] = 'ETag'
45
+
46
+ def [](key)
47
+ key = KeyMap[key]
48
+ super(key) || super(@names[key.downcase])
49
+ end
50
+
51
+ def []=(key, val)
52
+ key = KeyMap[key]
53
+ key = (@names[key.downcase] ||= key)
54
+ # join multiple values with a comma
55
+ val = val.to_ary.join(', ') if val.respond_to?(:to_ary)
56
+ super(key, val)
57
+ end
58
+
59
+ def fetch(key, ...)
60
+ key = KeyMap[key]
61
+ key = @names.fetch(key.downcase, key)
62
+ super(key, ...)
63
+ end
64
+
65
+ def delete(key)
66
+ key = KeyMap[key]
67
+ key = @names[key.downcase]
68
+ return unless key
69
+
70
+ @names.delete key.downcase
71
+ super(key)
72
+ end
73
+
74
+ def dig(key, *rest)
75
+ key = KeyMap[key]
76
+ key = @names.fetch(key.downcase, key)
77
+ super(key, *rest)
78
+ end
79
+
80
+ def include?(key)
81
+ @names.include? key.downcase
82
+ end
83
+
84
+ alias has_key? include?
85
+ alias member? include?
86
+ alias key? include?
87
+
88
+ def merge!(other)
89
+ other.each { |k, v| self[k] = v }
90
+ self
91
+ end
92
+
93
+ alias update merge!
94
+
95
+ def merge(other)
96
+ hash = dup
97
+ hash.merge! other
98
+ end
99
+
100
+ def replace(other)
101
+ clear
102
+ @names.clear
103
+ update other
104
+ self
105
+ end
106
+
107
+ def to_hash
108
+ {}.update(self)
109
+ end
110
+
111
+ def parse(header_string)
112
+ return unless header_string && !header_string.empty?
113
+
114
+ headers = header_string.split("\r\n")
115
+
116
+ # Find the last set of response headers.
117
+ start_index = headers.rindex { |x| x.start_with?('HTTP/') } || 0
118
+ last_response = headers.slice(start_index, headers.size)
119
+
120
+ last_response
121
+ .tap { |a| a.shift if a.first.start_with?('HTTP/') }
122
+ .map { |h| h.split(/:\s*/, 2) } # split key and value
123
+ .reject { |p| p[0].nil? } # ignore blank lines
124
+ .each { |key, value| add_parsed(key, value) }
125
+ end
126
+
127
+ protected
128
+
129
+ attr_reader :names
130
+
131
+ private
132
+
133
+ # Join multiple values with a comma.
134
+ def add_parsed(key, value)
135
+ if key?(key)
136
+ self[key] = self[key].to_s
137
+ self[key] << ', ' << value
138
+ else
139
+ self[key] = value
140
+ end
141
+ end
142
+ end
@@ -0,0 +1,81 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'monitor'
4
+
5
+ module LogStash::Inputs::AkamaiSiem::MiddlewareRegistry
6
+ # Adds the ability for other modules to register and lookup
7
+ # middleware classes.
8
+ def registered_middleware
9
+ @registered_middleware ||= {}
10
+ end
11
+
12
+ # Register middleware class(es) on the current module.
13
+ #
14
+ # @param mappings [Hash] Middleware mappings from a lookup symbol to a middleware class.
15
+ # @return [void]
16
+ #
17
+ # @example Lookup by a constant
18
+ #
19
+ # module Faraday
20
+ # class Whatever < Middleware
21
+ # # Middleware looked up by :foo returns Faraday::Whatever::Foo.
22
+ # register_middleware(foo: Whatever)
23
+ # end
24
+ # end
25
+ def register_middleware(**mappings)
26
+ middleware_mutex do
27
+ registered_middleware.update(mappings)
28
+ end
29
+ end
30
+
31
+ # Unregister a previously registered middleware class.
32
+ #
33
+ # @param key [Symbol] key for the registered middleware.
34
+ def unregister_middleware(key)
35
+ registered_middleware.delete(key)
36
+ end
37
+
38
+ # Lookup middleware class with a registered Symbol shortcut.
39
+ #
40
+ # @param key [Symbol] key for the registered middleware.
41
+ # @return [Class] a middleware Class.
42
+ # @raise [Faraday::Error] if given key is not registered
43
+ #
44
+ # @example
45
+ #
46
+ # module Faraday
47
+ # class Whatever < Middleware
48
+ # register_middleware(foo: Whatever)
49
+ # end
50
+ # end
51
+ #
52
+ # Faraday::Middleware.lookup_middleware(:foo)
53
+ # # => Faraday::Whatever
54
+ def lookup_middleware(key)
55
+ load_middleware(key) ||
56
+ raise(Faraday::Error, "#{key.inspect} is not registered on #{self}")
57
+ end
58
+
59
+ private
60
+
61
+ def middleware_mutex(&block)
62
+ @middleware_mutex ||= Monitor.new
63
+ @middleware_mutex.synchronize(&block)
64
+ end
65
+
66
+ def load_middleware(key)
67
+ value = registered_middleware[key]
68
+ case value
69
+ when Module
70
+ value
71
+ when Symbol, String
72
+ middleware_mutex do
73
+ @registered_middleware[key] = const_get(value)
74
+ end
75
+ when Proc
76
+ middleware_mutex do
77
+ @registered_middleware[key] = value.call
78
+ end
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,92 @@
1
+ # frozen_string_literal: true
2
+
3
+ class LogStash::Inputs::AkamaiSiem
4
+ Request = Struct.new(:http_method, :path, :headers, :body, :host, :url) do
5
+ extend MiddlewareRegistry
6
+ alias_method :member_get, :[]
7
+ private :member_get
8
+ alias_method :member_set, :[]=
9
+ private :member_set
10
+
11
+ # @param request_method [String]
12
+ # @yield [request] for block customization, if block given
13
+ # @yieldparam request [Request]
14
+ # @return [Request]
15
+ def self.create(request_method)
16
+ new(request_method).tap do |request|
17
+ yield(request) if block_given?
18
+ end
19
+ end
20
+
21
+ remove_method :headers=
22
+ # Replace request headers, preserving the existing hash type.
23
+ #
24
+ # @param hash [Hash] new headers
25
+ def headers=(hash)
26
+ if headers
27
+ headers.replace hash
28
+ else
29
+ member_set(:headers, hash)
30
+ end
31
+ end
32
+
33
+ def update_uri(url)
34
+ if url.respond_to? :query
35
+ if (query = url.query)
36
+ path = url.path = Addressable::URI.unencode(url.path.dup.gsub(/\/$/, ''))
37
+ end
38
+ else
39
+ anchor_index = path.index('#')
40
+ path = path.slice(0, anchor_index) unless anchor_index.nil?
41
+ path, query = path.split('?', 2)
42
+ end
43
+ self.host = url.host
44
+ self.path = path
45
+ self.url = url
46
+ end
47
+
48
+ # @param key [Object] key to look up in headers
49
+ # @return [Object] value of the given header name
50
+ def [](key)
51
+ headers[key]
52
+ end
53
+
54
+ # @param key [Object] key of header to write
55
+ # @param value [Object] value of header
56
+ def []=(key, value)
57
+ headers[key] = value
58
+ end
59
+
60
+ def to_a
61
+ [
62
+ self.http_method,
63
+ self.url.to_s,
64
+ headers: self.headers
65
+ ]
66
+ end
67
+
68
+ # Marshal serialization support.
69
+ #
70
+ # @return [Hash] the hash ready to be serialized in Marshal.
71
+ def marshal_dump
72
+ {
73
+ http_method: http_method,
74
+ body: body,
75
+ headers: headers,
76
+ path: path,
77
+ host: host
78
+ }
79
+ end
80
+
81
+ # Marshal serialization support.
82
+ # Restores the instance variables according to the +serialised+.
83
+ # @param serialised [Hash] the serialised object.
84
+ def marshal_load(serialised)
85
+ self.http_method = serialised[:http_method]
86
+ self.body = serialised[:body]
87
+ self.headers = serialised[:headers]
88
+ self.path = serialised[:path]
89
+ self.host = serialised[:host]
90
+ end
91
+ end
92
+ end