rack-padlock 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -1,36 +1,61 @@
1
- rack-padlock
2
- =======
1
+ # rack-padlock
3
2
 
4
- A toolkit for writing tests against rack applications that ensure all traffic on a page is secure.
3
+ A toolkit for rack applications that ensures _ALL_ content on a page is secure. The browser padlock is pretty important for commercial web applications. Modern sites rely on so many third party services: analytics, video players, social media widgets. With all these moving parts it's easy to end up with a broken padlock. Rack-Padlock will increase the visibility of padlock problems to your development team, and it's dead easy to use.
5
4
 
6
- ###Prerequisites
5
+ ## Prerequisites
7
6
 
8
- 1. You need to have a rack based application
9
- 2. The application must have a browser based integration test suite. I recommend capybara.
10
- 3. Your integration tests must use HTTPS
7
+ All you need to have a rack based application! (Rails, Sinatra, Camping, etc...)
11
8
 
12
9
  ## Setup
13
10
 
14
11
  Add rack-padlock gem to your test group
15
12
 
16
- ```bash
13
+ ```ruby
17
14
  group :test do
18
15
  gem 'rack-padlock'
19
16
  end
20
17
  ```
21
18
 
22
- Add rack-padlock middleware to your app
19
+ Add rack-padlock rake tasks to your app
23
20
 
24
- ```bash
25
- group :test do
26
- gem 'rack-padlock'
21
+ ```ruby
22
+ require 'rack/padlock'
23
+ load 'tasks/rack-padlock.rake'
24
+ ```
25
+
26
+ Specify what url's you want to test somewhere in your Rakefile
27
+
28
+ ```ruby
29
+ Rack::Padlock.padlock_uris = ["/secure", "/insecure"]
30
+ ```
31
+
32
+ If your application isn't a Rails app, then you need to add an environment rake task to your Rakefile like this
33
+ ```ruby
34
+ desc "setup application environment"
35
+ task :environment do
36
+ require 'your rack application'
37
+ Rack::Padlock.application = YourRackApplication
38
+ Rack::Padlock.padlock_uris = ["/secure", "/insecure"]
27
39
  end
28
40
  ```
41
+ ## Running Tests
42
+
43
+ Once you've set things up simply run
44
+
45
+ ```bash
46
+ rake padlock
47
+ ```
48
+
49
+ This will run the padlock tests. If any of your integration tests mix secure and insecure content, the padlock test will fail.
50
+
51
+ ## Example rack application
52
+
53
+ Have a look at a simple sinatra application that demonstrates rack-padlock at https://github.com/joshuacronemeyer/rack-padlock-example-app
29
54
 
30
- Please see the example application at https://github.com/joshuacronemeyer/rack-padlock-example-app
55
+ ## How it works
31
56
 
32
- how it works
33
- =======
57
+ Rack-Padlock starts your Rack app up with an SSL enabled webrick server. It puts a custom middleware in front of your application that implements a CSP policy. That policy requires the browser to notify us of any non SSL activity. The custom middleware intercepts these notifications and logs them. At the end of the run the rack-padlock test will either succeed or fail based on the presence of any policy violations.
34
58
 
59
+ ## References
35
60
 
36
- Please see https://dvcs.w3.org/hg/content-security-policy/raw-file/tip/csp-specification.dev.html
61
+ 1. http://www.w3.org/TR/CSP/
@@ -0,0 +1,42 @@
1
+ var startTime = Date.now();
2
+ var timeOut = 10000;
3
+ console.log('Padlock: JS client starting!');
4
+ var page = require('webpage').create(),
5
+ system = require('system'),
6
+ t, address;
7
+
8
+ if (system.args.length === 1) {
9
+ console.log('ERROR: You need to pass phantomjs some URLs to visit!');
10
+ phantom.exit();
11
+ }
12
+
13
+ var pagesToVisit = system.args.slice(1);
14
+ var numberOfPagesToVisit = pagesToVisit.length;
15
+ var numberOfPagesVisited = 0;
16
+
17
+ var visitPages = function(pages){
18
+ if(pages.length == 0){return;}
19
+ var thePage = pages.pop();
20
+ console.log("Opening " + thePage);
21
+ page.open(thePage, function (status) {
22
+ if (status !== 'success') {
23
+ console.log('FAIL to load the address: ' + thePage);
24
+ } else {
25
+ console.log('visited: ' + thePage );
26
+ }
27
+ numberOfPagesVisited++;
28
+ visitPages(pages);
29
+ });
30
+ };
31
+
32
+ var exitWhenDone = function(){
33
+ var executionTime = Date.now() - startTime;
34
+ if (numberOfPagesVisited == numberOfPagesToVisit || executionTime > timeOut) {
35
+ phantom.exit();
36
+ } else{
37
+ setTimeout(exitWhenDone,500);
38
+ }
39
+ };
40
+
41
+ visitPages(pagesToVisit);
42
+ exitWhenDone();
@@ -0,0 +1,24 @@
1
+ module Rack
2
+ class Padlock
3
+ class Phantomjs
4
+ KILL_TIMEOUT = 20 # seconds
5
+ attr_reader :pid, :binary
6
+
7
+ def initialize(addresses, binary=nil)
8
+ @binary = binary || 'phantomjs'
9
+ @addresses = addresses
10
+ @pid = nil
11
+ end
12
+
13
+ def command
14
+ js_path = ::File.expand_path('../padlock.js', __FILE__)
15
+ "#{@binary} --ignore-ssl-errors=yes #{js_path} #{@addresses.join(' ')}"
16
+ end
17
+
18
+ def start
19
+ puts "Starting up phantomjs\n"
20
+ Timeout.timeout(KILL_TIMEOUT) { system(command) }
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,18 @@
1
+ require "selenium-webdriver"
2
+ module Rack
3
+ class Padlock
4
+ class Selenium
5
+ def initialize(addresses)
6
+ @addresses = addresses
7
+ end
8
+
9
+ def start
10
+ puts "Starting up selenium webdriver\n"
11
+ @driver = ::Selenium::WebDriver.for :firefox
12
+ @driver.manage.timeouts.implicit_wait = 30
13
+ @addresses.each{|address| @driver.get(address)}
14
+ @driver.quit
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,104 @@
1
+ require 'timeout'
2
+ require 'rack'
3
+ module Rack
4
+ class Padlock
5
+
6
+ class Server
7
+ PORT = 9988
8
+ attr_reader :app
9
+
10
+ def initialize(app)
11
+ @app = app
12
+ @middleware = Rack::Padlock.new(@app)
13
+ @server_thread = nil
14
+ end
15
+
16
+ def boot
17
+ @server_thread = Thread.new do
18
+ webserver = Rack::Padlock::Webrick.run(@middleware, PORT)
19
+ end
20
+
21
+ Timeout.timeout(60) { @server_thread.join(0.1) until responsive? }
22
+ rescue Timeout::Error
23
+ raise "Rack application timed out during boot"
24
+ else
25
+ self
26
+ end
27
+
28
+ def responsive?
29
+ return false if @server_thread && @server_thread.join(0)
30
+
31
+ require "net/https"
32
+ require 'uri'
33
+ uri = URI.parse("#{base_uri}/padlock_middleware/poke")
34
+ http = Net::HTTP.new(uri.host, uri.port)
35
+ http.use_ssl = true
36
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
37
+ request = Net::HTTP::Get.new(uri.request_uri)
38
+ response = http.request(request)
39
+
40
+ return response.is_a?(Net::HTTPSuccess) || response.is_a?(Net::HTTPRedirection)
41
+ rescue Errno::ECONNREFUSED, Errno::EBADF
42
+ return false
43
+ end
44
+
45
+ def base_uri
46
+ "https://localhost:#{PORT}"
47
+ end
48
+ end
49
+
50
+ class Webrick
51
+ def self.run(app, port)
52
+ puts "Starting up SSL webrick\n"
53
+ require 'rack/handler/webrick'
54
+ require 'webrick/https'
55
+ require 'openssl'
56
+ webrick_options = {
57
+ :Port => (port),
58
+ :AccessLog => [],
59
+ :Logger => WEBrick::Log::new(nil, 0),
60
+ :SSLEnable => true,
61
+ :SSLVerifyClient => OpenSSL::SSL::VERIFY_NONE,
62
+ :SSLPrivateKey => OpenSSL::PKey::RSA.new(KEY),
63
+ :SSLCertificate => OpenSSL::X509::Certificate.new(CRT),
64
+ :SSLCertName => [["CN", WEBrick::Utils::getservername]]
65
+ }
66
+ webrick_options.merge({:Logger => WEBrick::Log::new($stdout, WEBrick::Log::DEBUG)}) if Rack::Padlock.debug?
67
+ Rack::Handler::WEBrick.run(app, webrick_options)
68
+ end
69
+
70
+ KEY=<<EOF
71
+ -----BEGIN RSA PRIVATE KEY-----
72
+ MIICXQIBAAKBgQDayqjBWENExonuc2RPbegDb7O2r5vw+iVl0MBF9sQAmuu3vuoN
73
+ UCeNgF2CFvMpFQFsQ8hm+qnnDQFU66+lEXfR5bfRd8whOIS7ysD5nDzr8wKhqX9s
74
+ 964zhVInvfEinmggyxz6BdkWTXsMblS1Z0JjsomFrhQkIkw82r5t7Hc4iQIDAQAB
75
+ AoGBALAo4i0iQq86Z84s7IQjit5RbtJVnGovDjNnG5h5ciDGm6nLNqnXcrE0vJVE
76
+ oy3dstKX1OBNTMUyrHLSfQ6b/OrvKw6dg7ndyFK+XO4zLFB5B0sCE5Bp05Ycjlj1
77
+ 8IAuu9k2e3ozDjf1tNpD80OTa8S3y4+4yxeN5QYbAd2eh+7tAkEA8WbVz8Cjaf9w
78
+ y53k5L9Rv7GP54CI2f7LAsla6TUqQsgjvKTOqalGm4O/7N62nj/JAyWWQl72d4GQ
79
+ xL2ZZyhCxwJBAOgFy5b0yNP/QywzEtpwP3JBrOIdYqV/oXxE0rCzJkWC94xm2J1p
80
+ 0198fNjgueAy4YnuMjR6nTGjBVCdU82fWi8CQB93t0ForCSiHrL8Nx02b1Kcs9SK
81
+ pcw88XvAgbBKtOKVskrh9Oqa3VBiYT9gXM/OIsbdPHQUau5zHkr3KCsRTXsCQQCT
82
+ bStBjeQVoDpkWUd/eJc32DcrrZRCqGhJd8mP8SU+QctdcPPugZGHOKhzfcddh7b7
83
+ V1ibM9Wx9m2oHW9kVf6NAkA1q90FzKwrpFmyzwKCe7wWhPd3GlN4qXvwdEW4kk1b
84
+ KTjyjrIXRt5UObL+ywhdkES8h2+rUFw5hXfyzIpafjyZ
85
+ -----END RSA PRIVATE KEY-----
86
+ EOF
87
+ CRT=<<EOF
88
+ -----BEGIN CERTIFICATE-----
89
+ MIIB8TCCAVoCCQCD/Pvld7jzMDANBgkqhkiG9w0BAQUFADA8MQswCQYDVQQGEwJV
90
+ UzELMAkGA1UECAwCQ0ExCzAJBgNVBAcMAlNGMRMwEQYDVQQKDApDb2xsZWdlc2V0
91
+ MCAXDTEzMDIwNzE5MzM1M1oYDzMwMTIwNjEwMTkzMzUzWjA8MQswCQYDVQQGEwJV
92
+ UzELMAkGA1UECAwCQ0ExCzAJBgNVBAcMAlNGMRMwEQYDVQQKDApDb2xsZWdlc2V0
93
+ MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDayqjBWENExonuc2RPbegDb7O2
94
+ r5vw+iVl0MBF9sQAmuu3vuoNUCeNgF2CFvMpFQFsQ8hm+qnnDQFU66+lEXfR5bfR
95
+ d8whOIS7ysD5nDzr8wKhqX9s964zhVInvfEinmggyxz6BdkWTXsMblS1Z0JjsomF
96
+ rhQkIkw82r5t7Hc4iQIDAQABMA0GCSqGSIb3DQEBBQUAA4GBACbe+qTXarpzRtRx
97
+ +v3AQhN/nMMKHvDwIhfiDlJva0DcRvWi9FDyyQVO8NA5YgcfMPI0iN1opEfOSrfG
98
+ mtyWupIL5lpn4EzW9r/0jOhjwA2NDN/BVYiFe4ovsPvJCOWti1bs7xMz7bSaFiNr
99
+ fi5nkNjLgLQmZHUj9/soMSfRGbP1
100
+ -----END CERTIFICATE-----
101
+ EOF
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,16 @@
1
+ module Rack
2
+ class Padlock
3
+ class StringUtil
4
+ def elide(string, max)
5
+ length = string.length
6
+ return string unless length > max
7
+ return string if max <= 0
8
+ amount_to_preserve_on_the_left = (max/2.0).ceil
9
+ amount_to_preserve_on_the_right = max - amount_to_preserve_on_the_left
10
+ left = string[0..(amount_to_preserve_on_the_left-1)]
11
+ right = string[-amount_to_preserve_on_the_right..-1]
12
+ "#{left}...#{right}"
13
+ end
14
+ end
15
+ end
16
+ end
@@ -1,5 +1,5 @@
1
1
  module Rack
2
2
  class Padlock
3
- VERSION = "0.0.1"
3
+ VERSION = "0.0.2"
4
4
  end
5
5
  end
data/lib/rack/padlock.rb CHANGED
@@ -1,40 +1,81 @@
1
1
  module Rack
2
2
  class Padlock
3
+ @@application = nil
4
+ @@padlock_uris = nil
5
+ @@debug = false
6
+ @@logfile = "tmp/padlock.log"
7
+
3
8
  POST_BODY = 'rack.input'.freeze
4
9
 
5
- def initialize(app, options={})
6
- default_options = {
7
- :log_file => "tmp/padlock.log"
8
- }
10
+ def initialize(app)
9
11
  @app = app
10
- @options = default_options.merge(options)
11
12
  end
12
13
 
13
14
  def call(env)
15
+ return poke_response if poke?(env)
14
16
  return capture_violation(env) if csp_policy_violation?(env)
15
17
  status, headers, body = @app.call(env)
16
18
  headers.merge!(csp_headers(env))
17
19
  [status, headers, body]
18
20
  end
19
-
21
+
22
+ def self.application=(app)
23
+ @@application = app
24
+ end
25
+
26
+ def self.application
27
+ @@application
28
+ end
29
+
30
+ def self.padlock_uris=(uri_list)
31
+ @@padlock_uris = uri_list
32
+ end
33
+
34
+ def self.padlock_uris(base_uri)
35
+ @@padlock_uris.map {|path| "#{base_uri}#{path}" } if @@padlock_uris
36
+ end
37
+
38
+ def self.debug=(flag)
39
+ @@debug = flag
40
+ end
41
+
42
+ def self.debug?
43
+ @@debug
44
+ end
45
+
46
+ def self.logfile=(log)
47
+ @@logfile = log
48
+ end
49
+
50
+ def self.logfile
51
+ @@logfile
52
+ end
20
53
  private
21
54
 
22
55
  def capture_violation(env)
23
56
  violation = env[POST_BODY].read
24
- PadlockFile.write(@options[:log_file], violation)
25
- [200, {}, []]
57
+ PadlockFile.write(Padlock.logfile, violation)
58
+ [200, {"Content-Length"=>"0"}, []]
26
59
  end
27
60
 
61
+ def poke_response
62
+ [200, {}, []]
63
+ end
64
+
28
65
  def csp_policy_violation?(env)
29
66
  env['PATH_INFO'] =~ /padlock_middleware\/report$/
30
67
  end
31
68
 
69
+ def poke?(env)
70
+ env['PATH_INFO'] =~ /padlock_middleware\/poke$/
71
+ end
72
+
32
73
  def csp_headers(env)
33
74
  host = env["HTTP_HOST"]
34
75
  report_uri = "#{host}/padlock_middleware/report"
35
76
  csp_header_names = %w(Content-Security-Policy-Report-Only X-Content-Security-Policy-Report-Only X-WebKit-CSP-Report-Only)
36
77
  csp_headers = {}
37
- csp_header_names.each{|name| csp_headers[name] = "default-src https: 'unsafe-inline' 'unsafe-eval'; report-uri http://#{report_uri}"}
78
+ csp_header_names.each{|name| csp_headers[name] = "default-src https: 'unsafe-inline' 'unsafe-eval'; report-uri https://#{report_uri}"}
38
79
  csp_headers
39
80
  end
40
81
 
@@ -1,15 +1,37 @@
1
1
  require 'rainbow'
2
- PADLOCK_LOG = 'tmp/padlock.log'
2
+ require 'rack/padlock'
3
+ require 'rack/padlock/server'
4
+ require 'rack/padlock/selenium'
5
+ require 'rack/padlock/string_util'
3
6
 
4
7
  desc "Test for padlock"
5
- task :padlock_test => [:padlock_clean, :test] do
6
- contents = File.open(PADLOCK_LOG, 'r') { |f| f.readlines }
7
- if File.size? PADLOCK_LOG
8
+ task :padlock_test => [:environment] do
9
+ rails_app = Rails.application if defined?(Rails)
10
+ app = Rack::Padlock.application || rails_app
11
+ puts "Padlock Test: checking #{app} for insecure content.".foreground(:green)
12
+ server = Rack::Padlock::Server.new(app)
13
+ server.boot
14
+ uris = Rack::Padlock.padlock_uris(server.base_uri) || [server.base_uri]
15
+ client = Rack::Padlock::Selenium.new(uris)
16
+ client.start
17
+ end
18
+
19
+ desc "Test for padlock"
20
+ task :padlock => [:padlock_clean, :padlock_test, :padlock_check]
21
+
22
+ desc "Clean padlock logs"
23
+ task :padlock_check do
24
+ contents = File.open(Rack::Padlock.logfile, 'r') { |f| f.readlines }
25
+ if File.size? Rack::Padlock.logfile
8
26
  puts "Padlock test failure: Insecure content is being loaded on the page.".foreground(:red)
9
27
  contents.each do |line|
10
- blocked_uri = line.match(/blocked-uri":"([^"]+)/)[1].foreground(:yellow)
11
- violated_directive = line.match(/violated-directive":"([^"]+)/)[1].foreground(:magenta)
12
- puts "Request for #{blocked_uri} has violated directive #{violated_directive}"
28
+ what_match = line.match(/blocked-uri":"([^"]+)/)
29
+ why_match = line.match(/violated-directive":"([^"]+)/)
30
+ next unless what_match && why_match
31
+ blocked_uri = what_match[1].foreground(:yellow)
32
+ violated_directive = why_match[1].foreground(:magenta)
33
+ util = Rack::Padlock::StringUtil.new
34
+ puts "Request for #{util.elide(blocked_uri, 200)} has violated directive #{util.elide(violated_directive, 200)}"
13
35
  end
14
36
  exit 1
15
37
  else
@@ -19,5 +41,5 @@ end
19
41
 
20
42
  desc "Clean padlock logs"
21
43
  task :padlock_clean do
22
- File.truncate('tmp/padlock.log', 0) if File.exist?(PADLOCK_LOG)
44
+ File.truncate('tmp/padlock.log', 0) if File.exist?(Rack::Padlock.logfile)
23
45
  end
@@ -49,7 +49,7 @@ class RackPadlockTest < MiniTest::Unit::TestCase
49
49
 
50
50
  class Rack::Padlock::PadlockFile
51
51
  @@last_output = ""
52
- def self.write(data)
52
+ def self.write(file, data)
53
53
  @@last_output = data
54
54
  end
55
55
 
@@ -0,0 +1,18 @@
1
+ require File.join(File.dirname(__FILE__), 'test_helper')
2
+
3
+ class StringUtilTest < MiniTest::Unit::TestCase
4
+
5
+ describe "elide" do
6
+ before do
7
+ @util = Rack::Padlock::StringUtil.new
8
+ end
9
+
10
+ it "should add ellipsis and shorten words" do
11
+ @util.elide("hootinanny", 4).must_equal "ho...ny"
12
+ @util.elide("hootinanny", 10).must_equal "hootinanny"
13
+ @util.elide("hootinanny", 11).must_equal "hootinanny"
14
+ @util.elide("hootinanny", 9).must_equal "hooti...anny"
15
+ @util.elide("hootinanny", 0).must_equal "hootinanny"
16
+ end
17
+ end
18
+ end
data/test/test_helper.rb CHANGED
@@ -2,13 +2,13 @@ require 'minitest/autorun'
2
2
  require 'rack/mock'
3
3
  require 'rack/test'
4
4
  require 'rack/padlock'
5
-
5
+ require 'rack/padlock/string_util'
6
6
  class MiniTest::Unit::TestCase
7
7
  include Rack::Test::Methods
8
8
 
9
9
  def app; Rack::Lint.new(@app); end
10
10
 
11
- def mock_app(options = {})
11
+ def mock_app
12
12
  main_app = lambda { |env|
13
13
  request = Rack::Request.new(env)
14
14
  headers = {'Content-Type' => "text/html"}
@@ -16,7 +16,7 @@ class MiniTest::Unit::TestCase
16
16
  }
17
17
 
18
18
  builder = Rack::Builder.new
19
- builder.use Rack::Padlock, options
19
+ builder.use Rack::Padlock
20
20
  builder.run main_app
21
21
  @app = builder.to_app
22
22
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rack-padlock
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-02-07 00:00:00.000000000 Z
12
+ date: 2013-02-10 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rack
16
- requirement: &70300117186540 !ruby/object:Gem::Requirement
16
+ requirement: &70095896651180 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70300117186540
24
+ version_requirements: *70095896651180
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: rainbow
27
- requirement: &70300117186000 !ruby/object:Gem::Requirement
27
+ requirement: &70095900907220 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,21 @@ dependencies:
32
32
  version: '0'
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *70300117186000
35
+ version_requirements: *70095900907220
36
+ - !ruby/object:Gem::Dependency
37
+ name: selenium-webdriver
38
+ requirement: &70095900905920 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ type: :runtime
45
+ prerelease: false
46
+ version_requirements: *70095900905920
36
47
  - !ruby/object:Gem::Dependency
37
48
  name: bundler
38
- requirement: &70300117185120 !ruby/object:Gem::Requirement
49
+ requirement: &70095900904820 !ruby/object:Gem::Requirement
39
50
  none: false
40
51
  requirements:
41
52
  - - ! '>='
@@ -43,10 +54,10 @@ dependencies:
43
54
  version: '0'
44
55
  type: :development
45
56
  prerelease: false
46
- version_requirements: *70300117185120
57
+ version_requirements: *70095900904820
47
58
  - !ruby/object:Gem::Dependency
48
59
  name: rake
49
- requirement: &70300117183780 !ruby/object:Gem::Requirement
60
+ requirement: &70095900903940 !ruby/object:Gem::Requirement
50
61
  none: false
51
62
  requirements:
52
63
  - - ! '>='
@@ -54,10 +65,10 @@ dependencies:
54
65
  version: '0'
55
66
  type: :development
56
67
  prerelease: false
57
- version_requirements: *70300117183780
68
+ version_requirements: *70095900903940
58
69
  - !ruby/object:Gem::Dependency
59
70
  name: minitest
60
- requirement: &70300117183120 !ruby/object:Gem::Requirement
71
+ requirement: &70095900903060 !ruby/object:Gem::Requirement
61
72
  none: false
62
73
  requirements:
63
74
  - - ! '>='
@@ -65,10 +76,10 @@ dependencies:
65
76
  version: '0'
66
77
  type: :development
67
78
  prerelease: false
68
- version_requirements: *70300117183120
79
+ version_requirements: *70095900903060
69
80
  - !ruby/object:Gem::Dependency
70
81
  name: rack-test
71
- requirement: &70300117182600 !ruby/object:Gem::Requirement
82
+ requirement: &70095900902260 !ruby/object:Gem::Requirement
72
83
  none: false
73
84
  requirements:
74
85
  - - ! '>='
@@ -76,7 +87,7 @@ dependencies:
76
87
  version: '0'
77
88
  type: :development
78
89
  prerelease: false
79
- version_requirements: *70300117182600
90
+ version_requirements: *70095900902260
80
91
  description: A Gem for testing web applications don't generate mixed secure/insecure
81
92
  traffic. Keep that browser padlock locked!
82
93
  email: joshuacronemeyer@gmail.com
@@ -84,12 +95,18 @@ executables: []
84
95
  extensions: []
85
96
  extra_rdoc_files: []
86
97
  files:
98
+ - lib/rack/padlock/padlock.js
99
+ - lib/rack/padlock/phantomjs.rb
100
+ - lib/rack/padlock/selenium.rb
101
+ - lib/rack/padlock/server.rb
102
+ - lib/rack/padlock/string_util.rb
87
103
  - lib/rack/padlock/version.rb
88
104
  - lib/rack/padlock.rb
89
105
  - lib/rack-padlock.rb
90
106
  - lib/tasks/rack-padlock.rake
91
107
  - README.md
92
108
  - test/rack_padlock_test.rb
109
+ - test/string_util_test.rb
93
110
  - test/test_helper.rb
94
111
  homepage: https://github.com/joshuacronemeyer/rack-padlock
95
112
  licenses: []
@@ -117,4 +134,5 @@ specification_version: 3
117
134
  summary: A Toolkit for writing tests that ensure all traffic on a page is secure.
118
135
  test_files:
119
136
  - test/rack_padlock_test.rb
137
+ - test/string_util_test.rb
120
138
  - test/test_helper.rb