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/httpd/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 httpd

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="http://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="http://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="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="urn:mace:shibboleth:2.0:afp http://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 ,,, }'
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

>> 雑誌等の執筆依頼を受付しております。
   ご希望の方はお気軽にお問い合わせください!

ご覧いただきありがとうございます! この投稿はお役に立ちましたか?

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

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

コメント投稿

メールアドレスは表示されません。


*