EC2上のログをtd-agent使ってCloudWatch Logsに投げようとしたらSSL認証エラーになった話
EC2上のログを、td-agentとfluent-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
バージョン情報
エラー解消までの道のり
使用している証明書の確認してみる
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がセキュリティ上の懸念と責任を持つことになるので、望ましくないとのこと。(英語読み間違えてたらすみません)
- https://github.com/aws/aws-sdk-core-ruby/issues/93
- https://github.com/aws/aws-sdk-core-ruby/issues/166
なぜ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-cliはbotocoreというAWS Interfaceライブラリを使用しており、それが証明書をバンドルしているので問題ない。