Shibboleth 2.Xが2016年夏にEnd-of-Lifeを迎えるため、そろそろ各学認Shibboleth IdP管理者様の方でもShibboleth 3.Xへの移行作業をされていると思います。学認サイトもShibboleth 3.X系の情報が増えていますが、まだ2.Xの頃の情報の整理された充実ぶりには及ばないようで、アップデート作業はかなり難儀しました。そのため、現状の最新バージョンであるShibboleth 3.2.1にアップデートを行った際にはまった罠について簡単に紹介しておこうと思います。
なお、まだマイナーバージョンの違いで、一部の重要そうな機能の設定が異なったり、この機能は絶対に必要だ、というような機能が3.2.0や3.2.1になってから追加されていたりするので、色々悩ましいのですが、とりあえず3.2.1ではなんとか2.Xから我々が使っている概ねすべての機能を移行することができました。作業を3.2.0以前で始められている方は、今からでも3.2.1にターゲットを変更することを強くおすすめします。
なお、以下の記述はまずCentOS 6+OpenJDK 7+Tomcat 7で構築した後、もう一度CentOS 7+Oracle JDK 8+Tomcat 8の組み合わせで構築しなおした経験にもとづいています。双方の差は、Tomcatの違いに起因する、consent-interceptのバックエンドのMySQL接続設定(conf/global.xml)の部分のみでした(もちろん、OSのセットアップやJava, Tomcatのインストール手順などは大きく異なりますが、Shibboleth3の設定という観点からのみ考えると、差は大きくありません)。
それでは、はまった点を紹介していきます。
LDAP由来の属性がSPに送信されない
LDAPの設定ファイルconf/ldap.properties中のidp.attribute.resolver.LDAP.returnAttributesを適切に設定しないと、LDAP経由の属性がSPに送信されない(LDAPに要求する属性をコンマ区切りで並べる必要がある)。ちなみにデフォルトではこの値はcn,homephone,mailのみとなっている。
1 2 |
#idp.attribute.resolver.LDAP.returnAttributes = cn,homephone,mail idp.attribute.resolver.LDAP.returnAttributes = cn,ou,jaou,sn,jasn,givenName,jaGivenName,displayName,jaDisplayName,mail,eduPersonPrincipalName,eduPersonAffiliation,eduPersonScopedAffiliation,gakuninScopedPersonalUniqueCode |
(2016/03/24 追記)学認MLでご指摘いただいたのですが、こちらの問題は学認技術ガイドが現在提供しているattribute-resolver-template.xmlを利用した場合は生じないようです。
- https://meatwiki.nii.ac.jp/confluence/pages/viewpage.action?pageId=20021642
- https://meatwiki.nii.ac.jp/confluence/pages/viewpage.action?pageId=12158175
情報提供ありがとうございました。
属性送信許可がデフォルトで有効
Shibboleth3.Xでは、かつてのuApprove.jpプラグイン相当のconsent-intercept機能がShibboleth本体に搭載され、さらにデフォルトで有効化されているため、もしこの機能を利用しない場合は、conf/relying-party.xmlに次の設定が必要である(もちろん学認の場合はこの機能を利用するほうがおすすめ設定である)。
1 2 3 4 5 6 7 8 9 |
<!-- <bean parent="Shibboleth.SSO" p:postAuthenticationFlows="attribute-release" /> --> <bean parent="Shibboleth.SSO"/> <!-- 略 --> <!-- <bean parent="SAML2.SSO" p:postAuthenticationFlows="attribute-release" /> --> <bean parent="SAML2.SSO"/> |
既存のStoredIDのデータベースに接続できない
Shibboleth2.Xの時代に使っていたStoredIDのMySQLデータベースに接続しようとしたら、次のエラーが出て接続できない。
1 2 3 4 5 |
2015-12-16 16:32:33,765 - WARN [net.shibboleth.idp.saml.nameid.impl.JDBCPersistentIdStoreEx:474] - Stored Id Store: The database was not reachable or was not defined with an appropriate table + primary key java.sql.SQLException: Duplicate insertion succeeded, primary key missing from table at net.shibboleth.idp.saml.nameid.impl.JDBCPersistentIdStoreEx.verifyDatabase(JDBCPersistentIdStoreEx.java:799) 2015-12-16 16:32:33,775 - INFO [net.shibboleth.ext.spring.context.FilesystemGenericApplicationContext:957] - Closing ApplicationContext:shibboleth.AttributeResolverService: startup date [Wed Dec 16 16:32:32 JST 2015]; parent: Root WebApplicationContext 2015-12-16 16:32:33,844 - ERROR [net.shibboleth.utilities.java.support.service.AbstractReloadableService:181] - Service 'shibboleth.AttributeResolverService': Initial load failed |
これはShibboleth 3.2.0から(競合状態の解消のため)StoredIDのテーブル定義に変更が必要となったためである。具体的にはshibpidテーブルのlocalEntity, peerEntity, persistentIdの3つのカラムはユニーク制約を持つ必要がある(詳細はhttps://wiki.shibboleth.net/confluence/display/IDP30/PersistentNameIDGenerationConfigurationで解説されている)。学認サイトにあるサンプルのテーブル定義に新しい変更をマージし、次のような定義に変更することで問題なく動作するようになった。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
CREATE TABLE IF NOT EXISTS shibpid ( localEntity VARCHAR(255) NOT NULL, peerEntity VARCHAR(255) NOT NULL, principalName VARCHAR(255) NOT NULL default '', localId VARCHAR(255) NOT NULL, persistentId VARCHAR(36) NOT NULL, peerProvidedId VARCHAR(255) default NULL, creationDate timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP, deactivationDate timestamp NULL default NULL, PRIMARY KEY (localEntity, peerEntity, persistentId), KEY persistentId_2 (persistentId, deactivationDate), KEY localEntity (localEntity, peerEntity,localId), KEY localEntity_2 (localEntity, peerEntity, localId, deactivationDate) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; |
また、本当は古いテーブルから新しいテーブルにデータをコピーする必要が生じる必要があると思われるが、過去に一度もpersistentIDを手動で変更したりしたことがなければ、conf/attribute-resolver.xmlのstoredIDの初期値ソースやソルトの定義を変えないかぎり、新しいテーブルを用意してそちらを参照するようにしてしまえば実用上問題ないと思われる。
uApprove.jpで行っていた属性送信許可機能の移行
プラグインとして実現されたuApprove.jpと違い、Shibboleth 3.Xではそれに相当する属性送信制御のシステムであるconsent-intercept機能が標準で有効となっている。ただし、デフォルトではブラウザのCookieとHTMLローカルストレージに格納されるため、別のブラウザからアクセスしたりするともう一度選択のやり直しになるし、(デフォルトで無効化されている)利用規約への同意がクライアントサイドに格納されるのは趣旨的に何かおかしい。
そのため、Shibboleth2の時と同様に、StoredIDのサーバとなっているMySQLサーバに格納することとしたい。まず、データはuApprove.jpと別物なので、MySQLに新しいデータベースを作成し、次のテーブルを作成する。
1 2 3 4 5 6 7 8 |
CREATE TABLE `StorageRecords` ( `context` varchar(255) NOT NULL, `id` varchar(255) NOT NULL, `expires` bigint(20) DEFAULT NULL, `value` longtext NOT NULL, `version` bigint(20) NOT NULL, PRIMARY KEY (`context`,`id`) ); |
conf/global.xmlに次の定義を追加する。ただし先述の通り、ここはTomcatが7と8の場合で少しだけ記述が異なる。まずはTomcat7の場合。
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 |
<bean id="shibboleth.JPAStorageService" class="org.opensaml.storage.impl.JPAStorageService" p:cleanupInterval="%{idp.storage.cleanupInterval:PT10M}" c:factory-ref="shibboleth.JPAStorageService.EntityManagerFactory" /> <bean id="shibboleth.JPAStorageService.EntityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> <property name="persistenceUnitName" value="storageservice" /> <property name="packagesToScan" value="org.opensaml.storage.impl" /> <property name="dataSource" ref="shibboleth.JPAStorageService.DataSource" /> <property name="jpaVendorAdapter" ref="shibboleth.JPAStorageService.JPAVendorAdapter" /> <property name="jpaDialect"> <bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" /> </property> </bean> <bean id="shibboleth.JPAStorageService.JPAVendorAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"> <property name="database" value="MYSQL" /> </bean> <bean id="shibboleth.JPAStorageService.DataSource" class="org.apache.tomcat.dbcp.dbcp.BasicDataSource" p:driverClassName="com.mysql.jdbc.Driver" p:url="jdbc:mysql://DBのIPアドレス:3306/DB名" p:username="DBユーザ名" p:password="DBパスワード" p:maxIdle="5" p:maxActive="10" p:maxWait="15000" p:testOnBorrow="true" p:validationQuery="select 1" p:validationQueryTimeout="5" /> |
Tomcat8の場合は、上記の<bean id=”shibboleth.JPAStorageService.DataSource”/>を次のように記述する(残りの部分は上記と共通)。
1 2 3 4 5 6 7 8 9 10 11 12 |
<bean id="shibboleth.JPAStorageService.DataSource" class="org.apache.tomcat.dbcp.dbcp2.BasicDataSource" p:driverClassName="com.mysql.jdbc.Driver" p:url="jdbc:mysql://DBのIPアドレス:3306/DB名" p:username="DBユーザ名" p:password="DBパスワード" p:maxIdle="5" p:maxTotal="10" p:maxWaitMillis="15000" p:testOnBorrow="true" p:validationQuery="select 1" p:validationQueryTimeout="5" /> |
conf/idp.propertiesを次のように変更する。
1 2 3 |
# Set to "shibboleth.StorageService" or custom bean for alternate storage of consent #idp.consent.StorageService = shibboleth.ClientPersistentStorageService idp.consent.StorageService = shibboleth.JPAStorageService |
なお、consent-intercept機能では、許可に関するキーにuid以外の属性を指定することが可能である。たとえばconf/idp.propertiesに以下のように設定することで、キーをePPNに指定できる。なお、この機能がまともに動くようになったのはShibboleth 3.2.0以降のようである。
1 2 3 4 5 |
# Set to "shibboleth.consent.AttributeConsentStorageKey" to use an attribute # to key user consent storage records (and set the attribute name) #idp.consent.userStorageKey = shibboleth.consent.PrincipalConsentStorageKey idp.consent.userStorageKey = shibboleth.consent.AttributeConsentStorageKey idp.consent.userStorageKeyAttribute = eduPersonPrincipalName |
確認画面で属性の表示順を指定するには、conf/intercept/consent-intercept-config.xmlで次のように設定する(順番は一例)。この機能はShibboleth 3.2.1以降で利用可能(3.2.0では違った形式でサポート、それ以前は属性名の文字コード順固定)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<util:list id="shibboleth.consent.attribute-release.AttributeDisplayOrder"> <value>givenName</value> <value>surname</value> <value>displayName</value> <value>jaSurname</value> <value>jaGivenName</value> <value>jaDisplayName</value> <value>mail</value> <value>gakuninScopedPersonalUniqueCode</value> <value>eduPersonPrincipalName</value> <value>eduPersonAffiliation</value> <value>eduPersonScopedAffiliation</value> <value>organizationName</value> <value>jaOrganizationName</value> <value>eduPersonTargetedID</value> <value>eduPersonEntitlement</value> </util:list> |
uApprove.jpで行っていた利用規約同意機能の移行
consent-intercept機能で利用規約への同意を取る場合は、次のように設定する。まず、conf/relying-party.xmlを次のように変更する。
1 2 3 4 5 6 7 8 9 |
<!-- <bean parent="Shibboleth.SSO" p:postAuthenticationFlows="attribute-release" /> --> <bean parent="Shibboleth.SSO" p:postAuthenticationFlows="#{ {'terms-of-use', 'attribute-release'} }" /> ... (略) ... <!-- <bean parent="SAML2.SSO" p:postAuthenticationFlows="attribute-release" /> --> <bean parent="SAML2.SSO" p:postAuthenticationFlows="#{ {'terms-of-use', 'attribute-release'} }" /> |
conf/intercept/consent-intercept-config.xmlで、shibboleth.consent.terms-of-use.Keyのaliasの部分を次のように書き換える。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<!-- <alias alias="shibboleth.consent.terms-of-use.Key" name="shibboleth.RelyingPartyIdLookup.Simple" /> --> <!-- This activates a single Terms of Use text to be presented once before the user sees the first time the attribute release consent dialog. --> <alias alias="shibboleth.consent.terms-of-use.Key" name="shibboleth.SingleTermsOfUseText" /> <bean id="shibboleth.SingleTermsOfUseText" class="com.google.common.base.Functions" factory-method="constant"> <constructor-arg value="my-terms-of-use-0" /> </bean> |
messages/consent-messages.propertiesのサンプルをコメントアウトし、上で指定した「my-terms-of-use-0」の定義を加える。
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 |
#https\://sp.example.org = example-tou-1 #example-tou-1.title = Example Terms of Use #example-tou-1.text = <em>*** This is an example ToU - tailor due to your needs ***</em> \ # <p>Example organization AAI services: Terms of Use (ToU)</p> \ # <strong>A. Data Protection Sample Clause</strong> \ # <p> \ # "The End User notes that personal data about the End User is compiled from generally \ # available sources and from communications received from the End User and other \ # Universities as well as from off-site sources. The policy relating to the use and procession \ # of such data is posted on the University website at [...]. Such data will be used, inter alia, \ # to authenticate and authorize the access to and use of various resources within \ # the University and on other sites ("Approved Uses"). The End User hereby consents to \ # the collection, processing, use and release of such data to the extent reasonably necessary \ # for the Approved Uses. Such consent includes, but is not limited to, the release \ # of personal data to other institutions by employing cookies and electronically exchanging, \ # caching and storing personal authorization attributes." \ # </p> \ # <strong>B. Limitation of Liability</strong> \ # <p> \ # "To the extent permitted by the applicable law, the End User hereby waives all and any \ # claims for cost and damages, whether direct or indirect, incidental, or consequential(including, \ # inter alia, loss of use and lost profits), both in contract and in tort, arising from \ # the use or in any way related to the inter-organizational authentication and authorization \ # services which allow the End User to access certain resources of other organizations. \ # This waiver of claims shall be valid and effective in relation to all participants of \ # the inter-organizational authentication and authorization services including the AAI \ # Service Provider and its affiliates, officers, employees and agents." \ # </p> my-terms-of-use-0 = my-tou-0 my-tou-0.title = Example Terms of Use my-tou-0.text = <p>Example organization Terms of Use (ToU)</p> \ <p>Lorem ipsum dolor sit amet, \ consectetur adipiscing elit. \ </p> |
利用規約のバージョンを上げるには、my-terms-of-use-1のように、後ろに番号を足して新しい規約に更新すれば良い(consent-intercept機能はキーとしてmy-terms-of-use-0の部分を使うので、利用規約を更新した場合に新たに同意を取り直させたい場合は、この部分の文字列を変更する必要がある)。このあたりは利用規約のXML中にバージョン番号があったuApprove.jpよりわかりにくくなっているが、利用規約にHTMLが簡単に使えるようになっている点は、uApprove.jpよりわかりやすくなっている。
(利用規約同意機能に関してはこちらを参考にした。https://www.switch.ch/aai/guides/idp/user-consent/)
FPSPで実現されていたSP毎の属性送信設定機能の移行
以前パッチで提供されていたFPSP(Filter Per SP)機能は、似た機能がShibboleth 3では標準でサポートされた。有効化するには次のように設定する。
まず、conf/relying-party.xmlに次のように設定する(ここは先ほど利用規約の設定をした場所と同じなので、terms-of-useの設定が入っているが、同機能を利用しないのであれば不要)。
1 2 3 4 5 6 7 8 9 |
<!-- <bean parent="Shibboleth.SSO" p:postAuthenticationFlows="attribute-release" /> --> <bean parent="Shibboleth.SSO" p:postAuthenticationFlows="#{ {'context-check', 'terms-of-use', 'attribute-release'} }" /> ... (略) ... <!-- <bean parent="SAML2.SSO" p:postAuthenticationFlows="attribute-release" /> --> <bean parent="SAML2.SSO" p:postAuthenticationFlows="#{ {'context-check', 'terms-of-use', 'attribute-release'} }" /> |
そして、conf/intercept/context-check-intercept-config.xmlに次のように設定する。ただしここでは、
- entityID-A: edupersonAffiliationがfacultyもしくはstaffの場合に利用できる
- entityID-B: edupersonAffiliationがfacultyの場合に利用できる
- それ以外: 常に利用できる
という条件を仮定している(例の中のentityID-AとentityID-BはそれぞれのSPのentityIDに置き換える)。
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 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
<bean id="shibboleth.context-check.Condition" parent="shibboleth.Conditions.OR"> <constructor-arg> <list> <bean id="shibboleth.context-check.Condition" parent="shibboleth.Conditions.AND"> <constructor-arg> <list> <bean parent="shibboleth.Conditions.RelyingPartyId" c:candidates="#{ 'entityID-A' }" /> <bean class="net.shibboleth.idp.profile.logic.SimpleAttributePredicate" p:useUnfilteredAttributes="true"> <property name="attributeValueMap"> <map> <entry key="eduPersonAffiliation"> <list> <value>faculty</value> <value>staff</value> </list> </entry> </map> </property> </bean> </list> </constructor-arg> </bean> <bean id="shibboleth.context-check.Condition" parent="shibboleth.Conditions.AND"> <constructor-arg> <list> <bean parent="shibboleth.Conditions.RelyingPartyId" c:candidates="#{ 'entityID-B' }" /> <bean class="net.shibboleth.idp.profile.logic.SimpleAttributePredicate" p:useUnfilteredAttributes="true"> <property name="attributeValueMap"> <map> <entry key="eduPersonAffiliation"> <list> <value>faculty</value> </list> </entry> </map> </property> </bean> </list> </constructor-arg> </bean> <bean id="shibboleth.context-check.Condition" parent="shibboleth.Conditions.NOT"> <constructor-arg> <list> <bean parent="shibboleth.Conditions.RelyingPartyId" c:candidates="#{{ 'entityID-A', 'entityID-B' }}" /> </list> </constructor-arg> </bean> </list> </constructor-arg> </bean> |
この設定は https://meatwiki.nii.ac.jp/confluence/pages/viewpage.action?pageId=20021272 を参考にした。
ところが、このやり方だと、「それ以外」の定義部分にもAとBのEntityIDを書かなければならず、メンテナンス性が悪い上にミスをしやすく、ミスをした場合にセキュリティ上の問題が生じる可能性がある。
上のロジックを擬似コードで幾分わかりやすく書くと、次のようになる。
1 2 3 4 5 |
if (relyingPartyID == "entityID-A" && edupersonAffiliation in ("faculty", "staff") || relyingPartyID == "entityID-B" && edupersonAffiliation in ("faculty") || (relyingPartyID != "entityID-A" && relyingPartyID != "entityID-B")) { /* ユーザ情報を送信する */ } |
この3つめの「(relyingPartyID != “entityID-A” && relyingPartyID != “entityID-B”)」の部分を書かずにすむように、等価な次のロジックに変えてみる(許可する条件をorで並べるのではなく、許可しない条件をor並べてその全体を否定する)。
1 2 3 4 |
if (!((relyingPartyID == "entityID-A" && !edupersonAffiliation in ("faculty", "staff")) || (relyingPartyID == "entityID-B" && !edupersonAffiliation in ("faculty")))) { /* ユーザ情報を送信する */ } |
これをconf/intercept/context-check-intercept-config.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 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
<bean id="shibboleth.context-check.Condition" parent="shibboleth.Conditions.NOT"> <constructor-arg> <list> <bean id="shibboleth.context-check.Condition" parent="shibboleth.Conditions.OR"> <constructor-arg> <list> <bean id="shibboleth.context-check.Condition" parent="shibboleth.Conditions.AND"> <constructor-arg> <list> <bean parent="shibboleth.Conditions.RelyingPartyId" c:candidates="#{ 'entityID-A' }" /> <bean id="shibboleth.context-check.Condition" parent="shibboleth.Conditions.NOT"> <constructor-arg> <list> <bean class="net.shibboleth.idp.profile.logic.SimpleAttributePredicate" p:useUnfilteredAttributes="true"> <property name="attributeValueMap"> <map> <entry key="eduPersonAffiliation"> <list> <value>faculty</value> <value>staff</value> </list> </entry> </map> </property> </bean> </list> </constructor-arg> </bean> </list> </constructor-arg> </bean> <bean id="shibboleth.context-check.Condition" parent="shibboleth.Conditions.AND"> <constructor-arg> <list> <bean parent="shibboleth.Conditions.RelyingPartyId" c:candidates="#{ 'entityID-B' }" /> <bean id="shibboleth.context-check.Condition" parent="shibboleth.Conditions.NOT"> <constructor-arg> <list> <bean class="net.shibboleth.idp.profile.logic.SimpleAttributePredicate" p:useUnfilteredAttributes="true"> <property name="attributeValueMap"> <map> <entry key="eduPersonAffiliation"> <list> <value>faculty</value> </list> </entry> </map> </property> </bean> </list> </constructor-arg> </bean> </list> </constructor-arg> </bean> </list> </constructor-arg> </bean> </list> </constructor-arg> </bean> |
たしかにentityIDを複数回書く必要はなくなったが、行数が長くなり、また二重否定になったため少し頭を使う必要が増えたので、やや痛し痒しである。
この方法は学認メーリングリストでのNII西村先生のアドバイスによるものである。
メッセージのローカライズ
/opt/shibboleth-idp/messagesにある以下のファイルがメッセージの多国語化のためのカタログファイルとなっている。
- authn-messages.properties: ログイン画面等のためのメッセージ
- consent-messages.properties: 属性送信許可・利用規約同意などのためのメッセージ
- error-messages.properties:エラー画面のためのメッセージ
これらにそれぞれ「_ja」をつけたファイルを作成し(authn-messages_ja.properties, consent-messages_ja.properties, error-messages_ja.properties)、内容を日本語化すれば、ブラウザ設定で日本語が英語より上位にある場合は「_ja」の内容で画面表示される。
オリジナルのメッセージを加えたり、そもそも画面自体をカスタマイズしていた場合は、後述するVelocityテンプレートの内容をカスタマイズした上で、このファイルに新たなメッセージを追加すればよい。
ロゴファイルなど、言語によってファイル名を変えたい場合も、メッセージとしてファイル名の文字列を定義すればよい。
1 2 |
idp.keio.logo = ttl_login_en.gif idp.keio.splogo = ttl_keio_sp_en.jpg |
上記のように定義して、参照側のVelocityテンプレートの部分で
1 |
<img src="$request.getContextPath()/common/images/#springMessage("idp.keio.splogo")" /> |
のように参照すれば良い。
なお、反映にはTomcatの再起動が必要な模様。
画面のカスタマイズ
画面のカスタマイズを行う場合は、Shibboleth 2の時代はJSPを直接編集していたが、Shibboleth 3ではVelocityで記述されたテンプレートのvmファイルを編集する。ファイルは/opt/shibboleth-idp/views以下にある。編集は即座に反映され、Tomcatの再起動などは不要である。
メッセージの参照は、次のように「#springMessageText(“パラメータ名”, “代替文字列”)」で参照可能。パラメータ名はmessages/*.propertiesファイルで自由に定義できる。
1 |
<dt>#springMessageText("idp.login.username", "Username")</dt> |
プロジェクトのトップのロケーションは次のように「$request.getContextPath()」で参照可能。
1 |
<link rel="stylesheet" type="text/css" href="$request.getContextPath()/common/css/common.css" media="all" /> |
簡単なカスタマイズであれば上記2つがあれば何とかなる。
属性創出確認などのテンプレートはviews/interceptの下にあるが、uApprove.jpとは根本的に異なったロジックで作られているので、属性のリスト部分などに関しては新しいファイルを元に作りなおしたほうがよい。
なお、CSSや画像ファイルなどを更新する場合は、相変わらずidp.warファイルをbin/build.shでビルドして、/usr/java/tomcat/webapp/idp.warを上書きする必要がある(tomcatが動いている状態で上書きするのがおすすめ)。
CSSはVelocityによる管轄対象外のようなので、CSS中でurl()などでパラメータの展開が必要なパスを参照していたり、条件によって文言やファイル名を切り替えたい場合などは、vmファイル中のHTMLで、<style>タグを使ってその部分のCSSを記述するなどの方法が必要となる。
ログにクライアントのIPアドレスやセッションIDを入れる
以前、ここで紹介した方法でShibbolethのログをPostgreSQLに格納しているのだが、そこで紹介した「Shibbolethのidp-audit.logにクライアントのIPアドレスやセッションIDを入れる」方法にもShibboleth3では変更が必要だった。
なお、Shibboleth2ではログに入れられるパラメータとして、クライアントのIPアドレス、IdPセッションID、JSESSIONIDの3つがあったが、Shibboleth3ではクライアントのIPアドレス、JSESSIONID、サーバのホスト名、サーバのポート番号の4つになり、IdPセッションIDがなくなってしまった。ただし、私が見た限りではJSESSIONIDが等しいリクエストはIdPセッションIDも等しかったようなので、意味が無いために設定から消えたのかもしれない。
idp-audit.logとidp-consent-audit.logの各業末尾にクライアントIPアドレスとJSESSIONIDを追加する設定はconf/logback.xmlを次のように変更する(<encoder/>の中の<Pattern/>の部分を修正する)。
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 |
<!-- Audit log. --> <appender name="IDP_AUDIT" class="ch.qos.logback.core.rolling.RollingFileAppender"> <File>${idp.logfiles}/idp-audit.log</File> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <fileNamePattern>${idp.logfiles}/idp-audit-%d{yyyy-MM-dd}.log.gz</fileNamePattern> <maxHistory>${idp.loghistory:-180}</maxHistory> </rollingPolicy> <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> <charset>UTF-8</charset> <!-- <Pattern>%msg%n</Pattern> --> <Pattern>%msg%mdc{idp.remote_addr}|%mdc{idp.jsessionid}|%n</Pattern> </encoder> </appender> <!-- Consent audit log. --> <appender name="IDP_CONSENT_AUDIT" class="ch.qos.logback.core.rolling.RollingFileAppender"> <File>${idp.logfiles}/idp-consent-audit.log</File> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <fileNamePattern>${idp.logfiles}/idp-consent-audit-%d{yyyy-MM-dd}.log.gz</fileNamePattern> <maxHistory>${idp.loghistory:-180}</maxHistory> </rollingPolicy> <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> <charset>UTF-8</charset> <!-- <Pattern>%msg%n</Pattern> --> <Pattern>%msg%mdc{idp.remote_addr}|%mdc{idp.jsessionid}|%n</Pattern> </encoder> </appender> |
ちなみにその他のパラメータとしては、idp.server_hostname(サーバのホスト名)、idp.server_port(サーバのポート番号)があるようだが、どちらもShibboleth 3.2以降のサポートのようである。
問題点・TODO
現状で未解決な問題点。
属性送信・規約同意に関する承認状況の移行
uApprove-JPで承認した規約同意や属性送信内容を新しい属性送信機構に移行することが難しい(手間を掛かける価値がどの程度あるのか不明)。規約同意は、わりと単純な構成なので移行することも不可能ではないが、属性送信機構は複雑そうである。
属性送信同意機能が必須属性も非送信を選択することが可能
属性送信同意機能がShibboleth本体に取り込まれたのはよいが、必須属性もチェックボックスで外すことができるようになってしまった。SPは必須属性が送信されていないので、おそらくエラーで終了する。
ピンバック: Shibboleth IdPのログをPostgreSQLに格納する | 慶應義塾ITC本部・技術メモ