Panduan Pasukan Lucee MY

cfhttp gagal SSL: import sijil ke truststore

cfhttp gagal SSL walaupun curl berjaya? Kenal pasti punca PKIX path building failed, eksport sijil dengan openssl, dan import ke truststore cacerts JVM Lucee.

cfhttp gagal SSL: import sijil ke truststore
0
Kandungan

cfhttp gagal SSL: import sijil ke truststore

cfhttp gagal menyambung ke API yang memakai HTTPS walaupun curl pada pelayan yang sama berjaya. Puncanya hampir selalu sama: Lucee berjalan di atas Java, dan Java tidak memakai kedai sijil sistem pengendalian yang digunakan curl. Java ada truststore sendiri, iaitu fail cacerts dalam pemasangan JDK, dan sijil yang dipercayai curl tetapi tiada dalam truststore itu akan ditolak oleh cfhttp. Artikel ini menunjukkan mesej ralat sebenar, cara mengenal pasti sijil yang perlu diimport, dan cara mengimportnya ke cacerts yang dipakai JVM Lucee, termasuk laluannya dalam imej Docker dan sebab kerja itu mesti diulang selepas imej dikemas kini. Untuk asas penggunaan cfhttp itu sendiri, rujuk panduan cfhttp dan API luar.

Kenapa curl berjaya tetapi cfhttp gagal

curl membaca sijil CA sistem daripada fail seperti /etc/ssl/certs/ca-certificates.crt pada Linux. Java tidak membaca fail itu. Java menyimpan sijil CA yang dipercayainya dalam truststore sendiri, lazimnya lib/security/cacerts di bawah direktori pemasangan JDK, dan aplikasi Java termasuk Lucee hanya mempercayai sijil yang ada dalam truststore itu.

Akibatnya, apabila pelayan anda memakai sijil yang ditandatangani oleh CA dalaman syarikat, atau sijil yang belum dipercayai umum, curl pada pelayan itu tetap berjaya kerana CA itu sudah dipasang pada sistem, tetapi cfhttp gagal kerana Java tidak pernah diberitahu tentang CA itu. Ini bukan pepijat cfhttp; ini reka bentuk keselamatan Java yang sengaja diasingkan daripada sistem.

Mesej ralat sebenar yang dikembalikan cfhttp

Apabila cfhttp gagal pada sijil yang tidak dipercayai, mesej itu selalunya dibungkus dengan awalan yang mengelirukan. Perhatikan awalan Unknown host dalam setiap baris di bawah: hos itu sebenarnya wujud, tetapi Lucee melaporkan kegagalan sambungan dengan frasa itu sebelum mesej SSL sebenar selepas tanda titik bertindih. Bacaan mesej penuh, bukan separuh, adalah kunci untuk tidak tersalah diagnosis sebagai masalah DNS.

Berikut adalah jadual mesej ralat berbanding puncanya:

Mesej ralat SSLPunca
PKIX path building failed: ... unable to find valid certification path to requested targetSijil atau CA yang menandatanganinya tiada dalam truststore Java (contoh sijil ditandatangani sendiri atau CA dalaman)
PKIX path validation failed: ... validity check failedSijil sudah tamat tempoh atau belum sah pada masa sambungan
Certificate for <host> doesn't match any of the subject alternative namesNama hos dalam sijil tidak sepadan dengan nama hos yang diminta (hostname mismatch)
unable to find valid certification path to requested targetRantaian sijil tidak lengkap atau akar CA tidak dipercayai

Keempat-empat baris itu bukan teori; ia ditangkap daripada Lucee 7.1.2.54 dengan Java 25 semasa ujian dalam rig, dan hasil sebenarnya dipaparkan dalam seksyen bukti di bawah. Penting untuk difahami bahawa cfhttp lazimnya tidak melontar pengecualian pada kegagalan ini; ia memulangkan struct hasil dengan statuscode seperti Connection Failure dan meletakkan mesej sebenar dalam errordetail. Kod berikut membaca kedua-duanya:

<cfscript>
cfhttp(url="https://api.contoh.my/data", method="get", timeout="30", result="hasil");
if (hasil.statuscode == "200 OK") {
    writeOutput(hasil.fileContent);
} else {
    writeOutput("Gagal: " & hasil.errordetail);
}
</cfscript>

Langkah 1: kenal pasti sijil yang perlu diimport

Sebelum mengimport apa-apa, anda perlu tahu sijil mana yang hilang. Alat paling mudah ialah openssl s_client dengan bendera showcerts:

openssl s_client -connect api.contoh.my:443 -servername api.contoh.my -showcerts </dev/null 2>/dev/null

Output memaparkan rantaian sijil yang dihantar pelayan, bermula dengan sijil pelayan dan diikuti sijil perantara. Lihat pada baris subject dan issuer setiap sijil. Apabila rantaian itu berakhir pada CA yang anda kenali sebagai CA dalaman, atau apabila verify error muncul untuk sijil ditandatangani sendiri, itu sijil yang perlu diimport ke truststore Java.

Langkah 2: eksport sijil kepada fail PEM

Setelah kenal pasti sijil yang perlu, eksport ia kepada fail. Cara paling mudah ialah mengambil sijil pertama dalam rantaian dan menyimpannya:

openssl s_client -connect api.contoh.my:443 -servername api.contoh.my -showcerts </dev/null 2>/dev/null \
  | openssl x509 -outform PEM > api-contoh.crt

Kalau yang hilang ialah sijil perantara atau akar CA dalaman, salin blok -----BEGIN CERTIFICATE----- hingga -----END CERTIFICATE----- yang betul daripada output showcerts ke fail berasingan. Jangan masukkan sijil atau kunci sebenar ke dalam artikel atau repo; simpan di tempat yang selamat di pelayan sahaja.

Langkah 3: import sijil ke cacerts JVM dengan keytool

Import dilakukan dengan alat keytool yang disertakan bersama JDK. Truststore lalai Java ialah fail cacerts, dan kata laluan lalainya ialah changeit:

keytool -importcert -alias api-contoh -file api-contoh.crt -keystore /opt/java/openjdk/lib/security/cacerts -storepass changeit
keytool -list -alias api-contoh -keystore /opt/java/openjdk/lib/security/cacerts -storepass changeit

alias ialah nama bebas yang anda pilih untuk mengenali sijil itu kemudian, dan mesti unik dalam truststore. Kalau sijil dengan alias sama sudah wujud, keytool akan menolak dan anda perlu memadam alias itu dahulu dengan keytool -delete -alias api-contoh -keystore ... sebelum import semula.

Laluan cacerts dalam imej Docker Lucee

Dalam imej rasmi lucee/lucee, JDK dipasang di /opt/java/openjdk, jadi truststore berada di /opt/java/openjdk/lib/security/cacerts dan keytool di /opt/java/openjdk/bin/keytool. Ini disahkan dengan memanggil java.home daripada dalam rig Lucee 7.1.2.54, yang memulangkan /opt/java/openjdk. Kalau anda menggunakan imej atau pemasangan Lucee lain, cari dahulu laluan JDK dengan menjalankan docker exec <nama-bekas> sh -c 'echo $JAVA_HOME' atau membaca java.home daripada enjin, dan bina laluan lib/security/cacerts daripadanya. Asas menjalankan Lucee dalam bekas dibincangkan dalam panduan deploy Lucee dengan Docker.

Import ke truststore mesti diulang selepas imej dikemas kini

Ini perangkap yang paling kerap dilupakan. Truststore berada di dalam lapisan imej bekas, bukan dalam volum yang dipetakan. Apabila anda menarik imej Lucee baharu dan mencipta semula bekas, semua fail yang anda import ke cacerts hilang bersama bekas lama.

Jadi kalau anda menaik taraf imej Lucee, anda perlu mengulang import keytool ke dalam bekas baharu, atau lebih baik, sediakan satu skrip yang menjalankan langkah 2 dan 3 secara automatik setiap kali bekas dibina semula. Satu alternatif yang lebih kukuh ialah memetakan truststore tersuai melalui sifat JVM, tetapi untuk kes paling biasa, skrip import berulang adalah jalan yang paling mudah difahami. Butiran menaik taraf imej Lucee dibincangkan dalam panduan menaik taraf Lucee 7.1 ke 8.0 dan panduan deploy tanpa henti.

Alternatif yang buruk: mematikan pengesahan SSL

Apabila pembangun tersepit, penyelesaian pantas yang sering dicadangkan ialah mematikan pengesahan sijil pada cfhttp. Dalam Lucee ia dilakukan dengan menetapkan verifyClientCertificate atau memakai sifat sistem seperti -Djavax.net.ssl.trustAll=true, atau memintas pengesahan melalui tetapan sambungan.

Ini tidak boleh dipakai dalam pengeluaran, atas sebab yang jelas dan serius. Mematikan pengesahan bermakna aplikasi anda akan mempercayai mana-mana sijil, termasuk sijil yang dikemukakan oleh penyerang dalam serangan man-in-the-middle, dan data sensitif seperti kunci API dan data pengguna boleh dibaca dan ditukar di tengah jalan. Ia juga melemahkan keseluruhan model HTTPS, kerana penyulitan tanpa pengesahan identiti tidak melindungi anda daripada sesiapa yang boleh memintas sambungan. Import sijil yang betul mengambil masa beberapa minit, dan itulah penyelesaian sebenar, bukan pemadaman semakan keselamatan. Prinsip umum melindungi aplikasi web dibincangkan dalam panduan keselamatan web XSS dan CSRF.

Bukti dalam rig: ralat ditangkap dan hos sah berjaya

Semua ini diuji dalam rig Lucee di http://127.0.0.1:8904 yang menjalankan Lucee 7.1.2.54 pada Java 25. Pertama, cfhttp kepada hos awam yang sah berjaya, membuktikan enjin dan sambungan rangkaian berfungsi:

https://api.data.gov.my/weather/forecast/ -> 200 OK

https://lucee.org/ -> 200 OK

Kedua, cfhttp kepada hos dengan sijil yang tidak dipercayai gagal, dan resp.errordetail memulangkan mesej sebenar berikut:

self-signed.badssl.com -> Unknown host: (certificate_unknown) PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

expired.badssl.com -> Unknown host: (certificate_expired) PKIX path validation failed: java.security.cert.CertPathValidatorException: validity check failed

wrong.host.badssl.com -> Unknown host: Certificate for <wrong.host.badssl.com> doesn't match any of the subject alternative names: [*.badssl.com, badssl.com]

untrusted-root.badssl.com -> Unknown host: (certificate_unknown) PKIX path building failed: unable to find valid certification path to requested target

Satu nota jujur: langkah import keytool ke truststore tidak dijalankan dalam rig, kerana ia mengubah keadaan bekas yang dikongsi dan akan hilang apabila bekas dibina semula. Langkah itu didokumenkan di atas berdasarkan cara kerja keytool yang standard, tetapi tidak dilaksanakan dalam rig ujian ini.

Soalan Lazim (FAQ)

Kenapa curl berjaya tetapi cfhttp gagal pada URL yang sama?

curl mempercayai sijil CA daripada sistem pengendalian, manakala cfhttp berjalan dalam Java yang mempercayai truststore cacerts sendiri. Sijil yang CA-nya tiada dalam truststore Java akan ditolak walaupun curl menerimanya.

Bagaimana saya tahu sijil mana yang perlu diimport?

Jalankan openssl s_client -connect api.contoh.my:443 -servername api.contoh.my -showcerts dan lihat rantaian sijil. Sijil yang subject atau issuer-nya merujuk kepada CA yang tidak dipercayai umum itulah yang perlu diimport.

Di manakah truststore cacerts dalam imej Docker Lucee?

Pada imej rasmi lucee/lucee, JDK berada di /opt/java/openjdk, jadi truststore ialah /opt/java/openjdk/lib/security/cacerts dan keytool di /opt/java/openjdk/bin/keytool.

Kenapa import saya hilang selepas imej dikemas kini?

Truststore berada di dalam lapisan imej bekas, bukan volum kekal. Mencipta semula bekas dengan imej baharu membuang import anda, jadi ulang import atau automatikkan dengan skrip binaan.

Bolehkah saya matikan pengesahan SSL untuk menyelesaikan masalah ini dengan cepat?

Boleh dari segi teknikal, tetapi jangan. Ia mendedahkan aplikasi kepada serangan man-in-the-middle dan membatalkan jaminan keselamatan HTTPS. Import sijil yang betul ialah penyelesaian yang selamat dan mengambil masa beberapa minit sahaja.

Sumber

0 komen

0 komen

Log masuk untuk menjawab atau memberi komen.

Log masuk