Fixed Generate Script
This commit is contained in:
240
scripts-backup/generate-report.pl
Executable file
240
scripts-backup/generate-report.pl
Executable file
@@ -0,0 +1,240 @@
|
||||
#!/usr/bin/env perl
|
||||
use strict;
|
||||
use warnings;
|
||||
use JSON::MaybeXS;
|
||||
use LWP::UserAgent;
|
||||
use HTTP::Request;
|
||||
use MIME::Base64 qw(encode_base64);
|
||||
use Date::Parse qw(str2time);
|
||||
use POSIX qw(strftime);
|
||||
use File::Spec;
|
||||
use File::Basename;
|
||||
use HTTP::Cookies;
|
||||
|
||||
# CONFIG
|
||||
my $basedir = dirname(__FILE__);
|
||||
my $input_file = File::Spec->catfile($basedir, 'web_list.json');
|
||||
my $output_file = File::Spec->catfile($basedir, 'web_check.json');
|
||||
my $false_html = File::Spec->catfile($basedir, 'sld-check-false.html');
|
||||
my $timeout = 10; # timeout secondi
|
||||
my $openssl_timeout_bin = (-x '/usr/bin/timeout' ? '/usr/bin/timeout' :
|
||||
-x '/bin/timeout' ? '/bin/timeout' : '');
|
||||
|
||||
# ===== helpers =====
|
||||
sub read_json_file {
|
||||
my ($path) = @_;
|
||||
open my $fh, '<', $path or die "Cannot open $path: $!\n";
|
||||
local $/;
|
||||
my $json = <$fh>;
|
||||
close $fh;
|
||||
return decode_json($json);
|
||||
}
|
||||
|
||||
sub write_json_file {
|
||||
my ($path, $data) = @_;
|
||||
open my $out, '>', $path or die "Cannot write $path: $!\n";
|
||||
print $out encode_json($data);
|
||||
close $out;
|
||||
}
|
||||
|
||||
sub format_date_from_string {
|
||||
my ($raw) = @_;
|
||||
return undef unless defined $raw && $raw ne '';
|
||||
my $ts = str2time($raw);
|
||||
return undef unless $ts;
|
||||
return strftime("%d/%m/%Y", gmtime($ts));
|
||||
}
|
||||
|
||||
# Run openssl s_client -> parse notBefore notAfter issuer
|
||||
sub get_cert_info_openssl {
|
||||
my ($host, $timeout_sec) = @_;
|
||||
my $result = {
|
||||
status => 0,
|
||||
issued => undef,
|
||||
expiry => undef,
|
||||
company => undef,
|
||||
error => undef,
|
||||
};
|
||||
|
||||
# escape host for shell
|
||||
my $esc_host = $host;
|
||||
$esc_host =~ s/'/'\\''/g; # basic escape if used in single quotes
|
||||
my $cmd = sprintf("openssl s_client -connect %s:443 -servername %s -showcerts </dev/null 2>/dev/null | openssl x509 -noout -dates -issuer", $host, $host);
|
||||
if ($openssl_timeout_bin) {
|
||||
$cmd = join(' ', $openssl_timeout_bin, $timeout_sec, $cmd);
|
||||
}
|
||||
|
||||
my $out = qx{$cmd};
|
||||
my $exit = $? >> 8;
|
||||
|
||||
if ($exit != 0 || $out eq '') {
|
||||
$result->{error} = "openssl failed or timed out (exit=$exit)";
|
||||
return $result;
|
||||
}
|
||||
|
||||
my ($notBefore) = $out =~ /notBefore=(.+)/i;
|
||||
my ($notAfter) = $out =~ /notAfter=(.+)/i;
|
||||
my ($issuer) = $out =~ /issuer\s*=\s*(.+)/i;
|
||||
|
||||
my $issued_fmt = defined $notBefore ? format_date_from_string($notBefore) : undef;
|
||||
my $expiry_fmt = defined $notAfter ? format_date_from_string($notAfter) : undef;
|
||||
|
||||
# extract company from issuer: try O= then CN= else whole issuer
|
||||
my $company = undef;
|
||||
if (defined $issuer) {
|
||||
if ($issuer =~ /O=([^,\/]+)/) {
|
||||
$company = $1;
|
||||
} elsif ($issuer =~ /CN=([^,\/]+)/) {
|
||||
$company = $1;
|
||||
} else {
|
||||
$company = $issuer;
|
||||
}
|
||||
$company =~ s/^\s+|\s+$//g;
|
||||
}
|
||||
|
||||
my $is_valid = 0;
|
||||
if ($expiry_fmt) {
|
||||
my $ts = str2time($notAfter);
|
||||
$is_valid = ($ts && time() < $ts) ? 1 : 0;
|
||||
}
|
||||
|
||||
$result->{status} = $is_valid;
|
||||
$result->{issued} = $issued_fmt;
|
||||
$result->{expiry} = $expiry_fmt;
|
||||
$result->{company} = $company;
|
||||
$result->{error} = undef;
|
||||
return $result;
|
||||
}
|
||||
|
||||
# build URL from domain + path; ensure https:// prefix
|
||||
sub build_url {
|
||||
my ($domain, $path) = @_;
|
||||
$domain =~ s{^https?://}{}i;
|
||||
$domain =~ s{/$}{}; # remove trailing slash
|
||||
$path = '' unless defined $path;
|
||||
$path = '/' if $path eq '';
|
||||
$path = "/$path" unless $path =~ m{^/};
|
||||
return 'https://' . $domain . $path;
|
||||
}
|
||||
|
||||
# basic sanitize host (remove scheme and path)
|
||||
sub normalize_host {
|
||||
my ($domain) = @_;
|
||||
return undef unless defined $domain;
|
||||
$domain =~ s{^https?://}{}i;
|
||||
$domain =~ s{/.*$}{}; # remove path
|
||||
$domain =~ s/:\d+$//; # remove port if any
|
||||
return $domain;
|
||||
}
|
||||
|
||||
# ===== prepare LWP client =====
|
||||
my $ua = LWP::UserAgent->new(timeout => $timeout);
|
||||
# Browser-like user agent to avoid bot blocking
|
||||
$ua->agent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 ".
|
||||
"(KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36");
|
||||
$ua->default_header('Accept' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8');
|
||||
$ua->cookie_jar(HTTP::Cookies->new()); # maintain cookies
|
||||
$ua->max_redirect(7);
|
||||
|
||||
# ===== main =====
|
||||
die "Input file $input_file not found\n" unless -f $input_file;
|
||||
my $domains = read_json_file($input_file);
|
||||
die "Input JSON must be an array\n" unless ref($domains) eq 'ARRAY';
|
||||
|
||||
my @results;
|
||||
my $any_fail = 0;
|
||||
my $total_ssl_ok = 0;
|
||||
my $total_content_ok = 0;
|
||||
|
||||
foreach my $entry (@$domains) {
|
||||
# read fields (tolleranza nomi)
|
||||
my $host = $entry->{host} // '';
|
||||
my $domain = $entry->{domain} // '';
|
||||
my $path = exists $entry->{path} ? $entry->{path} : '';
|
||||
my $word = $entry->{'word-to-check'} // '';
|
||||
my $basic_auth = $entry->{basic_auth} ? 1 : 0;
|
||||
my $user = $entry->{basic_auth_name} // undef;
|
||||
my $pass = $entry->{basic_auth_pass} // $entry->{basic_auth_password} // $entry->{basic_auth_passwd} // undef;
|
||||
|
||||
# build url & ssl host
|
||||
my $url = build_url($domain, $path);
|
||||
my $ssl_host = normalize_host($domain) || $host || '';
|
||||
|
||||
# get cert info (openssl s_client)
|
||||
my $ssl_info = get_cert_info_openssl($ssl_host, $timeout);
|
||||
|
||||
# content check via LWP::UserAgent
|
||||
my $word_ok = 0;
|
||||
my $http_code = undef;
|
||||
my $content_err = undef;
|
||||
|
||||
# prepare request
|
||||
my $req = HTTP::Request->new(GET => $url);
|
||||
# add headers that often avoid 403
|
||||
$req->header('Accept-Language' => 'en-US,en;q=0.9');
|
||||
|
||||
if ($basic_auth && defined $user && defined $pass) {
|
||||
my $b64 = encode_base64("$user:$pass", '');
|
||||
$req->header('Authorization' => "Basic $b64");
|
||||
}
|
||||
|
||||
my $res = eval { $ua->request($req) };
|
||||
if ($@ or !defined $res) {
|
||||
$content_err = $@ || 'request failed';
|
||||
$word_ok = 0;
|
||||
} else {
|
||||
$http_code = $res->code;
|
||||
if ($res->is_success) {
|
||||
my $body = $res->decoded_content(charset => 'none');
|
||||
$word_ok = (index($body, $word) >= 0) ? 1 : 0;
|
||||
} else {
|
||||
$content_err = "HTTP $http_code - " . ($res->message // '');
|
||||
$word_ok = 0;
|
||||
}
|
||||
}
|
||||
|
||||
$total_ssl_ok++ if $ssl_info->{status} == 1;
|
||||
$total_content_ok++ if $word_ok == 1;
|
||||
$any_fail = 1 if ($ssl_info->{status} == 0 || $word_ok == 0);
|
||||
|
||||
push @results, {
|
||||
host => $host,
|
||||
domain => $domain,
|
||||
path => ($path eq '' ? '/' : $path),
|
||||
wordtocheck => $word,
|
||||
wordcheck_ok => $word_ok,
|
||||
sslcheck_ok => $ssl_info->{status} // 0,
|
||||
'ssl-released' => $ssl_info->{issued},
|
||||
'ssl-expiry' => $ssl_info->{expiry},
|
||||
'ssl-company' => $ssl_info->{company},
|
||||
# debug fields
|
||||
content_http_code => defined $http_code ? "$http_code" : undef,
|
||||
content_error => $content_err,
|
||||
ssl_error => $ssl_info->{error},
|
||||
};
|
||||
}
|
||||
|
||||
# write output
|
||||
open my $outfh, '>', $output_file or die "Cannot write $output_file: $!\n";
|
||||
print $outfh encode_json(\@results);
|
||||
close $outfh;
|
||||
|
||||
# manage sld-check-false.html
|
||||
if ($any_fail) {
|
||||
if (open my $fh, '>', $false_html) {
|
||||
print $fh "<html><body><h1>WARNING: some checks failed</h1>\n";
|
||||
print $fh "<p>Generated by check_web_final.pl</p>\n";
|
||||
print $fh "</body></html>\n";
|
||||
close $fh;
|
||||
} else {
|
||||
warn "Cannot write $false_html: $!\n";
|
||||
}
|
||||
} else {
|
||||
unlink $false_html if -f $false_html;
|
||||
}
|
||||
|
||||
# summary
|
||||
print "Check completato. Risultati salvati in $output_file\n";
|
||||
print "Totali: SSL ok = $total_ssl_ok, Content ok = $total_content_ok\n";
|
||||
|
||||
exit 0;
|
||||
63
scripts-backup/generate-report.sh
Executable file
63
scripts-backup/generate-report.sh
Executable file
@@ -0,0 +1,63 @@
|
||||
#!/bin/bash
|
||||
input="web_list.json"
|
||||
output="web_check.json"
|
||||
tmpfile=$(mktemp)
|
||||
|
||||
jq -c '.[]' "$input" | while read -r entry; do
|
||||
host=$(echo "$entry" | jq -r '.host')
|
||||
domain=$(echo "$entry" | jq -r '.domain')
|
||||
path=$(echo "$entry" | jq -r '.path')
|
||||
word=$(echo "$entry" | jq -r '.["word-to-check"]')
|
||||
basic_auth=$(echo "$entry" | jq -r '.basic_auth')
|
||||
user=$(echo "$entry" | jq -r '.basic_auth_name // empty')
|
||||
pass=$(echo "$entry" | jq -r '.basic_auth_pass // empty')
|
||||
|
||||
[[ -z "$path" ]] && path="/"
|
||||
|
||||
# --- SSL check ---
|
||||
ssl_info=$(echo | openssl s_client -servername "$domain" -connect "$domain:443" 2>/dev/null | openssl x509 -noout -dates -issuer)
|
||||
ssl_released=$(echo "$ssl_info" | grep 'notBefore' | cut -d= -f2)
|
||||
ssl_expiry=$(echo "$ssl_info" | grep 'notAfter' | cut -d= -f2)
|
||||
ssl_company=$(echo "$ssl_info" | grep 'issuer' | sed -n 's/.*O=\([^,]*\).*/\1/p')
|
||||
ssl_ok=0
|
||||
if [[ $(date -d "$ssl_expiry" +%s) -gt $(date +%s) ]]; then ssl_ok=1; fi
|
||||
|
||||
# --- Content check ---
|
||||
url="https://$domain$path"
|
||||
if [[ "$basic_auth" == "true" ]]; then
|
||||
content=$(curl -s -u "$user:$pass" "$url")
|
||||
else
|
||||
content=$(curl -s "$url")
|
||||
fi
|
||||
word_ok=0
|
||||
[[ "$content" == *"$word"* ]] && word_ok=1
|
||||
|
||||
# --- Scrivi in tmp JSON ---
|
||||
jq -n \
|
||||
--arg host "$host" \
|
||||
--arg domain "$domain" \
|
||||
--arg path "$path" \
|
||||
--arg word "$word" \
|
||||
--argjson wordcheck_ok "$word_ok" \
|
||||
--argjson sslcheck_ok "$ssl_ok" \
|
||||
--arg ssl_released "$ssl_released" \
|
||||
--arg ssl_expiry "$ssl_expiry" \
|
||||
--arg ssl_company "$ssl_company" \
|
||||
'{
|
||||
host: $host,
|
||||
domain: $domain,
|
||||
path: $path,
|
||||
wordtocheck: $word,
|
||||
wordcheck_ok: $wordcheck_ok,
|
||||
sslcheck_ok: $sslcheck_ok,
|
||||
"ssl-released": $ssl_released,
|
||||
"ssl-expiry": $ssl_expiry,
|
||||
"ssl-company": $ssl_company
|
||||
}' >> "$tmpfile"
|
||||
done
|
||||
|
||||
# --- Combina in array JSON ---
|
||||
jq -s '.' "$tmpfile" > "$output"
|
||||
rm "$tmpfile"
|
||||
|
||||
echo "Check completato. Output salvato in $output"
|
||||
Reference in New Issue
Block a user