ssh_scan_api 0.0.1.pre2 → 0.0.1

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
- SHA1:
3
- metadata.gz: 9e017981463ad9f0f6b8603541368d0cbbc21824
4
- data.tar.gz: 640d3e218c081b0bd08c4dba5ecc722b14831d6e
2
+ SHA256:
3
+ metadata.gz: 986e1fa32154fb3713c610f3339be18b71a9d4fa2306f7eebd7b427ebd0dc737
4
+ data.tar.gz: 785a82839c62ffe80e18576c6d0dbc47c1690c387f2f338ee32314b727cf8b02
5
5
  SHA512:
6
- metadata.gz: 09771fd4bed338ff605c8c499a9e7fc6b762e01793cc87ff050b53a58f13a90c2760681b919a4fc704ca0021d1d8d534ddf3d4ea64183290fbb7dc3eb51b62fa
7
- data.tar.gz: 8b21030f47a494ba2ae680de04f42916b3222a46ae9a4f41f1ca0a567bf4ed5fdcb401026648496d54438c7f522195c6d8c61db4d2721fccea0bdd82dd590789
6
+ metadata.gz: 2bf3fe77b3a2b3f3e9e9c4a0ad33ff5480712926a44eb546026d0cc91bdfa52350817dc9c238f4c379d3cba0ecf9e07070d7837ada598d1b1c9a216ff4aec869
7
+ data.tar.gz: 61a0ec0dfd5ad4bee3d548aea9a061d67d09f6f03bf14a05f0e720dc9ef96cc5c897c2e08a35a690c5923ce8857d7081b28783330a8f9548fcff40891d4a50f8
data/.gitignore CHANGED
@@ -2,6 +2,11 @@
2
2
  *.db
3
3
  /coverage/
4
4
 
5
+ config/api/config.yml
6
+ config/policies/mozilla_modern.yml
7
+ config/worker/config.yml
8
+ postgres-data/*
9
+
5
10
  ## Documentation cache and generated files:
6
11
  /.yardoc/
7
12
  /_yardoc/
@@ -16,8 +21,8 @@
16
21
  # for a library or gem, you might want to ignore these files since the code is
17
22
  # intended to run in multiple environments; otherwise, check them in:
18
23
  Gemfile.lock
19
- # .ruby-version
20
- # .ruby-gemset
24
+ .ruby-version
25
+ .ruby-gemset
21
26
 
22
27
  # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
23
28
  .rvmrc
@@ -1,30 +1,77 @@
1
1
  language: ruby
2
+ sudo: false
3
+ dist: trusty
4
+ before_install: gem update --system
5
+ addons:
6
+ postgresql: "9.6"
2
7
  matrix:
3
8
  include:
4
9
  - rvm: ruby-head
5
10
  env:
6
11
  - LABEL=unit_tests
12
+ - SSHSCAN_API_HOST=127.0.0.1
13
+ - SSHSCAN_API_PORT=8000
14
+ - SSHSCAN_API_ALLOWED_PORTS=22
15
+ - SSHSCAN_API_AUTHENTICATION=false
16
+ - SSHSCAN_DATABASE_HOST=database
17
+ - SSHSCAN_DATABASE_NAME=ssh_observatory
18
+ - SSHSCAN_DATABASE_USERNAME=sshobs
7
19
  services:
8
- - mongodb
20
+ - postgres
21
+ before_script:
22
+ - chmod u+x database/init-user-db-travis.sh
23
+ - database/init-user-db-travis.sh
9
24
  after_success:
10
25
  - coveralls
11
- - rvm: 2.3.0
26
+ - rvm: 2.5.0
12
27
  env:
13
28
  - LABEL=unit_tests
29
+ - SSHSCAN_API_HOST=127.0.0.1
30
+ - SSHSCAN_API_PORT=8000
31
+ - SSHSCAN_API_ALLOWED_PORTS=22
32
+ - SSHSCAN_API_AUTHENTICATION=false
33
+ - SSHSCAN_DATABASE_HOST=database
34
+ - SSHSCAN_DATABASE_NAME=ssh_observatory
35
+ - SSHSCAN_DATABASE_USERNAME=sshobs
14
36
  services:
15
- - mongodb
16
- - rvm: 2.2.0
37
+ - postgres
38
+ before_script:
39
+ - chmod u+x database/init-user-db-travis.sh
40
+ - database/init-user-db-travis.sh
41
+ - rvm: 2.3.6
17
42
  env:
18
43
  - LABEL=unit_tests
44
+ - SSHSCAN_API_HOST=127.0.0.1
45
+ - SSHSCAN_API_PORT=8000
46
+ - SSHSCAN_API_ALLOWED_PORTS=22
47
+ - SSHSCAN_API_AUTHENTICATION=false
48
+ - SSHSCAN_DATABASE_HOST=database
49
+ - SSHSCAN_DATABASE_NAME=ssh_observatory
50
+ - SSHSCAN_DATABASE_USERNAME=sshobs
19
51
  services:
20
- - mongodb
21
- - rvm: 2.1.3
52
+ - postgres
53
+ before_script:
54
+ - chmod u+x database/init-user-db-travis.sh
55
+ - database/init-user-db-travis.sh
56
+ - rvm: 2.2.9
22
57
  env:
58
+ - SSHSCAN_API_HOST=127.0.0.1
59
+ - SSHSCAN_API_PORT=8000
60
+ - SSHSCAN_API_ALLOWED_PORTS=22
61
+ - SSHSCAN_API_AUTHENTICATION=false
62
+ - SSHSCAN_DATABASE_HOST=database
63
+ - SSHSCAN_DATABASE_NAME=ssh_observatory
64
+ - SSHSCAN_DATABASE_USERNAME=sshobs
23
65
  - LABEL=unit_tests
24
66
  services:
25
- - mongodb
26
- - rvm: 2.0.0
67
+ - postgres
68
+ before_script:
69
+ - chmod u+x database/init-user-db-travis.sh
70
+ - database/init-user-db-travis.sh
71
+ - rvm: 2.5.0
27
72
  env:
28
- - LABEL=unit_tests
73
+ - LABEL=docker_build_tests
29
74
  services:
30
- - mongodb
75
+ - docker
76
+ script:
77
+ - docker-compose build
data/Gemfile CHANGED
@@ -1,4 +1,3 @@
1
1
  source "https://rubygems.org"
2
2
 
3
- gem 'coveralls', require: false
4
- gemspec
3
+ gemspec
data/README.md CHANGED
@@ -1,16 +1,15 @@
1
1
  # ssh_scan_api
2
2
 
3
+ [![Build Status](https://secure.travis-ci.org/mozilla/ssh_scan_api.png)](http://travis-ci.org/mozilla/ssh_scan_api)
4
+ [![Code Climate](https://codeclimate.com/github/mozilla/ssh_scan_api.png)](https://codeclimate.com/github/mozilla/ssh_scan_api)
5
+ [![Gem Version](https://badge.fury.io/rb/ssh_scan.svg)](https://badge.fury.io/rb/ssh_scan_api)
6
+ [![Join the chat at https://gitter.im/mozilla-ssh_scan/Lobby](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/mozilla-ssh_scan/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
7
+ [![Coverage Status](https://coveralls.io/repos/github/mozilla/ssh_scan_api/badge.svg?branch=master)](https://coveralls.io/github/mozilla/ssh_scan_api?branch=master)
8
+
3
9
  A web api to scale ssh_scan operations
4
10
 
5
11
  ## Setup
6
12
 
7
- To install and run as a gem, type:
8
-
9
- ```bash
10
- gem install ssh_scan_api
11
- ssh_scan_api
12
- ```
13
-
14
13
  To install and run from source, type:
15
14
 
16
15
  ```bash
@@ -35,18 +34,17 @@ bundle install
35
34
  ./bin/ssh_scan_api
36
35
  ```
37
36
 
38
- ## Rubies Supported
37
+ ## ssh_scan as a command-line tool?
38
+
39
+ This project is focused on providing ssh_scan as a service/API.
39
40
 
40
- This project is integrated with [travis-ci](http://about.travis-ci.org/) and is regularly tested to work with the following rubies:
41
+ If you would like to run ssh_scan from command-line, checkout the [ssh_scan](https://github.com/mozilla/ssh_scan) project.
42
+
43
+ ## Rubies Supported
41
44
 
42
- * [ruby-head](https://github.com/ruby/ruby)
43
- * [2.3.0](https://github.com/ruby/ruby/tree/ruby_2_1)
44
- * [2.2.0](https://github.com/ruby/ruby/tree/ruby_2_1)
45
- * [2.1.3](https://github.com/ruby/ruby/tree/ruby_2_1)
46
- * [2.1.0](https://github.com/ruby/ruby/tree/ruby_2_1)
47
- * [2.0.0](https://github.com/ruby/ruby/tree/ruby_2_0_0)
45
+ This project is integrated with [travis-ci](http://about.travis-ci.org/) and is regularly tested to work with multiple rubies.
48
46
 
49
- To checkout the current build status for these rubies, click [here](https://travis-ci.org/#!/mozilla/ssh_scan).
47
+ To checkout the current build status for these rubies, click [here](https://travis-ci.org/#!/mozilla/ssh_scan_api).
50
48
 
51
49
  ## Contributing
52
50
 
data/Rakefile CHANGED
@@ -5,7 +5,13 @@ require 'rspec'
5
5
  require 'rspec/core'
6
6
  require 'rspec/core/rake_task'
7
7
  require 'bundler/setup'
8
- require 'ssh_scan_api/version'
8
+ require "sinatra/activerecord/rake"
9
+
10
+ namespace :db do
11
+ task :load_config do
12
+ require "./lib/ssh_scan_api/api"
13
+ end
14
+ end
9
15
 
10
16
  $:.unshift File.join(File.dirname(__FILE__), "lib")
11
17
 
@@ -1,16 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
-
3
2
  $:.unshift File.join(File.dirname(__FILE__), "../lib")
4
-
5
3
  require 'ssh_scan_api'
6
4
 
7
- # Get the api config from command-line or via an example location
8
- config_file = ARGV[0] ||
9
- File.join(
10
- File.dirname(__FILE__),
11
- "../config/api/config.yml"
12
- )
13
- opts = YAML.load_file(config_file)
14
- opts["config_file"] = config_file
15
-
16
- SSHScan::API.run!(opts)
5
+ # Usage: ruby ./bin/ssh_scan_api
6
+ SSHScan::Api::Api.run!()
@@ -1,12 +1,11 @@
1
- #External Deps
1
+ # #External Deps
2
2
  require 'timeout'
3
3
  require 'resolv'
4
4
  require 'ssh_scan'
5
5
 
6
- #Internal Deps
7
- require 'ssh_scan_api/api'
6
+ # #Internal Deps
8
7
  require 'ssh_scan_api/version'
9
- require 'ssh_scan_api/job_queue'
10
- require 'ssh_scan_api/database'
11
- require 'ssh_scan_api/stats'
12
- require 'ssh_scan_api/authenticator'
8
+ require 'ssh_scan_api/api'
9
+ require 'ssh_scan_api/authenticator'
10
+ require 'ssh_scan_api/target_validator'
11
+ require 'ssh_scan_api/constants'
@@ -1,231 +1,296 @@
1
- require 'sinatra/base'
1
+ require 'sinatra'
2
+ require 'sinatra/activerecord'
2
3
  require 'sinatra/namespace'
3
- require 'json'
4
- require 'haml'
5
- require 'secure_headers'
6
- require 'thin'
7
4
  require 'securerandom'
8
- require 'ssh_scan'
9
- require 'ssh_scan_api/job_queue'
10
- require 'ssh_scan_api/database'
5
+ require 'secure_headers'
6
+ require 'ssh_scan_api/models/scan'
7
+ require 'ssh_scan_api/target_validator'
8
+ require 'ssh_scan_api/authenticator'
9
+ require 'pg'
11
10
 
12
11
  module SSHScan
13
- class API < Sinatra::Base
14
- if ENV['RACK_ENV'] == 'test'
15
- configure do
16
- set :job_queue, SSHScan::JobQueue.new()
17
- set :authentication, false
18
- config_file = File.join(Dir.pwd, "./config/api/config.yml")
19
- opts = YAML.load_file(config_file)
20
- opts["config_file"] = config_file
21
- set :db, SSHScan::Database.from_hash(opts)
12
+ module Api
13
+
14
+ class Api < Sinatra::Base
15
+ if ENV['RACK_ENV'] == 'test'
16
+ configure do
17
+ set :database_file, "lib/config/database.yml"
18
+ set :authentication, false
19
+ set :authenticator, SSHScan::Api::Authenticator.new()
20
+ set :target_validator, SSHScan::Api::TargetValidator.new()
21
+ set :allowed_ports, 22
22
+ set :protection, false
23
+ end
22
24
  end
23
- end
24
25
 
25
- # Configure all the secure headers we want to use
26
- use SecureHeaders::Middleware
27
- SecureHeaders::Configuration.default do |config|
28
- config.cookies = {
29
- secure: true, # mark all cookies as "Secure"
30
- httponly: true, # mark all cookies as "HttpOnly"
31
- }
32
- config.hsts = "max-age=31536000; includeSubdomains; preload"
33
- config.x_frame_options = "DENY"
34
- config.x_content_type_options = "nosniff"
35
- config.x_xss_protection = "1; mode=block"
36
- config.x_download_options = "noopen"
37
- config.x_permitted_cross_domain_policies = "none"
38
- config.referrer_policy = "no-referrer"
39
- config.csp = {
40
- default_src: ["'none'"],
41
- frame_ancestors: ["'none'"],
42
- upgrade_insecure_requests: true, # see https://www.w3.org/TR/upgrade-insecure-requests/
43
- }
44
- end
26
+ include SSHScan
27
+ register Sinatra::Namespace
28
+ register Sinatra::ActiveRecordExtension
45
29
 
46
- register Sinatra::Namespace
30
+ before do
31
+ content_type :json
32
+ end
47
33
 
48
- before do
49
- headers "Server" => "ssh_scan_api"
50
- headers "Cache-control" => "no-store"
51
- headers "Pragma" => "no-cache"
52
- end
34
+ # Configure all the secure headers we want to use
35
+ use SecureHeaders::Middleware
36
+ SecureHeaders::Configuration.default do |config|
37
+ config.cookies = {
38
+ secure: true, # mark all cookies as "Secure"
39
+ httponly: true, # mark all cookies as "HttpOnly"
40
+ }
41
+ config.hsts = "max-age=31536000; includeSubdomains; preload"
42
+ config.x_frame_options = "DENY"
43
+ config.x_content_type_options = "nosniff"
44
+ config.x_xss_protection = "1; mode=block"
45
+ config.x_download_options = "noopen"
46
+ config.x_permitted_cross_domain_policies = "none"
47
+ config.referrer_policy = "no-referrer"
48
+ config.csp = {
49
+ default_src: ["'none'"],
50
+ script_src: ["'none'"],
51
+ frame_ancestors: ["'none'"],
52
+ upgrade_insecure_requests: true, # see https://www.w3.org/TR/upgrade-insecure-requests/
53
+ }
54
+ end
53
55
 
54
- helpers do
55
- def cache_valid?(start_time)
56
- (Time.now - Time.parse(start_time.to_s)) / (60 * 60 * 24) < 1
56
+ before do
57
+ headers "Access-Control-Allow-Methods" => "GET, POST"
58
+ headers "Access-Control-Allow-Origin" => "*"
59
+ headers "Access-Control-Max-Age" => "86400"
60
+ headers "Cache-control" => "no-store"
61
+ headers "Pragma" => "no-cache"
62
+ headers "Server" => "ssh_scan_api"
57
63
  end
58
- end
59
64
 
60
- # Custom 404 handling
61
- not_found do
62
- content_type "text/plain"
63
- "Invalid request, see API documentation here: \
64
- https://github.com/mozilla/ssh_scan_api/wiki/ssh_scan-Web-API\n"
65
- end
65
+ # Custom 404 handling
66
+ not_found do
67
+ content_type "text/plain"
68
+ "Invalid request, see API documentation here: https://github.com/mozilla/ssh_scan_api/wiki/ssh_scan-Web-API\n"
69
+ end
66
70
 
67
- get '/' do
68
- content_type "text/plain"
69
- "See API documentation here: \
70
- https://github.com/mozilla/ssh_scan_api/wiki/ssh_scan-Web-API\n"
71
- end
71
+ get '/' do
72
+ content_type "text/plain"
73
+ "See API documentation here: https://github.com/mozilla/ssh_scan_api/wiki/ssh_scan-Web-API\n"
74
+ end
72
75
 
73
- get '/robots.txt' do
74
- content_type "text/plain"
75
- "User-agent: *\nDisallow: /\n"
76
- end
76
+ get '/robots.txt' do
77
+ content_type "text/plain"
78
+ "User-agent: *\nDisallow: /\n"
79
+ end
77
80
 
78
- get '/contribute.json' do
79
- content_type :json
80
- SSHScan::Constants::CONTRIBUTE_JSON.to_json
81
- end
81
+ get '/contribute.json' do
82
+ content_type :json
83
+ SSHScan::Api::Constants::CONTRIBUTE_JSON.to_json
84
+ end
82
85
 
83
- get '/__version__' do
84
- {
85
- :ssh_scan_version => SSHScan::VERSION,
86
- :api_version => SSHScan::API_VERSION,
87
- }.to_json
88
- end
86
+ get '/__version__' do
87
+ {
88
+ :api_version => SSHScan::Api::VERSION,
89
+ }.to_json
90
+ end
89
91
 
90
- namespace "/api/v1" do
91
- before do
92
- content_type :json
93
- if settings.authentication == true
94
- token = request.env['HTTP_SSH_SCAN_AUTH_TOKEN']
92
+ namespace "/api/v1" do
95
93
 
96
- # If a token is not provided, only localhost can proceed
97
- if token.nil? && request.ip != "127.0.0.1"
98
- halt '{"error" : "authentication failure"}'
94
+ post '/scan' do
95
+ port = params["port"] || 22
96
+
97
+ # Check to see if there is a recent scan we offer
98
+ begin
99
+ latest_scan = Scan.where(["target = ? and port = ?", params["target"], port]).last
100
+
101
+ # Return prior scan results if run within 2min of now
102
+ if latest_scan && (Time.now - latest_scan.creation_time < 120)
103
+ return {"uuid": latest_scan.scan_id}.to_json
104
+ end
105
+ rescue
106
+ ActiveRecord::Base.connection_pool.release_connection
99
107
  end
100
108
 
101
- # If a token is provided, it must be valid to proceed
102
- if token && settings.authenticator.valid_token?(token) == false
103
- halt '{"error" : "authentication failure"}'
109
+ # Perform a new scan
110
+ begin
111
+ scan = Scan.new do |s|
112
+ s.scan_id = SecureRandom.uuid
113
+ s.creation_time = Time.now
114
+ s.target = params["target"]
115
+ s.port = port
116
+ s.state = "QUEUED"
117
+ s.save
118
+ end
119
+ ensure
120
+ ActiveRecord::Base.connection_pool.release_connection
104
121
  end
122
+
123
+ return {"uuid": scan.scan_id}.to_json
105
124
  end
106
- end
107
125
 
108
- post '/scan' do
109
- options = {
110
- :sockets => [],
111
- :policy => File.join(Dir.pwd,
112
- '/config/policies/mozilla_modern.yml'),
113
- :timeout => 2,
114
- :verbosity => nil,
115
- #:fingerprint_database => "fingerprints.db",
116
- }
117
- options[:sockets] <<
118
- "#{params[:target]}:#{params[:port] ? params[:port] : "22"}"
119
- options[:policy_file] = options[:policy]
120
- options[:force] = params[:force] ? params[:force] : false
121
-
122
- unless options[:force] == 'true'
123
- available_result = settings.db.fetch_cached_result(params)
124
- unless available_result.nil?
125
- if cache_valid?(available_result[:start_time])
126
- return {
127
- uuid: available_result[:uuid]
128
- }.to_json
126
+ get '/scan/results' do
127
+ uuid = params[:uuid]
128
+
129
+ # If we don't get a uuid, we don't know what scan to pick up
130
+ return {"error" => "no uuid specified"}.to_json if uuid.nil? || uuid.empty?
131
+
132
+ begin
133
+ scan = Scan.find_by("scan_id": uuid)
134
+
135
+ if scan.nil?
136
+ return {"scan" => "UNKNOWN"}.to_json
137
+ end
138
+
139
+ case scan.state
140
+ when "QUEUED"
141
+ return {"status" => "QUEUED"}.to_json
142
+ when "ERRORED"
143
+ return {"status" => "ERRORED"}.to_json
144
+ when "RUNNNING"
145
+ return {"status" => "RUNNNING"}.to_json
146
+ when "COMPLETED"
147
+ return scan.raw_scan
148
+ else
149
+ return {"status" => "UNKNOWN"}.to_json
129
150
  end
151
+ ensure
152
+ ActiveRecord::Base.connection_pool.release_connection
130
153
  end
131
154
  end
132
- options[:uuid] = SecureRandom.uuid
133
- settings.job_queue.add(options)
134
- {
135
- uuid: options[:uuid]
136
- }.to_json
137
- end
138
155
 
139
- get '/scan/results' do
140
- uuid = params[:uuid]
141
- return {"scan" => "not found"}.to_json if uuid.nil? || uuid.empty?
142
- result = settings.db.find_scan_result(uuid)
143
- return {"scan" => "not found"}.to_json if result.nil?
144
- return result.to_json
145
- end
156
+ get '/work' do
157
+ # Always require authentication for this route
158
+ #authenticated?
159
+
160
+ worker_id = params[:worker_id]
146
161
 
147
- post '/scan/results/delete' do
148
- uuid = params[:uuid]
162
+ #uuid = settings.db.next_scan_in_queue
163
+ scan = SSHScan::Scan.find_by("state": "QUEUED")
149
164
 
150
- if uuid.nil? || uuid.empty?
151
- return {"deleted" => "false"}.to_json
152
- else
153
- scan = settings.db.find_scan_result(uuid)
154
- if scan.empty?
155
- return {"deleted" => "false"}.to_json
165
+ if scan
166
+ scan.state = "RUNNING"
167
+ scan.worker_id = worker_id
168
+ scan.save
169
+
170
+ return {
171
+ "work" => {
172
+ "uuid" => scan.scan_id,
173
+ "target" => scan.target,
174
+ "port" => scan.port,
175
+ }
176
+ }.to_json
156
177
  else
157
- settings.db.delete_scan(uuid)
158
- return {"deleted" => "true"}.to_json
178
+ return {"work" => false}.to_json
159
179
  end
160
180
  end
161
- end
162
181
 
163
- get '/scan/results/delete/all' do
164
- settings.db.delete_all
165
- end
182
+ post '/work/results/:worker_id/:uuid' do
183
+ # Always require authentication for this route
184
+ #authenticated?
185
+
186
+ worker_id = params[:worker_id]
187
+ uuid = params[:uuid]
188
+ result = JSON.parse(request.body.first).first
189
+
190
+ if worker_id.empty? || uuid.empty?
191
+ return {"accepted" => "false"}.to_json
192
+ end
193
+
194
+ begin
195
+ scan = Scan.find_by("scan_id": uuid)
196
+
197
+ # Make sure we have a relevant match scan
198
+ return {"accepted" => "false"}.to_json unless scan
199
+
200
+ if result["error"]
201
+ scan.state = "ERRORED"
202
+ scan.worker_id = worker_id
203
+ scan.raw_scan = result.to_json
204
+ scan.save
205
+ else
206
+ scan.state = "COMPLETED"
207
+ scan.worker_id = worker_id
208
+ scan.raw_scan = result.to_json
209
+ scan.save
210
+ end
211
+ ensure
212
+ ActiveRecord::Base.connection_pool.release_connection
213
+ end
166
214
 
167
- get '/work' do
168
- worker_id = params[:worker_id]
169
- logger.warn("Worker #{worker_id} polls for Job")
170
- job = settings.job_queue.next
171
- if job.nil?
172
- logger.warn("Worker #{worker_id} didn't get any work")
173
- {"work" => false}.to_json
174
- else
175
- logger.warn("Worker #{worker_id} got job #{job[:uuid]}")
176
- {"work" => job}.to_json
215
+ return {"accepted" => "true"}
177
216
  end
178
- end
179
217
 
180
- post '/work/results/:worker_id/:uuid' do
181
- worker_id = params['worker_id']
182
- uuid = params['uuid']
183
- result = JSON.parse(request.body.first).first
184
- socket = {}
185
- socket[:target] = result['ip']
186
- socket[:port] = result['port']
218
+ get '/stats' do
219
+ queued_max_age = 0
220
+
221
+ begin
222
+ oldest = Scan.where(state: "QUEUED").minimum(:creation_time)
223
+ ensure
224
+ ActiveRecord::Base.connection_pool.release_connection
225
+ end
226
+
227
+ if oldest
228
+ queued_max_age = (Time.now - oldest).to_i
229
+ end
187
230
 
188
- if worker_id.empty? || uuid.empty?
189
- return {"accepted" => "false"}.to_json
231
+ begin
232
+ report = {
233
+ "SCAN_STATES" => {
234
+ "QUEUED" => Scan.where(state: "QUEUED").count,
235
+ "BATCH_QUEUED" => Scan.where(state: "BATCH_QUEUED").count,
236
+ "RUNNING" => Scan.where(state: "RUNNING").count,
237
+ "ERRORED" => Scan.where(state: "ERRORED").count,
238
+ "COMPLETED" => Scan.where(state: "COMPLETED").count,
239
+ },
240
+ "QUEUED_MAX_AGE" => queued_max_age,
241
+ "GRADE_REPORT" => {
242
+ "A" => Scan.where(grade: "A").count,
243
+ "B" => Scan.where(grade: "B").count,
244
+ "C" => Scan.where(grade: "C").count,
245
+ "D" => Scan.where(grade: "D").count,
246
+ "F" => Scan.where(grade: "F").count,
247
+ }
248
+ # "AUTH_METHOD_REPORT" => settings.db.auth_method_report
249
+ }
250
+ ensure
251
+ ActiveRecord::Base.connection_pool.release_connection
252
+ end
253
+
254
+ return report.to_json
190
255
  end
191
- settings.stats.new_scan_request
192
- settings.db.add_scan(worker_id, uuid, result, socket)
193
- end
194
256
 
195
- get '/stats' do
196
- settings.stats.get_stats(settings.job_queue.size)
257
+ get '/__lbheartbeat__' do
258
+ {
259
+ :status => "OK",
260
+ :message => "Keep sending requests. I am still alive."
261
+ }.to_json
262
+ end
197
263
  end
198
264
 
199
- get '/__lbheartbeat__' do
200
- {
201
- :status => "OK",
202
- :message => "Keep sending requests. I am still alive."
203
- }.to_json
204
- end
205
- end
265
+ def self.run!(options = {}, &block)
266
+ set options
206
267
 
207
- def self.run!(options = {}, &block)
208
- set options
209
-
210
- configure do
211
- enable :logging
212
- set :bind, options["bind"] || '127.0.0.1'
213
- set :server, "thin"
214
- set :logger, Logger.new(STDOUT)
215
- set :job_queue, JobQueue.new()
216
- set :db, SSHScan::Database.from_hash(options)
217
- set :results, {}
218
- set :stats, SSHScan::Stats.new
219
- set :authentication, options["authentication"]
220
- set :authenticator, SSHScan::Authenticator.from_config_file(
221
- options["config_file"]
222
- )
223
- end
268
+ configure do
269
+ enable :logging
270
+ set :bind, ENV['SSHSCAN_API_HOST'] || '127.0.0.1'
271
+ set :port, (ENV['SSHSCAN_API_PORT'] || 8000).to_i
272
+ set :server, "thin"
273
+ set :logger, Logger.new(STDOUT)
274
+ #set :database_file, File.join(File.dirname(__FILE__),"../../config/database.yml")
224
275
 
225
- super do |server|
226
- # No SSL on app, SSL termination happens in nginx for a prod deployment
227
- server.ssl = false
276
+ database_adapter = 'postgresql'
277
+ database_host = ENV['SSHSCAN_DATABASE_HOST'] || '127.0.0.1'
278
+ database_name = ENV['SSHSCAN_DATABASE_NAME'] || 'ssh_observatory'
279
+ database_username = ENV['SSHSCAN_DATABASE_USERNAME'] || 'sshobs'
280
+ database_pool = 5
281
+ database_timeout = 5000
282
+
283
+ set :database, { adapter: database_adapter, database: database_name, username: database_username, host: database_host, pool: database_pool, timeout: database_timeout}
284
+ set :authentication, ENV['SSHSCAN_API_AUTHENTICATION'] == "true" || false
285
+ set :authenticator, SSHScan::Api::Authenticator.new()
286
+ set :target_validator, SSHScan::Api::TargetValidator.new()
287
+ set :allowed_ports, options["allowed_ports"]
288
+ set :protection, false
289
+ end
290
+
291
+ super
228
292
  end
293
+
229
294
  end
230
295
  end
231
- end
296
+ end