ritm 1.0.2 → 1.0.3

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
  SHA1:
3
- metadata.gz: 2f1109dfaeac6ea30bcc246368fbfa4588fd2dd2
4
- data.tar.gz: 22cabc4371ed6a45093b03e094bc2aa433a4362c
3
+ metadata.gz: e057b05ae3168ee5ff218a8c6ce01c46184e523c
4
+ data.tar.gz: 91438a6194dce60e5dc4827d76c5a5056e8db1c5
5
5
  SHA512:
6
- metadata.gz: a898d03940990af84ec7cab9cb172ebc28580179e86965f7be9b0ba806f9a5e51e6ded0e2c6863b91c678907403f00fd4ec442e6bce97faaded946b0a5b888e4
7
- data.tar.gz: d4b1462c4e80f8e8d14acc30e0452bbbf446d43df1899e6f9e1a61cb9dc607132717240abad80ddbd4b82ff19bcf566fd720d807cf70ff1a866d180d4dd337e7
6
+ metadata.gz: 71cc70b613e2d72c8914d8ce896f7baea3f11c85623490a915a7c88160303572df4a4a429b2651ec803c8138c2b586ac0cf998a71c0ce4bddd659c0d5b56e749
7
+ data.tar.gz: b2bcb23777a6c8cbaab3672c2f2954818d4d602cdfc6e08f45c289a118832ae735a6743727e9eba3e79d4240e249d6a89ba4d0abff8aa585dff20d3d62a5eb8f
@@ -2,7 +2,6 @@ require 'dot_hash'
2
2
  require 'set'
3
3
 
4
4
  module Ritm
5
- # Global Ritm settings
6
5
  class Configuration
7
6
  def default_settings # rubocop:disable Metrics/MethodLength
8
7
  {
@@ -60,12 +59,10 @@ module Ritm
60
59
  end
61
60
  end
62
61
 
63
- # Re-enable interception
64
62
  def enable
65
63
  @settings.intercept[:enabled] = true
66
64
  end
67
65
 
68
- # Disable interception
69
66
  def disable
70
67
  @settings.intercept[:enabled] = false
71
68
  end
@@ -1,7 +1,6 @@
1
1
  require 'zlib'
2
2
 
3
3
  module Ritm
4
- # ENCODER/DECODER of HTTP content
5
4
  module Encodings
6
5
  ENCODINGS = %i[identity gzip deflate].freeze
7
6
 
@@ -34,7 +33,6 @@ module Ritm
34
33
  class << self
35
34
  private
36
35
 
37
- # Returns data unchanged. Identity is the default value of Accept-Encoding headers.
38
36
  def identity(data)
39
37
  data
40
38
  end
@@ -1,6 +1,6 @@
1
1
  require 'faraday'
2
-
3
2
  require 'ritm/interception/intercept_utils'
3
+ require 'webrick/cookie'
4
4
 
5
5
  module Ritm
6
6
  # Forwarder that acts as a WEBrick <-> Faraday adaptor: Works this way:
@@ -13,6 +13,21 @@ module Ritm
13
13
  #
14
14
  # Besides the possible modifications to be done by interceptors there might be automated globally configured
15
15
  # transformations like header stripping/adding.
16
+
17
+ class ParamEncoder
18
+ def encode(params)
19
+ pairs = params.map { |k, v| "#{k}=#{v}" }
20
+ pairs.join('&')
21
+ end
22
+
23
+ def decode(query)
24
+ query.split('&').each_with_object({}) do |param, params|
25
+ k, v = param.split('=')
26
+ params[k] = v
27
+ end
28
+ end
29
+ end
30
+
16
31
  class HTTPForwarder
17
32
  include InterceptUtils
18
33
 
@@ -21,9 +36,11 @@ module Ritm
21
36
  @response_interceptor = response_interceptor
22
37
  @config = context_config
23
38
  # TODO: make SSL verification a configuration setting
24
- @client = Faraday.new(ssl: { verify: false }) do |conn|
39
+ @client = Faraday.new(
40
+ ssl: { verify: false },
41
+ request: { params_encoder: ParamEncoder.new }
42
+ ) do |conn|
25
43
  conn.adapter :net_http
26
- conn.proxy = @config.misc.upstream_proxy unless @config.misc.upstream_proxy.nil?
27
44
  end
28
45
  end
29
46
 
@@ -39,11 +56,10 @@ module Ritm
39
56
  def faraday_forward(request)
40
57
  req_method = request.request_method.downcase
41
58
  @client.send req_method do |req|
59
+ req.options[:proxy] = @config.misc.upstream_proxy
42
60
  req.url request.request_uri
43
61
  req.body = request.body
44
- request.header.each do |name, value|
45
- req.headers[name] = value
46
- end
62
+ request.header.each { |name, value| req.headers[name] = value }
47
63
  end
48
64
  end
49
65
 
@@ -51,7 +67,12 @@ module Ritm
51
67
  webrick_response.status = faraday_response.status
52
68
  webrick_response.body = faraday_response.body
53
69
  faraday_response.headers.each do |name, value|
54
- webrick_response[name] = value
70
+ case name
71
+ when 'set-cookie'
72
+ WEBrick::Cookie.parse_set_cookies(value).each { |cookie| webrick_response.cookies << cookie }
73
+ else
74
+ webrick_response[name] = value
75
+ end
55
76
  end
56
77
  webrick_response
57
78
  end
@@ -1,12 +1,11 @@
1
1
  require 'webrick'
2
- require 'ritm/interception/http_forwarder'
3
2
 
4
3
  module Ritm
5
4
  # Actual implementation of the SSL Reverse Proxy service (decoupled from the certificate handling)
6
5
  class RequestInterceptorServlet < WEBrick::HTTPServlet::AbstractServlet
7
- def initialize(server, request_interceptor, response_interceptor, conf)
6
+ def initialize(server, forwarder)
8
7
  super server
9
- @forwarder = HTTPForwarder.new(request_interceptor, response_interceptor, conf)
8
+ @forwarder = forwarder
10
9
  end
11
10
 
12
11
  def service(request, response)
@@ -1,6 +1,5 @@
1
1
  require 'ritm/session'
2
2
 
3
- # Main module
4
3
  module Ritm
5
4
  GLOBAL_SESSION = Session.new
6
5
 
@@ -9,7 +9,7 @@ module Ritm
9
9
  module Proxy
10
10
  # Patches WEBrick::HTTPServer SSL context creation to get
11
11
  # a callback on the 'Client Helo' step of the SSL-Handshake if SNI is specified
12
- # So we can create self-signed certificates on the fly
12
+ # So RitM can create self-signed certificates on the fly
13
13
  class CertSigningHTTPSServer < WEBrick::HTTPServer
14
14
  # Override
15
15
  def setup_ssl_context(config)
@@ -2,6 +2,7 @@ require 'ritm/proxy/ssl_reverse_proxy'
2
2
  require 'ritm/proxy/proxy_server'
3
3
  require 'ritm/certs/ca'
4
4
  require 'ritm/interception/handlers'
5
+ require 'ritm/interception/http_forwarder'
5
6
 
6
7
  module Ritm
7
8
  module Proxy
@@ -13,13 +14,11 @@ module Ritm
13
14
  build_proxy
14
15
  end
15
16
 
16
- # Starts the service (non blocking)
17
17
  def start
18
18
  @https.start_async
19
19
  @http.start_async
20
20
  end
21
21
 
22
- # Stops the service
23
22
  def shutdown
24
23
  @https.shutdown
25
24
  @http.shutdown
@@ -32,8 +31,10 @@ module Ritm
32
31
  ssl_proxy_host = @conf.ssl_reverse_proxy.bind_address
33
32
  ssl_proxy_port = @conf.ssl_reverse_proxy.bind_port
34
33
  @https_forward = "#{ssl_proxy_host}:#{ssl_proxy_port}"
35
- @request_interceptor = default_request_handler(session)
36
- @response_interceptor = default_response_handler(session)
34
+
35
+ request_interceptor = default_request_handler(session)
36
+ response_interceptor = default_response_handler(session)
37
+ @forwarder = HTTPForwarder.new(request_interceptor, response_interceptor, @conf)
37
38
 
38
39
  crt_path = @conf.ssl_reverse_proxy.ca.pem
39
40
  key_path = @conf.ssl_reverse_proxy.ca.key
@@ -47,17 +48,14 @@ module Ritm
47
48
  Logger: WEBrick::Log.new(File.open(File::NULL, 'w')),
48
49
  https_forward: @https_forward,
49
50
  ProxyVia: nil,
50
- request_interceptor: @request_interceptor,
51
- response_interceptor: @response_interceptor,
51
+ forwarder: @forwarder,
52
52
  ritm_conf: @conf)
53
53
  end
54
54
 
55
55
  def build_reverse_proxy
56
56
  @https = Ritm::Proxy::SSLReverseProxy.new(@conf.ssl_reverse_proxy.bind_port,
57
57
  @certificate,
58
- @conf,
59
- request_interceptor: @request_interceptor,
60
- response_interceptor: @response_interceptor)
58
+ @forwarder)
61
59
  end
62
60
 
63
61
  def ca_certificate(pem, key)
@@ -1,15 +1,12 @@
1
1
  require 'webrick'
2
2
  require 'webrick/httpproxy'
3
3
  require 'ritm/helpers/patches'
4
- require 'ritm/interception/intercept_utils'
5
4
 
6
5
  module Ritm
7
6
  module Proxy
8
7
  # Proxy server that accepts request and response intercept handlers for HTTP traffic
9
8
  # HTTPS traffic is redirected to the SSLReverseProxy for interception
10
9
  class ProxyServer < WEBrick::HTTPProxyServer
11
- include InterceptUtils
12
-
13
10
  def start_async
14
11
  trap(:TERM) { shutdown }
15
12
  trap(:INT) { shutdown }
@@ -28,20 +25,7 @@ module Ritm
28
25
  def proxy_service(req, res)
29
26
  # Proxy Authentication
30
27
  proxy_auth(req, res)
31
-
32
- # Request modifier handler
33
- intercept_request(@config[:request_interceptor], req, @config[:ritm_conf].intercept.request)
34
-
35
- begin
36
- send("do_#{req.request_method}", req, res)
37
- rescue NoMethodError
38
- raise WEBrick::HTTPStatus::MethodNotAllowed, "unsupported method `#{req.request_method}'."
39
- rescue StandardError => err
40
- raise WEBrick::HTTPStatus::ServiceUnavailable, err.message
41
- end
42
-
43
- # Response modifier handler
44
- intercept_response(@config[:response_interceptor], req, res, @config[:ritm_conf].intercept.response)
28
+ @config[:forwarder].forward(req, res)
45
29
  end
46
30
 
47
31
  # Override
@@ -11,9 +11,8 @@ module Ritm
11
11
  # Creates a HTTPS server with the given settings
12
12
  # @param port [Fixnum]: TCP port to bind the service
13
13
  # @param ca [Ritm::CA]: The certificate authority used to sign fake server certificates
14
- # @param request_interceptor [Proc]: If given, it will be invoked before proxying the request
15
- # @param response_interceptor [Proc]: If give, it will be invoked before sending back the response
16
- def initialize(port, ca, conf, request_interceptor: nil, response_interceptor: nil)
14
+ # @param forwarder [Ritm::HTTPForwarder]: Forwards http traffic with interception
15
+ def initialize(port, ca, forwarder)
17
16
  @ca = ca
18
17
  default_vhost = 'localhost'
19
18
  @server = CertSigningHTTPSServer.new(Port: port,
@@ -21,8 +20,7 @@ module Ritm
21
20
  Logger: WEBrick::Log.new(File.open(File::NULL, 'w')),
22
21
  ca: ca,
23
22
  **vhost_settings(default_vhost))
24
-
25
- @server.mount '/', RequestInterceptorServlet, request_interceptor, response_interceptor, conf
23
+ @server.mount '/', RequestInterceptorServlet, forwarder
26
24
  end
27
25
 
28
26
  def start_async
@@ -1,4 +1,3 @@
1
- # Ritm version
2
1
  module Ritm
3
- VERSION = '1.0.2'.freeze
2
+ VERSION = '1.0.3'.freeze
4
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ritm
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.2
4
+ version: 1.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sebastián Tello
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-12-25 00:00:00.000000000 Z
11
+ date: 2017-12-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: certificate_authority
@@ -142,14 +142,28 @@ dependencies:
142
142
  requirements:
143
143
  - - "~>"
144
144
  - !ruby/object:Gem::Version
145
- version: '1.4'
145
+ version: '2.0'
146
146
  type: :development
147
147
  prerelease: false
148
148
  version_requirements: !ruby/object:Gem::Requirement
149
149
  requirements:
150
150
  - - "~>"
151
151
  - !ruby/object:Gem::Version
152
- version: '1.4'
152
+ version: '2.0'
153
+ - !ruby/object:Gem::Dependency
154
+ name: sinatra-contrib
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - "~>"
158
+ - !ruby/object:Gem::Version
159
+ version: '2.0'
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - "~>"
165
+ - !ruby/object:Gem::Version
166
+ version: '2.0'
153
167
  - !ruby/object:Gem::Dependency
154
168
  name: thin
155
169
  requirement: !ruby/object:Gem::Requirement