21 changed files with 255 additions and 182 deletions
@ -0,0 +1,13 @@ |
|||
source 'https://rubygems.org' |
|||
|
|||
gem 'dotenv' |
|||
|
|||
gem 'sidekiq' |
|||
gem 'sidekiq-workflow', git: 'https://git.imirhil.fr/aeris/sidekiq-workflow.git', branch: :master |
|||
|
|||
gem 'simpleidn' |
|||
gem 'cryptcheck', '~> 2.0.0', path: '../engine' |
|||
|
|||
group :development do |
|||
gem 'amazing_print' |
|||
end |
@ -0,0 +1,85 @@ |
|||
GIT |
|||
remote: https://git.imirhil.fr/aeris/sidekiq-workflow.git |
|||
revision: 9600075c17e83f2013f0b7d6e35698bea6b0ee40 |
|||
branch: master |
|||
specs: |
|||
sidekiq-workflow (0.0.0) |
|||
colorize (~> 0.8) |
|||
redis (~> 4.3) |
|||
redlock (~> 1.2) |
|||
sidekiq |
|||
terminal-table (~> 3.0) |
|||
|
|||
PATH |
|||
remote: ../engine |
|||
specs: |
|||
cryptcheck (2.0.0) |
|||
amazing_print |
|||
colorize |
|||
httparty |
|||
nokogiri |
|||
parallel |
|||
ruby-progressbar |
|||
thor |
|||
|
|||
GEM |
|||
remote: https://rubygems.org/ |
|||
specs: |
|||
amazing_print (1.2.1) |
|||
colorize (0.8.1) |
|||
connection_pool (2.2.5) |
|||
dotenv (2.7.6) |
|||
foreman (0.87.2) |
|||
http_accept_language (2.1.1) |
|||
httparty (0.20.0) |
|||
mime-types (~> 3.0) |
|||
multi_xml (>= 0.5.2) |
|||
mime-types (3.4.1) |
|||
mime-types-data (~> 3.2015) |
|||
mime-types-data (3.2022.0105) |
|||
mini_portile2 (2.4.0) |
|||
multi_xml (0.6.0) |
|||
nokogiri (1.10.10) |
|||
mini_portile2 (~> 2.4.0) |
|||
parallel (1.19.2) |
|||
pg (1.2.3) |
|||
rack (2.0.9) |
|||
rack-protection (2.2.0) |
|||
rack |
|||
recursive-open-struct (1.1.3) |
|||
redis (4.4.0) |
|||
redlock (1.2.2) |
|||
redis (>= 3.0.0, < 5.0) |
|||
ruby-progressbar (1.11.0) |
|||
sidekiq (5.2.8) |
|||
connection_pool (~> 2.2, >= 2.2.2) |
|||
rack (< 2.1.0) |
|||
rack-protection (>= 1.5.0) |
|||
redis (>= 3.3.5, < 5) |
|||
simpleidn (0.2.1) |
|||
unf (~> 0.1.4) |
|||
terminal-table (3.0.2) |
|||
unicode-display_width (>= 1.1.1, < 3) |
|||
thor (1.2.1) |
|||
unf (0.1.4) |
|||
unf_ext |
|||
unf_ext (0.0.8.1) |
|||
unicode-display_width (2.1.0) |
|||
|
|||
PLATFORMS |
|||
x86_64-linux |
|||
|
|||
DEPENDENCIES |
|||
amazing_print |
|||
cryptcheck (~> 2.0.0)! |
|||
dotenv |
|||
foreman |
|||
http_accept_language |
|||
pg |
|||
recursive-open-struct |
|||
sidekiq |
|||
sidekiq-workflow! |
|||
simpleidn |
|||
|
|||
BUNDLED WITH |
|||
2.3.9 |
@ -0,0 +1,4 @@ |
|||
web: bundle exec guard -i |
|||
webpack: bundle exec webpack-dev-server |
|||
sidekiq: bundle exec sidekiq -q default |
|||
sidekiq_1_0: BUNDLE_GEMFILE=Gemfile-2.3 bin/sidekiq 1.0 -q tls_1_0 |
@ -1,59 +1,66 @@ |
|||
class CheckController < ApplicationController |
|||
before_action :check_host, except: %i(index) |
|||
helper_method :tls_type, :type |
|||
|
|||
def show |
|||
enqueue_host unless @analysis |
|||
@host = SimpleIDN.to_unicode @host |
|||
respond_to do |format| |
|||
format.html do |
|||
return render :processing if @analysis.pending |
|||
@result = @analysis.result.collect { |r| RecursiveOpenStruct.new r, recurse_over_arrays: true } |
|||
end |
|||
format.json { render json: @analysis } |
|||
end |
|||
end |
|||
|
|||
def refresh |
|||
unless @analysis.pending |
|||
if Rails.env == 'production' |
|||
refresh_allowed = @analysis.updated_at + Rails.configuration.refresh_delay |
|||
if Time.now < refresh_allowed |
|||
flash[:warning] = "Merci d’attendre au moins #{l refresh_allowed} pour rafraîchir" |
|||
return redirect_to action: :show, id: @host |
|||
end |
|||
end |
|||
enqueue_host |
|||
end |
|||
redirect_to action: :show |
|||
end |
|||
|
|||
protected |
|||
def default_args |
|||
end |
|||
|
|||
def enqueue_host |
|||
@analysis = Analysis.pending! self.type, @host, @args |
|||
self.worker.perform_async @analysis.host, *@analysis.args |
|||
end |
|||
|
|||
def check_host |
|||
@id = params[:id] |
|||
|
|||
if @id.end_with? '.json' |
|||
@id = @id.sub /\.json$/, '' |
|||
request.format = :json |
|||
end |
|||
|
|||
@host, @args = @id.split ':' |
|||
@host = SimpleIDN.to_ascii @host.downcase |
|||
if /[^a-zA-Z0-9.-]/ =~ @host |
|||
flash[:danger] = "Hôte #{@host} invalide" |
|||
redirect_to action: :index |
|||
return false |
|||
end |
|||
@args ||= default_args |
|||
|
|||
@analysis = Analysis[self.type, @host, @args] |
|||
end |
|||
before_action :check_host, except: %i[index] |
|||
before_action :exclude_robots_indexing |
|||
helper_method :tls_type, :type |
|||
|
|||
def show |
|||
enqueue_host unless @analysis |
|||
@host = SimpleIDN.to_unicode @host |
|||
respond_to do |format| |
|||
format.html do |
|||
return render :processing if @analysis.pending |
|||
@result = @analysis.result.collect { |r| RecursiveOpenStruct.new r, recurse_over_arrays: true } |
|||
end |
|||
format.json { render json: @analysis } |
|||
end |
|||
end |
|||
|
|||
def refresh |
|||
unless @analysis.pending |
|||
if Rails.env == 'production' |
|||
refresh_allowed = @analysis.updated_at + Rails.configuration.refresh_delay |
|||
if Time.now < refresh_allowed |
|||
flash[:warning] = "Merci d’attendre au moins #{l refresh_allowed} pour rafraîchir" |
|||
return redirect_to action: :show, id: @host |
|||
end |
|||
end |
|||
enqueue_host |
|||
end |
|||
redirect_to action: :show |
|||
end |
|||
|
|||
protected |
|||
|
|||
def exclude_robots_indexing |
|||
response.set_header 'X-Robots-Tag', |
|||
%i[none noarchive nosnippet notranslate noimageindex].join(',') |
|||
end |
|||
|
|||
def default_args |
|||
end |
|||
|
|||
def enqueue_host |
|||
@analysis = Analysis.pending! self.type, @host, @args |
|||
CheckWorkflow.start! self.type, @analysis.host, *@analysis.args |
|||
end |
|||
|
|||
def check_host |
|||
@id = params[:id] |
|||
|
|||
if @id.end_with? '.json' |
|||
@id = @id.sub /\.json$/, '' |
|||
request.format = :json |
|||
end |
|||
|
|||
@host, @args = @id.split ':' |
|||
@host = SimpleIDN.to_ascii @host.downcase |
|||
if /[^a-zA-Z0-9.-]/ =~ @host |
|||
flash[:danger] = "Hôte #{@host} invalide" |
|||
redirect_to action: :index |
|||
return false |
|||
end |
|||
@args ||= default_args |
|||
|
|||
@analysis = Analysis[self.type, @host, @args] |
|||
end |
|||
end |
|||
|
@ -0,0 +1,30 @@ |
|||
require 'simpleidn' |
|||
|
|||
class CheckJob |
|||
include Sidekiq::Workflow::Worker |
|||
sidekiq_options queue: :tls_1_0, retry: false |
|||
|
|||
def perform(type, host, *args, **_) |
|||
host = SimpleIDN.to_ascii host.downcase |
|||
result = self.analyze type, host, *args |
|||
args = nil if args.empty? |
|||
set_payload({ type: type, host: host, args: args, result: result }) |
|||
end |
|||
|
|||
def analyze(type, *args) |
|||
case type.to_sym |
|||
when :https |
|||
CryptCheck::Tls::Https.analyze *args |
|||
when :smtp |
|||
CryptCheck::Tls::Smtp.analyze *args |
|||
when :xmpp |
|||
CryptCheck::Tls::Xmpp.analyze *args |
|||
when :tls |
|||
CryptCheck::Tls.analyze *args |
|||
when :ssh |
|||
CryptCheck::Ssh.analyze *args |
|||
else |
|||
raise "Unsupported analysis #{type}" |
|||
end |
|||
end |
|||
end |
@ -0,0 +1,13 @@ |
|||
class PersistJob |
|||
include Sidekiq::Workflow::Worker |
|||
sidekiq_options retry: false |
|||
|
|||
def perform(*_, **_) |
|||
result = self.get_payload CheckJob, :json |
|||
type = result.fetch 'type' |
|||
host = result.fetch 'host' |
|||
args = result.fetch 'args' |
|||
result = result.fetch 'result' |
|||
Analysis.post! type, host, args, result |
|||
end |
|||
end |
@ -1,11 +0,0 @@ |
|||
class CheckWorker |
|||
include Sidekiq::Worker |
|||
sidekiq_options retry: false |
|||
|
|||
def perform(host, *args) |
|||
host = SimpleIDN.to_ascii host.downcase |
|||
result = self.analyze host, *args |
|||
args = nil if args.empty? |
|||
Analysis.post! self.type, host, args, result |
|||
end |
|||
end |
@ -1,12 +0,0 @@ |
|||
class HTTPSWorker < CheckWorker |
|||
sidekiq_options retry: false |
|||
|
|||
protected |
|||
def analyze(host, port) |
|||
CryptCheck::Tls::Https.analyze host, port |
|||
end |
|||
|
|||
def type |
|||
:https |
|||
end |
|||
end |
@ -1,12 +0,0 @@ |
|||
class SMTPWorker < CheckWorker |
|||
sidekiq_options retry: false |
|||
|
|||
protected |
|||
def analyze(host) |
|||
CryptCheck::Tls::Smtp.analyze host |
|||
end |
|||
|
|||
def type |
|||
:smtp |
|||
end |
|||
end |
@ -1,26 +0,0 @@ |
|||
class SSHWorker < CheckWorker |
|||
sidekiq_options retry: false |
|||
|
|||
protected |
|||
def analyze(host, port=22) |
|||
CryptCheck::Ssh.analyze host, port |
|||
end |
|||
|
|||
def type |
|||
:ssh |
|||
end |
|||
|
|||
def to_json(server) |
|||
{ |
|||
kex: server.kex, |
|||
encryption: server.encryption, |
|||
hmac: server.hmac, |
|||
compression: server.compression, |
|||
key_: server.key |
|||
} |
|||
end |
|||
|
|||
def grade_to_json(grade) |
|||
nil |
|||
end |
|||
end |
@ -1,12 +0,0 @@ |
|||
class TLSWorker < CheckWorker |
|||
sidekiq_options retry: false |
|||
|
|||
protected |
|||
def analyze(host, port) |
|||
CryptCheck::Tls.analyze host, port |
|||
end |
|||
|
|||
def type |
|||
:tls |
|||
end |
|||
end |
@ -1,12 +0,0 @@ |
|||
class XMPPWorker < CheckWorker |
|||
sidekiq_options retry: false |
|||
|
|||
protected |
|||
def analyze(host, type) |
|||
CryptCheck::Tls::Xmpp.analyze host, type |
|||
end |
|||
|
|||
def type |
|||
:xmpp |
|||
end |
|||
end |
@ -0,0 +1,6 @@ |
|||
class CheckWorkflow < Sidekiq::Workflow |
|||
def configure(*args, **kwargs) |
|||
check = job CheckJob, *args, **kwargs |
|||
job PersistJob, after: check |
|||
end |
|||
end |
@ -1,20 +1,8 @@ |
|||
#!/usr/bin/env ruby |
|||
$:.unshift File.expand_path File.join File.dirname(__FILE__), '../../cryptcheck/lib' |
|||
require 'rubygems' |
|||
require 'bundler/setup' |
|||
|
|||
$TESTING = false |
|||
$CELLULOID_DEBUG = false |
|||
|
|||
require 'sidekiq/cli' |
|||
|
|||
begin |
|||
cli = Sidekiq::CLI.instance |
|||
cli.parse |
|||
cli.run |
|||
rescue => e |
|||
raise e if $DEBUG |
|||
STDERR.puts e.message |
|||
STDERR.puts e.backtrace.join("\n") |
|||
exit 1 |
|||
end |
|||
#!/usr/bin/env bash |
|||
set -e |
|||
DIR="$(dirname "$(readlink -e "${BASH_SOURCE[0]}")")" |
|||
RAILS_DIR="$(readlink -f "$DIR/..")" |
|||
ENGINE_DIR="$(readlink -f "$RAILS_DIR/../engine")" |
|||
eval "$("$ENGINE_DIR/bin/load-rbenv" "$1")" |
|||
shift |
|||
bundle exec sidekiq -r "$RAILS_DIR/config/sidekiq.rb" $* |
|||
|
@ -0,0 +1,3 @@ |
|||
if redis_url = ENV['REDIS_URL'] |
|||
Sidekiq::Workflow.configure url: redis_url |
|||
end |
@ -0,0 +1,29 @@ |
|||
#!/usr/bin/env ruby |
|||
require 'rubygems' |
|||
require 'bundler/setup' |
|||
env = ENV.fetch 'RAILS_ENV', 'development' |
|||
Bundler.require env |
|||
|
|||
require 'dotenv' |
|||
Dotenv.load ".env.#{ENV['RAILS_ENV']}.local", ".env.#{ENV['RAILS_ENV']}", '.env.local', '.env' |
|||
|
|||
class Hash |
|||
def compact |
|||
select { |_, value| !value.nil? } |
|||
end |
|||
end |
|||
|
|||
require 'redis' |
|||
Redis.exists_returns_integer = true |
|||
redis_url = ENV.fetch 'REDIS_URL' |
|||
|
|||
require 'sidekiq' |
|||
Sidekiq.configure_server { |c| c.redis = { url: redis_url } } |
|||
Sidekiq.configure_client { |c| c.redis = { url: redis_url } } |
|||
require 'sidekiq/workflow' |
|||
redis_url = ENV['REDIS_URL'] |
|||
Sidekiq::Workflow.configure url: redis_url |
|||
|
|||
require 'cryptcheck' |
|||
load File.join __dir__, '../app/jobs/check_job.rb' |
|||
load File.join __dir__, '../app/jobs/persist_job.rb' |
Loading…
Reference in new issue