forked from RaymiiOrg/certificate-expiry-monitor
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Remy
committed
Aug 6, 2015
0 parents
commit 786395f
Showing
29 changed files
with
1,671 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
# Certificate Expiry Monitor | ||
|
||
## About | ||
|
||
Certificate Expiry Monitor is an open source monitoring tool for certificates. It monitors websites and emails you when the certificates are about to expire. | ||
|
||
See the example site: https://certificatemonitor.org/ | ||
|
||
## Requirements | ||
|
||
- PHP 5.6+ | ||
- OpenSSL | ||
- PHP must allow remote fopen. | ||
|
||
## Installation | ||
|
||
Unpack, change some variables, setup a cronjob and go! | ||
|
||
First get the code and unpack it to your webroot: | ||
|
||
cd /var/www/html/ | ||
git clone https://github.com/RaymiiOrg/certificate-expiry-monitor.git | ||
|
||
Create the database files, outside of your webroot. If you create these inside your webroot, everybody can read them. | ||
|
||
touch /var/www/certificate-expiry-monitor-db/pre_checks.json | ||
touch /var/www/certificate-expiry-monitor-db/checks.json | ||
touch /var/www/certificate-expiry-monitor-db/deleted_checks.json | ||
chown -R $wwwuser /var/www/certificate-expiry-monitor-db/*.json | ||
|
||
These files are used by the tool as database for checks. | ||
|
||
|
||
Change the location of these files in `variables.php`: | ||
|
||
|
||
// set this to a location outside of your webroot so that it cannot be accessed via the internets. | ||
|
||
$pre_check_file = '/var/ww/html/certificate-expiry-monitor/pre_checks.json'; | ||
$check_file = '/var/ww/html/certificate-expiry-monitor/checks.json'; | ||
$deleted_check_file = '/var/ww/html/certificate-expiry-monitor/deleted_checks.json'; | ||
|
||
Also change the `$current_domain` variable, it is used in all the emails. | ||
|
||
$current_domain = "certificatemonitor.org"; | ||
|
||
Set up the cronjob to run once a day: | ||
|
||
# /etc/cron.d/certificate-exipry-monitor | ||
1 1 * * * $wwwuser /path/to/php /var/ww/html/certificate-expiry-monitor/cron.php >> /var/log/certificate-expiry-monitor.log 2>&1 | ||
|
||
|
||
The default timeout for checks is 2 seconds. If this is to fast for your internal services, this can be raised in the `variables.php` file. | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
<?php | ||
// Copyright (C) 2015 Remy van Elst | ||
|
||
// This program is free software: you can redistribute it and/or modify | ||
// it under the terms of the GNU Affero General Public License as published by | ||
// the Free Software Foundation, either version 3 of the License, or | ||
// (at your option) any later version. | ||
|
||
// This program is distributed in the hope that it will be useful, | ||
// but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
// GNU Affero General Public License for more details. | ||
|
||
// You should have received a copy of the GNU Affero General Public License | ||
// along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
|
||
error_reporting(E_ALL & ~E_NOTICE); | ||
foreach (glob("functions/*.php") as $filename) { | ||
require($filename); | ||
} | ||
|
||
require('inc/header.php'); | ||
|
||
echo "<div class='content'><section id='result'>"; | ||
|
||
if ( isset($_POST['email']) && !empty($_POST['email']) && isset($_POST['domains']) && !empty($_POST['domains']) ) { | ||
|
||
$errors = array(); | ||
if (validate_email($_POST['email'])) { | ||
$email = htmlspecialchars($_POST['email']); | ||
} else { | ||
$errors[] = "Invalid email address."; | ||
} | ||
|
||
$domains = validate_domains($_POST['domains']); | ||
if ( count($domains['errors']) >= 1 ) { | ||
foreach ($domains['errors'] as $key => $value) { | ||
$errors[] = $value; | ||
} | ||
} | ||
|
||
if (is_array($errors) && count($errors) != 0) { | ||
$errors = array_unique($errors); | ||
foreach ($errors as $key => $value) { | ||
echo "<div class='alert alert-danger' role='alert'>"; | ||
echo htmlspecialchars($value); | ||
echo "</div>"; | ||
} | ||
echo "Please return and try again.<br>"; | ||
} elseif ( is_array($errors) && count($errors) == 0 && is_array($domains['domains']) && count($domains['domains']) != 0 && count($domains['domains']) < 21) { | ||
echo "<div class='alert alert-info' role='alert'>"; | ||
echo "Email: " . htmlspecialchars($email) . ".<br>"; | ||
echo "</div>"; | ||
foreach ($domains['domains'] as $key => $value) { | ||
$add_domain = add_domain_to_pre_check($value, $email, $_SERVER['REMOTE_ADDR']); | ||
if (is_array($add_domain["errors"]) && count($add_domain["errors"]) != 0) { | ||
$errors = array_unique($add_domain["errors"]); | ||
foreach ($add_domain["errors"] as $key => $err_value) { | ||
echo "<div class='alert alert-danger' role='alert'>"; | ||
echo htmlspecialchars($err_value); | ||
echo "</div>"; | ||
} | ||
} else { | ||
echo "<div class='alert alert-success' role='alert'>"; | ||
echo "Confirmation email sent. Please confirm your subscription email to complete the process.<br>"; | ||
echo "</div>"; | ||
} | ||
} | ||
} else { | ||
echo "<div class='alert alert-danger' role='alert'>"; | ||
echo "Too many domains.<br>"; | ||
echo "Please return and try again.<br>"; | ||
echo "</div>"; | ||
} | ||
} else { | ||
|
||
echo "<div class='alert alert-danger' role='alert'>";; | ||
echo "Error. Domain(s) and email address are required.<br>"; | ||
echo "Please return and try again.<br>"; | ||
echo "</div>"; | ||
} | ||
|
||
|
||
require('inc/faq.php'); | ||
|
||
require('inc/footer.php'); | ||
|
||
?> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
<?php | ||
// Copyright (C) 2015 Remy van Elst | ||
|
||
// This program is free software: you can redistribute it and/or modify | ||
// it under the terms of the GNU Affero General Public License as published by | ||
// the Free Software Foundation, either version 3 of the License, or | ||
// (at your option) any later version. | ||
|
||
// This program is distributed in the hope that it will be useful, | ||
// but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
// GNU Affero General Public License for more details. | ||
|
||
// You should have received a copy of the GNU Affero General Public License | ||
// along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
|
||
error_reporting(E_ALL & ~E_NOTICE); | ||
foreach (glob("functions/*.php") as $filename) { | ||
require($filename); | ||
} | ||
|
||
require('inc/header.php'); | ||
|
||
if ( isset($_GET['id']) && !empty($_GET['id']) ) { | ||
$id = htmlspecialchars($_GET['id']); | ||
$uuid_pattern = "/([a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12})/"; | ||
if (preg_match($uuid_pattern, $id)) { | ||
$add_domain = add_domain_check($id, $_SERVER['REMOTE_ADDR']); | ||
if (is_array($add_domain["errors"]) && count($add_domain["errors"]) != 0) { | ||
$errors = array_unique($add_domain["errors"]); | ||
foreach ($add_domain["errors"] as $key => $err_value) { | ||
echo "<div class='alert alert-danger' role='alert'>"; | ||
echo htmlspecialchars($err_value); | ||
echo "</div>"; | ||
} | ||
} else { | ||
echo "<div class='alert alert-success' role='alert'>"; | ||
echo "Check added. You will now receive notifications on certificate expiration events as described in the FAQ.<br>"; | ||
echo "</div>"; | ||
} | ||
} else { | ||
echo "<div class='alert alert-danger' role='alert'>";; | ||
echo "Error. ID is invalid.<br>"; | ||
echo "Please return and try again.<br>"; | ||
echo "</div>"; | ||
} | ||
} else { | ||
echo "<div class='alert alert-danger' role='alert'>";; | ||
echo "Error. ID is required.<br>"; | ||
echo "Please return and try again.<br>"; | ||
echo "</div>"; | ||
} | ||
|
||
require('inc/faq.php'); | ||
|
||
require('inc/footer.php'); | ||
|
||
?> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,164 @@ | ||
<?php | ||
// Copyright (C) 2015 Remy van Elst | ||
|
||
// This program is free software: you can redistribute it and/or modify | ||
// it under the terms of the GNU Affero General Public License as published by | ||
// the Free Software Foundation, either version 3 of the License, or | ||
// (at your option) any later version. | ||
|
||
// This program is distributed in the hope that it will be useful, | ||
// but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
// GNU Affero General Public License for more details. | ||
|
||
// You should have received a copy of the GNU Affero General Public License | ||
// along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
|
||
error_reporting(E_ALL & ~E_NOTICE); | ||
$result = array(); | ||
if (php_sapi_name() == "cli") { | ||
foreach (glob( __DIR__ . "/functions/*.php") as $filename) { | ||
require($filename); | ||
} | ||
|
||
$removal_queue = array(); | ||
$tmp_check_file = $check_file . ".tmp"; | ||
if (!copy($check_file, $tmp_check_file)) { | ||
echo "Failed to copy $check_file to $tmp_check_file.\n"; | ||
break; | ||
} | ||
|
||
$file = file_get_contents($tmp_check_file); | ||
if ($file === FALSE) { | ||
$result['errors'][] = "Can't open database."; | ||
} | ||
$json_a = json_decode($file, true); | ||
if ($json_a === null && json_last_error() !== JSON_ERROR_NONE) { | ||
$result['errors'][] = "Can't read database: " . htmlspecialchars(json_last_error()); | ||
|
||
} | ||
|
||
if (count($json_a) == 0) { | ||
echo "Empty checklist.\n"; | ||
exit; | ||
} | ||
|
||
foreach ($json_a as $key => $value) { | ||
$domain = $value['domain']; | ||
$email = $value['email']; | ||
echo "Domain: " . $domain . ".\n"; | ||
echo "Email: " . $email . ".\n"; | ||
|
||
$val_domain = validate_domains($domain); | ||
if (count($val_domain['errors']) >= 1 ) { | ||
$errors = $val_domain['errors']; | ||
foreach ($errors as $error_value) { | ||
echo "\t" . $error_value . ". \n"; | ||
} | ||
send_error_mail($domain, $email, $errors); | ||
$json_a[$key]['errors'] += 1; | ||
$check_json = json_encode($json_a); | ||
if(file_put_contents($check_file, $check_json, LOCK_EX)) { | ||
echo "\tError count updated to " . $json_a[$key]['errors'] . ".\n"; | ||
} else { | ||
echo "Can't write database.\n"; | ||
continue; | ||
} | ||
if ($json_a[$key]['errors'] >= 7) { | ||
echo "\tToo many errors. Adding domain to removal queue.\n"; | ||
$removal_queue[] = $key; | ||
} | ||
continue; | ||
} | ||
$raw_chain = get_raw_chain($domain); | ||
$counter = 0; | ||
foreach ($raw_chain['chain'] as $chain_key => $chain_value) { | ||
$counter += 1; | ||
$cert_exp_date = cert_expiry_date($chain_value); | ||
$cert_cn = cert_cn($chain_value); | ||
$cert_expiry = cert_expiry($chain_value); | ||
|
||
echo "\tCert Chain #" . $counter . ". Expiry Date: " . date("Y-m-d H:i:s T", $cert_exp_date) . ". Common Name: " . $cert_cn . "\n"; | ||
|
||
cert_expiry_emails($domain, $email, $cert_expiry, $chain_value); | ||
|
||
} | ||
$file = file_get_contents($check_file); | ||
if ($file === FALSE) { | ||
echo "\tCan't open database.\n"; | ||
continue; | ||
} | ||
$json_a = json_decode($file, true); | ||
if ($json_a === null && json_last_error() !== JSON_ERROR_NONE) { | ||
echo "\tCan't read database\n"; | ||
continue; | ||
} | ||
if ($json_a[$key]['errors'] != 0) { | ||
$json_a[$key]['errors'] = 0; | ||
$check_json = json_encode($json_a); | ||
if(file_put_contents($check_file, $check_json, LOCK_EX)) { | ||
echo "\tError count reset to 0.\n"; | ||
} else { | ||
echo "Can't write database.\n"; | ||
} | ||
} | ||
|
||
echo "\n"; | ||
|
||
} | ||
|
||
if ( count($removal_queue) != 0 ) { | ||
echo "Processing removal queue.\n"; | ||
foreach ($removal_queue as $remove_key => $remove_value) { | ||
$unsub_url = "http://" . $current_domain . "/unsubscribe.php?id=" . $remove_value; | ||
$file = file_get_contents($unsub_url); | ||
if ($file === FALSE) { | ||
echo "\tRemoval Error.\n"; | ||
continue; | ||
} else { | ||
echo "\tRemoved $remove_value.\n"; | ||
} | ||
} | ||
} | ||
|
||
// remove non-confirmed subs older than 7 days | ||
$tmp_pre_check_file = $pre_check_file . ".tmp"; | ||
if (!copy($pre_check_file, $tmp_pre_check_file)) { | ||
echo "Failed to copy $pre_check_file to $tmp_pre_check_file.\n"; | ||
} | ||
|
||
$tmp_pre_file = file_get_contents($tmp_pre_check_file); | ||
if ($tmp_pre_file === FALSE) { | ||
echo "Can't open database.\n"; | ||
} | ||
$tmp_pre_json_a = json_decode($tmp_pre_file, true); | ||
if ($tmp_pre_json_a === null && json_last_error() !== JSON_ERROR_NONE) { | ||
echo "Can't read database.\n"; | ||
} | ||
|
||
if (count($tmp_pre_json_a) == 0) { | ||
echo "Empty pre-checklist.\n"; | ||
exit; | ||
} | ||
|
||
foreach ($tmp_pre_json_a as $pre_key => $pre_value) { | ||
$today = strtotime(date("Y-m-d")); | ||
$pre_add_date = strtotime(date("Y-m-d",$pre_value['pre_add_date'])); | ||
$pre_add_diff = $today - $pre_add_date; | ||
if ($pre_add_diff > "604800") { | ||
unset($tmp_pre_json_a[$pre_key]); | ||
$tmp_pre_json = json_encode($tmp_pre_json_a); | ||
if(file_put_contents($pre_check_file, $tmp_pre_json, LOCK_EX)) { | ||
echo "Subscription for " . $pre_value['domain'] . " from " . $pre_value['email'] . " older than 7 days. Removing from subscription list.\n"; | ||
} else { | ||
echo "Failed to remove subscription for " . $pre_value['domain'] . " from " . $pre_value['email'] . " older than 7 days from subscription list.\n"; | ||
} | ||
} | ||
} | ||
|
||
} else { | ||
header('HTTP/1.0 301 Moved Permanently'); | ||
header('Location: /'); | ||
} | ||
|
||
?> |
Large diffs are not rendered by default.
Oops, something went wrong.
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
/* | ||
Copyright (C) 2015 Remy van Elst | ||
This program is free software: you can redistribute it and/or modify | ||
it under the terms of the GNU Affero General Public License as published by | ||
the Free Software Foundation, either version 3 of the License, or | ||
(at your option) any later version. | ||
This program is distributed in the hope that it will be useful, | ||
but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
GNU Affero General Public License for more details. | ||
You should have received a copy of the GNU Affero General Public License | ||
along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
*/ | ||
|
||
.footer { | ||
position: absolute; | ||
bottom: 0; | ||
width: 100%; | ||
padding-top: 5px; | ||
/* Set the fixed height of the footer here */ | ||
border-top: 1px gray dashed; | ||
height: 35px; | ||
background-color: #fff; | ||
} |
Binary file not shown.
Binary file not shown.
Empty file.
Oops, something went wrong.