PHP
SSL
Slack
Webhook

【PHP】SSL証明書の有効期限をチェックして、SlackにWebhookで通知

More than 1 year has passed since last update.

概要

PHPで、ウェブサイトのSSL証明書の有効期限をチェックして、有効期限が近いサイトがあれば、Slackに通知したい。

「ツール入れればいいじゃん」という話は、無しでお願いします・・・。お手軽重視!!

しらべた

自分が使うだけのものなので、あんまり時間をかけずにサクッと作りたかった。ので、とりあえずググりました。

参考にさせていただいたのは、以下の2記事。というか、ほとんどそのまま・・・。

実装

サクッと組み合わせたものを、そのまま 恥ずかしげもなく 公開。定数の定義位置が微妙なのは、非エンジニアでもドメイン追加しやすいように、という余計な配慮です。

ssl-watch.php
<?php

/**
 * SSL証明書期限切れ通知用プログラム
 */

// ここに、監視対象のドメインを追加(FQDN)
$domain_names = array(
    'example.com',
    );

// テストしたい場合は1にして手動実行すると、全て通知される。
define('IS_TEST', 0);

// 通知先のチャンネル名。@始まりでDM。
define('SLACK_CHANNEL_NAME', '#ssl_watch');

// Slack Incoming WebHooksのURL
define('SLACK_WEBHOOK_URL', 'https://hooks.slack.com/services/hogehogehogehogehogehoge');

$warning_messages = array();
foreach($domain_names as $domain_name){
    $stream_context = stream_context_create(array(
        'ssl' => array('capture_peer_cert' => true)
        ));
    $resource = stream_socket_client(
        'ssl://' . $domain_name . ':443',
        $errno,
        $errstr,
        30,
        STREAM_CLIENT_CONNECT,
        $stream_context
        );
    $cont = stream_context_get_params($resource);
    $parsed = openssl_x509_parse($cont['options']['ssl']['peer_certificate']);

    if(strpos($parsed['subject']['CN'], $domain_name) !== false){

        // 1ヶ月以内の場合は、通知
        $_ssl_limit = date('Y/m/d', $parsed['validTo_time_t']);
        if(IS_TEST || strtotime($_ssl_limit) < mktime(0, 0, 0, date('m') + 1, date('d'), date('Y'))){
            $_warning_message = "【SSL証明書期限】{$domain_name} ({$_ssl_limit})";
        }
    }else{
        // 取得できなかったドメインも通知
        $_warning_message = "【SSL証明書期限】{$domain_name} (取得失敗)";
    }

    if(!empty($_warning_message)){
        if(IS_TEST) $_warning_message = 'TEST '.$_warning_message;

        $warning_messages[] = $_warning_message;
        echo $_warning_message."\n";
    }
}

if(!empty($warning_messages)) SendSlack::send(implode("\n", $warning_messages));
return;

class SendSlack
{
    public static function send($text){
        $webhook_url = SLACK_WEBHOOK_URL;

        $message = array(
            'username' => 'Bot',
            "channel" => SLACK_CHANNEL_NAME,
            'text' => $text,
            "icon_emoji" => ":ghost:",
            );

        $options = array(
            'http' => array(
                'method' => 'POST',
                'header' => 'Content-Type: application/json',
                'content' => json_encode($message),
                ),
            'ssl' => array(
                'verify_peer' => false,
                'verify_peer_name' => false,
                ),
            );
        $response = file_get_contents($webhook_url, false, stream_context_create($options));
        $ret = $response === 'ok';
    }
}

実行

日次バッチなどでphpを実行すると、期限が1ヶ月以内に迫った場合は、以下のような感じでSlackに通知される。

【SSL証明書期限】example.com (2018/12/31)