tshield 0.13.5.0 → 0.14.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ab5c5057fe81ae295f572912c6955ce0ea0bd9be6b42fb515a7832fe3451459a
4
- data.tar.gz: 9c785dc23adb245fdfcc416698c551f7a45eaa32b5892a2cabea708f16fa2859
3
+ metadata.gz: 83eb12f572bdfd5f6fade21d83ee7d4883253aa9e42cad7fe0e9feac380d7ae6
4
+ data.tar.gz: c1718a13671ee6899321dcda86c6d6dbaad23c1389cc24c0b6ea3b684024c725
5
5
  SHA512:
6
- metadata.gz: 58fd33ddf9e466af5882e6522612b2b0fa05c95f728578fe50b014dca0777357bf5ccfa17605a86309c5742cb828dd2e52eb9bb2839096f594e1e75fef80e81b
7
- data.tar.gz: f085f1dcc7a3d861da1b28a0d07f3338f03dd5b27cdd234c283cecf0bce8a0dc66f26193755ea8f5b442cbf4953fb2bd4ce295f90257b76121ac7fdbcbdd38b0
6
+ metadata.gz: 003b70dbe21e80655ebfe6eae9e0260137a3f6e3e478200c04eefbc238ae72d8d172b62c4d980a934fd56a08eb7d2ad59d93b4d762a3c019e88d3e2e6cc39d46
7
+ data.tar.gz: 6c4ada87361e89edff1b8fe7353389861c3748986631ad9693d01f148c71fb2dbe06547b318d94c3247dc584081c047fc915f5d1d014d6026172b8cf406b5753
@@ -29,10 +29,7 @@ module TShield
29
29
  # generated directory
30
30
  #
31
31
  attr_reader :request
32
- attr_reader :domains
33
- attr_reader :tcp_servers
34
- attr_reader :session_path
35
- attr_reader :windows_compatibility
32
+ attr_reader :domains, :tcp_servers, :session_path, :windows_compatibility
36
33
 
37
34
  def initialize(attributes)
38
35
  attributes.each { |key, value| instance_variable_set("@#{key}", value) }
@@ -106,6 +103,7 @@ module TShield
106
103
 
107
104
  def send_header_content_type(domain)
108
105
  return domains[domain]['send_header_content_type'] != false if domains[domain]
106
+
109
107
  true
110
108
  end
111
109
 
@@ -140,6 +138,5 @@ module TShield
140
138
  def get_delay(domain, path)
141
139
  ((domains[domain] || {})['delay'] || {})[path] || 0
142
140
  end
143
-
144
141
  end
145
142
  end
@@ -114,7 +114,6 @@ module TShield
114
114
  logger.info("Response with delay of #{delay_in_seconds} seconds")
115
115
  sleep delay_in_seconds
116
116
  end
117
-
118
117
  end
119
118
  end
120
119
  end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TShield
4
+ # Increment counter for sessions requests
5
+ class GrpcCounter
6
+ def initialize
7
+ @requests = {}
8
+ end
9
+
10
+ def add(hexdigest)
11
+ count = @requests.fetch(hexdigest, 0)
12
+ count += 1
13
+ @requests[hexdigest] = count
14
+ end
15
+
16
+ def current(hexdigest)
17
+ @requests.fetch(hexdigest, 0)
18
+ end
19
+
20
+ def to_json(options = {})
21
+ @requests.to_json(options)
22
+ end
23
+ end
24
+ end
@@ -5,79 +5,127 @@ require 'tshield/sessions'
5
5
 
6
6
  module TShield
7
7
  module Grpc
8
+ # Grpc vcr module
8
9
  module VCR
10
+ # Path file to save Grpc request/response
11
+ class FilePath
12
+ attr_reader :path, :count
13
+
14
+ def initialize(path, count)
15
+ @path = path
16
+ @count = count
17
+ end
18
+ end
19
+
9
20
  def initialize
10
21
  @configuration = TShield::Configuration.singleton
11
22
  end
23
+
12
24
  def handler_in_vcr_mode(method_name, request, parameters, options)
13
25
  parameters.peer =~ /ipv6:\[(.+?)\]|ipv4:(.+?):/
14
26
  peer = Regexp.last_match(1) || Regexp.last_match(2)
15
27
 
16
28
  TShield.logger.info("request from #{parameters.peer}")
17
29
  @session = TShield::Sessions.current(peer)
30
+ @digest = hexdigest(request)
31
+ counter = @session ? request_count.current(@digest) : 0
18
32
 
19
33
  TShield.logger.info("grpc using session #{@session || 'default'}")
20
34
  module_name = options['module']
21
35
 
22
- path = create_destiny(module_name, method_name, request)
23
- save_request(path, request)
24
- response = saved_response(path)
25
- if response
26
- TShield.logger.info("returning saved response for request #{request.to_json} saved into #{hexdigest(request)}")
27
- return response
36
+ path = create_destiny(module_name, method_name)
37
+ @file_path = FilePath.new(path, counter)
38
+ save_request(request)
39
+ response = {}
40
+ saved_error
41
+ begin
42
+ response = saved_response
43
+ if response
44
+ TShield.logger.info("returning saved response for request #{request.to_json} saved into #{@digest}")
45
+ request_count.add(@digest) if @session
46
+ return response
47
+ end
48
+
49
+ response = send_request(request, module_name, options, method_name)
50
+ save_response(response)
51
+ rescue GRPC::BadStatus => e
52
+ save_error({ code: e.code, details: e.details })
53
+ raise e
28
54
  end
55
+ request_count.add(@digest) if @session
56
+ response
57
+ end
29
58
 
59
+ def send_request(request, module_name, options, method_name)
30
60
  TShield.logger.info("calling server to get response for #{request.to_json}")
31
61
  client_class = Object.const_get("#{module_name}::Stub")
32
62
  client_instance = client_class.new(options['hostname'], :this_channel_is_insecure)
33
- response = client_instance.send(method_name, request)
34
- save_response(path, response)
35
- response
63
+ client_instance.send(method_name, request)
64
+ end
65
+
66
+ def request_count
67
+ @session[:grpc_counter]
36
68
  end
37
69
 
38
70
  def encode_colon(value)
39
- value.gsub(':','%3a')
71
+ value.gsub(':', '%3a')
40
72
  end
41
73
 
42
- def saved_response(path)
43
- response_file = File.join(path, 'response')
74
+ def saved_response
75
+ response_file = File.join(@file_path.path, "#{@file_path.count}.response")
44
76
  return false unless File.exist? response_file
45
77
 
46
78
  content = JSON.parse File.open(response_file).read
47
- response_class = File.open(File.join(path, 'response_class')).read.strip
79
+ response_class = File.open(File.join(@file_path.path, "#{@file_path.count}.response_class")).read.strip
48
80
  Kernel.const_get(response_class).new(content)
49
81
  end
50
82
 
51
- def save_request(path, request)
52
- file = File.open(File.join(path, 'original_request'), 'w')
83
+ def saved_error
84
+ error_file = File.join(@file_path.path, "#{@file_path.count}.error")
85
+ return false unless File.exist? error_file
86
+
87
+ request_count.add(@digest) if @session
88
+ content = JSON.parse File.open(error_file).read
89
+ grpc_error = GRPC::BadStatus.new(content['code'], content['details'])
90
+ raise grpc_error
91
+ end
92
+
93
+ def save_request(request)
94
+ file = File.open(File.join(@file_path.path, "#{@file_path.count}.original_request"), 'w')
53
95
  file.puts request.to_json
54
96
  file.close
55
97
  end
56
98
 
57
- def save_response(path, response)
58
- file = File.open(File.join(path, 'response'), 'w')
99
+ def save_error(error)
100
+ file = File.open(File.join(@file_path.path, "#{@file_path.count}.error"), 'w')
101
+ file.puts error.to_json
102
+ file.close
103
+ request_count.add(@digest) if @session
104
+ end
105
+
106
+ def save_response(response)
107
+ file = File.open(File.join(@file_path.path, "#{@file_path.count}.response"), 'w')
59
108
  file.puts response.to_json
60
109
  file.close
61
110
 
62
- response_class = File.open(File.join(path, 'response_class'), 'w')
111
+ response_class = File.open(File.join(@file_path.path, "#{@file_path.count}.response_class"), 'w')
63
112
  response_class.puts response.class.to_s
64
113
  response_class.close
65
114
  end
66
115
 
67
- def complete_path(module_name, method_name, request)
116
+ def complete_path(module_name, method_name)
68
117
  @session_name = (@session || {})[:name]
69
118
  module_name = @configuration.windows_compatibility? ? encode_colon(module_name) : module_name
70
- path = ['requests', 'grpc', @session_name, module_name, method_name.to_s, hexdigest(request)].compact
71
- path
119
+ ['requests', @session_name, module_name, method_name.to_s, @digest].compact
72
120
  end
73
121
 
74
- def create_destiny(module_name, method_name, request)
122
+ def create_destiny(module_name, method_name)
75
123
  current_path = []
76
124
 
77
- path = complete_path(module_name, method_name, request)
125
+ path = complete_path(module_name, method_name)
78
126
  TShield.logger.info("using path #{path}")
79
- path.each do |path|
80
- current_path << path
127
+ path.each do |inner_path|
128
+ current_path << inner_path
81
129
  destiny = File.join current_path
82
130
  Dir.mkdir destiny unless File.exist? destiny
83
131
  end
data/lib/tshield/grpc.rb CHANGED
@@ -4,7 +4,6 @@ require 'grpc'
4
4
 
5
5
  require 'tshield/configuration'
6
6
  require 'tshield/grpc/vcr'
7
-
8
7
  module TShield
9
8
  module Grpc
10
9
  module RequestHandler
@@ -14,6 +13,7 @@ module TShield
14
13
  handler_in_vcr_mode(method_name, request, parameters, options)
15
14
  end
16
15
  end
16
+
17
17
  def self.run!
18
18
  @configuration = TShield::Configuration.singleton.grpc
19
19
 
@@ -41,6 +41,7 @@ module TShield
41
41
  handlers = []
42
42
  number_of_handlers = 0
43
43
  services.each do |file, options|
44
+
44
45
  require file
45
46
 
46
47
  base = Object.const_get("#{options['module']}::Service")
@@ -55,8 +56,7 @@ module TShield
55
56
  def self.build_handler(base, descriptions, number_of_handlers, options)
56
57
  handler = Class.new(base) do
57
58
  class << self
58
- attr_writer :options
59
- attr_reader :options
59
+ attr_accessor :options
60
60
  end
61
61
  descriptions.each do |service_name, description|
62
62
  puts description
@@ -5,6 +5,6 @@ require 'logger'
5
5
  # Logger instance for application
6
6
  module TShield
7
7
  def self.logger
8
- @logger ||= Logger.new(STDOUT)
8
+ @logger ||= Logger.new($stdout)
9
9
  end
10
10
  end
@@ -79,7 +79,6 @@ module TShield
79
79
  end
80
80
 
81
81
  def apply_set_cookie_header_values(raw_response, headers = {})
82
-
83
82
  headers_clone = headers.clone
84
83
 
85
84
  field = raw_response.get_fields('Set-Cookie')
@@ -98,6 +97,7 @@ module TShield
98
97
 
99
98
  raw_response.headers.each do |k, v|
100
99
  next if k == 'set-cookie'
100
+
101
101
  headers[k] = v unless configuration.not_save_headers(domain).include? k
102
102
  end
103
103
 
@@ -156,9 +156,10 @@ module TShield
156
156
  end
157
157
 
158
158
  def encode_for_windows_dir(directory)
159
- replace = [['<','%3c'],['>','%3e'],[':','%3a'],['"','%22'],['?','%3f'],[' ','%20'],['*','%2a'],['/','%2f']]
159
+ replace = [['<', '%3c'], ['>', '%3e'], [':', '%3a'], ['"', '%22'], ['?', '%3f'], [' ', '%20'], ['*', '%2a'],
160
+ ['/', '%2f']]
160
161
  replace.each do |value|
161
- directory = directory.gsub(value.first,value.last)
162
+ directory = directory.gsub(value.first, value.last)
162
163
  end
163
164
  directory
164
165
  end
@@ -171,7 +172,7 @@ module TShield
171
172
  else
172
173
  directory = url.gsub(%r{/}, '-').gsub(/^-/, '')
173
174
  end
174
- configuration.windows_compatibility? ? encode_for_windows_dir(directory) : directory
175
+ configuration.windows_compatibility? ? encode_for_windows_dir(directory) : directory
175
176
  end
176
177
  end
177
178
  end
@@ -2,6 +2,7 @@
2
2
 
3
3
  require 'tshield/logger'
4
4
  require 'tshield/counter'
5
+ require 'tshield/grpc/grpc_counter'
5
6
  require 'tshield/errors'
6
7
 
7
8
  module TShield
@@ -14,6 +15,7 @@ module TShield
14
15
  sessions[normalize_ip(ip)] = {
15
16
  name: name,
16
17
  counter: TShield::Counter.new,
18
+ grpc_counter: TShield::GrpcCounter.new,
17
19
  secondary_sessions: []
18
20
  }
19
21
  end
@@ -4,8 +4,8 @@ module TShield
4
4
  # Control version of gem
5
5
  class Version
6
6
  MAJOR = 0
7
- MINOR = 13
8
- PATCH = 5
7
+ MINOR = 14
8
+ PATCH = 0
9
9
  PRE = 0
10
10
 
11
11
  class << self
@@ -67,7 +67,7 @@ describe TShield::Configuration do
67
67
 
68
68
  describe 'SO compatibility' do
69
69
  it 'should be compatible with windows when configuration is true' do
70
- allow(YAML).to receive(:safe_load).and_return({:windows_compatibility => true })
70
+ allow(YAML).to receive(:safe_load).and_return({ windows_compatibility: true })
71
71
  TShield::Configuration.clear
72
72
  @configuration = TShield::Configuration.singleton
73
73
 
@@ -75,7 +75,7 @@ describe TShield::Configuration do
75
75
  end
76
76
 
77
77
  it 'should be compatible with Unix when configuration is false' do
78
- allow(YAML).to receive(:safe_load).and_return({:windows_compatibility => false })
78
+ allow(YAML).to receive(:safe_load).and_return({ windows_compatibility: false })
79
79
  TShield::Configuration.clear
80
80
  @configuration = TShield::Configuration.singleton
81
81
 
@@ -89,7 +89,6 @@ describe TShield::Configuration do
89
89
 
90
90
  expect(@configuration.windows_compatibility?).to eq(false)
91
91
  end
92
-
93
92
  end
94
93
  end
95
94
  context 'on config not exist' do
@@ -73,7 +73,6 @@ describe TShield::Controllers::Requests do
73
73
  allow(@configuration).to receive(:get_domain_for).and_return('example.org')
74
74
  allow(@configuration).to receive(:get_delay).and_return(0)
75
75
 
76
-
77
76
  allow(TShield::Options).to receive_message_chain(:instance, :break?)
78
77
  @mock_logger = double
79
78
  @controller = MockController.new(@mock_logger)
@@ -100,15 +99,15 @@ describe TShield::Controllers::Requests do
100
99
  allow(matched_response).to receive(:body).and_return('')
101
100
  allow(@mock_logger).to receive(:info)
102
101
 
103
- expect(TShield::RequestVCR).to receive(:new).with("/",{
104
- call: 0,
105
- headers: {},
106
- ip: "0.0.0.0",
107
- method: "GET",
108
- raw_query: "a=b",
109
- secondary_sessions: nil,
110
- session: nil
111
- })
102
+ expect(TShield::RequestVCR).to receive(:new).with('/', {
103
+ call: 0,
104
+ headers: {},
105
+ ip: '0.0.0.0',
106
+ method: 'GET',
107
+ raw_query: 'a=b',
108
+ secondary_sessions: nil,
109
+ session: nil
110
+ })
112
111
  @controller.treat(params, request, nil)
113
112
  end
114
113
  end
@@ -135,16 +134,15 @@ describe TShield::Controllers::Requests do
135
134
  allow(matched_response).to receive(:body).and_return('')
136
135
  allow(@mock_logger).to receive(:info)
137
136
 
138
- expect(TShield::RequestVCR).to receive(:new).with("/",{
139
- call: 0,
140
- headers: {'Content-Type' => 'application/json'},
141
- ip: "0.0.0.0",
142
- method: "GET",
143
- raw_query: "a=b",
144
- secondary_sessions: nil,
145
- session: nil
146
- })
147
-
137
+ expect(TShield::RequestVCR).to receive(:new).with('/', {
138
+ call: 0,
139
+ headers: { 'Content-Type' => 'application/json' },
140
+ ip: '0.0.0.0',
141
+ method: 'GET',
142
+ raw_query: 'a=b',
143
+ secondary_sessions: nil,
144
+ session: nil
145
+ })
148
146
 
149
147
  @controller.treat(params, request, nil)
150
148
  end
@@ -107,9 +107,9 @@ describe TShield::RequestVCR do
107
107
 
108
108
  it 'should create response directory in windows standard' do
109
109
  allow(@configuration).to receive(:domains).and_return(
110
- 'example.org' => {
111
- 'skip_query_params' => []
112
- }
110
+ 'example.org' => {
111
+ 'skip_query_params' => []
112
+ }
113
113
  )
114
114
 
115
115
  allow(@configuration).to receive(:windows_compatibility?).and_return(true)
@@ -118,28 +118,28 @@ describe TShield::RequestVCR do
118
118
  file_double = double
119
119
 
120
120
  allow(File).to receive(:join)
121
- .with('./requests/example.org', '%3fparam=value')
122
- .and_return('./requests/example.org/%3fparam=value')
121
+ .with('./requests/example.org', '%3fparam=value')
122
+ .and_return('./requests/example.org/%3fparam=value')
123
123
  allow(File).to receive(:join)
124
- .with('./requests/example.org/%3fparam=value', 'get')
125
- .and_return('./requests/example.org/%3fparam=value/get')
124
+ .with('./requests/example.org/%3fparam=value', 'get')
125
+ .and_return('./requests/example.org/%3fparam=value/get')
126
126
  allow(File).to receive(:join)
127
- .with('./requests/example.org/%3fparam=value/get', '0')
128
- .and_return('./requests/example.org/%3fparam=value/get/0')
127
+ .with('./requests/example.org/%3fparam=value/get', '0')
128
+ .and_return('./requests/example.org/%3fparam=value/get/0')
129
129
 
130
130
  allow(file_double).to receive(:read).and_return('{}')
131
131
 
132
132
  expect(File).to receive('open')
133
- .with('./requests/example.org/%3fparam=value/get/0.content', 'w')
134
- .and_return(file_double)
133
+ .with('./requests/example.org/%3fparam=value/get/0.content', 'w')
134
+ .and_return(file_double)
135
135
 
136
136
  expect(File).to receive('open')
137
- .with('./requests/example.org/%3fparam=value/get/0.json', 'w')
138
- .and_return(file_double)
137
+ .with('./requests/example.org/%3fparam=value/get/0.json', 'w')
138
+ .and_return(file_double)
139
139
 
140
140
  expect(file_double).to receive(:write).ordered.with('this is the body')
141
141
  expect(file_double).to receive(:write)
142
- .with("{\n \"status\": 200,\n \"headers\": {\n }\n}")
142
+ .with("{\n \"status\": 200,\n \"headers\": {\n }\n}")
143
143
  expect(file_double).to receive(:close)
144
144
  expect(file_double).to receive(:close)
145
145
 
@@ -148,7 +148,6 @@ describe TShield::RequestVCR do
148
148
  method: 'GET',
149
149
  call: 0
150
150
  end
151
-
152
151
  end
153
152
  end
154
153
 
@@ -161,7 +160,7 @@ describe TShield::RequestVCR do
161
160
  'this is the body'
162
161
  end
163
162
 
164
- def get_fields(field = "")
163
+ def get_fields(_field = '')
165
164
  []
166
165
  end
167
166
 
@@ -172,22 +171,19 @@ describe TShield::RequestVCR do
172
171
 
173
172
  class RawResponseCookiesMultipleValues
174
173
  def headers
175
- {'Set-Cookie' => ['FirstCookie=An Value', 'SecondCookie=An Value']}
174
+ { 'Set-Cookie' => ['FirstCookie=An Value', 'SecondCookie=An Value'] }
176
175
  end
177
176
 
178
177
  def body
179
178
  'this is the body'
180
179
  end
181
180
 
182
- def get_fields(field = "")
183
- self.headers[filed] unless self.headers.key?(field)
181
+ def get_fields(field = '')
182
+ headers[filed] unless headers.key?(field)
184
183
  end
185
184
 
186
185
  def code
187
186
  200
188
187
  end
189
188
  end
190
-
191
189
  end
192
-
193
-
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tshield
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.13.5.0
4
+ version: 0.14.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Diego Rubin
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2021-06-03 00:00:00.000000000 Z
12
+ date: 2021-10-18 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: grpc
@@ -415,6 +415,7 @@ files:
415
415
  - lib/tshield/errors.rb
416
416
  - lib/tshield/extensions/string_extensions.rb
417
417
  - lib/tshield/grpc.rb
418
+ - lib/tshield/grpc/grpc_counter.rb
418
419
  - lib/tshield/grpc/vcr.rb
419
420
  - lib/tshield/logger.rb
420
421
  - lib/tshield/matching/filters.rb
@@ -467,19 +468,19 @@ signing_key:
467
468
  specification_version: 4
468
469
  summary: Proxy for mocks API responses
469
470
  test_files:
470
- - spec/tshield/controllers/requests_spec.rb
471
+ - spec/spec_helper.rb
472
+ - spec/tshield/request_matching_spec.rb
473
+ - spec/tshield/sessions_spec.rb
474
+ - spec/tshield/request_vcr_spec.rb
471
475
  - spec/tshield/after_filter_spec.rb
472
- - spec/tshield/configuration_spec.rb
473
- - spec/tshield/fixtures/proto/test_services_pb.rb
476
+ - spec/tshield/grpc_spec.rb
477
+ - spec/tshield/options_spec.rb
474
478
  - spec/tshield/fixtures/config/tshield-without-grpc.yml
475
479
  - spec/tshield/fixtures/config/tshield-with-send-content-type-header_as_false.yml
476
- - spec/tshield/fixtures/config/tshield.yml
477
480
  - spec/tshield/fixtures/config/tshield-with-send-content-type-header.yml
481
+ - spec/tshield/fixtures/config/tshield.yml
482
+ - spec/tshield/fixtures/proto/test_services_pb.rb
478
483
  - spec/tshield/fixtures/matching/example.json
479
484
  - spec/tshield/fixtures/filters/example_filter.rb
480
- - spec/tshield/request_vcr_spec.rb
481
- - spec/tshield/sessions_spec.rb
482
- - spec/tshield/grpc_spec.rb
483
- - spec/tshield/options_spec.rb
484
- - spec/tshield/request_matching_spec.rb
485
- - spec/spec_helper.rb
485
+ - spec/tshield/controllers/requests_spec.rb
486
+ - spec/tshield/configuration_spec.rb