📜

Splunk Observability CloudでSSL証明書の有効期限を監視

2023/06/13に公開

はじめに

監視要件として、SSL証明書の有効期限をチェックしたいというものがあります。
Splunk Observability Cloud(OpenTelemetry Collector: Otel Collector)ではどのように行うかをまとめました。
※Otel Collectorがベースなので、本記事の内容はSplunk Observability Cloudに限定した内容ではありません。

OpenTelemetry CollectorでSSL証明書のメトリクスは取得できるか

答えは、現在(2023/6/13)はそのようなReceiverは存在しませんので、残念ながらNoです。
じゃあどうするかというとPrometheus Exporterをお借りします。

Prometheus Exporter

Otel CollectorではPrometheus Exporterのメトリクスを取得するためのPrometheus Receiverというものが提供されています(ややこしい)。
詳細は以下記事を参照ください。

https://qiita.com/symmr/items/148db3e2f0776ecc3d04

Prometheus SSL Certificate Exporter

Prometheus Exporterとして、SSL Certificate Exporterというものがあります。

https://github.com/ribbybibby/ssl_exporter

これは以下の方法で証明書に関するメトリクスを取得できます。

tcp: 任意のtarget(URL)上の証明書に関するメトリクスを取得
http: tcpと同じだが、Proxyを通したい場合に使用
file: ローカルのPEMファイルを取得
kubernetes: kubernetesのSecret(kubernetes.io/tls)から証明書を取得
kubeconfig: kubernetesのkubeconfig内のPEMファイルを取得

今回は外部公開サイトの監視のためtcpを使ってみたいと思います。

OpenTelemetry CollectorでPrometheus Receiverを使用

適当なホストにSplunk Otel Collectorが既にインストールされているとします。

同ホストにPrometheus SSL Certificate Exporterをインストールします。
※別のホストでもいいです。Otel CollectorからのScrape先を変えるだけです。

Build(Go言語)かDockerが可能なようなので、今回はDockerで起動します。

Prometheus SSL Certificate Exporter
docker run -d -p 9219:9219 ribbybibby/ssl-exporter:latest

次にOtel Collectorに設定を追加します。
試しにzenn.devprometheus.iowww.splunk.comの証明書を監視します。
※これは例なので、実際は自分たちが提供しているサービスのURLをターゲットにします。

/etc/otel/collector/agent_config.yaml
#prometheus receiverを追加
receivers:
  prometheus/ssl_exporter:
    config:
      scrape_configs:
      - job_name: "ssl"
        metrics_path: /probe
        scrape_interval: 10s
        static_configs:
        - targets:
            - zenn.dev:443
            - prometheus.io:443
            - www.splunk.com:443
        relabel_configs:
          - source_labels: [__address__]
            target_label: __param_target
          - source_labels: [__param_target]
            target_label: instance
          - target_label: __address__
            replacement: 127.0.0.1:9219

#既存のmetrics pipelineのreceiverに追加
service:
  pipelines:
    metrics:
      receivers: [hostmetrics, otlp, signalfx, smartagent/signalfx-forwarder, prometheus/ssl_exporter]
      processors: [memory_limiter, batch, resourcedetection]
      exporters: [signalfx]

Otel Collectorを再起動します。

sudo systemctl restart splunk-otel-collector

念のためログを見て、問題なく起動できているか確認します。

sudo journalctl | grep otelcol | grep ssl

Splunk Observability Cloudで確認

ダッシュボード化

メトリクスを取得できているか確認し、ダッシュボードに組み込みましょう。

Metric Finderでsslと検索します。

いくつか取得できています。
各メトリクスの詳細はSSL ExporterのGitHubを確認いただきたいですが、今回は期限切れ日を示すssl_cert_not_afterとSSLポーリングが成功したかを示すssl_probe_successを使いたいと思います。

ssl_cert_not_afterを開きます。

Data Tableを確認してみると、、、ターゲットにしていた3つのサイトの証明書について取得されていますね。成功です。

気になる点として
・ルート証明書も取得している ⇒ フィルタで除外する。dnsnamesが含まれているものが良さそうです。
・Valueが謎の巨大な数値 ⇒ これは有効期限のEpoch Time(秒)で結果が返ってきているためです。このままでは適切な監視ができないので、「残りx日」に変換してアラート設定を組み込みたいと思います。

「残りx日」にするには以下の計算をすればOKです。

残りx日 = (有効期限のEpoch time - 現時点のEpoch time)/(86400秒)

現時点のEpoch timeを取得するには、残念ながら今のところUI上からは設定できないので、代わりにSignalFlowでtime()を使います。

SignalFlowのEditorはPlot Editorタブから開けます。

現在の設定内容がSignalFlowで表示されました。

time()の解説ページを参考に、以下のように修正します。

before
A = data('ssl_cert_not_after', filter=filter('service.name', 'ssl')).publish(label='A')
after
expire_epochtime = data('ssl_cert_not_after', filter=filter('service.name', 'ssl') and filter('dnsnames', '*'))
now_epochtime = time()/1000
days_to_expire = floor((expire_epochtime-now_epochtime)/(24*60*60)).publish(label="days_to_expire")
detect(days_to_expire<60).publish(label="Certificates expiring soon!")

time()はミリセカンドのEpoch Timeが返されるので、1000で割っています。
days_to_expireに残りの日数が格納されるようにします。
最後の行のdetectは後続のアラート設定で使うための仕込みです。
60日を切ったらアラートを出すようにしています。この値は要件に合わせてセットしてください。

Data Tableを見てみましょう。それっぽい数値になりました。

prometheus.ioが53となっています。正しいか確かめてみます。

2023/8/5が有効期限です。これを仕込んだのが2023/6/12なので、53日後の期限切れで正しそうです。

後は見やすいように表示方法を色々設定してあげましょう。Listタイプがいいですね。期限切れが近いものを上に来るようにして60日を切っていたら赤くしてあげます。

最後にSave Asから適当なダッシュボードに保存すれば完了です。

次に、Otel CollectorからのSSLプローブが成功したかをチェックするためssl_probe_successをダッシュボードに組み込みます。成功が1、失敗が0といたってシンプルですので、このまま使います。

見やすくしましょう。Heatmapとかいかがですか。

Dashboardに保存します。

Detector

ダッシュボードを毎日眺めている訳にもいかないので、期限切れが近くなったらアラートを発報するようにします。Splunk Observability Cloudではアラート定義をDetectorと呼んでいます。

チャートの🔔アイコンから定義します。
SignalFlowを使った場合は若干特殊な手順です。

Alert RuleからEditします。

Alert Messageに緊急度や、証明書更新手順が載ったURLなども定義できます。

Alert Recipientsで通知先を設定しましょう。

最後に名前を付けてActivateします。

Saveします。

次に、Incident ID(DetectorのID)を取得します(この手順はSignalFlowを使わなかった場合は不要です)。

Alerts & Detectors > Detectorsから、今作成したDetectorを探します。

Detectorを開き、URLからIDをコピーしておきます。

次にChartにDetectorをLinkさせます。

SignalFlowの最後の行にalert定義がコメントアウト状態で追加されているので、コメントアウトを外し、IDを貼り付けてあげます。

これで完了です。

次にProbe Successの方もDetectorを仕込みます。
同じように🔔アイコンからDetectorを作成します。

Alert ConditionをStatic Thresholdにします。

閾値はBelow 1(1未満)にします。これでProbe Successが0になった場合に通知してくれます。
残りの設定は期限切れ日の時と同じです。
ChartとDetectorのLinkは自動的にされますので対応不要です。

Dashboardを見てみましょう。prometheus.ioが60日未満なのでDetectorが発動し、赤色の枠が表示されていますね。一方Probe Successは問題がないので緑色の枠です。このように、アラート状態かどうかをChartに紐づけて確認できます。

もちろんアラート画面からもLinkされたダッシュボードへの遷移ができます。

追記:Splunk Enterprise / Cloudで確認

上記ではIMでDashboard化、Detector作成しましたが、別の方法としてSplunk Enterprise / Cloud(以降、Splunk Core)でもメトリクスを取得し処理することができます。

Splunk CoreにSplunk Infrastructure Monitoring Add-onをインストールすることでSplunk CoreからObservability CloudにREST通信を行い、IMのメトリクスを取得できます。

一時的な取得、もしくは設定 > データ入力 > Splunk Infrastructure Monitoring Data Streamsからインデックス化ができます。

今回は簡単に一時的な取得でやってみましょう。

まずはAdd-onのセットアップをしておきます。REALMとAccess Tokenを指定することでメトリクス取得ができるようになります。

次にIMのダッシュボードからView SignalFlowをクリックし、SignalFlowを取得します。フィルターをかけてもいいですが、SPLで処理できるのでとりあえず全取得します。

SignalFlow
A = data('ssl_cert_not_after').publish(label='A')

Splunk Coreに戻り、このようにSPLを打ちます。Add-onに含まれる| simコマンドによりIMのメトリクスが取得できます。

SPL
| sim flow query="A = data('ssl_cert_not_after').publish(label='A')"

ドバドバと値が来ました。

いいですね。
もっと見やすくしつつ残り日数を計算してみましょう。

SPL
| sim flow query="A = data('ssl_cert_not_after').publish(label='A')"
| spath 
| search dnsnames=* "service.name"=ssl
| eval expire_epochtime=_value
| eval now_epochtime=now()
| eval days_to_expire = floor((expire_epochtime-now_epochtime)/(24*60*60))
| stats values(days_to_expire) as days_to_expire by service.instance.id

OK。

期限切れ間近のものに絞り込みたいので、最後にこんな感じで追加すれば絞り込めます。

SPL
...
| eval threshold=60
| where days_to_expire<threshold

名前を付けて保存 > アラート からアラート定義をします。
例えば、毎日9:00にチェックし、値があればSlackに送るようにします。

もちろんメッセージに$result.fieldname$で処理結果を埋め込むこともできます。
変数の取得方法の詳細はこちらを参照してください。

まとめ

本記事では、たまに監視要件であるSSL証明書期限監視の設定方法を見てきました。
Otel CollectorもSplunk Observability Cloudも拡張性が高くてよいですね。

Discussion