TypeScript(Node.js)からAzure OpenAI Serviceに接続しようとしたときにエラーが発生しました。
C:\ts_sample\node_modules\@azure\core-rest-pipeline\dist\commonjs\nodeHttpClient.js:187 reject(new restError_js_1.RestError(err.message, { code: (_a = err.code) !== null && _a !== void 0 ? _a : restError_js_1.RestError.REQUEST_SEND_ERROR, request }));
RestError: unable to verify the first certificate at ClientRequest.<anonymous> (C:\ts_sample\node_modules\@azure\core-rest-pipeline\dist\commonjs\nodeHttpClient.js:187:24) at Object.onceWrapper (node:events:633:26) at ClientRequest.emit (node:events:518:28) at TLSSocket.socketErrorListener (node:_http_client:500:9) at TLSSocket.emit (node:events:518:28) at emitErrorNT (node:internal/streams/destroy:169:8) at emitErrorCloseNT (node:internal/streams/destroy:128:3) at process.processTicksAndRejections (node:internal/process/task_queues:82:21) { code: ‘UNABLE_TO_VERIFY_LEAF_SIGNATURE’,
Pythonの時も発生した「プライベート認証局のルート証明書がない問題」と同様と思われたので、GPTに解決方法を聞いてみました。
GPTの回答
このエラー「unable to verify the first certificate」と「UNABLE_TO_VERIFY_LEAF_SIGNATURE」は、Node.jsのHTTPSクライアントがサーバーのSSL証明書の信頼チェーンを検証できないことを示しています。特に、プライベート認証局(CA)によって発行された証明書を使用している場合、Node.jsはデフォルトの信頼ストアにそのCAのルート証明書がないため、このエラーが発生することがあります。
この問題を解決するには、Node.jsにプライベートCAのルート証明書を認識させる必要があります。以下の方法で設定できます:
1. HTTPS エージェントの設定
Node.jsでカスタムHTTPSエージェントを使用して、特定のルート証明書を追加する方法です。例として、Azure OpenAI Serviceに接続するコードを以下のように設定できます。
import { Configuration, OpenAIApi } from "openai";
import * as https from 'https';
import * as fs from 'fs';
// ルート証明書を読み込む
const ca = fs.readFileSync('path/to/your/rootCA.pem');
// HTTPSエージェントの設定
const agent = new https.Agent({
ca: ca // 読み込んだルート証明書を追加
});
// OpenAI APIの設定
const configuration = new Configuration({
apiKey: "your-openai-api-key",
httpsAgent: agent // カスタムHTTPSエージェントを使用
});
const openai = new OpenAIApi(configuration);
// 例えばChatGPTモデルを使って何かを実行する
async function fetchGPTResponse() {
try {
const response = await openai.createCompletion("text-davinci-002", {
prompt: "Translate the following English text to Japanese: 'Hello, how are you?'",
max_tokens: 60
});
console.log(response.data.choices[0].text);
} catch (error) {
console.error(error);
}
}
fetchGPTResponse();
この方法では、特定のHTTPSリクエストにのみカスタム証明書を使用するため、他のリクエストには影響を与えません。
2. グローバル設定の変更
Node.jsのグローバルエージェントの設定を変更し、すべてのHTTPSリクエストでカスタムルート証明書を使用する方法もあります。これは環境変数を通じて設定できます:
NODE_EXTRA_CA_CERTS=path/to/your/rootCA.pem node yourscript.js
この設定方法はアプリケーション全体に影響を与えるため、他の外部サービスへのリクエストにも影響する可能性があることを注意してください。
解消方法
GPTの回答のうち「グローバル設定の変更」で解消させました。
まず、必要なパッケージをインストールします。cross-env
を使用すると、プラットフォームに依存することなく環境変数を設定できます。
npm install --save-dev cross-env
package.json
のscriptsのstartに環境変数を含める(cross-env NODE_EXTRA_CA_CERTS=./cacert.pem
)ことで、npm start
や npm run script-name
などのコマンドを通じてアプリケーションを起動する際に自動的に設定を適用させることができます。
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "tsc",
"start": "cross-env NODE_EXTRA_CA_CERTS=./cacert.pem node ./src/index.js"
},
rootCA.pemには以下のようなフォーマットで、ルート証明書を記載すればOKです。
-----BEGIN CERTIFICATE-----
MIIDdzCCAl+gAwIBAgIEUj7NSDANBgkqhk...(中略)...JAeVb
WgnVNs6Sg9C3Nfg4VFsHmH/rLYIvY8vWB1=
-----END CERTIFICATE-----
PEM形式の証明書は、”—–BEGIN CERTIFICATE—–” と “—–END CERTIFICATE—–” で囲まれたベース64エンコードされたデータを含んでいます。