http_observatory 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/Rakefile +34 -0
- data/lib/http_observatory.rb +4 -0
- data/lib/http_observatory/api.rb +47 -0
- data/lib/http_observatory/connection.rb +19 -0
- data/lib/http_observatory/engine.rb +16 -0
- data/lib/http_observatory/models/base.rb +17 -0
- data/lib/http_observatory/models/grade_distribution.rb +16 -0
- data/lib/http_observatory/models/host_history.rb +23 -0
- data/lib/http_observatory/models/recent_scans.rb +15 -0
- data/lib/http_observatory/models/scan.rb +35 -0
- data/lib/http_observatory/models/scanner_states.rb +20 -0
- data/lib/http_observatory/models/test_result.rb +25 -0
- data/lib/http_observatory/request.rb +39 -0
- data/lib/http_observatory/version.rb +3 -0
- data/lib/tasks/http_observatory_tasks.rake +4 -0
- data/test/api_test.rb +21 -0
- data/test/dummy/README.rdoc +28 -0
- data/test/dummy/Rakefile +6 -0
- data/test/dummy/app/assets/javascripts/application.js +13 -0
- data/test/dummy/app/assets/stylesheets/application.css +15 -0
- data/test/dummy/app/controllers/application_controller.rb +5 -0
- data/test/dummy/app/helpers/application_helper.rb +2 -0
- data/test/dummy/app/views/layouts/application.html.erb +14 -0
- data/test/dummy/bin/bundle +3 -0
- data/test/dummy/bin/rails +4 -0
- data/test/dummy/bin/rake +4 -0
- data/test/dummy/bin/setup +29 -0
- data/test/dummy/config.ru +4 -0
- data/test/dummy/config/application.rb +26 -0
- data/test/dummy/config/boot.rb +5 -0
- data/test/dummy/config/database.yml +25 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +41 -0
- data/test/dummy/config/environments/production.rb +79 -0
- data/test/dummy/config/environments/test.rb +42 -0
- data/test/dummy/config/initializers/assets.rb +11 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy/config/initializers/cookies_serializer.rb +3 -0
- data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/test/dummy/config/initializers/inflections.rb +16 -0
- data/test/dummy/config/initializers/mime_types.rb +4 -0
- data/test/dummy/config/initializers/session_store.rb +3 -0
- data/test/dummy/config/initializers/to_time_preserves_timezone.rb +10 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/test/dummy/config/locales/en.yml +23 -0
- data/test/dummy/config/routes.rb +56 -0
- data/test/dummy/config/secrets.yml +22 -0
- data/test/dummy/db/test.sqlite3 +0 -0
- data/test/dummy/log/test.log +360 -0
- data/test/dummy/public/404.html +67 -0
- data/test/dummy/public/422.html +67 -0
- data/test/dummy/public/500.html +66 -0
- data/test/dummy/public/favicon.ico +0 -0
- data/test/http_observatory_test.rb +8 -0
- data/test/test_helper.rb +21 -0
- metadata +196 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 8705f933037bbacf62aeaedbc2ff9780863c7435
|
4
|
+
data.tar.gz: 8bcce65b569a306e0cbe1c19c62fc206534f27e0
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 43842f6bd243c41ab1dd41c8e26df00b6bacd7bc7cbd5cddc672db54762ead8cd966f2a683b92e5a30f207128d931e5d8cc9357ef131ec358e88d868b695840a
|
7
|
+
data.tar.gz: 082eee075dc7aafd81a027d6304588e07acf387a11a3d4dcb64ee61ec08cca5fb76175c90b5b0a9dd78b6356e1bdc69021b765d5960e7f98242b171b717cb98b
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2017 Simon Franzen
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
begin
|
2
|
+
require 'bundler/setup'
|
3
|
+
rescue LoadError
|
4
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
5
|
+
end
|
6
|
+
|
7
|
+
require 'rdoc/task'
|
8
|
+
|
9
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
10
|
+
rdoc.rdoc_dir = 'rdoc'
|
11
|
+
rdoc.title = 'HttpObservatory'
|
12
|
+
rdoc.options << '--line-numbers'
|
13
|
+
rdoc.rdoc_files.include('README.rdoc')
|
14
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
15
|
+
end
|
16
|
+
|
17
|
+
|
18
|
+
|
19
|
+
|
20
|
+
|
21
|
+
|
22
|
+
Bundler::GemHelper.install_tasks
|
23
|
+
|
24
|
+
require 'rake/testtask'
|
25
|
+
|
26
|
+
Rake::TestTask.new(:test) do |t|
|
27
|
+
t.libs << 'lib'
|
28
|
+
t.libs << 'test'
|
29
|
+
t.pattern = 'test/**/*_test.rb'
|
30
|
+
t.verbose = false
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
task default: :test
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module HttpObservatory
|
2
|
+
#
|
3
|
+
# Api for application
|
4
|
+
#
|
5
|
+
class Api
|
6
|
+
class << self
|
7
|
+
|
8
|
+
def get_analyze(host)
|
9
|
+
response = Request.get('analyze', { 'host' => host })
|
10
|
+
Scan.new(response)
|
11
|
+
end
|
12
|
+
|
13
|
+
def post_analyze(host, params={})
|
14
|
+
response = Request.post('analyze', { 'host' => host, 'hidden' => params[:hidden], 'rescan' => params[:rescan] })
|
15
|
+
Scan.new(response)
|
16
|
+
end
|
17
|
+
|
18
|
+
def get_scan_results(scan_id)
|
19
|
+
response = Request.get("getScanResults", { 'scan' => scan_id })
|
20
|
+
response.keys.map{|key| TestResult.new(response[key]) }
|
21
|
+
end
|
22
|
+
|
23
|
+
def get_recent_scans(params={})
|
24
|
+
params[:min] = params[:min] ? params[:min] : 0
|
25
|
+
params[:max] = params[:max] ? params[:max] : 20
|
26
|
+
response = Request.get('getRecentScans', { min: params[:min], max: params[:max] })
|
27
|
+
RecentScans.new(response)
|
28
|
+
end
|
29
|
+
|
30
|
+
def get_host_history(host)
|
31
|
+
response = Request.get("getHostHistory", { 'host' => host })
|
32
|
+
response.map{|history| HostHistory.new(history) }
|
33
|
+
end
|
34
|
+
|
35
|
+
def get_grade_distribution
|
36
|
+
response = Request.get('getGradeDistribution')
|
37
|
+
GradeDistribution.new(response)
|
38
|
+
end
|
39
|
+
|
40
|
+
def get_scanner_states
|
41
|
+
response = Request.get('getScannerStates')
|
42
|
+
ScannerStates.new(response)
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'faraday'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
module HttpObservatory
|
5
|
+
#
|
6
|
+
# See https://github.com/mozilla/http-observatory/blob/master/httpobs/docs/api.md
|
7
|
+
#
|
8
|
+
class Connection
|
9
|
+
BASE = 'https://http-observatory.security.mozilla.org/api/v1'
|
10
|
+
|
11
|
+
def self.api
|
12
|
+
Faraday.new(url: BASE) do |faraday|
|
13
|
+
faraday.response :logger
|
14
|
+
faraday.adapter Faraday.default_adapter
|
15
|
+
faraday.headers['Content-Type'] = 'application/json'
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require "http_observatory/models/base"
|
2
|
+
require "http_observatory/models/grade_distribution"
|
3
|
+
require "http_observatory/models/host_history"
|
4
|
+
require "http_observatory/models/recent_scans"
|
5
|
+
require "http_observatory/models/scan"
|
6
|
+
require "http_observatory/models/test_result"
|
7
|
+
require "http_observatory/models/scanner_states"
|
8
|
+
require "http_observatory/connection"
|
9
|
+
require "http_observatory/request"
|
10
|
+
require "http_observatory/api"
|
11
|
+
|
12
|
+
module HttpObservatory
|
13
|
+
class Engine < ::Rails::Engine
|
14
|
+
isolate_namespace HttpObservatory
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module HttpObservatory
|
2
|
+
|
3
|
+
#
|
4
|
+
# Base Class for API objects
|
5
|
+
#
|
6
|
+
class Base
|
7
|
+
attr_accessor :errors
|
8
|
+
|
9
|
+
def initialize(args = {})
|
10
|
+
args.each do |name, value|
|
11
|
+
attr_name = name.to_s.downcase.underscore
|
12
|
+
send("#{attr_name}=", value) if respond_to?("#{attr_name}=")
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module HttpObservatory
|
2
|
+
|
3
|
+
#
|
4
|
+
# Host History Object
|
5
|
+
#
|
6
|
+
# https://github.com/mozilla/http-observatory/blob/master/httpobs/docs/api.md#grade-distribution
|
7
|
+
#
|
8
|
+
class GradeDistribution < Base
|
9
|
+
attr_accessor :distribution
|
10
|
+
|
11
|
+
def initialize(args = {})
|
12
|
+
self.distribution = args
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module HttpObservatory
|
2
|
+
|
3
|
+
#
|
4
|
+
# Host History Object
|
5
|
+
#
|
6
|
+
# https://github.com/mozilla/http-observatory/blob/master/httpobs/docs/api.md#host-history
|
7
|
+
#
|
8
|
+
class HostHistory < Base
|
9
|
+
|
10
|
+
attr_accessor :end_time,
|
11
|
+
:end_time_unix_timestamp,
|
12
|
+
:grade,
|
13
|
+
:scan_id,
|
14
|
+
:score
|
15
|
+
|
16
|
+
# def initialize(args = {})
|
17
|
+
# super(args)
|
18
|
+
# end
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
|
23
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module HttpObservatory
|
2
|
+
#
|
3
|
+
# Recent Scans Object
|
4
|
+
#
|
5
|
+
# https://github.com/mozilla/http-observatory/blob/master/httpobs/docs/api.md#recent-scans
|
6
|
+
#
|
7
|
+
class RecentScans < Base
|
8
|
+
attr_accessor :results
|
9
|
+
|
10
|
+
def initialize(args = {})
|
11
|
+
self.results = args
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module HttpObservatory
|
2
|
+
|
3
|
+
#
|
4
|
+
# Scan Object
|
5
|
+
#
|
6
|
+
# https://github.com/mozilla/http-observatory/blob/master/httpobs/docs/api.md#scan
|
7
|
+
#
|
8
|
+
# The scan can exist in one of six states:
|
9
|
+
# * ABORTED aborted for internal technical reasons
|
10
|
+
# * FAILED failed to complete, typically due to the site being unavailable or timing out
|
11
|
+
# * FINISHED completed successfully
|
12
|
+
# * PENDING issued by the API but not yet picked up by a scanner instance
|
13
|
+
# * STARTING assigned to a scanning instance
|
14
|
+
# * RUNNING currently in the process of scanning a website
|
15
|
+
|
16
|
+
class Scan < Base
|
17
|
+
attr_accessor :end_time, # timestamp for when the scan completed
|
18
|
+
:grade, # final grade assessed upon a completed scan
|
19
|
+
:hidden, # whether the scan results are unlisted on the recent results page
|
20
|
+
:response_headers, # the entirety of the HTTP response headers
|
21
|
+
:likelihood_indicator, # Mozilla risk likelihod indicator that is the equivalent of the grade
|
22
|
+
:scan_id, # unique ID number assigned to the scan
|
23
|
+
:score, # final score assessed upon a completed (FINISHED) scan
|
24
|
+
:start_time, # timestamp for when the scan was first requested
|
25
|
+
:state, # the current state of the scan
|
26
|
+
:tests_failed, # the number of subtests that were assigned a fail result
|
27
|
+
:tests_passed, # the number of subtests that were assigned a passing result
|
28
|
+
:tests_quantity # the total number of tests available and assessed at the time of the scan
|
29
|
+
|
30
|
+
# def initialize(args = {})
|
31
|
+
# super(args)
|
32
|
+
# end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module HttpObservatory
|
2
|
+
#
|
3
|
+
# Scanner State
|
4
|
+
#
|
5
|
+
# https://github.com/mozilla/http-observatory/blob/master/httpobs/docs/api.md#scanner-state
|
6
|
+
#
|
7
|
+
class ScannerStates < Base
|
8
|
+
|
9
|
+
attr_accessor :aborted, # aborted for internal technical reasons
|
10
|
+
:failed, # failed to complete, typically due to the site being unavailable or timing out
|
11
|
+
:finished, # completed successfully
|
12
|
+
:pending, # issued by the API but not yet picked up by a scanner instance
|
13
|
+
:starting, # assigned to a scanning instance
|
14
|
+
:running # currently in the process of scanning a website
|
15
|
+
|
16
|
+
# def initialize(args = {})
|
17
|
+
# super(args)
|
18
|
+
# end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module HttpObservatory
|
2
|
+
#
|
3
|
+
# Scan Object
|
4
|
+
#
|
5
|
+
# https://github.com/mozilla/http-observatory/blob/master/httpobs/docs/api.md#tests
|
6
|
+
#
|
7
|
+
class TestResult < Base
|
8
|
+
|
9
|
+
attr_accessor :expectation, # the expectation for a test result going in
|
10
|
+
:name, # the name of the test; this should be the same as the parent object's name
|
11
|
+
:output, # artifacts related to the test; these can vary widely between tests and are not guaranteed to be stable
|
12
|
+
:pass, # whether the test passed or failed; a test that meets or exceeds the expectation will be marked as passed
|
13
|
+
:result, # result of the test
|
14
|
+
:score_description, # short description describing what result means
|
15
|
+
:score_modifier # how much the result of the test affected the final score; should range between +5 and -50
|
16
|
+
|
17
|
+
# output data
|
18
|
+
# data generally as close to the raw output of the test as is possible. For example, in the strict-transport-security test, output -> data contains the raw Strict-Transport-Security header
|
19
|
+
# ???? other values under output have keys that vary; for example, the strict-transport-security test has a includeSubDomains key that is either set to True or False. Similarly, the redirection test contains a route key that contains an array of the URLs that were redirected to. See example below for more available keys.
|
20
|
+
|
21
|
+
# def initialize(args = {})
|
22
|
+
# super(args)
|
23
|
+
# end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module HttpObservatory
|
2
|
+
|
3
|
+
class Request
|
4
|
+
class << self
|
5
|
+
|
6
|
+
def get(path, query = {})
|
7
|
+
response, status = get_json(path, query)
|
8
|
+
status == 200 ? response : errors(response)
|
9
|
+
end
|
10
|
+
|
11
|
+
def post(path, query)
|
12
|
+
response, status = post_json(path, query)
|
13
|
+
status == 201 ? response : errors(response)
|
14
|
+
end
|
15
|
+
|
16
|
+
def errors(response)
|
17
|
+
error = { errors: { status: response["status"], message: response["message"] } }
|
18
|
+
response.merge(error)
|
19
|
+
end
|
20
|
+
|
21
|
+
def get_json(root_path, query = {})
|
22
|
+
query_string = query.map{|k,v| "#{k}=#{v}"}.join("&")
|
23
|
+
response = api.get("#{root_path}?#{query_string}")
|
24
|
+
[JSON.parse(response.body), response.status]
|
25
|
+
end
|
26
|
+
|
27
|
+
def post_json(root_path, query = {})
|
28
|
+
query_string = query.map{|k,v| "#{k}=#{v}"}.join("&")
|
29
|
+
response = api.post("#{root_path}?#{query_string}")
|
30
|
+
[JSON.parse(response.body), response.status]
|
31
|
+
end
|
32
|
+
|
33
|
+
def api
|
34
|
+
Connection.api
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
data/test/api_test.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class ApiTest < ActiveSupport::TestCase
|
4
|
+
|
5
|
+
# just a test if requests are working
|
6
|
+
setup do
|
7
|
+
WebMock.stub_request(:any, /api\/v1/).to_return(body: {}.to_json, status: 200,
|
8
|
+
headers: { 'Content-Length' => 3 })
|
9
|
+
end
|
10
|
+
|
11
|
+
test 'api_text' do
|
12
|
+
HttpObservatory::Api.get_analyze('www.zauberware.com')
|
13
|
+
HttpObservatory::Api.post_analyze('www.zauberware.com')
|
14
|
+
HttpObservatory::Api.get_scan_results(123123123)
|
15
|
+
HttpObservatory::Api.get_host_history('www.zauberware.com')
|
16
|
+
HttpObservatory::Api.get_recent_scans
|
17
|
+
HttpObservatory::Api.get_grade_distribution
|
18
|
+
HttpObservatory::Api.get_scanner_states
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
== README
|
2
|
+
|
3
|
+
This README would normally document whatever steps are necessary to get the
|
4
|
+
application up and running.
|
5
|
+
|
6
|
+
Things you may want to cover:
|
7
|
+
|
8
|
+
* Ruby version
|
9
|
+
|
10
|
+
* System dependencies
|
11
|
+
|
12
|
+
* Configuration
|
13
|
+
|
14
|
+
* Database creation
|
15
|
+
|
16
|
+
* Database initialization
|
17
|
+
|
18
|
+
* How to run the test suite
|
19
|
+
|
20
|
+
* Services (job queues, cache servers, search engines, etc.)
|
21
|
+
|
22
|
+
* Deployment instructions
|
23
|
+
|
24
|
+
* ...
|
25
|
+
|
26
|
+
|
27
|
+
Please feel free to use a different markup language if you do not plan to run
|
28
|
+
<tt>rake doc:app</tt>.
|
data/test/dummy/Rakefile
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
// This is a manifest file that'll be compiled into application.js, which will include all the files
|
2
|
+
// listed below.
|
3
|
+
//
|
4
|
+
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
|
5
|
+
// or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path.
|
6
|
+
//
|
7
|
+
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
|
8
|
+
// compiled file.
|
9
|
+
//
|
10
|
+
// Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details
|
11
|
+
// about supported directives.
|
12
|
+
//
|
13
|
+
//= require_tree .
|