Alligator Swamp

技術メモ

EC2上のログをtd-agent使ってCloudWatch Logsに投げようとしたらSSL認証エラーになった話

EC2上のログを、td-agentfluent-plugin-cloudwatch-logsを使ってCloudWatch Logsに送信しようとしたところ、SSL認証エラーが発生したので、エラーの解決方法を調べたのでまとめてみた。間違っている箇所があれば指摘ください!

before_shutdown failed error="SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed"

tl;dr

EC2でtd-agent使ってCloudWatch Logsにログを送信する場合は、/etc/sysconfig/td-agentに以下を追記すると上手くいくはず。

export SSL_CERT_FILE=/etc/pki/tls/cert.pem

バージョン情報

  • Amazon Linux AMI 2015.03
  • td-agent 2.2.0-0
  • fluent-plugin-cloudwatch-logs 0.0.7

エラー解消までの道のり

使用している証明書の確認してみる

td-agentに同梱されているrubyがどの証明書を使用しているかを確認。

$ /opt/td-agent/embedded/bin/ruby -r openssl -e 'p OpenSSL::X509::DEFAULT_CERT_FILE'
"/opt/td-agent/embedded/ssl/cert.pem"

td-agentに同梱されている証明書を使用しているようだ。

EC2組み込みの証明書を使用してみる

EC2の証明書は以下のパスにある。

/etc/pki/tls/cert.pem

OpenSSL::X509::DEFAULT_CERT_FILE_ENVで指定される文字列名で環境変数を指定すると、rubyが使用する証明書を変更できるのでそれを使う。

$ ruby -r openssl -e 'p OpenSSL::X509::DEFAULT_CERT_FILE_ENV'
"SSL_CERT_FILE"

td-agentはinitスクリプト内で/etc/sysconfig/td-agentを読み込むので、そこに以下の設定を書く

export SSL_CERT_FILE=/etc/pki/tls/cert.pem

td-agentを再起動して確認

service td-agent restart

td-agentを実行すると正常にログを送信することが出来た。

その他調べたこと

aws-sdk-rubyに証明書がバンドルされていないのか

aws-sdk-v1ではバンドルされていたが、aws-sdk-v2からバンドルしなくなった。

なぜaws-sdk-v2から証明書がバンドルされなくなったのか

証明書をバンドルすることで、SDKがセキュリティ上の懸念と責任を持つことになるので、望ましくないとのこと。(英語読み間違えてたらすみません)

なぜfluent-plugin-s3ではエラーにならないのか

fluent-plugin-s3はaws-sdk-v1を使用しているため。

fluent-plugin-cloudwatch-logsもaws-sdk-v1を使用すればよいのでは

aws-sdk-v2にしかCloudWatch Logsの実装は組み込まれてなくて、v1にバックポートもする予定ないらしい。

Amazon Linux以外のOSだとどうなの?

手元のMacでCentOS6.6の環境を作って試したけど、認証エラーが発生した。Amazon Linux以外では、aws-sdk-v1にバンドルされてる証明書を使わないとダメかもしれない。

CloudWatch Logs Agentはなんで大丈夫なの?

CloueWatch Logs AgentとはAWS公式のログ収集エージェント。内部的にはaws-cli(Python製)が使われている。aws-clibotocoreというAWS Interfaceライブラリを使用しており、それが証明書をバンドルしているので問題ない。