From 1743b6e3f9d0af8111f52abdcecf4f2cfe954a87 Mon Sep 17 00:00:00 2001 From: av2k Date: Tue, 1 Aug 2017 10:06:50 +0200 Subject: [PATCH] Add Certificate checking --- index.php | 2 +- src/bootstrap.php | 3 +- src/includes/functions.inc.php | 17 +- src/lang/de_DE.lang.php | 3 + src/lang/en_US.lang.php | 3 + src/lang/ja_JP.lang.php | 327 ++++++++++++++++++ src/psm/Module/Error/ErrorModule.php | 2 +- .../Controller/AbstractServerController.php | 1 + .../Server/Controller/ServerController.php | 5 + src/psm/Util/Install/Installer.php | 4 +- src/psm/Util/Server/ArchiveManager.php | 41 ++- src/psm/Util/Server/Archiver/LogsArchiver.php | 20 +- src/psm/Util/Server/ServerValidator.php | 13 + src/psm/Util/Server/Updater/StatusUpdater.php | 45 ++- .../module/server/server/update.tpl.html | 6 + 15 files changed, 459 insertions(+), 33 deletions(-) create mode 100644 src/lang/ja_JP.lang.php diff --git a/index.php b/index.php index ed223c87..87ac4d13 100644 --- a/index.php +++ b/index.php @@ -45,4 +45,4 @@ try { // it that somehow also doesnt exist, we have a bit of an issue // and we really have no reason catch it $router->run(PSM_MODULE_DEFAULT); -} \ No newline at end of file +} diff --git a/src/bootstrap.php b/src/bootstrap.php index ec134fe6..03a164ba 100644 --- a/src/bootstrap.php +++ b/src/bootstrap.php @@ -92,4 +92,5 @@ if(!defined('PSM_INSTALL') || !PSM_INSTALL) { } $lang = psm_get_conf('language', 'en_US'); -psm_load_lang($lang); \ No newline at end of file +psm_load_lang($lang); + diff --git a/src/includes/functions.inc.php b/src/includes/functions.inc.php index b509929d..c216fc24 100644 --- a/src/includes/functions.inc.php +++ b/src/includes/functions.inc.php @@ -355,6 +355,21 @@ function psm_curl_get($href, $header = false, $body = true, $timeout = null, $ad return $result; } +/** + * Get SSL certificate information about the peer + * + * @param string $href + * @return array + */ +function psm_cert_info_get($href, $port) { + $host = parse_url($href, PHP_URL_HOST); + $stream_context = stream_context_create( array( "ssl" => array("capture_peer_cert" => TRUE ) ) ); + $stream_client = stream_socket_client("ssl://" . $host . ":$port", $errno, $errstr, 30, STREAM_CLIENT_CONNECT, $stream_context ); + $cert = stream_context_get_params( $stream_client ); + $cert_info = openssl_x509_parse( $cert['options']['ssl']['peer_certificate'] ); + return $cert_info; +} + /** * Get a "nice" timespan message * @@ -728,4 +743,4 @@ function psm_password_decrypt($key, $encryptedString) ); return $decrypted; -} \ No newline at end of file +} diff --git a/src/lang/de_DE.lang.php b/src/lang/de_DE.lang.php index 65da7201..8935a72e 100644 --- a/src/lang/de_DE.lang.php +++ b/src/lang/de_DE.lang.php @@ -155,6 +155,8 @@ $sm_lang = array( 'hour' => 'Stunde', 'warning_threshold' => 'Warnschwelle', 'warning_threshold_description' => 'Anzahl der fehlgeschlagenen Überprüfungen, bevor der Status als offline markiert wird.', + 'ssl_cert_expiry_days' => 'Zertifikatsgültigkeit', + 'ssl_cert_expiry_days_description' => 'Anzahl der Tage, die das SSL-Zertifikat noch gültig sein soll.', 'chart_last_week' => 'Letzte Woche', 'chart_history' => 'Historie', // Charts date format according jqPlot date format http://www.jqplot.com/docs/files/plugins/jqplot-dateAxisRenderer-js.html @@ -172,6 +174,7 @@ $sm_lang = array( 'error_server_ip_bad_website' => 'Die eingegebene Webseiten-URL ist ungültig.', 'error_server_type_invalid' => 'Der gewählte Server-Typ ist ungültig.', 'error_server_warning_threshold_invalid' => 'Die Warnschwelle muss eine gültige ganze Zahl größer als 0 sein.', + 'error_server_ssl_cert_expiry_days_invalid' => 'Die verbleibenden Tage des SSL-Zertifikats müssen eine gültige ganze Zahl größer oder gleich 0 sein.', ), 'config' => array( 'general' => 'Allgemein', diff --git a/src/lang/en_US.lang.php b/src/lang/en_US.lang.php index 99012424..8a1aeb6c 100644 --- a/src/lang/en_US.lang.php +++ b/src/lang/en_US.lang.php @@ -168,6 +168,8 @@ $sm_lang = array( 'hour' => 'Hour', 'warning_threshold' => 'Warning threshold', 'warning_threshold_description' => 'Number of failed checks required before it is marked offline.', + 'ssl_cert_expiry_days' => 'SSL Certificate Validity', + 'ssl_cert_expiry_days_description' => 'The minimum remaining days the SSL certificate is still valid.', 'chart_last_week' => 'Last week', 'chart_history' => 'History', // Charts date format according jqPlot date format http://www.jqplot.com/docs/files/plugins/jqplot-dateAxisRenderer-js.html @@ -185,6 +187,7 @@ $sm_lang = array( 'error_server_ip_bad_website' => 'The website URL is not valid.', 'error_server_type_invalid' => 'The selected server type is invalid.', 'error_server_warning_threshold_invalid' => 'The warning threshold must be a valid integer greater than 0.', + 'error_server_ssl_cert_expiry_days' => 'The remaining days for SSL certificate validity must be a valid integer greater than or equal to 0.', ), 'config' => array( 'general' => 'General', diff --git a/src/lang/ja_JP.lang.php b/src/lang/ja_JP.lang.php new file mode 100644 index 00000000..ad07e962 --- /dev/null +++ b/src/lang/ja_JP.lang.php @@ -0,0 +1,327 @@ +. + * + * @package phpservermon + * @author Pepijn Over + * @copyright Copyright (c) 2008-2017 Pepijn Over + * @license http://www.gnu.org/licenses/gpl.txt GNU GPL v3 + * @version Release: v3.2.0 + * @link http://www.phpservermonitor.org/ + **/ + +$sm_lang = array( + 'name' => '日本語 - Japanese', + 'locale' => array('ja_JP.UTF-8', 'ja_JP', 'Japan', 'Japanese'), + 'locale_tag' => 'ja', + 'locale_dir' => 'ltr', + 'system' => array( + 'title' => 'サーバーモニター', + 'install' => 'インストール', + 'action' => 'アクション', + 'save' => 'セーブ', + 'edit' => '編集', + 'delete' => '削除', + 'date' => '日時', + 'message' => 'メッセージ', + 'yes' => 'はい', + 'no' => 'いいえ', + 'insert' => '挿入', + 'add_new' => '新規に追加', + 'update_available' => '新しいバージョン({version}) がリリースされています。ここから入手可能です: http://www.phpservermonitor.org.', + 'back_to_top' => 'トップに戻る', + 'go_back' => '戻る', + 'ok' => 'OK', + 'cancel' => 'キャンセル', + // date/time format according the strftime php function format parameter http://php.net/manual/function.strftime.php + 'short_day_format' => '%B %e', + 'long_day_format' => '%B %e, %Y', + 'yesterday_format' => '昨日の %k:%M', + 'other_day_format' => '%A at %k:%M', + 'never' => 'なし', + 'hours_ago' => '%d 時間前', + 'an_hour_ago' => '1時間くらい前', + 'minutes_ago' => '%d 分前', + 'a_minute_ago' => '1分くらい前', + 'seconds_ago' => '%d 秒前', + 'a_second_ago' => '<1秒', + ), + 'menu' => array( + 'config' => '設定', + 'server' => 'サーバー', + 'server_log' => 'ログ', + 'server_status' => 'ステータス', + 'server_update' => 'アップデート', + 'user' => 'ユーザー', + 'help' => 'ヘルプ', + ), + 'users' => array( + 'user' => 'ユーザー', + 'name' => '名前', + 'user_name' => 'ユーザーネーム', + 'password' => 'パスワード', + 'password_repeat' => 'パスワードを繰り返す', + 'password_leave_blank' => '空白のままにしておく', + 'level' => 'レベル', + 'level_10' => '管理者(Administrator)', + 'level_20' => 'ユーザー(User)', + 'level_description' => '管理者(Administrators) はフルアクセス権があります:サーバーの管理、 ユーザーとグローバル設定を変更できます。
ユーザー(Users)は、割り当てられたサーバーのアップデータのみを表示して実行できます。', + 'mobile' => 'モバイル', + 'email' => 'メールアドレス', + 'pushover' => 'プッシュオーバー', + 'pushover_description' => 'プッシュオーバーサービスは、リアルタイムで通知を受け取るのが簡単にできます。詳細についてはこちらをご覧ください: https://pushover.net/', + 'pushover_key' => 'プッシュオーバーキー', + 'pushover_device' => 'プッシュオーバーデバイス', + 'pushover_device_description' => '指定したデバイスに送信します。空欄ですべてのデバイスに送信できます。', + 'delete_title' => 'ユーザーを削除', + 'delete_message' => '本当にユーザーを削除しますか?: \'%1\'?', + 'deleted' => 'ユーザーを削除しました。', + 'updated' => 'ユーザー情報を更新しました。', + 'inserted' => 'ユーザーを追加しました。', + 'profile' => 'プロフィール', + 'profile_updated' => 'あなたのプロフィールは更新されました。', + 'error_user_name_bad_length' => 'ユーザーネームは2~64文字以内で入力してください。', + 'error_user_name_invalid' => 'ユーザー名は、アルファベット、数字とアンダーバーのみを含むことができます。', + 'error_user_name_exists' => '登録しようとしたユーザー名は既にデータベースに登録されています。', + 'error_user_email_bad_length' => 'メールアドレスは5~255文字以内で入力してください。', + 'error_user_email_invalid' => 'メールアドレスが無効です。', + 'error_user_level_invalid' => '指定したレベルが無効です。', + 'error_user_no_match' => 'このユーザー名は存在しません。', + 'error_user_password_invalid' => 'パスワードが無効です。', + 'error_user_password_no_match' => '確認のパスワードが一致しません。', + ), + 'log' => array( + 'title' => 'ログエントリー', + 'type' => 'タイプ', + 'status' => 'ステータス', + 'email' => 'メール', + 'sms' => 'SMS', + 'pushover' => 'プッシュオーバー', + 'no_logs' => 'ログがありません', + ), + 'servers' => array( + 'server' => 'サーバー', + 'status' => 'ステータス', + 'label' => 'ラベル', + 'domain' => 'ドメイン/IP', + 'timeout' => 'タイムアウト', + 'timeout_description' => '指定した秒数、サーバーのレスポンスを待ちます。', + 'authentication_settings' => '認証設定(オプション)', + 'website_username' => 'ユーザー名', + 'website_username_description' => 'ユーザー名でウェブサイトにアクセスします。 (サポートはApache認証のみです。)', + 'website_password' => 'パスワード', + 'website_password_description' => 'Password to access the site. The password is encrypted in the database.', + 'fieldset_monitoring' => 'モニター', + 'fieldset_permissions' => '権限', + 'port' => 'ポート', + 'custom_port' => 'カスタムポート', + 'popular_ports' => '主要なポート', + 'please_select' => '選択してください', + 'type' => 'タイプ', + 'type_website' => 'ウェブサイト', + 'type_service' => 'サービス', + 'type_ping' => 'Ping', + 'pattern' => '文字列/パターンを検索', + 'pattern_description' => '指定した文字列/パターンが存在しない場合は、「オフライン」としてマークされます。また、標準的な計算式は許可されています。', + 'last_check' => '最後の確認', + 'last_online' => '最後のオンライン', + 'monitoring' => 'モニタリング', + 'no_monitoring' => 'モニタリングなし', + 'email' => 'メール', + 'send_email' => 'メールを送信', + 'sms' => 'SMS', + 'send_sms' => 'SMSを送信', + 'pushover' => 'プッシュオーバー', + 'users' => 'ユーザー', + 'delete_title' => 'サーバーを削除', + 'delete_message' => '本当にこのサーバーを削除しますか?: \'%1\'?', + 'deleted' => 'サーバーを削除しました。', + 'updated' => 'サーバーを更新しました。', + 'inserted' => 'サーバーを追加しました。', + 'latency' => 'レイテンシ', + 'latency_max' => 'レイテンシ(最大)', + 'latency_min' => 'レイテンシ(最小)', + 'latency_avg' => 'レイテンシ(アベレージ)', + 'uptime' => '稼働時間', + 'year' => '年', + 'month' => '月', + 'week' => '週間', + 'day' => '日', + 'hour' => '時間', + 'warning_threshold' => '警告閾値', + 'warning_threshold_description' => 'オフラインとしてマークされる前に失敗したチェックの数', + 'chart_last_week' => '最後の週間', + 'chart_history' => '履歴', + // Charts date format according jqPlot date format http://www.jqplot.com/docs/files/plugins/jqplot-dateAxisRenderer-js.html + 'chart_day_format' => '%Y-%m-%d', + 'chart_long_date_format' => '%Y-%m-%d %H:%M:%S', + 'chart_short_date_format' => '%m/%d %H:%M', + 'chart_short_time_format' => '%H:%M', + 'warning_notifications_disabled_sms' => 'SMS 通知は無効です。', + 'warning_notifications_disabled_email' => 'メール通知は無効です。', + 'warning_notifications_disabled_pushover' => 'プッシュオーバー通知は無効です。', + 'error_server_no_match' => 'サーバーが見つかりません', + 'error_server_label_bad_length' => 'ラベルは1~255文字以内で入力してください。', + 'error_server_ip_bad_length' => 'ドメイン/IPは1~255文字以内で入力してください。', + 'error_server_ip_bad_service' => '無効なIPです。', + 'error_server_ip_bad_website' => 'ウェブサイトのURLが無効です。', + 'error_server_type_invalid' => '選択されたサーバータイプが無効です。', + 'error_server_warning_threshold_invalid' => '警告のしきい値は、0より大きい有効な整数でなければなりません。', + ), + 'config' => array( + 'general' => '基本', + 'language' => '言語', + 'show_update' => 'アップデートをチェックしますか?', + 'password_encrypt_key' => '暗号鍵パスワード', + 'password_encrypt_key_note' => 'このキーは、Webサイトにアクセスするためにサーバーに保存されているパスワードを暗号化するために使用されます。 キーが変更された場合、保存されたパスワードは無効です!', + 'proxy' => 'プロキシを有効化する', + 'proxy_url' => 'プロキシのURL', + 'proxy_user' => 'プロキシのユーザー名', + 'proxy_password' => 'プロキシのパスワード', + 'email_status' => 'メールの送信を許可', + 'email_from_email' => 'アドレスからのメール', + 'email_from_name' => '名前からのメール', + 'email_smtp' => 'SMTPを有効にしますか?', + 'email_smtp_host' => 'SMTPホスト', + 'email_smtp_port' => 'SMTPポート', + 'email_smtp_security' => 'SMTPセキュリティ', + 'email_smtp_security_none' => 'なし', + 'email_smtp_username' => 'SMTPのユーザー名', + 'email_smtp_password' => 'SMTPのパスワード', + 'email_smtp_noauth' => '空白で認証なしになります', + 'sms_status' => 'テキストメッセージの送信を許可する', + 'sms_gateway' => 'このゲートウェイは、メッセージの送信に使用されます。', + 'sms_gateway_mosms' => 'Mosms', + 'sms_gateway_mollie' => 'Mollie', + 'sms_gateway_spryng' => 'Spryng', + 'sms_gateway_inetworx' => 'Inetworx', + 'sms_gateway_clickatell' => 'Clickatell', + 'sms_gateway_textmarketer' => 'Textmarketer', + 'sms_gateway_smsglobal' => 'SMSGlobal', + 'sms_gateway_octopush' => 'Octopush', + 'sms_gateway_smsit' => 'Smsit', + 'sms_gateway_freevoipdeal' => 'FreeVoipDeal', + 'sms_gateway_freemobilesms' => 'FreeMobileSMS', + 'sms_gateway_clicksend' => 'ClickSend', + 'sms_gateway_nexmo' => 'Nexmo', + 'sms_gateway_smsgw' => 'SMSgw', + 'sms_gateway_username' => 'ゲートウェイのユーザー名', + 'sms_gateway_password' => 'ゲートウェイのパスワード', + 'sms_from' => '送信者の電話番号:', + 'pushover_status' => 'プッシュオーバーのメッセージを送信することを許可する', + 'pushover_description' => 'プッシュオーバーは、リアルタイムの通知を簡単に取得できるサービスです。 詳細については、ウェブサイトをご覧ください。', + 'pushover_clone_app' => 'クリックでプッシュオーバーアプリケーションを作成できます。', + 'pushover_api_token' => 'プッシュオーバーアプリケーションのAPIトークン', + 'pushover_api_token_description' => 'プッシュオーバーを使用するには、事前にウェブサイトでアプリを登録してApp APIトークンを入力する必要があります。', + 'alert_type' => '通知するタイミングを選択', + 'alert_type_description' => '状態の変化: '. + 'サーバーのステータスが変更されたときに通知を受け取ります。 だからオンライン -> オフラインまたはオフライン -> オンライン。
'. + '
オフライン: '. + 'サーバーが*初めての間*オフラインになったときに通知を受け取ります。 例えば、'. + 'あなたのcronの仕事は15分ごとです。あなたのサーバーは午前1時にダウンし、午前6時まで停止します。 '. + '午前1時に1つの通知が届きます。
'. + '
常に: '. + 'サイトが数時間にわたってオフラインになっていても、スクリプトが実行され、サイトが停止するたびに通知を受け取ります。', + 'alert_type_status' => '状況の変化', + 'alert_type_offline' => 'オフライン', + 'alert_type_always' => '常に', + 'alert_proxy' => '有効にしても、プロキシはサービスに使用されません', + 'alert_proxy_url' => 'フォーマット: ホスト:ポート', + 'log_status' => 'ログステータス', + 'log_status_description' => 'ログステータスがTRUEに設定されている場合、モニターは通知設定が渡されるたびにイベントを記録します。', + 'log_email' => 'スクリプトによって送信された電子メールを記録する', + 'log_sms' => 'スクリプトによって送信されたテキストメッセージを記録する', + 'log_pushover' => 'スクリプトによって送信されたプッシュオーバーメッセージを記録する', + 'updated' => '設定は更新されました。', + 'tab_email' => 'メール', + 'tab_sms' => 'SMS', + 'tab_pushover' => 'プッシュオーバー', + 'settings_email' => 'メール設定', + 'settings_sms' => 'テキストメッセージ設定', + 'settings_pushover' => 'プッシュオーバー設定', + 'settings_notification' => '通知設定', + 'settings_log' => 'ログ設定', + 'settings_proxy' => 'プロキシ設定', + 'auto_refresh' => '自動更新', + 'auto_refresh_servers' => + 'サーバーページを自動更新します。
'. + ''. + '時間を秒で指定し、0に設定すると更新しません。'. + '', + 'seconds' => '秒', + 'test' => 'テスト', + 'test_email' => 'あなたのユーザープロフィールで指定されたアドレスに電子メールが送信されます。', + 'test_sms' => 'あなたのユーザープロフィールで指定された電話番号にSMSが送信されます。', + 'test_pushover' => 'あなたのユーザープロフィールで指定されたユーザー キー/デバイスにプッシュオーバーが送信されます。', + 'send' => '送信', + 'test_subject' => 'テスト', + 'test_message' => 'これはテストメッセージです', + 'email_sent' => 'メールが送信されました', + 'email_error' => 'メールを送信中にエラーが発生しました', + 'sms_sent' => 'SMSが送信されました', + 'sms_error' => 'SMSを送信中にエラーが発生しました', + 'sms_error_nomobile' => 'テストSMSの送信に失敗: あなたのプロフィールに有効な電話番号がありません', + 'pushover_sent' => 'プッシュオーバー通知が送信されました', + 'pushover_error' => 'プッシュオーバー通知を送信中にエラーが発生しました: %s', + 'pushover_error_noapp' => 'テスト通知の送信に失敗しました:グローバル設定にAPIトークンがありません', + 'pushover_error_nokey' => 'テスト通知の送信に失敗しました:あなたのプロフィールに有効なプッシュオーバーキーがありません', + 'log_retention_period' => 'ログ保存期間', + 'log_retention_period_description' => '通知のログおよびサーバー稼働時間のアーカイブを保持する日数。 ログのクリーンアップを無効にするには、0を入力します。', + 'log_retention_days' => '日', + ), + // for newlines in the email messages use
+ 'notifications' => array( + 'off_sms' => 'サーバー \'%LABEL%\' はダウンしています: ip=%IP%, ポート=%PORT%. エラー=%ERROR%', + 'off_email_subject' => '重要: サーバー \'%LABEL%\' がダウンしています!', + 'off_email_body' => "サーバーへの接続に失敗しました:

Server: %LABEL%
IP: %IP%
ポート: %PORT%
エラー: %ERROR%
日時: %DATE%", + 'off_pushover_title' => 'サーバー \'%LABEL%\' がダウンしています!', + 'off_pushover_message' => "サーバーへの接続に失敗しました:

Server: %LABEL%
IP: %IP%
ポート: %PORT%
エラー: %ERROR%
日時: %DATE%", + 'on_sms' => 'サーアb- \'%LABEL%\' は動作しています: ip=%IP%, port=%PORT%', + 'on_email_subject' => '重要: サーバー \'%LABEL%\' は動作しています', + 'on_email_body' => "サーバー '%LABEL%' は動作中です:

サーバー: %LABEL%
IP: %IP%
ポート: %PORT%
日時: %DATE%", + 'on_pushover_title' => 'サーバー \'%LABEL%\' は動作しています', + 'on_pushover_message' => "サーバー '%LABEL%' は動作中です:

サーバー: %LABEL%
IP: %IP%
ポート: %PORT%
日時: %DATE%", + ), + 'login' => array( + 'welcome_usermenu' => 'ようこそ、 %user_name%', + 'title_sign_in' => 'サインインしてください。', + 'title_forgot' => 'パスワードを忘れましたか?', + 'title_reset' => 'パスワードをリセットする', + 'submit' => '送信', + 'remember_me' => 'ログイン状態を保持する', + 'login' => 'ログイン', + 'logout' => 'ログアウト', + 'username' => 'ユーザー名', + 'password' => 'パスワード', + 'password_repeat' => 'パスワードを繰り返してください', + 'password_forgot' => 'パスワードを忘れましたか?', + 'password_reset' => 'パスワードをリセットする', + 'password_reset_email_subject' => 'PHP Server Monitorのパスワードをリセットする', + 'password_reset_email_body' => 'パスワードをリセットするには、次のリンクを使用してください。 1時間で期限切れになりますのでご注意ください。

%link%', + 'error_user_incorrect' => '指定されたユーザー名が見つかりませんでした。', + 'error_login_incorrect' => '情報が間違っています。', + 'error_login_passwords_nomatch' => '指定されたパスワードが一致しません。', + 'error_reset_invalid_link' => '指定したリセットリンクは無効です。', + 'success_password_forgot' => 'パスワードをリセットする方法に関する情報が電子メールで送信されました。', + 'success_password_reset' => 'パスワードは正常にリセットされました。ログインしてください。', + ), + 'error' => array( + '401_unauthorized' => '未認証', + '401_unauthorized_description' => 'このページを表示する権限がありません。', + ), +); diff --git a/src/psm/Module/Error/ErrorModule.php b/src/psm/Module/Error/ErrorModule.php index 434831d5..9bb2c6b8 100644 --- a/src/psm/Module/Error/ErrorModule.php +++ b/src/psm/Module/Error/ErrorModule.php @@ -43,4 +43,4 @@ class ErrorModule implements ModuleInterface { ); } -} +} \ No newline at end of file diff --git a/src/psm/Module/Server/Controller/AbstractServerController.php b/src/psm/Module/Server/Controller/AbstractServerController.php index 8f01f61d..7a25b76d 100644 --- a/src/psm/Module/Server/Controller/AbstractServerController.php +++ b/src/psm/Module/Server/Controller/AbstractServerController.php @@ -77,6 +77,7 @@ abstract class AbstractServerController extends AbstractController { `s`.`pushover`, `s`.`warning_threshold`, `s`.`warning_threshold_counter`, + `s`.`ssl_cert_expiry_days`, `s`.`timeout`, `s`.`website_username`, `s`.`website_password` diff --git a/src/psm/Module/Server/Controller/ServerController.php b/src/psm/Module/Server/Controller/ServerController.php index 667158b3..80c135c2 100644 --- a/src/psm/Module/Server/Controller/ServerController.php +++ b/src/psm/Module/Server/Controller/ServerController.php @@ -203,6 +203,7 @@ class ServerController extends AbstractServerController { 'edit_value_warning_threshold' => $edit_server['warning_threshold'], 'edit_website_username' => $edit_server['website_username'], 'edit_website_password' => empty($edit_server['website_password']) ? '' : sha1($edit_server['website_password']), + 'edit_value_ssl_cert_expiry_days' => $edit_server['ssl_cert_expiry_days'], 'edit_type_selected_' . $edit_server['type'] => 'selected="selected"', 'edit_active_selected_' . $edit_server['active'] => 'selected="selected"', 'edit_email_selected_' . $edit_server['email'] => 'selected="selected"', @@ -268,6 +269,7 @@ class ServerController extends AbstractServerController { 'header_name' => psm_POST('header_name', ''), 'header_value' => psm_POST('header_value', ''), 'warning_threshold' => intval(psm_POST('warning_threshold', 0)), + 'ssl_cert_expiry_days' => intval(psm_POST('ssl_cert_expiry_days', 0)), 'active' => in_array($_POST['active'], array('yes', 'no')) ? $_POST['active'] : 'no', 'email' => in_array($_POST['email'], array('yes', 'no')) ? $_POST['email'] : 'no', 'sms' => in_array($_POST['sms'], array('yes', 'no')) ? $_POST['sms'] : 'no', @@ -303,6 +305,7 @@ class ServerController extends AbstractServerController { $server_validator->type($clean['type']); $server_validator->ip($clean['ip'], $clean['type']); $server_validator->warningThreshold($clean['warning_threshold']); + $server_validator->sslCertExpiryDays($clean['ssl_cert_expiry_days']); } catch(\InvalidArgumentException $ex) { $this->addMessage(psm_get_lang('servers', 'error_' . $ex->getMessage()), 'error'); return $this->executeEdit(); @@ -482,6 +485,8 @@ class ServerController extends AbstractServerController { 'label_users' => psm_get_lang('servers', 'users'), 'label_warning_threshold' => psm_get_lang('servers', 'warning_threshold'), 'label_warning_threshold_description' => psm_get_lang('servers', 'warning_threshold_description'), + 'label_ssl_cert_expiry_days' => psm_get_lang('servers', 'ssl_cert_expiry_days'), + 'label_ssl_cert_expiry_days_description' => psm_get_lang('servers', 'ssl_cert_expiry_days_description'), 'label_action' => psm_get_lang('system', 'action'), 'label_save' => psm_get_lang('system', 'save'), 'label_go_back' => psm_get_lang('system', 'go_back'), diff --git a/src/psm/Util/Install/Installer.php b/src/psm/Util/Install/Installer.php index ad7d107e..5d705137 100644 --- a/src/psm/Util/Install/Installer.php +++ b/src/psm/Util/Install/Installer.php @@ -237,6 +237,7 @@ class Installer { `pushover` enum('yes','no') NOT NULL default 'yes', `warning_threshold` mediumint(1) unsigned NOT NULL DEFAULT '1', `warning_threshold_counter` mediumint(1) unsigned NOT NULL DEFAULT '0', + `ssl_cert_expiry_days` mediumint(1) unsigned NOT NULL DEFAULT '0', `timeout` smallint(1) unsigned NULL DEFAULT NULL, `website_username` varchar(255) DEFAULT NULL, `website_password` varchar(255) DEFAULT NULL, @@ -321,7 +322,7 @@ class Installer { $this->execSQL($queries); } - + /** * Upgrade for v3.0.0 release */ @@ -490,6 +491,7 @@ class Installer { protected function upgrade321() { $queries = array(); $queries[] = "ALTER TABLE `" . PSM_DB_PREFIX . "servers` ADD COLUMN `header_name` VARCHAR(255) AFTER `pattern`, ADD COLUMN `header_value` VARCHAR(255) AFTER `header_name`"; + $queries[] = "ALTER TABLE `" . PSM_DB_PREFIX . "servers` ADD `ssl_cert_expiry_days` MEDIUMINT( 1 ) UNSIGNED NOT NULL DEFAULT '0' AFTER `warning_threshold_counter`"; $this->execSQL($queries); } } diff --git a/src/psm/Util/Server/ArchiveManager.php b/src/psm/Util/Server/ArchiveManager.php index 94dbc54a..8d3926ef 100644 --- a/src/psm/Util/Server/ArchiveManager.php +++ b/src/psm/Util/Server/ArchiveManager.php @@ -52,49 +52,55 @@ class ArchiveManager { */ protected $retention_period; - public function __construct(\psm\Service\Database $db) { + public function __construct( \psm\Service\Database $db ) { $this->db = $db; - $this->setRetentionPeriod(psm_get_conf('log_retention_period', 365)); + $this->setRetentionPeriod( psm_get_conf( 'log_retention_period', 365 ) ); - $this->archivers[] = new Archiver\UptimeArchiver($db); - $this->archivers[] = new Archiver\LogsArchiver($db); + $this->archivers[] = new Archiver\UptimeArchiver( $db ); + $this->archivers[] = new Archiver\LogsArchiver( $db ); } /** * Archive one or more servers. + * * @param int $server_id + * * @return boolean */ - public function archive($server_id = null) { + public function archive( $server_id = null ) { $result = true; - foreach($this->archivers as $archiver) { - if(!$archiver->archive($server_id)) { + foreach ( $this->archivers as $archiver ) { + if ( ! $archiver->archive( $server_id ) ) { $result = false; } } + return $result; } /** * Cleanup old records for one or more servers + * * @param int $server_id + * * @return boolean */ - public function cleanup($server_id = null) { + public function cleanup( $server_id = null ) { $result = true; - if(!$this->retention_period) { + if ( ! $this->retention_period ) { // cleanup is disabled return $result; } $retdate = new \DateTime(); - $retdate->sub($this->retention_period); + $retdate->sub( $this->retention_period ); - foreach($this->archivers as $archiver) { - if(!$archiver->cleanup($retdate, $server_id)) { + foreach ( $this->archivers as $archiver ) { + if ( ! $archiver->cleanup( $retdate, $server_id ) ) { $result = false; } } + return $result; } @@ -102,18 +108,21 @@ class ArchiveManager { * Set retention period for this archive run. * * Set period to 0 to disable cleanup altogether. + * * @param \DateInterval|int $period \DateInterval object or number of days (int) + * * @return \psm\Util\Server\ArchiveManager */ - public function setRetentionPeriod($period) { - if(is_object($period) && $period instanceof \DateInterval) { + public function setRetentionPeriod( $period ) { + if ( is_object( $period ) && $period instanceof \DateInterval ) { $this->retention_period = $period; - } elseif(intval($period) == 0) { + } elseif ( intval( $period ) == 0 ) { // cleanup disabled $this->retention_period = false; } else { - $this->retention_period = new \DateInterval('P' . intval($period) . 'D'); + $this->retention_period = new \DateInterval( 'P' . intval( $period ) . 'D' ); } + return $this; } } \ No newline at end of file diff --git a/src/psm/Util/Server/Archiver/LogsArchiver.php b/src/psm/Util/Server/Archiver/LogsArchiver.php index 619d7fa2..dd647f73 100644 --- a/src/psm/Util/Server/Archiver/LogsArchiver.php +++ b/src/psm/Util/Server/Archiver/LogsArchiver.php @@ -40,7 +40,7 @@ class LogsArchiver implements ArchiverInterface { */ protected $db; - function __construct(Database $db) { + function __construct( Database $db ) { $this->db = $db; } @@ -48,23 +48,25 @@ class LogsArchiver implements ArchiverInterface { * Currently there is not really a log archive. * * It stays in the log table until cleaned up. + * * @param int $server_id */ - public function archive($server_id = null) { + public function archive( $server_id = null ) { return true; } - public function cleanup(\DateTime $retention_date, $server_id = null) { - $sql_where_server = ($server_id !== null) - // this is obviously not the cleanest way to implement this when using paramter binding.. sorry. - ? ' `server_id` = ' . intval($server_id) . ' AND ' - : ''; + public function cleanup( \DateTime $retention_date, $server_id = null ) { + $sql_where_server = ( $server_id !== null ) + // this is obviously not the cleanest way to implement this when using paramter binding.. sorry. + ? ' `server_id` = ' . intval( $server_id ) . ' AND ' + : ''; $this->db->execute( - "DELETE FROM `".PSM_DB_PREFIX."log` WHERE {$sql_where_server} `datetime` < :latest_date", - array('latest_date' => $retention_date->format('Y-m-d 00:00:00')), + "DELETE FROM `" . PSM_DB_PREFIX . "log` WHERE {$sql_where_server} `datetime` < :latest_date", + array( 'latest_date' => $retention_date->format( 'Y-m-d 00:00:00' ) ), false ); + return true; } } \ No newline at end of file diff --git a/src/psm/Util/Server/ServerValidator.php b/src/psm/Util/Server/ServerValidator.php index 819e3e63..9de86393 100644 --- a/src/psm/Util/Server/ServerValidator.php +++ b/src/psm/Util/Server/ServerValidator.php @@ -136,4 +136,17 @@ class ServerValidator { } return true; } + + /** + * Check SSL expiry days + * @param int $value + * @return boolean + * @throws \InvalidArgumentException + */ + public function sslCertExpiryDays($value) { + if(!is_numeric($value)) { + throw new \InvalidArgumentException('server_ssl_expiry_days_invalid'); + } + return true; + } } diff --git a/src/psm/Util/Server/Updater/StatusUpdater.php b/src/psm/Util/Server/Updater/StatusUpdater.php index de986923..95e96c59 100644 --- a/src/psm/Util/Server/Updater/StatusUpdater.php +++ b/src/psm/Util/Server/Updater/StatusUpdater.php @@ -83,7 +83,7 @@ class StatusUpdater { 'server_id' => $server_id, ), array( 'server_id', 'ip', 'port', 'label', 'type', 'pattern', 'header_name', 'header_value', 'status', 'active', 'warning_threshold', - 'warning_threshold_counter', 'timeout', 'website_username', 'website_password' + 'warning_threshold_counter', 'ssl_cert_expiry_days', 'timeout', 'website_username', 'website_password' )); if(empty($this->server)) { return false; @@ -192,6 +192,8 @@ class StatusUpdater { fclose($fp); } + $this->check_ssl($this->server, $this->error, $status); + // check if server is available and rerun if asked. if(!$status && $run < $max_runs) { return $this->updateService($max_runs, $run + 1); @@ -207,6 +209,7 @@ class StatusUpdater { * @return boolean */ protected function updateWebsite($max_runs, $run = 1) { + $result = ''; $starttime = microtime(true); // We're only interested in the header, because that should tell us plenty! @@ -279,15 +282,51 @@ class StatusUpdater { } } } - + + + $this->check_ssl($this->server, $this->error, $result); + + // check if server is available and rerun if asked. if(!$result && $run < $max_runs) { return $this->updateWebsite($max_runs, $run + 1); } - + return $result; } + + /** + * Check if a server speaks SSL and if the certificate is not expired. + * @param string $error + * @param bool $result + */ + private function check_ssl($server, &$error, &$result) { + if(($ssl_cert_expiry_days = $server['ssl_cert_expiry_days']) > 0) { + $cert_info = psm_cert_info_get($server['ip'], $server['port']); + if( empty( $cert_info) ) { + $error = "SSL is disabled."; + $result = false; + } else { + $current_time = time(); + $seconds_per_day = 86400; + $cert_valid_until = $cert_info['validTo_time_t']; + $latest_time = $current_time + $seconds_per_day*$ssl_cert_expiry_days; + if( $latest_time > $cert_valid_until ) { + $remaining_time = $cert_valid_until - $current_time; + $remaining_days = (int)( $remaining_time / $seconds_per_day ); + if( $remaining_days >= 0 ) { + $error = "SSL certificate expiring: $remaining_days days left."; + } else { + $remaining_days *= -1; + $error = "SSL certificate expired since $remaining_days."; + } + $result = false; + } + } + } + } + /** * Get the error returned by the update function * diff --git a/src/templates/default/module/server/server/update.tpl.html b/src/templates/default/module/server/server/update.tpl.html index 1b1636aa..71fe25dc 100644 --- a/src/templates/default/module/server/server/update.tpl.html +++ b/src/templates/default/module/server/server/update.tpl.html @@ -78,6 +78,12 @@ +
+ +
+ +
+