エラー:nodejsの最初の証明書を確認できません


141

URLを使用してjiraサーバーからファイルをダウンロードしようとしていますが、エラーが発生します。エラーを確認するためにコードに証明書を含める方法

Error: unable to verify the first certificate in nodejs

at Error (native)
    at TLSSocket.<anonymous> (_tls_wrap.js:929:36)

  at TLSSocket.emit (events.js:104:17)

at TLSSocket._finishInit (_tls_wrap.js:460:8)

私のNodejsコード:

var https = require("https");
var fs = require('fs');
var options = {
    host: 'jira.example.com',
    path: '/secure/attachment/206906/update.xlsx'
};

https.get(options, function (http_res) {

    var data = "";


    http_res.on("data", function (chunk) {

        data += chunk;
    });


    http_res.on("end", function () {

        var file = fs.createWriteStream("file.xlsx");
        data.pipe(file);

    });
});

これを解決できましたか?
sharad jain

1
証明書の検証を無効にするなどの別の手順を使用して実行
Labeo

もう少し詳しく説明してもらえますか?これは私にとって本当に役に立ちます
sharad jain

rejectUnauthorizedが必要な証明書の検証については、以下の回答を参照してください
Labeo、

回答:


120

適切なルート証明書を追加してみてください

これは、許可されていないエンドポイントを盲目的に受け入れるだけの場合よりもずっと安全なオプションであり、最後の手段としてのみ使用する必要があります。

これは追加するのと同じくらい簡単です

require('https').globalAgent.options.ca = require('ssl-root-cas/latest').create();

あなたのアプリケーションに。

SSLルートCAはNPMパッケージは、(ここで使用されるような)は、この問題に関して、非常に便利なパッケージです。


9
この回答は、SSLの利点全体を無効にするのではなく、実際に問題を修正するため、ほとんどの場合に使用する必要があります。
mikemaccana 2016

12
ssl-root-casモジュールのREADMEに記載されているように、この問題の最も一般的な原因の1つは、証明書に中間CA証明書が埋め込まれていないことです。何かを試す前に、証明書を修正してみてください;)
Laurent VB

SSL-root-casパッケージも必要ない場合があります。globalAgents.option.certをフルチェーン証明書に設定するだけです。それが私の問題を解決したものです。
smartexpert

1
mkcertは「フルチェーン」証明書を作成しません。証明書を$(mkcert -CAROOT)/rootCA.pem新しい証明書ファイルで入手可能なルート証明書と連結し、https.globalAgent.options.ca = fs.readFileSync('fullchain.pem')github.com/FiloSottile/mkcert/issues/76
Frosty Z

セキュリティを重視ssl-root-casするために、npmモジュールには、mozilla.orgにハードコードされたgit.coolaj86.com/coolaj86/ssl-root-cas.js/src/branch/master/…へのリクエストがあります。Mozillaはおそらく安全ですが、攻撃経路のようです。
Avindra Goolcharan

60

すべてのリクエストを安全でなくなる別の汚いハック:

process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = 0

8
これは、上記のLabeoの回答と同じくらい危険ではないようです。
ocramot

4
それは異なり、env変数はソースコードの外部で設定できるため、コーディングを変更する必要はありません。
jzacharuk

1
この答えは危険です。TLSが提供するセキュリティを無効にします。
Flimm

1
これは私にとってはとても役に立ちました。私の場合、私はlocalhost通信しているだけなので、セキュリティは問題ではありません。
Mike S

実際、localhostをテストするだけで十分です。テスト後は必ず削除してください。
ニコ

44

nodejsの最初の証明書を検証できないため、無許可の拒否が必要です

 request({method: "GET", 
        "rejectUnauthorized": false, 
        "url": url,
        "headers" : {"Content-Type": "application/json",
        function(err,data,body) {
    }).pipe(
       fs.createWriteStream('file.html'));

129
この答えは危険です。もう1つはより安全です。
mikemaccana 2016

3
そうすることで、SSLによって提供されるセキュリティが削除されるので、開発にのみ使用してください。
Sylvain

11
証明書を確認しないと、相手の身元を確認できないため、なりすましのホストに感染する可能性があります。ただし、証明書をチェックしなくても、(簡単に)スパイできない暗号化された通信を取得できます。したがって、この行を追加しても、SSLの「セキュリティが取り除かれる」ことはなく、別のコメント投稿者が「SSLの利点全体を無効にする」こともできます。
Bob Pollack

4
SSL検証を無効にしても問題の解決にはなりません。:-)
Siddhu

9
これは、ノードリクエストライブラリを使用している場合に機能します。私はどちらですか。そしてありがとう、それは私の開発の緊急の必要性を解決します。
Alan

29

ダウンロードしようとしているサーバーが正しく構成されていない可能性があります。ブラウザで機能しても、キャッシュが空のクライアントが検証するために必要なチェーンにすべてのパブリック証明書が含まれていない可能性があります。

SSLlabsツールでサイトを確認することをお勧めします:https ://www.ssllabs.com/ssltest/

このエラーを探します。

このサーバーの証明書チェーンは不完全です。

この:

チェーンの問題.........不完全


DigiCert Inc.から承認された私の証明書に対してこの問題(チェーンの問題.........不完全)が発生しました。これを修正する手順は何ですか?
imarchuang 2018年

@imarchuangつまり、サーバーはドメインの証明書だけでなく、中間証明書も提供する必要があります。このコメントではこれ以上詳しく説明することはできませんが、うまくいけば、それであなたを正しい方向に向けることができるでしょう。
Flimm、2018年

おかげで多く、我々はあまりにも、ルート証明書をコーミングで考え出した
imarchuang

ありがとうございます!私は自分の証明書が不完全であることを発見しましたが、ChromeとFirefoxでは完全に機能しましたが、electronアプリでは機能しませんでしたcat domainname.crt domainname.ca-bundle > domainname-ssl-bundle.crt
。nginx

25

unable to verify the first certificate

証明書チェーンが不完全です。

これは、接続しているWebサーバーが正しく構成されておらず、送信した証明書チェーンに中間証明書が含まれていないことを意味します。

証明書チェーン

次のようになります。

  1. サーバー証明書-中間者によって署名された証明書を保存します。
  2. 中間証明書-ルートによって署名された証明書を格納します。
  3. ルート証明書-自己署名証明書を保管します。

中間証明書は、サーバー証明書と共にサーバーにインストールする必要があります。
ルート証明書は、ソフトウェアアプリケーション、ブラウザ、オペレーティングシステムに組み込まれています。

証明書を提供するアプリケーションは完全なチェーンを送信する必要があります。これは、サーバー証明書自体とすべての中間物を意味します。ルート証明書はクライアントに知られているはずです。

問題を再現する

ブラウザを使用してhttps://incomplete-chain.badssl.comにアクセスします。

エラーは表示されません(アドレスバーの南京錠は緑色です)。
これは、サーバーから送信されない場合、ブラウザーがチェーンを完了する傾向があるためです。

次に、Nodeを使用してhttps://incomplete-chain.badssl.comに接続します

// index.js
const axios = require('axios');

axios.get('https://incomplete-chain.badssl.com')
  .then(function (response) {
    console.log(response);
  })
  .catch(function (error) {
    console.log(error);
  });

ログ:「エラー:最初の証明書を確認できません」。

解決

証明書チェーンを自分で完了する必要があります。

それを行うには:

1:不足している中間証明書を.pemフォーマットで取得する必要があります。

A:使用してノードの内蔵証明書ストアを拡張しNODE_EXTRA_CA_CERTS

2b:または、caオプションを使用して独自の証明書バンドル(中間およびルート)を渡します。

1.中間証明書を取得するにはどうすればよいですか?

使用opensslGit for Windowsに付属)。

リモートサーバーの証明書の詳細を保存します。

openssl s_client -connect incomplete-chain.badssl.com:443 -servername incomplete-chain.badssl.com | tee logcertfile

私たちは発行者を探しています(中間証明書はサーバー証明書の発行者/署名者です):

openssl x509 -in logcertfile -noout -text | grep -i "issuer"

署名証明書のURIが表示されます。それをダウンロードしてください:

curl --output intermediate.crt http://cacerts.digicert.com/DigiCertSHA2SecureServerCA.crt

最後に、次のように変換し.pemます。

openssl x509 -inform DER -in intermediate.crt -out intermediate.pem -text

2a。NODE_EXTRA_CERTS

私はcross-envを使用してpackage.jsonファイルに環境変数を設定しています:

"start": "cross-env NODE_EXTRA_CA_CERTS=\"C:\\Users\\USERNAME\\Desktop\\ssl-connect\\intermediate.pem\" node index.js"

2b。caオプション

このオプションは、ノードの組み込みルートCAを上書きします。

そのため、独自のルートCAを作成する必要があります。ssl-root-casを使用します

次に、https証明書バンドル(ルートおよび中間)で構成されたカスタムエージェントを作成します。axiosリクエストを行うときにこのエージェントを渡します。

// index.js
const axios = require('axios');
const path = require('path');
const https = require('https');
const rootCas = require('ssl-root-cas').create();

rootCas.addFile(path.resolve(__dirname, 'intermediate.pem'));
const httpsAgent = new https.Agent({ca: rootCas});

axios.get('https://incomplete-chain.badssl.com', { httpsAgent })
  .then(function (response) {
    console.log(response);
  })
  .catch(function (error) {
    console.log(error);
  });

カスタムhttpsエージェントを作成してに渡す代わりaxiosに、httpsグローバルエージェントに証明書を配置できます。

// Applies to ALL requests (whether using https directly or the request module)
https.globalAgent.options.ca = rootCas;

リソース:

  1. https://levelup.gitconnected.com/how-to-resolve-certificate-errors-in-nodejs-app-involving-ssl-calls-781ce48daded
  2. https://www.npmjs.com/package/ssl-root-cas
  3. https://github.com/nodejs/node/issues/16336
  4. https://www.namecheap.com/support/knowledgebase/article.aspx/9605/69/how-to-check-ca-chain-installation
  5. /superuser/97201/how-to-save-a-remote-server-ssl-certificate-locally-as-a-file/
  6. .crtを.pemに変換する方法

非常に詳細な説明。

本当にすばらしいです!うまくいきませんでした。
Tom Chadaravicius

6

これは実際に私のためにそれを解決しました、https://www.npmjs.com/package/ssl-root-cas

// INCORRECT (but might still work)
var server = https.createServer({
  key: fs.readFileSync('privkey.pem', 'ascii'),
  cert: fs.readFileSync('cert.pem', 'ascii') // a PEM containing ONLY the SERVER certificate
});

// CORRECT (should always work)
var server = https.createServer({
  key: fs.readFileSync('privkey.pem', 'ascii'),
  cert: fs.readFileSync('fullchain.pem', 'ascii') // a PEM containing the SERVER and ALL INTERMEDIATES
});

1
つまり、追加のライブラリを必要としないよう、最善の解決策の私見であると簡単です
マーティン・シュナイダー

4

以下のようにリクエストオプションを変更することでこれを行うことができる場合があります。自己署名証明書または欠落している仲介者を使用している場合、strictSSLをfalseに設定しても、要求パッケージが証明書を検証することは強制されません。

var options = {
   host: 'jira.example.com',
   path: '/secure/attachment/206906/update.xlsx',
   strictSSL: false
}

これで問題が解決しました。「http」の代わりに「request」モジュールを使用しています。ありがとう!
Bruno Nunes

2

GoDaddy SSL CC証明書

GoDaddy証明書でバックエンドAPIサーバーに接続しようとしたときにこれを経験しました。問題を解決するために使用したコードは次のとおりです。

var rootCas = require('ssl-root-cas/latest').create();

rootCas
  .addFile(path.join(__dirname, '../config/ssl/gd_bundle-g2-g1.crt'))
  ;

// will work with all https requests will all libraries (i.e. request.js)
require('https').globalAgent.options.ca = rootCas;

PS:

バンドルされた証明書を使用し、ライブラリをインストールすることを忘れないでください npm install ssl-root-cas


1
これは私にとってはうまくいきましたが、インポート中は「ssl-root-cas / latest」の代わりに「ssl-root-cas」を使用する必要がありました。
クリシュナ

2

これは私のために働きました=>エージェントを追加し、「rejectUnauthorized」をfalseに設定しました

const https = require('https'); //Add This
const bindingGridData = async () => {
  const url = `your URL-Here`;
  const request = new Request(url, {
    method: 'GET',
    headers: new Headers({
      Authorization: `Your Token If Any`,
      'Content-Type': 'application/json',
    }),
    //Add The Below
    agent: new https.Agent({
      rejectUnauthorized: false,
    }),
  });
  return await fetch(request)
    .then((response: any) => {
      return response.json();
    })
    .then((response: any) => {
      console.log('response is', response);
      return response;
    })
    .catch((err: any) => {
      console.log('This is Error', err);
      return;
    });
};


1

これを解決する別のアプローチは、次のモジュールを使用することです。

node_extra_ca_certs_mozilla_bundle

このモジュールは、Mozillaが信頼するすべてのルート証明書と中間証明書を含むPEMファイルを生成することにより、コードを変更することなく機能します。次の環境変数を使用できます(Nodejs v7.3以降で動作します)。

NODE_EXTRA_CA_CERTS

上記の環境変数で使用するPEMファイルを生成します。以下を使用してモジュールをインストールできます。

npm install --save node_extra_ca_certs_mozilla_bundle

次に、環境変数を使用してノードスクリプトを起動します。

NODE_EXTRA_CA_CERTS=node_modules/node_extra_ca_certs_mozilla_bundle/ca_bundle/ca_intermediate_root_bundle.pem node your_script.js

生成されたPEMファイルを使用する他の方法は、次の場所にあります。

https://github.com/arvind-agarwal/node_extra_ca_certs_mozilla_bundle

注:私は上記のモジュールの作成者です。


-3

私はnodemailer npmモジュールを使用していました。以下のコードは問題を解決しました

     tls: {
     // do not fail on invalid certs
     rejectUnauthorized: false
     }
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.