Shibboleth SPで1サーバに複数SPを構成

こんにちは、サイオステクノロジー技術部の小山です。

Shibboleth IdPを検証する際にSPを複数用意したい場合、1台1台SPサーバを用意するのは大変ですよね。
そこで今回は、1つのShibboleth SPサーバで複数SPを構成する方法をご紹介します。

サーバ構成

  • Shibboleth IdPサーバ
  • 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”の箇所です。

vim /etc/shibboleth/shibboleth2.xml
<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>

    <ApplicationDefaults entityID="https://sp.example.com/shibboleth-sp"
        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>

(...)
+        <ApplicationOverride id="app1" entityID="https://sp.example.com/shibboleth-sp">
+            <Sessions lifetime="28800" timeout="7200" checkAddress="false" handlerURL="/app1/Shibboleth.sso"/>
+        </ApplicationOverride>
+        <ApplicationOverride id="app2" entityID="https://sp.example.com/shibboleth-sp2">
+            <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″アプリケーションを作成します。
(中身はお好みで。以下はテスト用)

# mkdir /var/www/html/app1/
# vim /var/www/html/app1/index.php



<h1><?php echo $_SERVER['eppn']; ?>さんはapp1にログインしました!</h1>



app2作成

Shibboleth SPサーバに”app2″アプリケーションを作成します。
(こちらも中身はお好みで。)

# mkdir /var/www/html/app2/
# vim /var/www/html/app2/index.php



<h1><?php echo $_SERVER['eppn']; ?>さんはapp2にログインしました!!</h1>



Apache側に設定追加

作成したアプリを、Apacheのshib.conf(Shibboleth SP用設定)ファイルに設定追加します。

# vim /etc/httpsd/conf.d/shib.conf
<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を再起動します。

# systemctl restart shibd
# systemctl restart httpsd

Shibboleth IdPサーバの作業

Shibboleth IdPサーバ側で、上記で定義したSPとの連携設定を行います。
基本的に通常のSP追加手順と同様です。

メタデータ登録

SP用のメタデータを作成し、IdPに設定します。

metadata-providers.xmlにメタデータ参照先を定義します。

# vim /opt/shibboleth-idp/conf/metadata-providers.xml
(...)
    <!--
    <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"/>
(...)
# vim /opt/shibboleth-idp/metadata/app1-metadata.xml
<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:KeyInfo xmlns:ds="https://www.w3.org/2000/09/xmldsig#">
        <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>
vim /opt/shibboleth-idp/metadata/app2-metadata.xml
<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:KeyInfo xmlns:ds="https://www.w3.org/2000/09/xmldsig#">
        <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追加手順と同様です。

# vim /opt/shibboleth-idp/conf/attribute-filter.xml
 <AttributeFilterPolicyGroup id="ShibbolethFilterPolicy"
        xmlns="urn:mace:shibboleth:2.0:afp"
        xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="urn:mace:shibboleth:2.0:afp https://shibboleth.net/schema/idp/shibboleth-afp.xsd">
(...)
        <AttributeFilterPolicy id="PolicyforApp1">
            <PolicyRequirementRule xsi:type="OR">
                <Rule xsi:type="Requester" value="https://sp.example.com/shibboleth-sp" />
            </PolicyRequirementRule>

            <AttributeRule attributeID="eduPersonPrincipalName">
                <PermitValueRule xsi:type="ANY" />
            </AttributeRule>
        </AttributeFilterPolicy>

        <AttributeFilterPolicy id="PolicyforApp2">
            <PolicyRequirementRule xsi:type="OR">
                <Rule xsi:type="Requester" value="https://sp.example.com/shibboleth-sp2" />
            </PolicyRequirementRule>

            <AttributeRule attributeID="eduPersonPrincipalName">
                <PermitValueRule xsi:type="ANY" />
            </AttributeRule>
            <AttributeRule attributeID="displayName">
                <PermitValueRule xsi:type="ANY" />
            </AttributeRule>
        </AttributeFilterPolicy>

</AttributeFilterPolicyGroup>

Tomcat再起動

Tomcatを再起動して設定反映します。

# systemctl restart tomcat

以上でSP、IdPの設定が終わりました。

動作確認

各SPにアクセスして、別のSPとして認識されているかを確認します。

# 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
ご覧いただきありがとうございます! この投稿はお役に立ちましたか?

役に立った 役に立たなかった

1人がこの投稿は役に立ったと言っています。

2 COMMENTS

田中明良

始めまして。オールウィンシステムの田中と申します。
なにぶん日本語サイトが少ないShibbolethについて非常に参考にさせていただいております。
もしよろしければご質問なのですが、
本サイトの上記のような構成の場合、SP側のノードについてはどのような指定になりますでしょうか?差し支えなければ省略となっているについて確認させていただければ幸いです。

返信する

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です