1. ホーム
  2. node.js

[解決済み] axiosがSSL証明書を使用するように設定するにはどうしたらよいですか?

2022-02-07 14:54:18

質問

axiosでapiエンドポイントにリクエストしようとしているのですが、以下のエラーが発生します。 Error: unable to verify the first certificate

axios が使用している https モジュールが、サーバーで使用されている SSL 証明書を確認できないようです。

ブラウザでサーバーにアクセスすると、証明書は有効で、それを見たりダウンロードしたりすることができます。また、ブラウザからhttpsでapiにリクエストすることも可能です。

検証をオフにすることで回避できるのですが このコードは動作します。

const result = await axios.post(
    `https://${url}/login`,
    body,
    {
      httpsAgent: new https.Agent({
        rejectUnauthorized: false
      })
    }
  )

問題は、これではSSL証明書が検証されないため、セキュリティホールが開いてしまうことです。

axiosが証明書を信頼し、正しく検証するように設定するにはどうしたらよいですか。

解決方法は?

古い質問ですが、ここにたどり着いた人のためにチャイムを鳴らしておきます。専門家はいません。お近くのセキュリティの専門家にご相談ください。

Axiosはhttp(s)クライアントで、httpクライアントは通常匿名でTLSに参加します。言い換えれば、サーバーは誰が接続しようとしているのかを特定することなく、その接続を受け入れるのです。これは、サーバーとクライアントがハンドシェイクを完了する前にお互いを確認する、例えば相互TLSとは異なります。

インターネットは恐ろしい場所なので、なりすましの公開エンドポイントに接続されないようにクライアントを保護したいのです。このため、プライベートデータを送信する前に、クライアントがサーバーを特定できるようにします。

// DO NOT DO THIS IF SHARING PRIVATE DATA WITH SERVICE
const httpsAgent = new https.Agent({ rejectUnauthorized: false });

これは、StackOverflow で、あらゆる言語での https クライアント接続の失敗に関する回答として、しばしば投稿されます(さらにひどく upvoted されます)。さらに悪いことに、この方法は通常うまくいき、開発者のブロックを解除し、彼らは陽気な道を進んでいくのです。しかし、彼らは確かにドアを開けることができましたが、それは誰のドアなのでしょうか?サーバーの身元確認を行わなかったため、クライアントは、会社のイントラネットに接続した際に、悪意ある人物に盗聴されているかどうかを知る術がないのです。

サービスが公開SSL証明書を持っている場合は https.Agent なぜなら、あなたのオペレーティングシステムは、一般に信頼されているCA証明書の共通セットを提供しているからです。これは通常、ブラウザが使用するように設定されているCA証明書のセットと同じで、そのためデフォルトのaxiosクライアントは以下のようにヒットします。 https://google.com を、わずかな手間で実現することができます。

サービスにプライベート SSL 証明書(テスト用に自分で署名したもの、または会社の内部機密を保護するために会社のプライベート CA によって署名されたもの)がある場合、https エージェントは、サーバー証明書に署名するために使用したプライベート CA を信頼するように設定されなければなりません。

const httpsAgent = new https.Agent({ ca: MY_CA_BUNDLE });

ここで MY_CA_BUNDLE は CA 証明書の配列で、 ヒットしたいエンドポイントのサーバ証明書と、 その証明書の完全な証明書チェーンが .pem 形式を使用します。トラストルートまでのチェーンにあるすべての証明書を含める必要があります。


これらのオプションはどこで文書化されていますか?

<ブロッククオート

HTTPSとは、TLS/SSL上のHTTPプロトコルのことです。Node.jsでは、これは別のモジュールとして実装されています。

そのため https.Agent に渡されたオプションをマージしたものです。 tls.connect() tls.createSecureContext() .