こんにちは、サイオステクノロジー武井(Twitter:@noriyukitakei)です。今回は、Shibbolethの開発環境を整えるためのイロハをお伝えしたいと思います。
Shibbolethとは?
Shibbolethとは、大学などでよく使われる学術系オープンソースシングルサインオンシステムです。SAMLをベースとしており、認証のデータソースにはOpenLDAPやRDBなどを使うことができたり、その他様々な条件でSAML Responseを生成できます。ここまでこのブログをご覧になった人は、多分Shibbolethを愛している人ですよね。これ以上、多くを語らなくてもよいかとおもっております。
どんなときにShibbolethの開発環境を使うの?
ShibbolethはOSSですので、もちろん独自の認証方式を追加するといった拡張が可能です。そのためにはもちろん開発環境が必要ですよね。そんなときにShibbolethの開発環境を使います。
また、Shibboleth自体の動きを知りたいときに、開発環境があればデバッグをしながら探ることもできます。例えば、設定したとおりに動かないとか、そんなときに有効ですよね。
さぁ、Shibbolethの開発環境を使って、Shibbolethをアナタ色に染めましょう!!
Shibbolethの開発環境の構成
Shibbolethの開発環境の構築方法は以下のWikiにて公開されています。
https://wiki.shibboleth.net/confluence/display/IDP4/How+to+Run+the+Testbed+in+Eclipse+with+Jetty+9.4
Shibbolethの開発環境はEclipseとJetty(組み込みのJ2EEアプリケーションサーバー)で構成されています。
開発環境の構築は、上記のWikiの通りにやれば構築できると思いますが、実はそうは行きません(2020年10月1日現時点)。
上記の手順に加えて若干の修正が必要であり、そしてその修正を加えるためには、やはり開発環境の仕組みや構成をわかっていないときついものがあります。2020年10月1日時点での開発環境構築方法は、その修正ポイントも含めて本ブログに記載しますが、またいつどう変わるかもわかりません(実際頻繁に変わります)。そんな変更に対応するためには、やっぱり仕組みを理解しておかないとキツイものがあります。
ということで、以下にShibbolethの開発環境の構成や仕組みをご説明します。
構成するパーツ
Shibbolethの開発環境は以下のパーツで成り立っております。
■ java-idp-testbedリポジトリ
Shibbolethの開発環境のメインのリポジトリで、中身はEclipseのプロジェクトです。そのままEclipseにインポートして使います。
このプロジェクトの役割は、Shibbolethを動かすための組み込みJ2EEアプリケーションサーバーであるJettyを起動するためのものです。
Jetty本体やJettyの設定ファイルは別途取得します(後述します)。
■ java-idp-jetty-baseリポジトリ
Jettyの設定ファイルを格納しているリポジトリで、これも中身はEclipseのプロジェクトです。そのままEclipseにインポートして使います。
java-idp-testbedプロジェクトからJettyを起動するときに、Jetty本体の設定ファイルではなく、このプロジェクトの設定ファイルを見るように指定しています。
■ Jetty本体
Jettyの本体です。以下のURLからダウンロードします。
https://www.eclipse.org/jetty/download.html
このJetty本体も、 java-idp-testbedプロジェクトからJettyを起動するときに、その起動のための引数として指定します。
つまり、 java-idp-testbedは以下の2つを指定して、Jettyを起動します。
- Jettyの設定ファイルを格納しているjava-idp-jetty-baseプロジェクト
- Jetty本体
■ java-identity-providerリポジトリ
Shibboleth本体のソースコードが格納されているリポジトリで、これもまたEclipseプロジェクトになっています。
中身は、30以上のプロジェクトから成るマルチなMavenプロジェクトの構成となっています。
java-idp-testbedの中身
idp-testbed-jetty-9.4.launchというファイルがあり、これはJavaアプリケーションの起動スクリプトみたいなものです。これからJettyを起動するようになっています。中身は以下のようになっています。
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <launchConfiguration type="org.eclipse.jdt.launching.localJavaApplication"> <stringAttribute key="bad_container_name" value="/idp-testbed-jetty-9.4"/> <listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS"> <listEntry value="/idp-testbed/src/main/java/Main.java"/> </listAttribute> <listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES"> <listEntry value="1"/> </listAttribute> <booleanAttribute key="org.eclipse.jdt.launching.ATTR_EXCLUDE_TEST_CODE" value="true"/> <booleanAttribute key="org.eclipse.jdt.launching.ATTR_USE_CLASSPATH_ONLY_JAR" value="false"/> <booleanAttribute key="org.eclipse.jdt.launching.ATTR_USE_START_ON_FIRST_THREAD" value="true"/> <stringAttribute key="org.eclipse.jdt.launching.CLASSPATH_PROVIDER" value="org.eclipse.m2e.launchconfig.classpathProvider"/> <stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="Main"/> <stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-Djetty.home=[Jettyをインストールしたディレクトリ] -Didp.home=classpath: -Didp.webflows=classpath*:/flows -Djava.io.tmpdir=tmp"/> <stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="idp-testbed"/> <stringAttribute key="org.eclipse.jdt.launching.SOURCE_PATH_PROVIDER" value="org.eclipse.m2e.launchconfig.sourcepathProvider"/> <stringAttribute key="org.eclipse.jdt.launching.WORKING_DIRECTORY" value="${workspace_loc:idp-jetty-base/src/main/resources/jetty-base}"/> </launchConfiguration>
org.eclipse.debug.core.MAPPED_RESOURCE_PATHSで指定されている部分が、実際の実行ファイルであると思います。そして、/idp-testbed/src/main/java/Main.javaにはJettyを呼び出すための記述があります。
/** Start Jetty */ public class Main { /** * @param args command-line arguments */ public static void main(String[] args) { org.eclipse.jetty.start.Main.main(args); } }
org.eclipse.jdt.launching.PROGRAM_ARGUMENTSで指定しているidp.homeはShibbolethの設定ファイルを格納するディレクトリ(/opt/shibboleth-idp)に相当する部分ですが、今回はクラスパスが通るところ(classpath:*)になっています。これは実質上では、idp-confプロジェクトのsrc/main/resourcesディレクトリ以下になります。idp-confプロジェクトはShibbolethの設定ファイルを格納している専用のEclipseプロジェクトになります。なので、Shibbolethの設定をいじりたければ、idp-confプロジェクトの設定ファイルを修正することになります。
また、org.eclipse.jdt.launching.WORKING_DIRECTORYでは、Jettyの設定ファイルの場所を指定しています。これは、idp-jetty-baseプロジェクトを指しています。
/src/main配下はテスト用SPを構成するためのJavaファイル諸々があります。
java-idp-jetty-baseの中身
構成は以下のような感じです。Jettyを起動するための設定ファイル群があります。
特筆すべきは、webappsディレクトリ配下で、ここに起動するWebアプリケーションの設定(Contentファイル)を書きます。idp.xmlはShibboleth IdPを起動するためのContextファイルです。<Set name=”war”>…</Set>の部分で実際のWebアプリケーションが配置されているディレクトリを指定しています。idp-warプロジェクトを指定しているようで、ここにはShibboleth IdPを起動するためのファイル(web.xmlなど)があります。Shibboleth IdPを動作させるために必要なライブラリは、java-identity-providerをインポートしたときにできた30以上のたくさんのプロジェクトを参照しています。MavenのModuleで実現しています。<Set name=”contextPath”>…</Set>でContentパスを指定していて、/idpでアクセスできるようになってますね。
<?xml version="1.0"?> <!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "https://www.eclipse.org/jetty/configure_9_3.dtd"> <!-- =============================================================== --> <!-- Configure the Shibboleth IdP webapp --> <!-- =============================================================== --> <Configure class="org.eclipse.jetty.webapp.WebAppContext"> <Set name="war">../../../../../java-identity-provider/idp-war/src/main/webapp</Set> <Set name="contextPath"><SystemProperty name="idp.context.path" default="/idp" /></Set> <Set name="extractWAR">false</Set> <Set name="copyWebDir">false</Set> <Set name="copyWebInf">true</Set> </Configure>
testbed.xmlは、テスト用SPを起動するためのContextファイルで、以下のようになっています。<Set name=”war”>…</Set>のjava-idp-testbedのsrc/main/webapp(テスト用SPの構成ファイル)を指定しています。。<Set name=”contextPath”>…</Set>でContentパスを指定していて、/でアクセスできるようになってますね。
<?xml version="1.0"?> <!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "https://www.eclipse.org/jetty/configure_9_0.dtd"> <Configure class="org.eclipse.jetty.webapp.WebAppContext"> <Set name="war">../../../../../java-idp-testbed/src/main/webapp/</Set> <Set name="contextPath">/</Set> <Set name="extractWAR">false</Set> <Set name="copyWebDir">false</Set> <Set name="copyWebInf">true</Set> </Configure>
Shibbolethの開発環境の構築方法
では、いよいよShibbolethの開発環境の構築方法を記載します。基本は以下のWikiベースですが、足りない部分も含めて補足して書いています。
https://wiki.shibboleth.net/confluence/display/IDP4/How+to+Run+the+Testbed+in+Eclipse+with+Jetty+9.4
また、この手順は2020年10月1日時点で稼働確認が取れたものであり、また時が経つと手順が変わるかもしれません。いや、絶対変わると思います。なので、いずれ変わったときのためにも、この手順で雰囲気を掴んで頂けたら幸いです。
Eclipseのダウンロードとインストール
まず、Eclipseをダウンロードします。Wikiに記載のEclipseをダウンロードしてきたほうが確実です。2020年10月1日時点では、Eclipse2019-06のようです。以下のサイトからダウンロードしてインストールします。
https://www.eclipse.org/eclipseide/2019-06/
リポジトリのClone
先程ご説明した3つのリポジトリをCloneします。全て同じディレクトリでCloneして下さい。
$ git clone https://git.shibboleth.net/git/java-identity-provider $ git clone https://git.shibboleth.net/git/java-idp-jetty-base $ git clone https://git.shibboleth.net/git/java-idp-testbed
次に気をつけなければいけないのは、java-idp-jetty-baseは以下のブランチにチェックアウトしなければなりません。mainのブランチ(昔はmasterと呼ばれていたものです)はどうやらtestbed用ではなかったらしく、構成が全然違うのですね。ワタシ、これで結構ハマりました。それ、早く言ってよ。。。
$ cd java-idp-jetty-base $ git checkout -b 9.4-testbed-eclipse
Jettyのダウンロード
以下のサイトからJettyをダウンロードします。
https://www.eclipse.org/jetty/download.html
ここで気をつけなければいけないのは、ダウンロードするJettyのバージョンは、java-idp-testbedリポジトリ内のpom.xmlの<jetty.version>XXX.XXX.XXX</jetty.version>に記載のXXX.XXX.XXXに合わせて下さい。java-idp-testbedからJettyを起動するためには、JettyのEclipse用のプラグインが必要なのですが、そのプラグインのバージョンと本体のバージョンを合わせなければいけないためです。java-idp-testbedのpom.xmlにも以下のような記述があります。
<dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-start</artifactId> <version>${jetty.version}</version> </dependency>
Eclipseへのインポート
先程Cloneした3つのリポジトリ(Eclipseプロジェクト)をインポートして下さい。手順はEclipseから、File > Import > Maven > Existing Maven Projectsの順にクリックして、3つのリポジトリをインポートして下さい。以下のようにたくさんのプロジェクトができると思います。
IdP WARのビルド
用途は不明ですが、Wikiによると実施しなくてはいけないそうです。
$ cd java-identity-provider/idp-war $ mvn clean package -DskipTests $ rm target/idp-war-*/WEB-INF/lib/idp-*.jar
Jettyに必要なライブラリのダウンロード
実はあまりよくわかってないですが、これも手順通りです。
$ cd java-idp-jetty-base/src/main/resources/jetty-base $ java -jar [Jettyをインストールしたディレクトリ]/start.jar --create-files
jetty-logback-access.xmlの修正
これより移行は、Wikiの手順にはない設定です。ログの出力先などを定義するlogback-access.xmlの場所を定義するjetty-logback-access.xmlを修正する必要があります。java-idp-jetty-base/src/main/resources/jetty-base/etc/jetty-logback-access.xmlを以下のように修正して下さい。
<Set name="resource">/logback-access.xml</Set> ↓ <Set name="resource">/system/conf/logback-access.xml</Set>
クラスパスが通っている場所を指定して上げる必要があるのですが、デフォルトの/logback-access.xmlだとFileNotFoundのエラーになってしまいます。。。これも結構ハマりました。
廃止予定されているAPIへの参照禁止のエラー回避
これは出る環境と出ない環境があるかもしれません。私のところでは、このエラーが出てビルドが成功しなかったので、回避方法を書いておきます。
Windowsの場合: Windows – >設定 – > Java – >コンパイラ – >エラー/警告 – >廃止予定および制限されているAPI – >禁止された参照(アクセス規則): – > warningへの変更
Mac OS X/Linuxの場合: Eclipse – >設定 – > Java – >コンパイラ – >エラー/警告 – >廃止予定および制限されているAPI – >禁止された参照(アクセスルール): – > warningへの変更
java-idp-testbedプロジェクトのpom.xmlの変更
java-idp-testbedプロジェクトのpom.xmlで何故か存在しないライブラリの依存関係の設定があったので、以下を削除します。
<dependency> <groupId>${idp.groupId}</groupId> <artifactId>idp-conf-impl</artifactId> <version>${idp.version}</version> </dependency>
java-idp-testbedプロジェクトの起動ファイルの修正
java-idp-testbedプロジェクトにあるidp-testbed-jetty-9.4.launch(Javaアプリケーションを起動するための構成ファイル)をちょっと修正します。
以下がidp-testbed-jetty-9.4.launchの中身なのですが、[Jettyをインストールしたディレクトリ]の部分に、Jettyをインストールしたディレクトリのパスを入力して下さい。
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <launchConfiguration type="org.eclipse.jdt.launching.localJavaApplication"> <stringAttribute key="bad_container_name" value="/idp-testbed-jetty-9.4"/> <listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS"> <listEntry value="/idp-testbed/src/main/java/Main.java"/> </listAttribute> <listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES"> <listEntry value="1"/> </listAttribute> <booleanAttribute key="org.eclipse.jdt.launching.ATTR_EXCLUDE_TEST_CODE" value="true"/> <booleanAttribute key="org.eclipse.jdt.launching.ATTR_USE_CLASSPATH_ONLY_JAR" value="false"/> <booleanAttribute key="org.eclipse.jdt.launching.ATTR_USE_START_ON_FIRST_THREAD" value="true"/> <stringAttribute key="org.eclipse.jdt.launching.CLASSPATH_PROVIDER" value="org.eclipse.m2e.launchconfig.classpathProvider"/> <stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="Main"/> <stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-Djetty.home=[Jettyをインストールしたディレクトリ] -Didp.home=classpath: -Didp.webflows=classpath*:/flows -Djava.io.tmpdir=tmp"/> <stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="idp-testbed"/> <stringAttribute key="org.eclipse.jdt.launching.SOURCE_PATH_PROVIDER" value="org.eclipse.m2e.launchconfig.sourcepathProvider"/> <stringAttribute key="org.eclipse.jdt.launching.WORKING_DIRECTORY" value="${workspace_loc:idp-jetty-base/src/main/resources/jetty-base}"/> </launchConfiguration>
ちなみにorg.eclipse.jdt.launching.PROGRAM_ARGUMENTSで指定しているidp.homeはShibbolethの設定ファイルを格納するディレクトリ(/opt/shibboleth-idp)に相当する部分ですが、今回はクラスパスが通るところ(classpath:*)になっています。これは実質上では、idp-confプロジェクトのsrc/main/resourcesディレクトリ以下になります。idp-confプロジェクトはShibbolethの設定ファイルを格納している専用のEclipseプロジェクトになります。なので、Shibbolethの設定をいじりたければ、idp-confプロジェクトの設定ファイルを修正して下さい。
また、org.eclipse.jdt.launching.WORKING_DIRECTORYでは、Jettyの設定ファイルの場所を指定しています。これは、idp-jetty-baseプロジェクトを指しています。
いよいよ起動!!
java-idp-testbedプロジェクトにあるidp-testbed-jetty-9.4.launch(Javaアプリケーションを起動するための構成ファイル)を右クリックして、「Debug As」→「idp-testbed-jetty-9.4」の順にクリックして下さい。以下のような感じになります。
そして以下のURLにアクセスして下さい。
https://localhost:8443/index.html
以下の画面が表示されれば成功です!!
もちろんブレークポイント打ったところで止まります!!
ちょっとしたノウハウ
ここではちょっとしたノウハウを記載します。
Shibbolethのバージョンを変える
開発対象やデバッグ対象のShibbolethのバージョンを変えたい場合があります。そのときは、java-identity-providerリポジトリのtagを適宜必要なバージョンのものにチェックアウトして下さい。ただしその際、念の為java-idp-testbedプロジェクトのpom.xmlの変更をしておいたほうがいいと思います。
以下のidp.version、opensaml.version、spring-extensions.version、cas-client.versionの4つを、ipd-parentプロジェクトのpom.xmlのものと合わせて下さい。そして、プロジェクトをビルドし直して下さい。
<properties> <idp.groupId>net.shibboleth.idp</idp.groupId> <idp.version>4.0.1</idp.version> <idp-jetty-base.version>9.4.1-SNAPSHOT</idp-jetty-base.version> <jetty.version>9.4.28.v20200408</jetty.version> <opensaml.groupId>org.opensaml</opensaml.groupId> <opensaml.version>4.0.1</opensaml.version> <spring-extensions.version>6.0.0</spring-extensions.version> <cas-client.version>3.5.1</cas-client.version> </properties>
Shibbolethのポート番号を変える
デフォルトでは8443ですが、443に変えたいときがあるかもしれません。そのときは、java-idp-jetty-baseプロジェクトのsrc/main/resources/jetty-base/start.d/idp-testbed-eclipse.iniを以下のように修正して下さい。
jetty.ssl.port=8443 ↓ jetty.ssl.port=443
別の環境で動いていたShibbolethをデバッグしたい
例えば別の環境(検証環境や本番環境など)で動いていたShibbolethをデバッグしたいとかそういうときがあるかもしれません。リモートデバッグでもいいのですが、環境的に難しい場合は、Jettyの起動引数でShibbolethの設定ファイルを指定するところがあるので、そこを変更すればOKです。
具体的には、別の環境で稼働しているShibbolethの/opt/shibboleth-idp配下をEclipseが稼働しているPCにダウンロードしてきて、java-idp-testbedプロジェクトにあるidp-testbed-jetty-9.4.launch(Javaアプリケーションを起動するための構成ファイル)を修正します。以下がそのidp-testbed-jetty-9.4.launchの内容ですが、[Shibbolethの設定ファイルがあるディレクトリへのパス]を、先程ダウンロードしてきたShibbolethの設定ファイルがあるディレクトリへのパスに変更して下さい。LDAP等の外部のデータベースは別途Eclipseから接続できるような環境に用意して上げる必要があります。SSHがつながる環境であればポートフォワードするのが一番手っ取り早いと思います。
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <launchConfiguration type="org.eclipse.jdt.launching.localJavaApplication"> <stringAttribute key="bad_container_name" value="/idp-testbed-jetty-9.4"/> <listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS"> <listEntry value="/idp-testbed/src/main/java/Main.java"/> </listAttribute> <listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES"> <listEntry value="1"/> </listAttribute> <booleanAttribute key="org.eclipse.jdt.launching.ATTR_EXCLUDE_TEST_CODE" value="true"/> <booleanAttribute key="org.eclipse.jdt.launching.ATTR_USE_CLASSPATH_ONLY_JAR" value="false"/> <booleanAttribute key="org.eclipse.jdt.launching.ATTR_USE_START_ON_FIRST_THREAD" value="true"/> <stringAttribute key="org.eclipse.jdt.launching.CLASSPATH_PROVIDER" value="org.eclipse.m2e.launchconfig.classpathProvider"/> <stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="Main"/> <stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-Djetty.home=[Jettyをインストールしたディレクトリ] -Didp.home=[Shibbolethの設定ファイルがあるディレクトリへのパス] -Didp.webflows=[Shibbolethの設定ファイルがあるディレクトリへのパス]/flows -Djava.io.tmpdir=tmp"/> <stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="idp-testbed"/> <stringAttribute key="org.eclipse.jdt.launching.SOURCE_PATH_PROVIDER" value="org.eclipse.m2e.launchconfig.sourcepathProvider"/> <stringAttribute key="org.eclipse.jdt.launching.WORKING_DIRECTORY" value="${workspace_loc:idp-jetty-base/src/main/resources/jetty-base}"/> </launchConfiguration>
そして、もしweb.xml等の変更や別のライブラリ(外部のjarや独自開発のjarなど)を参照してる場合は、idp-warプロジェクトのsrc/main/webapp以下に配置をして下さい。
まとめ
さぁ、アナタもShibbolethの開発環境を使って、Shibbolethをアナタ色に染めましょう!!