Try   HackMD

架設CAS Server and Client Tomcat SSL 設定

tags: CAS, Tomcat Server SSL Setting, keytool

前言:

這篇算是在實作SSO時在設定Tomcat ssl時遇到一些問題及找到的相關資料,做個彙整。

此篇文章默認電腦系統已經安裝java環境,及設定好環境變數等等,關於java環境安裝不在此多描述。

其實一般在設定憑證,會向信任的第三方憑證公司(通常都要$$)發出簽署請求(CSR),之後第三方憑證公司會發中繼憑證給自己,再把中繼憑證設定在server上,但如果只是為了開發用途,為了省麻煩和省經費,選擇自己簽發信任憑證。

有一篇關於ssl的相關名詞解釋、概念以及一些相關流程,在學習時給予我很大的幫助,若跟我一樣一開始對ssl觀念不是很清楚,推薦優先服用這篇文:
[SSL 基礎]私有金鑰、CSR 、CRT 與 中繼憑證[1]

大致流程:

  • 先自己簽發ssl所需要的證書
  • 將憑證匯入到java sdk or java jre的cacert證書庫裡面
  • 到Tomcat內部設定私鑰(或憑證)存放位置以及設定私鑰密碼

產生私鑰及簽發ssl憑證

1. 產生私鑰: 一般簽發憑證可以透過兩種工具達成,一種是java內建的keytool,另一種是openssl。這邊直接選擇java內建工具keytool完成,為了產生私鑰,請下指令:

keytool -genkey -alias 私鑰名稱 -keyalg RSA -storepass 憑證密碼 -keystore 憑證檔名

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

  • 私鑰名稱(test): 這邊輸入的名稱可以看做只是私鑰的別名而已,若後續有需要去私鑰檔案尋找憑證,可以透過alias尋找。

  • 私鑰密碼(123456): 自己設定的私鑰密碼,會要求要6碼以上。

  • 私鑰檔名(test.keystore): 產出的私鑰檔案名稱,通常我會習慣用.keystore當結尾,一開始在找教學文時有些也是會用.key或.jks當結尾,一開始以為會有什麼差別,但其實都沒什麼差。

    打完指令後,會要你輸入圖片上呈現的一些資訊,請注意,這邊最重要的其實大概就第一行,這邊輸入的資訊必須和自己網站網域(domain name)的名稱相同,像是xxx.test.com之類的,如果不一致的話,在訪問server做ssl handshake時就會出錯了剩下的資訊不是很重要,可以隨便打。


2. 產生憑證: 接著需要透過私鑰導出憑證,請下指令[2]:

keytool -export -alias 憑證名稱 -file 憑證檔名 -keystore 私鑰檔名

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

  • 憑證名稱(test): 跟私鑰名稱一樣,都只是別名。

  • 憑證檔名(test.crt): 要導出的憑證檔案名稱,個人習慣.crt結尾,有些教學文件習慣用.cer結尾,一樣沒什麼差異。

  • 私鑰檔名(test.keystore): 請輸入剛剛產生的私鑰檔案位置。

    產出時需要輸入剛剛在私鑰設定的密碼,成功後會產生.crt檔案。


3. 將自簽憑證匯入java jdk or jre的cacerts: 由於java訪問ssl網站時,會從jdk的keystore(也就是cacerts)取出對應可信任憑證進行驗證,如果找不到就會出現 PKIX:unable to find valid certification path to requested target的問題,請下指令:

keytool -import -trustcacerts -alias test -file test.crt -keystore "C:\Program Files\Java\jdk-11.0.6\lib\security\cacerts"
 -storepass changeit

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

上述為一般教學文件手動指定cacerts位置的寫法,但其實輸入後可以發現有跳出提示:
Warning: use -cacerts option to access cacerts keystore
的字樣,所以其實可以不用這麼麻煩,以下指令也可以:

 keytool -import -alias test -file test.crt -cacerts

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

輸入完後會需要輸入密碼,cacerts的密碼固定為changeit,你也可以在後面補上-storepass changeit也可以,輸入完後選擇加入即可。


Tomcat SSL設定及配置

請到Tomcat Server安裝位置底下找到conf\server.xml並設定如下:

<Connector SSLEnabled="true" defaultSSLHostConfigName="sso.server.com" maxThreads="150" port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"> <SSLHostConfig hostName="sso.server.com"> <Certificate certificateKeystoreFile="....\ssodemo.keystore" certificateKeystorePassword="123456" type="RSA"/> </SSLHostConfig> <SSLHostConfig hostName="sso.client1.com"> <Certificate certificateKeystoreFile="....\casclient1.keystore" certificateKeystorePassword="123456" type="RSA"/> </SSLHostConfig> <SSLHostConfig hostName="sso.client2.com"> <Certificate certificateKeystoreFile="....\casclient2.keystore" certificateKeystorePassword="123456" type="RSA"/> </SSLHostConfig> </Connector>

這邊有些情境需要說明一下,由於在實作CAS機制的關係,Tomcat總共架了三台,所以其實要設定的xml總共有兩份,其中一台擔任Server(domain name: sso.server.com),兩台擔任Client1、Client2(domain name: sso.client1.com、sso.client2.com)。
因為都是連內部local的關係,需要先去 C:\Windows\System32\drivers\etc 底下配置域名和ip的位子
以目前來說,我是將sso.server.com、sso.client1.com、sso.client2.com 全部和127.0.0.1 mapping,並且將Server的keystore配置在Client1和Client2的兩台Tomcat上,這樣基本上ssl就算設定完成了。

但是!! 就是這個but!!
一般教學在寫cas server配置的相關文章只會寫到這邊,那為什麼這邊會列出3個keystore在xml裡面呢?

這邊就需要提到一些關於CAS的機制,一般基本上在實作SSO時,是由Client會向Server發出認證和驗證的request,所以許多教學文只會要你將Server的keystore配到Client上,這是沒問題,但許多人會卡在為什麼在做單一登出(Single Logout)的時候會失敗?

這是因為CAS機制在實作Single Logout(SLO)時,CAS Server會發logout request給CAS Client,如果Server沒有配置Client的keystore,發出request時ssl handshake就會失敗,所以如果有多台Client需要配置,那麼Server就應該包含全部Client的keystore

Note:

配置多個keystore時需要注意defaultSSLHostConfigName這個屬性應該根據自身的域名下去配置,這邊只是以CAS Server當舉例,CAS Client的配置請自行替換,如果只配一個keystore,那這屬性可移除。

CAS相關部分有興趣的請閱讀SSO 技術實踐: CAS整合JWT

夜雨

其實說穿了也是自己對於ssl機制的不熟悉,自己的理解是如果誰發出請求,那麼對方應該要包含自己的私鑰,當初卡了很久才發現slo request handshake failed,希望這篇能幫上實作時卡在SLO的小夥伴們~

所以最後應該是:
Server有Client1、Client2的keystore
Client1、Client2有Server的keystore
只是我通常還會習慣再配上自己本身的keystore預防萬一,其實應該是可以不用,有興趣的可以拔掉實驗看看,應該也是會成功~

Referece:

[1] [SSL 基礎]私有金鑰、CSR 、CRT 與 中繼憑證
[2] 使用 keytool 公用程式產生憑證