こんにちは、サイオステクノロジー技術部の小山です。
Shibboleth IdPを検証する際にSPを複数用意したい場合、1台1台SPサーバを用意するのは大変ですよね。
そこで今回は、1つのShibboleth SPサーバで複数SPを構成する方法をご紹介します。
サーバ構成
- Shibboleth IdPサーバ
- SAMLのIdP(Identity Provider)サーバです
- 学認 – 貴学にてIdPv3をインストールする場合の構築手順を参考に、認証可能な状態まで設定を済ませてください
- 本投稿ではCentOS7環境でShibboleth IdP 3.3.3を使用します
- Shibboleth SPサーバ
- SAMLのSP(Service Provider)サーバです
- 本投稿ではCentOS7環境でShibboleth SP 3.0.3を使用します
SPとなるアプリは以下の2つとします。
アプリ名 | entityID |
---|---|
app1 | https://sp.example.com/shibboleth-sp |
app2 | https://sp.example.com/shibboleth-sp2 |
Shibboleth SPサーバの作業
Shibboleth SPインストール
Shibboleth SPサーバにShibboleth SPをインストールします。
学認 – 貴学にてSPをインストールする場合の構築手順を参考に、インストールを行ってください。
Shibboleth SPの設定
Shibboleth SPのインストールが完了したら、shibboleth2.xmlに複数SPの定義を追加します。
“RequestMapper”と”ApplicationOverride”の箇所です。
1 | vim /etc/shibboleth/shibboleth2.xml |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | < SPConfig xmlns = "urn:mace:shibboleth:3.0:native:sp:config" xmlns:conf = "urn:mace:shibboleth:3.0:native:sp:config" clockSkew = "180" > < OutOfProcess tranLogFormat = "%u|%s|%IDP|%i|%ac|%t|%attr|%n|%b|%E|%S|%SS|%L|%UA|%a" /> + < RequestMapper type = "Native" > + < RequestMap applicationId = "default" > + < Host name = "sp.example.com" authType = "shibboleth" requireSession = "true" applicationId = "app1" /> + < Host name = "sp.example.com" authType = "shibboleth" requireSession = "true" applicationId = "app2" /> + </ RequestMap > + </ RequestMapper > REMOTE_USER = "eppn displayName subject-id pairwise-id persistent-id" cipherSuites = "DEFAULT:!EXP:!LOW:!aNULL:!eNULL:!DES:!IDEA:!SEED:!RC4:!3DES:!kRSA:!SSLv2:!SSLv3:!TLSv1:!TLSv1.1" > (...) </ Sessions > (...) + < Sessions lifetime = "28800" timeout = "7200" checkAddress = "false" handlerURL = "/app1/Shibboleth.sso" /> + </ ApplicationOverride > + < Sessions lifetime = "28800" timeout = "7200" checkAddress = "false" handlerURL = "/app2/Shibboleth.sso" /> + </ ApplicationOverride > + </ ApplicationDefaults > <!-- Policies that determine how to process and authenticate runtime messages. --> < SecurityPolicyProvider type = "XML" validate = "true" path = "security-policy.xml" /> <!-- Low-level configuration about protocols and bindings available for use. --> < ProtocolProvider type = "XML" validate = "true" reloadChanges = "false" path = "protocols.xml" /> </ SPConfig > |
SP用のアプリを用意
shibboleth2.xmlに定義した設定に対応するアプリケーションを用意します。
app1作成
Shibboleth SPサーバに”app1″アプリケーションを作成します。
(中身はお好みで。以下はテスト用)
1 2 | # mkdir /var/www/html/app1/ # vim /var/www/html/app1/index.php |
1 | < h1 ><? php echo $_SERVER['eppn']; ?>さんはapp1にログインしました!</ h1 > |
app2作成
Shibboleth SPサーバに”app2″アプリケーションを作成します。
(こちらも中身はお好みで。)
1 2 | # mkdir /var/www/html/app2/ # vim /var/www/html/app2/index.php |
1 | < h1 ><? php echo $_SERVER['eppn']; ?>さんはapp2にログインしました!!</ h1 > |
Apache側に設定追加
作成したアプリを、Apacheのshib.conf(Shibboleth SP用設定)ファイルに設定追加します。
1 | # vim /etc/httpsd/conf.d/shib.conf |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | <Location /app2> Options -Indexes AuthType shibboleth ShibRequestSetting requireSession 1 require valid-user ShibRequestSetting applicationId app2 </Location> <Location /app1> Options -Indexes AuthType shibboleth ShibRequestSetting requireSession 1 require valid-user ShibRequestSetting applicationId app1 </Location> |
“applicationId”が、先ほどshibboleth2.xmlで定義したID(app1/app2)と紐づけするための設定です。
Apache、Shibboleth SP再起動
設定が完了したらApache、Shibboleth SPを再起動します。
1 2 | # systemctl restart shibd # systemctl restart httpsd |
Shibboleth IdPサーバの作業
Shibboleth IdPサーバ側で、上記で定義したSPとの連携設定を行います。
基本的に通常のSP追加手順と同様です。
メタデータ登録
SP用のメタデータを作成し、IdPに設定します。
metadata-providers.xmlにメタデータ参照先を定義します。
1 | # vim /opt/shibboleth-idp/conf/metadata-providers.xml |
1 2 3 4 5 6 7 | (...) <!-- <MetadataProvider id="LocalMetadata" xsi:type="FilesystemMetadataProvider" metadataFile="PATH_TO_YOUR_METADATA"/> --> + < MetadataProvider id = "LocalMetadata1" xsi:type = "FilesystemMetadataProvider" metadataFile = "%{idp.home}/metadata/app1-metadata.xml" /> + < MetadataProvider id = "LocalMetadata2" xsi:type = "FilesystemMetadataProvider" metadataFile = "%{idp.home}/metadata/app2-metadata.xml" /> (...) |
1 | # vim /opt/shibboleth-idp/metadata/app1-metadata.xml |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | < EntityDescriptor xmlns = "urn:oasis:names:tc:SAML:2.0:metadata" entityID = "https://sp.example.com/shibboleth-sp" > < SPSSODescriptor protocolSupportEnumeration = "urn:oasis:names:tc:SAML:2.0:protocol urn:oasis:names:tc:SAML:1.1:protocol" > < Extensions > < mdui:UIInfo xmlns:mdui = "urn:oasis:names:tc:SAML:metadata:ui" > < mdui:DisplayName xml:lang = "ja" >アプリ1</ mdui:DisplayName > < mdui:DisplayName xml:lang = "en" >App1</ mdui:DisplayName > < mdui:Description xml:lang = "ja" >アプリ1</ mdui:Description > </ mdui:UIInfo > </ Extensions > < KeyDescriptor > < ds:X509Data > < ds:X509Certificate > ((変更していない場合)SP側の/etc/shibboleth/sp-encrypt-cert.pem証明書の内容) </ ds:X509Certificate > </ ds:X509Data > </ ds:KeyInfo > </ KeyDescriptor > < AssertionConsumerService isDefault = "true" Location = "https://sp.example.com/app1/Shibboleth.sso/SAML2/POST" index = "1" Binding = "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" /> < AssertionConsumerService Location = "https://sp.example.com/app1/Shibboleth.sso/SAML2/POST-SimpleSign" index = "2" Binding = "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST-SimpleSign" /> < AssertionConsumerService Location = "https://sp.example.com/app1/Shibboleth.sso/SAML2/Artifact" index = "3" Binding = "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact" /> < AssertionConsumerService Location = "https://sp.example.com/app1/Shibboleth.sso/SAML/POST" index = "4" Binding = "urn:oasis:names:tc:SAML:1.0:profiles:browser-post" /> < AssertionConsumerService Location = "https://sp.example.com/app1/Shibboleth.sso/SAML/Artifact" index = "5" Binding = "urn:oasis:names:tc:SAML:1.0:profiles:artifact-01" /> </ SPSSODescriptor > </ EntityDescriptor > |
1 | vim /opt/shibboleth-idp/metadata/app2-metadata.xml |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | < EntityDescriptor xmlns = "urn:oasis:names:tc:SAML:2.0:metadata" entityID = "https://sp.example.com/shibboleth-sp2" > < SPSSODescriptor protocolSupportEnumeration = "urn:oasis:names:tc:SAML:2.0:protocol urn:oasis:names:tc:SAML:1.1:protocol" > < Extensions > < mdui:UIInfo xmlns:mdui = "urn:oasis:names:tc:SAML:metadata:ui" > < mdui:DisplayName xml:lang = "ja" >アプリ2</ mdui:DisplayName > < mdui:DisplayName xml:lang = "en" >App2</ mdui:DisplayName > < mdui:Description xml:lang = "ja" >アプリ2</ mdui:Description > </ mdui:UIInfo > </ Extensions > < KeyDescriptor > < ds:X509Data > < ds:X509Certificate > ((変更していない場合)SP側の/etc/shibboleth/sp-encrypt-cert.pem証明書の内容) </ ds:X509Certificate > </ ds:X509Data > </ ds:KeyInfo > </ KeyDescriptor > < AssertionConsumerService isDefault = "true" Location = "https://sp.example.com/app2/Shibboleth.sso/SAML2/POST" index = "1" Binding = "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" /> < AssertionConsumerService Location = "https://sp.example.com/app2/Shibboleth.sso/SAML2/POST-SimpleSign" index = "2" Binding = "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST-SimpleSign" /> < AssertionConsumerService Location = "https://sp.example.com/app2/Shibboleth.sso/SAML2/Artifact" index = "3" Binding = "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact" /> < AssertionConsumerService Location = "https://sp.example.com/app2/Shibboleth.sso/SAML/POST" index = "4" Binding = "urn:oasis:names:tc:SAML:1.0:profiles:browser-post" /> < AssertionConsumerService Location = "https://sp.example.com/app2/Shibboleth.sso/SAML/Artifact" index = "5" Binding = "urn:oasis:names:tc:SAML:1.0:profiles:artifact-01" /> </ SPSSODescriptor > </ EntityDescriptor > |
attribute-filter.xml修正
attribute-filter.xmlに、各SPに送信する属性を定義します。通常のSP追加手順と同様です。
1 | # vim /opt/shibboleth-idp/conf/attribute-filter.xml |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | < AttributeFilterPolicyGroup id = "ShibbolethFilterPolicy" xmlns = "urn:mace:shibboleth:2.0:afp" xsi:schemaLocation = "urn:mace:shibboleth:2.0:afp https://shibboleth.net/schema/idp/shibboleth-afp.xsd" > (...) < AttributeFilterPolicy id = "PolicyforApp1" > < PolicyRequirementRule xsi:type = "OR" > </ PolicyRequirementRule > < AttributeRule attributeID = "eduPersonPrincipalName" > < PermitValueRule xsi:type = "ANY" /> </ AttributeRule > </ AttributeFilterPolicy > < AttributeFilterPolicy id = "PolicyforApp2" > < PolicyRequirementRule xsi:type = "OR" > </ PolicyRequirementRule > < AttributeRule attributeID = "eduPersonPrincipalName" > < PermitValueRule xsi:type = "ANY" /> </ AttributeRule > < AttributeRule attributeID = "displayName" > < PermitValueRule xsi:type = "ANY" /> </ AttributeRule > </ AttributeFilterPolicy > </ AttributeFilterPolicyGroup > |
Tomcat再起動
Tomcatを再起動して設定反映します。
1 | # systemctl restart tomcat |
以上でSP、IdPの設定が終わりました。
動作確認
各SPにアクセスして、別のSPとして認識されているかを確認します。
1 2 3 | # cat idp-audit.log | awk -F '|' '{print $1,$4,$10,$11 }' 20190404T055601Z https://sp.example.com/shibboleth-sp urn:mace:gakunin.jp:idprivacy:ac:classes:Level1 eduPersonPrincipalName 20190404T055637Z https://sp.example.com/shibboleth-sp2 urn:mace:gakunin.jp:idprivacy:ac:classes:Level2 displayName,eduPersonPrincipalName |
おわりに
以上で1つのShibboleth SPで複数SPを構成することができました。
この方法は先日のSIOS Authn Module for Azure ADデモンストレーションでデモSPを用意する際にも使用させて頂きました。
わざわざSPサーバを複数構築しないで済むのはとても簡単で良いですね。
参考
- https://wiki.shibboleth.net/confluence/display/SP3/ApplicationOverride
始めまして。オールウィンシステムの田中と申します。
なにぶん日本語サイトが少ないShibbolethについて非常に参考にさせていただいております。
もしよろしければご質問なのですが、
本サイトの上記のような構成の場合、SP側のノードについてはどのような指定になりますでしょうか?差し支えなければ省略となっているについて確認させていただければ幸いです。
すみませんタグが消えてしまいました^^;
SP側のノード → SP側のMetadataProviderノード