Better error handling
parent
e17e793070
commit
2b134ba712
1
Gemfile
1
Gemfile
|
@ -22,6 +22,7 @@ end
|
|||
group :development, :test do
|
||||
gem 'puma'
|
||||
gem 'web-console'
|
||||
gem 'awesome_print'
|
||||
|
||||
gem 'pry-rails'
|
||||
|
||||
|
|
|
@ -8,12 +8,10 @@ class CheckController < ApplicationController
|
|||
respond_to do |format|
|
||||
format.html do
|
||||
return render :processing if @result.pending
|
||||
return render :no_tls if @result.no_tls
|
||||
end
|
||||
format.json do
|
||||
render json: case
|
||||
when @result.pending then :pending
|
||||
when @result.no_tls then :no_tls
|
||||
else @result
|
||||
end
|
||||
end
|
||||
|
@ -34,7 +32,7 @@ class CheckController < ApplicationController
|
|||
|
||||
protected
|
||||
def enqueue_host
|
||||
Datastore.pending self.type, @id, @port
|
||||
Datastore.pending self.type, @host, @port
|
||||
self.worker.perform_async *(@port.blank? ? [@host] : [@host, @port])
|
||||
@result = OpenStruct.new pending: true , date: Time.now
|
||||
end
|
||||
|
|
|
@ -3,19 +3,20 @@ class Datastore
|
|||
@@index.create unless @@index.exists?
|
||||
|
||||
def self.host(type, host, port)
|
||||
result = @@index.type(type).get self.key(host, port)
|
||||
key = self.key host, port
|
||||
result = @@index.type(type).get key
|
||||
result.date = Time.parse result.date
|
||||
result
|
||||
rescue Stretcher::RequestError::NotFound
|
||||
end
|
||||
|
||||
def self.pending(type, host, port)
|
||||
self.post type, host, port, { pending: true }
|
||||
self.post type, host, port, { pending: true, date: DateTime.now }
|
||||
end
|
||||
|
||||
def self.post(type, host, port, data)
|
||||
data[:date] = DateTime.now
|
||||
@@index.type(type).put self.key(host, port), data
|
||||
key = self.key host, port
|
||||
@@index.type(type).put key, data
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
<div id="check" class="container">
|
||||
<div class="row">
|
||||
<div class="col-sm-8 col-sm-offset-2">
|
||||
<h1>
|
||||
[<%= self.type.to_s.upcase %>] <%= @host %> ne supporte pas <%= self.tls_type %>
|
||||
</h1>
|
||||
<% if Time.now - @result.date >= Rails.configuration.refresh_delay %>
|
||||
<%= link_to 'Rafraîchir', {action: :refresh}, class: %i(btn btn-default pull-right) %>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -3,7 +3,6 @@
|
|||
<div class="col-sm-11">
|
||||
<h1>
|
||||
[<%= self.type.to_s.upcase %>] <%= @host %> <span class="small">(<%= l @result.date %>)</span>
|
||||
<%= rank_label @result.score.rank %>
|
||||
</h1>
|
||||
</div>
|
||||
<% if Time.now - @result.date >= Rails.configuration.refresh_delay %>
|
||||
|
@ -12,16 +11,35 @@
|
|||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
<br/>
|
||||
<%
|
||||
@result.hosts.each do |host|
|
||||
if host.error
|
||||
error, host = host.error, host.host
|
||||
%>
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
<h2><%= host.name %> - <%= host.ip %> : <%= host.port %></h2>
|
||||
Error during analysis :
|
||||
<span class="label label-error"><%= error %></span>
|
||||
</div>
|
||||
</div>
|
||||
<%
|
||||
else
|
||||
host, grade, handshake = host.host, host.grade, host.handshake
|
||||
%>
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
<h2><%= host.name %> - <%= host.ip %> : <%= host.port %></h2>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-6">
|
||||
<% scores = @result.score.details %>
|
||||
<table class="table table-bordered table-condensed table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th colspan="2">
|
||||
Scores
|
||||
<%= rank_label @result.score.rank %>
|
||||
<%= rank_label grade.rank %>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
@ -33,7 +51,7 @@
|
|||
'Total' => 'score'}.each do |name, v| %>
|
||||
<tr>
|
||||
<th class="col-sm-4"><%= name %></th>
|
||||
<td class="col-sm-8"><%= score_progress scores[v] %></td>
|
||||
<td class="col-sm-8"><%= score_progress grade.details[v] %></td>
|
||||
</tr>
|
||||
<% end %>
|
||||
</tbody>
|
||||
|
@ -44,20 +62,20 @@
|
|||
<tbody>
|
||||
<tr>
|
||||
<th class="col-sm-4">Protocoles</th>
|
||||
<td class="col-sm-8"><%= protocol_labels @result.protocols %></td>
|
||||
<td class="col-sm-8"><%= protocol_labels handshake.protocols %></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Clefs</th>
|
||||
<td>
|
||||
<p>Certificat : <%= key_label @result[:key] %></p>
|
||||
<p>Diffie Hellman : <%= key_labels @result.dh %></p>
|
||||
<p>Certificat : <%= key_label handshake[:key] %></p>
|
||||
<p>Diffie Hellman : <%= key_labels handshake.dh %></p>
|
||||
</td>
|
||||
</tr>
|
||||
<% { 'Bonnes pratiques' => :success,
|
||||
'Alertes' => :warning,
|
||||
'Dangers' => :danger,
|
||||
'Erreurs' => :error }.each do |name, color|
|
||||
names = @result.score[color]
|
||||
names = grade[color]
|
||||
next if names.nil? or names.empty?
|
||||
%>
|
||||
<tr>
|
||||
|
@ -100,8 +118,8 @@
|
|||
</thead>
|
||||
<tbody>
|
||||
<% CryptCheck::Tls::Server::EXISTING_METHODS.each do |protocol|
|
||||
ciphers = CryptCheck::Tls::Cipher.sort(@result.ciphers.select { |c| c.protocol == protocol.to_s }
|
||||
.collect { |c| CryptCheck::Tls::Cipher.new protocol, [c.name, nil, c[:size]], c.dh, @result[:key] })
|
||||
ciphers = CryptCheck::Tls::Cipher.sort(handshake.ciphers.select { |c| c.protocol == protocol.to_s }
|
||||
.collect { |c| CryptCheck::Tls::Cipher.new protocol, [c.name, nil, c[:size]], c.dh, handshake[:key] })
|
||||
unless ciphers.empty? %>
|
||||
<tr>
|
||||
<th colspan="12"><%= protocol_label protocol %></th>
|
||||
|
@ -133,4 +151,6 @@
|
|||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<% end
|
||||
end %>
|
||||
</div>
|
||||
|
|
|
@ -11,7 +11,27 @@
|
|||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
<br/>
|
||||
<%
|
||||
@result.hosts.each do |host|
|
||||
if host.error
|
||||
error, host = host.error, host.host
|
||||
%>
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
<h2><%= host.name %> - <%= host.ip %> : <%= host.port %></h2>
|
||||
Error during analysis :
|
||||
<span class="label label-error"><%= error %></span>
|
||||
</div>
|
||||
</div>
|
||||
<%
|
||||
else
|
||||
host, server = host.host, host.handshake
|
||||
%>
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
<h2><%= host.name %> - <%= host.ip %> : <%= host.port %></h2>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
<table class="table table-bordered table-condensed table-striped">
|
||||
|
@ -19,7 +39,7 @@
|
|||
<tr>
|
||||
<th>Échange de clef</th>
|
||||
</tr>
|
||||
<% @result.kex.each do |kex| %>
|
||||
<% server.kex.each do |kex| %>
|
||||
<tr>
|
||||
<td><%= kex_label kex %></td>
|
||||
</tr>
|
||||
|
@ -28,7 +48,7 @@
|
|||
<tr>
|
||||
<th>Chiffrement</th>
|
||||
</tr>
|
||||
<% @result.encryption.each do |cipher| %>
|
||||
<% server.encryption.each do |cipher| %>
|
||||
<tr>
|
||||
<td><%= cipher_label cipher %></td>
|
||||
</tr>
|
||||
|
@ -37,7 +57,7 @@
|
|||
<tr>
|
||||
<th>HMAC</th>
|
||||
</tr>
|
||||
<% @result.hmac.each do |hmac| %>
|
||||
<% server.hmac.each do |hmac| %>
|
||||
<tr>
|
||||
<td><%= hmac_label hmac %></td>
|
||||
</tr>
|
||||
|
@ -46,7 +66,7 @@
|
|||
<tr>
|
||||
<th>Compression</th>
|
||||
</tr>
|
||||
<% @result.compression.each do |compression| %>
|
||||
<% server.compression.each do |compression| %>
|
||||
<tr>
|
||||
<td><%= compression_label compression %></td>
|
||||
</tr>
|
||||
|
@ -55,7 +75,7 @@
|
|||
<tr>
|
||||
<th>Clefs</th>
|
||||
</tr>
|
||||
<% @result['key'].each do |key| %>
|
||||
<% server.key_.each do |key| %>
|
||||
<tr>
|
||||
<td><%= key_label key %></td>
|
||||
</tr>
|
||||
|
@ -64,4 +84,6 @@
|
|||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<% end
|
||||
end %>
|
||||
</div>
|
||||
|
|
|
@ -7,40 +7,56 @@ class CheckWorker
|
|||
end
|
||||
|
||||
def perform(host, port=nil)
|
||||
host = SimpleIDN.to_ascii host.downcase
|
||||
result = begin
|
||||
grade = self.analyze *(port ? [host, port] : [host])
|
||||
raise CryptCheck::Tls::Server::TLSNotAvailableException if grade.is_a? CryptCheck::Tls::TlsNotSupportedGrade
|
||||
server = grade.server
|
||||
result = {
|
||||
key: key_to_json(server.key),
|
||||
dh: server.dh.collect { |k| key_to_json k },
|
||||
protocols: server.supported_protocols,
|
||||
ciphers: server.supported_ciphers.collect { |c| { protocol: c.protocol, name: c.name, size: c.size, dh: key_to_json(c.dh) } },
|
||||
score: {
|
||||
rank: grade.grade,
|
||||
details: {
|
||||
score: grade.score,
|
||||
protocol: grade.protocol_score,
|
||||
key_exchange: grade.key_exchange_score,
|
||||
cipher_strengths: grade.cipher_strengths_score
|
||||
},
|
||||
error: grade.error,
|
||||
danger: grade.danger,
|
||||
warning: grade.warning,
|
||||
success: grade.success
|
||||
}
|
||||
}
|
||||
host = SimpleIDN.to_ascii host.downcase
|
||||
hosts = self.analyze *(port ? [host, port] : [host])
|
||||
hosts = hosts.collect do |host, result|
|
||||
name, ip, p = host
|
||||
host = { name: name, ip: ip, port: p }
|
||||
|
||||
self.result server, grade, result
|
||||
rescue CryptCheck::Tls::Server::TLSNotAvailableException
|
||||
{ no_tls: true }
|
||||
if result.is_a? CryptCheck::AnalysisFailure
|
||||
next {
|
||||
host: host,
|
||||
error: result.to_s
|
||||
}
|
||||
end
|
||||
|
||||
grade = result
|
||||
server = grade.server
|
||||
{
|
||||
host: host,
|
||||
handshake: to_json(server),
|
||||
grade: grade_to_json(grade)
|
||||
}
|
||||
end
|
||||
result = { date: DateTime.now, hosts: hosts }
|
||||
Datastore.post self.type, host, port, result
|
||||
end
|
||||
|
||||
protected
|
||||
def result(_, _, result)
|
||||
result
|
||||
def to_json(server)
|
||||
{
|
||||
key: key_to_json(server.key),
|
||||
dh: server.dh.collect { |k| key_to_json k },
|
||||
protocols: server.supported_protocols,
|
||||
ciphers: server.supported_ciphers.collect { |c| { protocol: c.protocol, name: c.name, size: c.size, dh: key_to_json(c.dh) } },
|
||||
|
||||
}
|
||||
end
|
||||
|
||||
private
|
||||
def grade_to_json(grade)
|
||||
{
|
||||
rank: grade.grade,
|
||||
details: {
|
||||
score: grade.score,
|
||||
protocol: grade.protocol_score,
|
||||
key_exchange: grade.key_exchange_score,
|
||||
cipher_strengths: grade.cipher_strengths_score
|
||||
},
|
||||
error: grade.error,
|
||||
danger: grade.danger,
|
||||
warning: grade.warning,
|
||||
success: grade.success
|
||||
}
|
||||
end
|
||||
end
|
||||
|
|
|
@ -10,8 +10,9 @@ class HTTPSWorker < CheckWorker
|
|||
:https
|
||||
end
|
||||
|
||||
def result(server, _, hash)
|
||||
hash[:hsts] = server.hsts
|
||||
hash
|
||||
def to_json(server)
|
||||
result = super
|
||||
result[:hsts] = server.hsts
|
||||
result
|
||||
end
|
||||
end
|
||||
|
|
|
@ -2,8 +2,8 @@ class SMTPWorker < CheckWorker
|
|||
sidekiq_options retry: false
|
||||
|
||||
protected
|
||||
def analyze(host, port=25)
|
||||
CryptCheck::Tls::Smtp.analyze host, port
|
||||
def analyze(host)
|
||||
CryptCheck::Tls::Smtp.analyze_domain host
|
||||
end
|
||||
|
||||
def type
|
||||
|
|
|
@ -1,21 +1,26 @@
|
|||
class SSHWorker
|
||||
include Sidekiq::Worker
|
||||
class SSHWorker < CheckWorker
|
||||
sidekiq_options retry: false
|
||||
|
||||
def perform(host, port=nil)
|
||||
host = SimpleIDN.to_ascii host.downcase
|
||||
result = begin
|
||||
server = CryptCheck::Ssh.analyze host, port
|
||||
{
|
||||
kex: server.kex,
|
||||
encryption: server.encryption,
|
||||
hmac: server.hmac,
|
||||
compression: server.compression,
|
||||
key: server.key
|
||||
}
|
||||
rescue CryptCheck::Ssh::Server::SshNotAvailableException
|
||||
{ no_tls: true }
|
||||
end
|
||||
Datastore.post :ssh, host, port, result
|
||||
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
|
||||
|
|
|
@ -3,10 +3,16 @@ class XMPPWorker < CheckWorker
|
|||
|
||||
protected
|
||||
def analyze(host)
|
||||
CryptCheck::Tls::Xmpp.analyze host
|
||||
CryptCheck::Tls::Xmpp.analyze_domain host
|
||||
end
|
||||
|
||||
def type
|
||||
:xmpp
|
||||
end
|
||||
|
||||
def to_json(server)
|
||||
result = super
|
||||
result[:required] = server.required?
|
||||
result
|
||||
end
|
||||
end
|
||||
|
|
|
@ -6,4 +6,5 @@ options = {
|
|||
}
|
||||
client = Sidekiq::Client.new Sidekiq::RedisConnection.create options
|
||||
clazz, *args = ARGV
|
||||
clazz += 'Worker'
|
||||
client.push({ 'class' => clazz, 'args' => args })
|
||||
|
|
Loading…
Reference in New Issue