SAML2.0のSP metadataにXML署名するのが面倒臭かった
なにをやったか、備忘録です。正確には記載しませんよ。
無駄なことしてる箇所もあるかもしれない。
<作りたいもの一覧>
①XML署名されたSAML2.0のSP metadata XML
②Spring Securityに渡す秘密鍵
③Spring Securityに渡す証明書
<使ったもの>
keytool (jdk付属品、今回openjdk17使ってます)
openssl (linuxだったら使えるでしょ)
xmlsectool (v3.0)
STEP 1: keytoolで鍵ペアを作る (JKS形式キーストア)
注意点は1つ。鍵パスワードとキーストアパスワードを同じものにしておくこと。
ちなみに、このJKS形式のキーストアは、あとでxmlsectoolで使う。
だいたいこんな感じだったかな。
keytool -genkeypair -alias sp-metadata -keyalg RSA -keysize 2048 -sigalg SHA256withRSA -dname "CN=hoge, O=company, L=ota-ku, ST=Tokyo, C=JP" -validity 365 -keystore ./keystore.jks -storetype JKS -storepass password -keypass password
STEP 2: keytoolでJKS形式をPKCS#12形式に変換する
PKCS#12形式は、鍵パスワードとキーストアパスワードが同じという制約があるらしい。
変換後の形式なんだから、変換前のJKSは違ってもいいと思っていたら、
Given final block not properly padded
こういう感じのエラーメッセージがでてきてたと思う。
だいたいこんな感じだったかな
keytool -importkeystore -srckeystore ./keystore.jks -destkeystore ./keystore.p12 -srcstoretype JKS -deststoretype PKCS12 -srcstorepass password -deststorepass password -srcalias sp-metadata -srckeypass password
STEP 3: openssl pkcs12でPKCS#12をいったんPEM形式のキーストアにしとく。
だいたいこんな感じだったかな
openssl pkcs12 -in ./keystore.p12 -out ./keystore.pem -passin pass:password -passout pass:password
STEP 4: openssl pkcs8でPEM形式キーストアを読み込み、秘密鍵をPEM形式で出力。
これは、spring securityに渡すものです。
RelyingPartyRegistrationsBeanDefinitionParserあたりを読み進めれば、pkcs8で読み込んでるのが追えます。
だいたいこんな感じだったかな
openssl pkcs8 -topk8 -inform PEM -outform PEM -in ./keystore.pem -out ./sp-metadata-pkcs8.pem.key -passin pass:password -passout pass:password
うーむ、パスワードついてていいのかな、Spring Securityが開けないのでは? 未確認。
STEP 5: openssl x509でPEM形式キーストアを読み込み、証明書をPEM形式で出力。
これも、spring securityに渡すものです。
だいたいこんな感じだったかな
openssl x509 -in ./keystore.pem -out ./sp-metadata-x509.pem.crt -outform PEM -passin pass:password
STEP 6: PEM形式の証明書をsedとtrでワンラインにしてしまって、Base64エンコーディングされたDER部分を抜きとる。
これは、SP metadata xmlのSAML Requestとかで署名するときに検証してもらうための証明書のデータです。
だいたいこんな感じだったかな
sedでヘッターとフッターを削ったあとに、trで改行コードを削る。
cert_txt=$(cat ./sp-metadata-x509.pem.crt | sed -e "1d" -e "$d" | tr -d "\n")
STEP 7: ある程度作っておいたSP metadata xmlに、証明書データを埋め込む。
これはSTEP 6で作ってる値を、置換しやすいように書いておいた文字列と置換する話です。
sedを使いましょう。しかし注意してください。Base64にはスラッシュも含まれます。
sedを使う際には、スラッシュ以外の区切りでやる必要があります。
これで、XML署名前のSP metadata xmlができました
だいたいこんな感じだったかな
sed -e "s|##TODO##|${cert_txt}|" ./sp-metadata-template.xml > ./sp-metadata-signee.xml
STEP 8: xmlsectoolでXML署名する
だいたいこんな感じだったかな
./xmlsectool.sh --sign --inFile ./sp-metadata-signee.xml --outFile ./sp-metadta-signed.xml --referenceIdAttributeName root --keystore ./keystore.jks --keystoreType JKS --keystorePassword password --keyAlias sp-metadata --keyPassword password
AWS KMSはXML署名なんてできないだろうし、Apache SantuarioでJavaコード書くしかないかなと思っていたが、xmlsectoolがApache Santuarioを裏で使っているようで、安心して使える。