diff --git a/.rspec b/.rspec new file mode 100644 index 0000000..0145afd --- /dev/null +++ b/.rspec @@ -0,0 +1,3 @@ +--require spec_helper +--format progress +--format html --out tmp/rspec.html diff --git a/Gemfile b/Gemfile index 03c05cc..9d53cf4 100644 --- a/Gemfile +++ b/Gemfile @@ -19,6 +19,7 @@ gem 'http_accept_language' gem 'recursive-open-struct' gem 'ruby-progressbar' gem 'public_suffix' +gem 'amazing_print' gem 'uglifier' gem 'sass-rails' @@ -46,7 +47,6 @@ end group :development, :test do gem 'pry-byebug' - gem 'amazing_print' end group :test do diff --git a/app/controllers/stats_controller.rb b/app/controllers/stats_controller.rb new file mode 100644 index 0000000..08b991c --- /dev/null +++ b/app/controllers/stats_controller.rb @@ -0,0 +1,2 @@ +class StatsController < ApplicationController +end diff --git a/app/javascript/css/application.scss b/app/javascript/css/application.scss index a2ca26a..7aef540 100644 --- a/app/javascript/css/application.scss +++ b/app/javascript/css/application.scss @@ -87,6 +87,7 @@ td.error { $color-critical: #d9534f; $color-error: #e4804e; $color-warning: #f0ad4e; +$color-effort: #6c757d; $color-good: #beb052; $color-best: #8db457; $color-great: #5cb85c; @@ -195,3 +196,71 @@ table.scoring img { max-width: 140px; } } + +/** Navigation tabs */ +.tab-content { + border: 1px solid $nav-pills-link-active-bg; + border-bottom-left-radius: .3rem; + border-bottom-right-radius: .3rem; +} + +.nav-pills .nav-link { + border-radius: .3rem; + font-weight: bold; +} + +.nav-pills .nav-link.active { + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; + font-weight: bolder; +} + +/** Chart CSS */ +.cumulative-datas { + position: relative; + display: flex; + flex-direction: row; + width: 100%; + + &-content { + position: absolute; + height: 2rem; + } +} + +.cumulative-data { + height: 2rem; + line-height: 2rem; + display: inline-block; + white-space: nowrap; + text-overflow: ellipsis; + margin-right: .1rem; + padding-left: .3rem; +} + +/** Progress bar */ +.progress { + box-shadow: 0 0 .1rem $dark; + height: 1.4rem; +} +.progress-critical { + background-color: $color-critical; +} +.progress-error { + background-color: $color-error; +} +.progress-warning { + background-color: $color-warning; +} +.progress-effort { + background-color: $color-effort; +} +.progress-good { + background-color: $color-good; +} +.progress-best { + background-color: $color-best; +} +.progress-great { + background-color: $color-great; +} diff --git a/app/javascript/packs/application.js b/app/javascript/packs/application.js index ab97118..7cfd0c2 100644 --- a/app/javascript/packs/application.js +++ b/app/javascript/packs/application.js @@ -1 +1,2 @@ import 'css/application' +import 'bootstrap/js/dist/tab' diff --git a/app/views/stats/index.html.erb b/app/views/stats/index.html.erb new file mode 100644 index 0000000..41c056a --- /dev/null +++ b/app/views/stats/index.html.erb @@ -0,0 +1,167 @@ +<% colors = { + "A+" => 'great', + "good" => 'great', + "A" => 'great', + "B+" => 'best', + "B" => 'best', + "C+" => 'good', + "C" => 'good', + "D" => 'effort', + "E" => 'warning', + "F" => 'error', + "G" => 'critical', + "bad" => 'critical', + "ssl" => 'critical', + "tls" => 'error', + "tls1_2" => 'effort', + "tls1_2_only" => 'great' +} %> + + + + diff --git a/bin/rspec b/bin/rspec new file mode 100755 index 0000000..a6c7852 --- /dev/null +++ b/bin/rspec @@ -0,0 +1,29 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +# +# This file was generated by Bundler. +# +# The application 'rspec' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require "pathname" +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", + Pathname.new(__FILE__).realpath) + +bundle_binstub = File.expand_path("../bundle", __FILE__) + +if File.file?(bundle_binstub) + if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ + load(bundle_binstub) + else + abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. +Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") + end +end + +require "rubygems" +require "bundler/setup" + +load Gem.bin_path("rspec-core", "rspec") diff --git a/bin/stats b/bin/stats index 2a39cd6..d429af2 100755 --- a/bin/stats +++ b/bin/stats @@ -49,29 +49,78 @@ class Analysis end end -sites = YAML.load_file Rails.root.join 'config/sites.yml' - -workflows = [] -sites.each do |type, domains| - domains.each do |domain| - puts "Refreshing #{domain}" - @analysis = Analysis.pending! :https, domain, 443 - workflows << CheckWorkflow.start!(:https, @analysis.host, *@analysis.args) +# sites = YAML.load_file Rails.root.join 'config/sites.yml' +# +# workflows = [] +# sites.each do |type, domains| +# domains.each do |domain| +# puts "Refreshing #{domain}" +# @analysis = Analysis.pending! :https, domain, 443 +# workflows << CheckWorkflow.start!(:https, @analysis.host, *@analysis.args) +# end +# end +# workflows.each &:wait +# +# sites.each do |type, domains| +# domains = domains.collect do |domain| +# analysis = Analysis[:https, domain, 443] +# stats = { +# grade: analysis.grade, +# tls: analysis.tls, +# ciphers: analysis.ciphers, +# pfs: analysis.pfs +# } +# [domain, stats] +# end.to_h +# +# Stat.create! :"sites_#{type}", domains +# end + +# general stat +services = Analysis.group(:service).order(service: :asc).count +Stat.create! :request_per_service, { labels: services.keys, dataset: services.values } + +# grade per service for https, smtp, tls and xmpp +%i[https smtp tls xmpp].each do |name| + services = Analysis.where service: name, pending: false + + grades = Hash.new 0 + tls = %i[tls1_2_only tls1_2 tls ssl].to_h { [_1, 0] } + ciphers = %i[good bad].to_h { [_1, 0] } + pfs = %i[pfs_only pfs no_pfs].to_h { [_1, 0] } + + progress = ProgressBar.create title: name, total: services.count, + format: '%t | %c/%u %W | %e' + services.find_in_batches do |batch| + batch.each do |service| + if (g = service.grade) + grades[g] += 1 + end + + if (t = service.tls) + tls[t] += 1 + end + + if (c = service.ciphers) + ciphers[c] += 1 + end + + if (p = service.pfs) + pfs[p] += 1 + end + progress.increment + end end -end -workflows.each &:wait - -sites.each do |type, domains| - domains = domains.collect do |domain| - analysis = Analysis[:https, domain, 443] - stats = { - grade: analysis.grade, - tls: analysis.tls, - ciphers: analysis.ciphers, - pfs: analysis.pfs - } - [domain, stats] - end.to_h - - Stat.create! :"sites_#{type}", domains + + ap "grades_for_#{name}" => grades + Stat.create! "grades_for_#{name}", grades + + ap "tls_for_#{name}" => tls + Stat.create! "tls_for_#{name}", tls + + ap "ciphers_for_#{name}" => ciphers + Stat.create! "ciphers_for_#{name}", ciphers + + ap "pfs_for_#{name}" => pfs + Stat.create! "pfs_for_#{name}", pfs end diff --git a/config/locales/fr.yml b/config/locales/fr.yml index c11f2ae..359a8cc 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -61,6 +61,19 @@ fr: Fingerprint: Empreinte "Fingerprint: %{fingerprint}": "Empreinte : %{fingerprint}" + stats: + index: + ciphers: + title: Suites de chiffrement supportées + good: Uniquement des sécurisées + bad: Au moins une non sécurisée + tls: + title: Versions de SSL/TLS supportées + tls1_2_only: TLSv1.2+ + tls1_2: TLSv1.2 supporté + tls: TLSv1.0+ mais pas TLSv1.2 + ssl: SSLv2 ou SSLv3 supporté + date: abbr_day_names: - dim diff --git a/config/routes.rb b/config/routes.rb index 0e78c30..0b4bc3b 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -16,7 +16,7 @@ root 'site#index' post '/' => 'site#check' - get 'sites' => 'site#sites' + resources :stats, only: %i[index] %i[banks insurances gouv.fr].each do |name| get name, controller: :sites, action: name diff --git a/db/schema.rb b/db/schema.rb index 4d92865..7684c0c 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -33,5 +33,4 @@ t.jsonb "data" t.index ["name", "date"], name: "index_stats_on_name_and_date", unique: true end - end diff --git a/package.json b/package.json index 76422be..fd067f4 100644 --- a/package.json +++ b/package.json @@ -5,6 +5,7 @@ "author": "aeris ", "license": "AGPL-3.0-or-later", "dependencies": { + "@popperjs/core": "^2.11.5", "@rails/webpacker": "5.4.3", "bootstrap": "^5.1.3", "font-awesome": "^4.7.0",