はじめに

多くの組織では、セキュリティ確保のため従業員のインターネット利用を監視、制限しています。
アイレットでも同じく従業員の Web アクセスの監視、制限のためのセキュリティ製品が導入されています。

これらのセキュリティ製品は、HTTPS 通信を検査するために、組織が管理するルート証明書を介して Web アクセスを処理します。
このため、AWS SDK などのサービスが、信頼されていない証明書に関するエラーを出すことがあります。

この記事では、AWS SDK for JavaScript でカスタム証明書を信頼する方法を示します。

import { BedrockRuntimeClient } from "@aws-sdk/client-bedrock-runtime"

const client = new BedrockRuntimeClient({})

===
NghttpError: Protocol error
    at Http2Session.onSessionInternalError (node:internal/http2/core:809:26)
    at Http2Session.callbackTrampoline (node:internal/async_hooks:130:17) {
  code: 'ERR_HTTP2_ERROR',
  errno: -505,
  '$metadata': { attempts: 1, totalRetryDelay: 0 },
  pregelTaskId: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxx'
}

証明書について

証明書は、その信頼関係に基づいて主に『信頼された証明書』『カスタムルート証明書』『自己署名証明書』の3つに大きく区分されます。

これらの区分は、技術的な違いがあるわけではなく、『信頼関係』によるものです。

信頼された証明書

パソコン等の OS には、あらかじめ信頼された認証局の一覧(ルート証明書)が組み込まれています。
これらの認証局は、相互に信頼関係を構築しています。

信頼された証明書は、DigiCert や AWS Certificate Manager (ACM) などの信頼された証明機関によって発行された証明書です。
これらは、通常利用されている証明書で、AWS SDK のようなライブラリを利用する上で制限などはありません。

カスタムルート証明書

カスタムルート証明書は、主に組織 (企業や団体) などによって管理されています。

管理、検査、ログの保管などの目的のため、組織は内部のインターネット通信を復号して検査する必要が出てくる場合があります。

これらの目的のため、組織が管理するルート証明書を組織のパソコンに配布して、組織が一時的に解読できるようにしています。

この例では、組織内のパソコンがインターネット上のサービスを利用する際に証明書不一致のエラーを受信する可能性があります。

自己署名証明書

サービス ( https://example.com/ など) の証明書を、信頼された証明書ではなく、自身で署名するものです。

運用中の Web サービスで利用されるものではなく、一時的なテスト用途で利用されるものです。
今回の記事では、自己署名証明書は扱いません。

カスタムルート証明書環境での AWS SDK 利用

カスタムルート証明書が適用されている環境で AWS SDK を利用する場合、考えられる手段は主に 2つです。

一つは証明書検証を無効にすること、もう一つはカスタムルート証明書を明示的に信頼することです。
それぞれ、以下で詳細に示します。

証明書検証の無効化

証明書検証の無効化は、決して行うべきではありません。

証明書検証は、中間者攻撃を含めた通信の安全性を担保するうえで必須の機能です。
一時的であれ、証明書検証を無効化することは、情報漏洩やマルウェア感染など、多くのリスクが発生します。

カスタムルート証明書の信頼

カスタムルート証明書の信頼は、組織内での利用において問題ありません。

組織が適切に作成し、管理・公開しているカスタムルート証明書を信頼すること自体は、通常の運用において追加のセキュリティリスクを引き起こしません。
そのため、今回の例では、こちらを実現する方法を示します。

カスタムルート証明書の信頼を実現するコードは下記の通りです。

import { NodeHttpHandler } from "@smithy/node-http-handler"
import { BedrockRuntimeClient } from "@aws-sdk/client-bedrock-runtime"

// custom root certificate
export const cert = `
-----BEGIN CERTIFICATE-----
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
-----END CERTIFICATE-----
`

const client = new BedrockRuntimeClient({
    requestHandler: new NodeHttpHandler({
       httpsAgent: new https.Agent({
            ca: [customCaCert],
        })
    }),
})

ここで重要なのは、NodeHttpHandler です。

これは、AWS SDK が利用する Node の HTTP Handler を明示的に指定する方法です。
この中で、httpAgent を指定して、カスタムした https.Agent を利用することが可能です。

https.Agent には、ca オプションとしてカスタムルート証明書を指定できます。

これにより、『はじめに』に示したようなエラーは改善されます。

まとめ

組織内において、セキュリティ維持のためにカスタムルート証明書を利用するケースは避けて通れません。
しかし、このような状況下で安易に証明書検証を無効化してしまうと、プログラムが動作する環境に大きなセキュリティリスクが発生します。

ここで示したような方法を用いて、正しくカスタムルート証明書を適用してください。