manticore 0.4.0-java → 0.4.1-java

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 19e1191d64f814d4e5eeac2a74ea1cb9ec964451
4
- data.tar.gz: 973396d996c2d9bb26491fe88e8566ee27809304
3
+ metadata.gz: c68549109cd024c3e482eaed8cd316d9c316570d
4
+ data.tar.gz: 6844c804051ce09e9f31ccf3ffd4d14d5d294fe9
5
5
  SHA512:
6
- metadata.gz: 0dbfd05b0f5a02a31cde7696dac20baacfa9c981ae0c054d91fd203d2165d3fb42bf3add0363a7b49cb1a91e4c9047911be823c0409238783d8b19acad078088
7
- data.tar.gz: 6eeeded09429d4275256cc81a70e8e12314f70ca7d7c9276160d2c0f982323aa23d3658315dec7dac64b11fed97e5d402fdb728d23224d8f7330ac08f06dfd70
6
+ metadata.gz: 5f98cbb04885e180f8b692338648460a6b51220168e648629f5dcea0281871e94f16ca8cfd0470bcd33cceb2fed2914fe50b25e00f5226fc59c9e3786005feb9
7
+ data.tar.gz: d0a49ec53bb0286a2b6eed9cff0d819f80749317d280150040bf43d54126a9ec6e0a5bf2262c0d13b6c2f297fa8b3b8004e8f02b6e3ae0a2e9c179060a9753b6
Binary file
data.tar.gz.sig CHANGED
Binary file
@@ -1,4 +1,9 @@
1
- ## v0.4.1 (pending)
1
+ ## v0.4
2
+
3
+ ### v0.4.1 (pending)
4
+
5
+ * Add support for ssl[:ca_file], ssl[:client_cert], and ssl[:client_key], to emulate OpenSSL features in other Ruby HTTP clients
6
+ * Integrate Faraday adapter for Manticore
2
7
 
3
8
  ### v0.4.0
4
9
 
@@ -0,0 +1,101 @@
1
+ require 'faraday'
2
+
3
+ module Faraday
4
+ class Adapter
5
+ class Manticore < Faraday::Adapter
6
+ dependency { require 'manticore' }
7
+
8
+ class ParallelManager
9
+ def client=(client)
10
+ @client ||= client
11
+ end
12
+
13
+ def run
14
+ @client.execute! if @client
15
+ end
16
+ end
17
+
18
+ self.supports_parallel = true
19
+ def self.setup_parallel_manager(options = {})
20
+ ParallelManager.new
21
+ end
22
+
23
+ def client(env)
24
+ @client ||= begin
25
+ opts = {}
26
+ if ssl = env[:ssl].to_hash
27
+ opts[:ssl] = {}
28
+ opts[:ssl][:verify] = :disable if ssl[:verify] == false
29
+ opts[:ssl][:ca_file] = ssl[:ca_file]
30
+ opts[:ssl][:client_cert] = ssl[:client_cert]
31
+ opts[:ssl][:client_key] = ssl[:client_key]
32
+ end
33
+ ::Manticore::Client.new(opts)
34
+ end
35
+ end
36
+
37
+ def call(env)
38
+ super
39
+
40
+ opts = {}
41
+ if env.key? :request_headers
42
+ opts[:headers] = env[:request_headers]
43
+ opts[:headers].reject! {|k, _| k.downcase == "content-length" } # Manticore computes Content-Length
44
+ end
45
+ body = read_body(env)
46
+ opts[:body] = body if body
47
+
48
+ if req = env[:request]
49
+ opts[:request_timeout] = opts[:connect_timeout] = opts[:socket_timeout] = req[:timeout] if req.key?(:timeout)
50
+ opts[:connect_timeout] = opts[:socket_timeout] = req[:open_timeout] if req.key?(:open_timeout)
51
+ if prx = req[:proxy]
52
+ opts[:proxy] = {
53
+ :url => prx[:uri].to_s,
54
+ :user => prx[:user],
55
+ :password => prx[:password]
56
+ }
57
+ end
58
+ end
59
+
60
+ cl = client(env)
61
+ if parallel?(env)
62
+ env[:parallel_manager].client = cl
63
+ cl = cl.async
64
+ end
65
+
66
+ last_exception = nil
67
+
68
+ req = cl.send(env[:method].to_s.downcase, env[:url].to_s, opts)
69
+ req.on_success do |response|
70
+ save_response(env, response.code, response.body || "", response.headers)
71
+ env[:response].finish(env) if parallel?(env)
72
+ end
73
+
74
+ req.on_failure do |err|
75
+ case err
76
+ when ::Manticore::Timeout
77
+ raise TimeoutError, err
78
+ when ::Manticore::SocketException, ::Java::JavaUtilConcurrent::ExecutionException
79
+ raise ConnectionFailed, err
80
+ when ::Manticore::ClientProtocolException
81
+ raise Faraday::SSLError, err
82
+ else
83
+ raise err
84
+ end
85
+ end
86
+
87
+ req.call unless parallel?(env)
88
+ @app.call env
89
+ end
90
+
91
+ def parallel?(env)
92
+ !env[:parallel_manager].nil?
93
+ end
94
+
95
+ def read_body(env)
96
+ env[:body].respond_to?(:read) ? env[:body].read : env[:body]
97
+ end
98
+ end
99
+ register_middleware nil, :manticore => :Manticore
100
+ end
101
+ end
@@ -1,7 +1,6 @@
1
1
  require 'java'
2
2
  require 'uri'
3
3
  require 'cgi'
4
- require 'cgi/cookie'
5
4
 
6
5
  jars = ["httpcore-4.3.3", "httpclient-4.3.6", "commons-logging-1.1.3", "commons-codec-1.6.jar", "httpmime-4.3.6.jar"]
7
6
  jars.each do |jar|
@@ -1,4 +1,5 @@
1
1
  require 'thread'
2
+ require 'base64'
2
3
 
3
4
  module Manticore
4
5
  # General Timeout exception thrown for various Manticore timeouts
@@ -72,9 +73,11 @@ module Manticore
72
73
  include_package "java.util.concurrent"
73
74
  include_package "org.apache.http.client.protocol"
74
75
  include_package 'org.apache.http.conn.ssl'
76
+ include_package "java.security.cert"
77
+ include_package "java.security.spec"
78
+ include_package "java.security"
75
79
  java_import "org.apache.http.HttpHost"
76
80
  java_import "javax.net.ssl.SSLContext"
77
- java_import "java.security.KeyStore"
78
81
  java_import "org.manticore.HttpGetWithEntity"
79
82
  java_import "org.apache.http.auth.UsernamePasswordCredentials"
80
83
 
@@ -141,6 +144,9 @@ module Manticore
141
144
  # @option options [String] ssl[:keystore] (nil) Path to a custom key store to use for client certificate authentication
142
145
  # @option options [String] ssl[:keystore_password] (nil) Password used for decrypting the client auth key store
143
146
  # @option options [String] ssl[:keystore_type] (nil) Format of the key store, ie "JKS" or "PKCS12". If left nil, the type will be inferred from the keystore filename.
147
+ # @option options [String] ssl[:ca_file] (nil) OpenSSL-style path to an X.509 certificate to use to validate SSL certificates
148
+ # @option options [String] ssl[:client_cert] (nil) OpenSSL-style path to an X.509 certificate to use for client authentication
149
+ # @option options [String] ssl[:client_key] (nil) OpenSSL-style path to an RSA key to use for client authentication
144
150
  # @option options [boolean] ssl[:track_state] (false) Turn on or off connection state tracking. This helps prevent SSL information from leaking across threads, but means that connections
145
151
  # can't be shared across those threads. This should generally be left off unless you know what you're doing.
146
152
  def initialize(options = {})
@@ -554,18 +560,59 @@ module Manticore
554
560
  raise "Invalid value for :verify. Valid values are (:all, :browser, :default)"
555
561
  end
556
562
 
557
-
558
563
  context = SSLContexts.custom
564
+ setup_trust_store ssl_options, context, trust_strategy
565
+ setup_key_store ssl_options, context
559
566
 
567
+ SSLConnectionSocketFactory.new context.build, ssl_options[:protocols].to_java(:string), ssl_options[:cipher_suites].to_java(:string), verifier
568
+ end
569
+
570
+ def setup_trust_store(ssl_options, context, trust_strategy)
560
571
  trust_store = get_store(:truststore, ssl_options) if ssl_options.key?(:truststore)
572
+
573
+ # Support OpenSSL-style ca_file. We don't support ca_path for now.
574
+ if ssl_options[:ca_file]
575
+ trust_store ||= blank_keystore
576
+ open(ssl_options[:ca_file]) do |fp|
577
+ cert_collection = CertificateFactory.get_instance("X509").generate_certificates(fp.to_inputstream).to_a
578
+ cert_collection.each do |cert|
579
+ trust_store.set_certificate_entry(cert.getSubjectX500Principal.name, cert)
580
+ end
581
+ end
582
+ end
583
+
561
584
  context.load_trust_material(trust_store, trust_strategy)
585
+ end
586
+
587
+ KEY_EXTRACTION_REGEXP = /(?:^-----BEGIN(.* )PRIVATE KEY-----\n)(.*?)(?:-----END\1PRIVATE KEY.*$)/m
588
+ def setup_key_store(ssl_options, context)
589
+ key_store = get_store(:keystore, ssl_options) if ssl_options.key?(:keystore)
562
590
 
563
- if ssl_options.key?(:keystore)
564
- key_store = get_store(:keystore, ssl_options)
565
- context.load_key_material(key_store, ssl_options.fetch(:keystore_password, nil).to_java.toCharArray)
591
+ # Support OpenSSL-style bare X.509 certs with an RSA key
592
+ # This is really dumb - we have to b64-decode the key ourselves.
593
+ if ssl_options[:client_cert] && ssl_options[:client_key]
594
+ key_store ||= blank_keystore
595
+ certs, key = nil, nil
596
+ open(ssl_options[:client_cert]) do |fp|
597
+ certs = CertificateFactory.get_instance("X509").generate_certificates(fp.to_inputstream).to_array([].to_java(Certificate))
598
+ end
599
+
600
+ keystore_password = ssl_options.fetch(:keystore_password, "").to_java.toCharArray
601
+ # Add each of the keys in the given keyfile into the keystore.
602
+ open(ssl_options[:client_key]) do |fp|
603
+ key_parts = fp.read.scan(KEY_EXTRACTION_REGEXP)
604
+ key_parts.each do |type, b64key|
605
+ body = Base64.decode64 b64key
606
+ spec = PKCS8EncodedKeySpec.new(body.to_java_bytes)
607
+ type = type.strip
608
+ type = "RSA" if type == ""
609
+ key = KeyFactory.getInstance(type).generatePrivate(spec)
610
+ key_store.set_key_entry("key-#{Digest::SHA1.hexdigest(body)}", key, keystore_password, certs)
611
+ end
612
+ end
566
613
  end
567
614
 
568
- SSLConnectionSocketFactory.new context.build, ssl_options[:protocols].to_java(:string), ssl_options[:cipher_suites].to_java(:string), verifier
615
+ context.load_key_material(key_store, keystore_password) if key_store
569
616
  end
570
617
 
571
618
  def get_trust_store(options)
@@ -583,6 +630,10 @@ module Manticore
583
630
  end
584
631
  end
585
632
 
633
+ def blank_keystore
634
+ KeyStore.get_instance(KeyStore.get_default_type).tap {|k| k.load(nil, nil) }
635
+ end
636
+
586
637
  def guess_store_type(filename)
587
638
  if filename.end_with?(".p12")
588
639
  "pkcs12"
@@ -1,3 +1,3 @@
1
1
  module Manticore
2
- VERSION = "0.4.0"
2
+ VERSION = "0.4.1"
3
3
  end
@@ -112,6 +112,29 @@ describe Manticore::Client do
112
112
  end
113
113
  end
114
114
 
115
+ context 'when ca_file is given' do
116
+ let(:client) { Manticore::Client.new :ssl => {verify: :strict, ca_file: File.expand_path("../../ssl/ca_cert.crt", __FILE__) } }
117
+
118
+ it "should verify the request and succeed" do
119
+ expect { client.get("https://localhost:55444/").body }.to_not raise_exception
120
+ end
121
+ end
122
+
123
+ context 'when client_cert and client_key are given' do
124
+ let(:client) { Manticore::Client.new(
125
+ :ssl => {
126
+ verify: :strict,
127
+ ca_file: File.expand_path("../../ssl/ca_cert.crt", __FILE__),
128
+ client_cert: File.expand_path("../../ssl/client.crt", __FILE__),
129
+ client_key: File.expand_path("../../ssl/client.key", __FILE__)
130
+ })
131
+ }
132
+
133
+ it "should successfully auth requests" do
134
+ expect(client.get("https://localhost:55445/").body).to match("hello")
135
+ end
136
+ end
137
+
115
138
  context 'when off' do
116
139
  let(:client) { Manticore::Client.new :ssl => {:verify => :none} }
117
140
 
Binary file
@@ -0,0 +1,22 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIDlTCCAX0CAQEwDQYJKoZIhvcNAQEFBQAwYTELMAkGA1UEBhMCVVMxCzAJBgNV
3
+ BAgMAk1EMRIwEAYDVQQHDAlCYWx0aW1vcmUxEDAOBgNVBAMMB1Rlc3QgQ0ExHzAd
4
+ BgkqhkiG9w0BCQEWEHRlc3RAZXhhbXBsZS5jb20wIBcNMTQxMjEwMjIwMzMxWhgP
5
+ MjExNDExMTYyMjAzMzFaMEIxCzAJBgNVBAYTAlhYMRUwEwYDVQQHDAxEZWZhdWx0
6
+ IENpdHkxHDAaBgNVBAoME0RlZmF1bHQgQ29tcGFueSBMdGQwgZ8wDQYJKoZIhvcN
7
+ AQEBBQADgY0AMIGJAoGBANf8i2rFB1llfRuNuERJyvXCR9cHEvW7jAXXUbrWRAFJ
8
+ yAE466ZYPWBZZ241iQOFsEAtjldly80USyD0Nfx18M6FR6dppH/cqEsLKT6Esa5X
9
+ ASOMJhgftiU2CvjIkVSVlIdTACetnoLLGF926F7lyNgAS4b9PZdg4QFr2Ih04NSx
10
+ AgMBAAEwDQYJKoZIhvcNAQEFBQADggIBAKWAYd1Cgzu9lvhjweeO2HI9eLk7pr/c
11
+ 1f6yOLxwfZyxCVYkQ906/YVcO+vvb+R1gbHEw3cHED9SgIZARvNNM9I2YFk/KFEg
12
+ 3N8mo37KOHu4HGyhRcJqB90P7umwVyWJn2iXe8Wus/eWsszBgXyPM3Xa7Wwy7aBw
13
+ AXAnrRhESethWI3vH3yAJeT1RG1rGjEqEuojfDxgzKvt08PgMwkN8VY0b7XdAdXj
14
+ ycXCmhaTLveM9BQVYY/LrrMR4ynVM6Fv3GXR3Sz/Eup4sJTXo3DhZ4rSBAPkyHCD
15
+ wxcmrjEL9eMG8kqXT4y/UQyXYhWKbFB3InnfZCh/QJ1+JqpIhi+tEMrVRvMrYp7l
16
+ /6ZGml4wHlCL+ky/wG30sgTHpj+S8PG96LnJ+kXnkxycq6vCRJEfRmXhh70swIiv
17
+ Pgh6RAZu6AdVX+gztnD0oSbez39hb4qcolLjlSO2msBTbQ2lp9zNrB4MqzuAgC1K
18
+ CWs2oBm6NrrR4+Sx/JjLmQcoSeuFooUmloL1c5XRv1B7vpx9P2Do0aF6Xksvli0w
19
+ 62n72nI7nF8VfyKjjEABk6dNBK0dYFrO+5pWJ4KEdOt2fVw5pduB4K2TN12z0LlY
20
+ ItFnYxmFPzUGleMHZsHASsMPlNtroE4p6O+ofNfrwwBzSQ+G+KDoC94TzOF2pf69
21
+ A3NjNKNgxgG5
22
+ -----END CERTIFICATE-----
@@ -0,0 +1,16 @@
1
+ -----BEGIN PRIVATE KEY-----
2
+ MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBANf8i2rFB1llfRuN
3
+ uERJyvXCR9cHEvW7jAXXUbrWRAFJyAE466ZYPWBZZ241iQOFsEAtjldly80USyD0
4
+ Nfx18M6FR6dppH/cqEsLKT6Esa5XASOMJhgftiU2CvjIkVSVlIdTACetnoLLGF92
5
+ 6F7lyNgAS4b9PZdg4QFr2Ih04NSxAgMBAAECgYEAg0qy/P40D3WP7VXiszAgPfAR
6
+ d3aHYfTVkx9mQSrKP/Y3q/aL2Jw/AviV1PqaBRgZIYoPwrTQhCNX3/pTbtnKvMDr
7
+ Py5l9AHGvzWx9ThYV/ErcVNEFUNegTeiIKPcX8jh72s62PVRU0ZYUNPUh2cShZjr
8
+ qcLn+QKpxpnuuMPxgDkCQQD7NRFbkfq3Q7lwDN8/GMmBHxv/HOpLdLmWT7ua9OE9
9
+ JnVjml89fT31rM9D/YVZaf3kIe6y1xehRhCUfrlhnufnAkEA3Bt0E5DT0/utRgXS
10
+ 4xA5LHvnZ0R5mHGPd6m0/3c7uf3epeHUakE3HBvsp9Ys/87hByq/R7QCoTE2MVhg
11
+ uSZrpwJAIgeoWE1IN3dXMZSs0XFcKr+6HS8fliUz1ubqNS2jLZN+J4YMDNpggF1u
12
+ nnlDjT9Mg5ENMvDsZI6HRHZ+SnkqVQJAApzo0dqkSR3xvqUPDdcBdr+5zYYIk4C1
13
+ nUwMdAPsV5bl774wkVpY1yKVuqBWRGsmTLl7L9S5O0SkSg2siEYmfQJBAOEwqhs7
14
+ tkLpUpWv3+0V2Lv/0CuXrqgacXxebQ8MfcH9YpWV0M54kJ7u/4gNCXgj66pDAqfE
15
+ bU+RhxY82ohb5uo=
16
+ -----END PRIVATE KEY-----
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: manticore
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.4.1
5
5
  platform: java
6
6
  authors:
7
7
  - Chris Heald
@@ -92,6 +92,7 @@ files:
92
92
  - ext/manticore/org/manticore/HttpGetWithEntity.java
93
93
  - ext/manticore/org/manticore/Manticore.java
94
94
  - gem-public_cert.pem
95
+ - lib/faraday/adapter/manticore.rb
95
96
  - lib/jar/commons-codec-1.6.jar
96
97
  - lib/jar/commons-logging-1.1.3.jar
97
98
  - lib/jar/httpclient-4.3.6.jar
@@ -114,8 +115,11 @@ files:
114
115
  - spec/manticore/response_spec.rb
115
116
  - spec/manticore/stubbed_response_spec.rb
116
117
  - spec/spec_helper.rb
118
+ - spec/ssl/ca_cert.crt
117
119
  - spec/ssl/ca_cert.pem
118
120
  - spec/ssl/ca_key.pem
121
+ - spec/ssl/client.crt
122
+ - spec/ssl/client.key
119
123
  - spec/ssl/client.p12
120
124
  - spec/ssl/localhost.key
121
125
  - spec/ssl/localhost.pem
@@ -153,8 +157,11 @@ test_files:
153
157
  - spec/manticore/response_spec.rb
154
158
  - spec/manticore/stubbed_response_spec.rb
155
159
  - spec/spec_helper.rb
160
+ - spec/ssl/ca_cert.crt
156
161
  - spec/ssl/ca_cert.pem
157
162
  - spec/ssl/ca_key.pem
163
+ - spec/ssl/client.crt
164
+ - spec/ssl/client.key
158
165
  - spec/ssl/client.p12
159
166
  - spec/ssl/localhost.key
160
167
  - spec/ssl/localhost.pem
metadata.gz.sig CHANGED
Binary file