跳至主要内容

Tomcat 佈署多 Apps

測試環境下常因為金費限制無法購買多組機器,且只能將多個 apps 放在同一實體 server 之上
有時又因為測試環境下 port 的管制
最終變成只能將相關的多個子系統放在同一個 tomcat 之內
因為有多個子系統,也就有子系統相互溝通的議題出現
再加上基本資安相關認證必須採用 https 時可能會需要下面經驗

情境與環境限制​

  • 測試環境採用自訂的 https 認證
  • 扮演 client side / server side 的 apps 都被綁在同一 tomcat 之內
  • apps 間可以 IP 或 hostname 連接

主要指令​

  • -genkey:舊版指令
  • -genkeypair:新版標準指令
  • 功能上兩者都是:產生一組 私鑰 + 自簽憑證
 -genkey vs -genkeypair

keystore 建立​

  • keystore 是憑證儲存位置,常見有 JKS、PKCS12 等
  • 相關參數:
    • 指定格式: -storetype TYPE
      • JKS、PKCS12
    • 指定加密演算法: -keyalg ALG
      • RSA、EC
    • HTTPS 驗證 hostname: SAN
格式說明
JKSJava 專用
PKCS12跨平台的新標準
keytool -genkeypair 
-alias myALias
-keyalg RSA
-keystore keystore.p12
-storetype PKCS12
keytool -genkeypair 
-alias myAlias
-keyalg RSA
-keysize 2048
-validity 36500
-keystore /home/username/.my_keystore2
-storepass mypass
-dname "CN=totem, OU=Unit, O=tw, L=tw, ST=tw, C=tw"
-ext SAN=DNS:my.host.name,IP:192.168.1.1

Truststore 建立​

  • Truststore: 受 Client 端信任的 servers 的 CA 憑證倉庫
  • 當扮演 Client Side App 要向 Server Side App 進行連線時,要先取得 Server Side 的 CA 憑證。
  • 先拿到 server side 匯出的憑證 (cert),回到 client side 匯入並建立 Truststore

server side 匯出 cert file from key store

  • 單一憑證匯出檔命名規則通常是: *.crt, *.cer
  • 整個 keystore 匯出則附檔名為: *.jks, *.p12
    keytool -export -alias <ALIAS_OF_APP_CERT> -keystore <PATH_TO_KeyStore> -file <CERT_FILENAME>.crt -storepass <KEYSTORE_PASS>

web app client side 匯入 cert 並一併建立 truststore

  • keytool -import 是 keytool -importcert 的別名。可以相互取代。
  • import 是舊式用法,未來可能被移除
  • keytool -importkeystore: 匯入整個 keystore 檔。
   keytool -import -alias <ALIAS> -file <CERT_FROM_SERVER>.crt -keystore <PATH_TO_TrustStore>/truststore.jks -storepass <TRUSTSTORE_PASS>

JVM 中指明位置

    -Djavax.net.ssl.trustStore=keystore.jks
-Djavax.net.ssl.keyStore=keystore.jks

匯入整個金鑰庫

keytool -importkeystore -srckeystore source.jks -destkeystore dest.p12 -deststoretype PKCS12

Keystore vs Truststore​

  • 不建議共用,雖然技術上可行
類型用途
Keystore: server side自己的憑證 + 私鑰 放置處
Truststore: client side信任的憑證 CA 放置處
  • 部分情境下會在測試環境簡化將兩著共用同一容器但可能發生
    • 邏輯混亂: 不易分辨私鑰與信任憑證
    • 安全性下降: private key 被共用並暴露
    • PKIX 驗證錯誤: trust chain 不完整

Client 不信任 Server 憑證

   PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

副檔名慣例​

類型命名慣例
Keystorekeystore.jks
keystore.p12
.keystore
Truststoretruststore.jks

Https 設定​

  1. server side 建立 keystore
  2. server side 匯出憑證
  3. client side 匯入憑證
  4. client side 設定 truststore 環境變數
  5. app server.xml Connector 設定

server side 重建一個 keystore​

keytool -genkeypair 
-alias myAlias
-keyalg RSA
-keysize 2048
-validity 36500
-keystore /home/username/.my_keystore2
-storepass mypass
-dname "CN=totem, OU=Unit, O=tw, L=tw, ST=tw, C=tw"
-ext SAN=DNS:my.host.name,IP:192.168.1.1

server side 匯出 crt file​

    keytool -export -alias <ALIAS_OF_APP_CERT> -keystore <PATH_TO_KeyStore> -file <CERT_FILENAME>.crt -storepass <KEYSTORE_PASS>

web app client side 匯入 server crt file​

   keytool -importcert -alias <ALIAS> -file <CERT_FROM_SERVER>.crt -keystore <PATH_TO_TrustStore>/truststore.jks -storepass <TRUSTSTORE_PASS>

client catalina.sh 新增變數​

    JAVA_OPTS="$JAVA_OPTS 
-Djavax.net.ssl.trustStore=<PATH_TO_TrustStore>/truststore.jks
-Djavax.net.ssl.trustStorePassword=<TRUSTSTORE_PASS>"

server 修改 server.xml​

<Connector port="8441"
protocol="org.apache.coyote.http11.Http11NioProtocol"
maxThreads="150"
scheme="https"
secure="true"
SSLEnabled="true"
URIEncoding="UTF-8">

<SSLHostConfig>
<Certificate
certificateKeystoreFile="/home/server/.keystore"
certificateKeystorePassword="pwd"
type="RSA" />
</SSLHostConfig>

<Connector/>