Edited at

EC2上に構築したOpenAMのSAMLv2.0FederationよりSSOを実装する

More than 1 year has passed since last update.

今回SSOを実施するにあたって以下の記事を参照しました。


1. IdP側の環境構築


1-1. EC2の構築


1. EC2インスタンスを作成します。


  • AMI: Amazon Linux AMI 2017.09.1 (HVM), SSD Volume Type - ami-ceafcba8

  • InstanceType: t2.xlarge

  • SecurityGroup:


    • Inbound: HTTP及びSSHのみに設定し、IP制限だけ実施(今回HTTPSは使用しないのと、試験用のためIP制限設定)

    • Outbound: FullAccess



🤖 ~  ⌚ 13:06:52

⚡ aws ec2 describe-security-groups --group-names OpenAM | jq '.SecurityGroups[].IpPermissions,.SecurityGroups[].IpPermissionsEgress'
[
{
"FromPort": 80,
"IpProtocol": "tcp",
"IpRanges": [
{
"CidrIp": "<接続元IPaddr>"
}
],
"Ipv6Ranges": [],
"PrefixListIds": [],
"ToPort": 80,
"UserIdGroupPairs": []
},
{
"FromPort": 22,
"IpProtocol": "tcp",
"IpRanges": [
{
"CidrIp": "<接続元IPaddr>"
}
],
"Ipv6Ranges": [],
"PrefixListIds": [],
"ToPort": 22,
"UserIdGroupPairs": []
}
]
[
{
"IpProtocol": "-1",
"IpRanges": [
{
"CidrIp": "0.0.0.0/0"
}
],
"Ipv6Ranges": [],
"PrefixListIds": [],
"UserIdGroupPairs": []
}
]


2. ElasticIPの設定

ElasticIPを対象のインスタンスに設定し、IPアドレスを固定します。

(参照) Elastic IP アドレス - Amazon Elastic Compute Cloud

ドメインの設定(EC2のDHCPoptionで自動設定されるdomainを使用すると失敗したので、今回はRoute53で設定しました。以下Domain: www.example.com とします)


3. Network設定

(EC2の作成が完了したら)対象のインスタンスにSSH経由で接続し、/etc/hosts/及び、/etc/sysconfig/networkに以下の内容を追加及び変更します。

🤖 ~  ⌚ 13:07:02

⚡ ssh OpenAM

[ec2-user@ip-xxx-xxx-xxx-xxx ~]$ sudo vim /etc/sysconfig/network

HOSTNAME=openam, www.example.com #serverのホスト名とDomain名をFQDN形式で変更します

[ec2-user@ip-xxx-xxx-xxx-xxx ~]$ sudo vim /etc/hosts

<ElasticIPで設定したIPaddress> www.example.com #ElasticIPaddr 及び Domain を追加します

以上でEC2の基本設定は完了です。

次にApache+tomcat7でWebserverの設定を実施します。


1-2. Webserverの構築


1. 必要なpackageのインストール

対象のインスタンスに接続し、必要なApache関連のpackageインストール及び確認を実施します。

[ec2-user@ip-xxx-xxx-xxx-xxx ~]$ sudo yum update -y

[ec2-user@ip-xxx-xxx-xxx-xxx ~]$ sudo yum install httpd -y
[ec2-user@ip-xxx-xxx-xxx-xxx ~]$ sudo chkconfig httpd on
[ec2-user@ip-xxx-xxx-xxx-xxx ~]$ sudo yum install -y openssl openssl-devel mod_ssl
[ec2-user@ip-xxx-xxx-xxx-xxx ~]$ sudo service httpd start
Starting httpd: [ OK ]
[ec2-user@ip-xxx-xxx-xxx-xxx ~]$ ps aux | grep httpd
root 8322 0.0 0.9 204156 9608 ? Ss 06:17 0:00 /usr/sbin/httpd
apache 8324 0.0 0.6 204156 6604 ? S 06:17 0:00 /usr/sbin/httpd
apache 8325 0.0 0.6 204156 6604 ? S 06:17 0:00 /usr/sbin/httpd
apache 8326 0.0 0.6 204156 6604 ? S 06:17 0:00 /usr/sbin/httpd
apache 8327 0.0 0.6 204156 6604 ? S 06:17 0:00 /usr/sbin/httpd
apache 8328 0.0 0.6 204156 6604 ? S 06:17 0:00 /usr/sbin/httpd
apache 8329 0.0 0.6 204156 6604 ? S 06:17 0:00 /usr/sbin/httpd
apache 8330 0.0 0.6 204156 6604 ? S 06:17 0:00 /usr/sbin/httpd
apache 8331 0.0 0.6 204156 6604 ? S 06:17 0:00 /usr/sbin/httpd

これでApacheが起動することを確認できました。

次にtomcat7関連の設定を実施します。最初にJavaの確認だけ実施します。今回使用したEC2には元々OpenJDKベースのJavaがインストールされていますが、これをOracleJDKに変えたい場合は適宜変更ください(OpenJDKでも問題ないです)。

[ec2-user@ip-xxx-xxx-xxx-xxx ~]$ java -version

java version "1.7.0_161"
OpenJDK Runtime Environment (amzn-2.6.12.0.75.amzn1-x86_64 u161-b00)
OpenJDK 64-Bit Server VM (build 24.161-b00, mixed mode)
[ec2-user@ip-xxx-xxx-xxx-xxx ~]$ sudo yum install -y tomcat7 tomcat7-webapps tomcat7-admin-webapps
[ec2-user@ip-xxx-xxx-xxx-xxx ~]$ sudo chkconfig tomcat7 on


2. tomcat7の設定

tomcat7の設定ファイルのバックアップを作成します。

[ec2-user@ip-xxx-xxx-xxx-xxx ~]$ cd /etc/tomcat7/

[ec2-user@ip-xxx-xxx-xxx-xxx tomcat7]$ sudo cp tomcat-users.xml tomcat-users.xml.template
[ec2-user@ip-xxx-xxx-xxx-xxx tomcat7]$ sudo cp server.xml server.xml.template
[ec2-user@ip-xxx-xxx-xxx-xxx tomcat7]$ ls -a
. catalina.policy logging.properties tomcat7.conf web.xml
.. catalina.properties server.xml tomcat-users.xml
Catalina context.xml server.xml.template tomcat-users.xml.template


tomcat-users.xml

各設定ファイルを変更していきます。まずはtomcat-users.xmlの最下部にある下記内容のコメントアウトを外します。

[ec2-user@ip-xxx-xxx-xxx-xxx tomcat7]$ sudo vim tomcat-users.xml

<user name="admin" password="*******" roles="admin,manager,admin-gui,admin-script,manager-gui,manager-script,manager-jmx,manager-status" />

このusernameとpasswordは後にOpenAM関連を設定する際のページを開く際に必要となりますので、適宜変更してください。

元の設定ファイルと比べると以下の内容になります。

[ec2-user@ip-xxx-xxx-xxx-xxx tomcat7]$ sudo diff tomcat-users.xml tomcat-users.xml.template

50c50
< <user name="admin" password="*******" roles="admin,manager,admin-gui,admin-script,manager-gui,manager-script,manager-jmx,manager-status" />
---
> <!-- <user name="admin" password="adminadmin" roles="admin,manager,admin-gui,admin-script,manager-gui,manager-script,manager-jmx,manager-status" /> -->


server.xml

<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />をコメントアウトします。

[ec2-user@ip-xxx-xxx-xxx-xxx tomcat7]$ sudo vim server.xml

<!-- <Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" /> -->

元の設定ファイルと比べると以下の内容となります。

[ec2-user@ip-xxx-xxx-xxx-xxx tomcat7]$ sudo diff server.xml server.xml.template

71c71
< <!-- <Connector port="8080" protocol="HTTP/1.1"
---
> <Connector port="8080" protocol="HTTP/1.1"
73c73
< redirectPort="8443" /> -->
---
> redirectPort="8443" />


3. Webserver(Apache+tomcat7)の設定

/etc/httpd/conf/httpd.confに下記内容を追加し、Apacheへの接続をtomcat7側に向けます。

<Location />

ProxyPass ajp://localhost:8009/
</Location>

Apache及びtomcat7の再起動及び起動します。

[ec2-user@ip-xxx-xxx-xxx-xxx ~]$ sudo tomcat7 start

[ec2-user@ip-xxx-xxx-xxx-xxx ~]$ sudo service httpd restart
Stopping httpd: [ OK ]
Starting httpd: [ OK ]

先ほど設定したDomain(www.example.com)にHTTP経由(http://www.example.com/)で接続し、tomcatのページが表示されることを確認します。

🤖 ~  ⌚ 14:02:40

⚡ curl http://www.example.com/ | head -20
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 11197 0 11197 0 0 127k 0 --:--:-- --:--:-- --:--:-- 128k

<!DOCTYPE html>

<html lang="en">
<head>
<title>Apache Tomcat/7.0.84</title>
<link href="favicon.ico" rel="icon" type="image/x-icon" />
<link href="favicon.ico" rel="shortcut icon" type="image/x-icon" />
<link href="tomcat.css" rel="stylesheet" type="text/css" />
</head>

<body>
<div id="wrapper">
<div id="navigation" class="curved container">
<span id="nav-home"><a href="http://tomcat.apache.org/">Home</a></span>
<span id="nav-hosts"><a href="/docs/">Documentation</a></span>
<span id="nav-config"><a href="/docs/config/">Configuration</a></span>
<span id="nav-examples"><a href="/examples/">Examples</a></span>
<span id="nav-wiki"><a href="http://wiki.apache.org/tomcat/FrontPage">Wiki</a></span>

実際にブラウザ経由で確認すると以下のページが表示されます。

openam_1_showtomcat.png

これでWebserver側の設定は完了です。


2. OpenAMインストール及びログインまで

OpenAMについてはForgerockにて管理されており、現在は製品名が変更されているようです。

OpenAM - Wikipedia


OpenAMはSun MicrosystemsのOpenSSOを起源に持つ。OracleによるSun Microsystemsの買収後、OracleがOpenSSOの開発中止を決定したため、ForgeRock(英語: ForgeRock)社がその開発とサポートを継続することを2010年2月に発表した。[1] OpenSSOの製品名はOracleが権利を保持し続けたため、製品名をOpenAMに変更したうえで、ForgeRock社がスポンサーとなるフォークとしてOpenAMがスタートした。


ForgeRockはSun Microsystemsのオリジナルのロードマップを提供し続けることをかつて発表していたが、[2][3] 実際には既にオープンソースコミュニティを閉鎖しており、パーミッシブライセンス(英語: Permissive software licence)の元でのプラットフォームの新たな開発を許していない。[4] これ以降オープンソース版のOpenAMは、ForgeRock共同開発パートナー[5][6]のオープンソース・ソリューション・テクノロジ株式会社[7]にて公開が継続されている。なお、OpenAM 14.0 よりForgeRock Access Management 5.0 に製品名が変更された。[8]



2-1. Forgerockでインストールメディアの取得

今回は OpenAM 13.0.0 を使用します。Downloads - BackStage より、.warファイルを選択します。

openam_2_installmedia.png

このメディアを対象インスタンスの/usr/share/tomcat7/webappsへ移動します。またこの時.warの名前をopenamに変更してから上記ディレクトリに移動します。


2-2. OpenAMのインストール及びログイン

再度 http://www.example.com/ よりtomcatのページに戻り、OpenAMの設定を行います。ここからGUI上で行います。


1. OpenAMへのアクセス

下記”Manager App”を選択すると、Basic認証が入るので、先ほどtomcat-users.xmlで設定したusername及びpasswordを入力します。

openam_3_manageapp.png

すると”Tomcat Webアプリケーションマネージャ“が開くので、下記/openamを選択します。

openam_4_openamSetting.png

以下の画面が出力されるので、”カスタム設定”を選択します。この後CustomerAgreementの画面が出力されるので、”同意”します。

openam_5_forgelockSetting.png


2. OpenAMの設定

以下のように設定します。


一般設定

openam_6_1_openam.png


Server設定

openam_6_2_openam.png


設定ストア

“OpenAM”を選択します。”ホスト名”はそのままで、”Port”、”管理者Port”、”JMXPort”を以下のように設定します。

openam_6_3_openam.png


ユーザーデータストア設定

“OpenAM のユーザーデータストア”を選択します。

openam_6_4_openam.png


サイト設定

今回LBの設定は実施しないので、”いいえ”を選択します。

openam_6_5_openam.png


デフォルトのポリシーエージェントユーザー

特に今回はこのユーザーを使用しません。このPasswordは、1つ目に設定した”amAdmin”のPasswordと同様のものは使用できません。

openam_6_6_openam.png

最後に確認画面が表示されるので内容を確認し、OpenAMの設定は完了です。無事設定が完了すると以下の画面が表示されます。失敗した場合はもう一度.warファイルと/openamディレクトリを削除したもう一度やり直す必要があります。

トラシューは OpenAMインストール時の注意点とトラブルシューティングの方法 | OSS ∞ Lab に記載があります。

openam_6_7_openam.png

設定完了後、管理者としてログインします。Passwordには、この”OpenAMの設定”の”一般設定”にて入力したPasswordを入力します。

openam_6_8_openam.png

ログインに成功すると以下の画面が出力されます。

openam_6_9_openam.png


3. CoTの設定

ここからが後半戦です。以下ではIdP(OpenAM)側と、SP(AWS)側の設定を実施します。


3-1. IdP(OpenAM)側の設定

ログイン成功後の上記Realmを選択します。その後まずは、IdP側の設定を行うため、以下の”Create SAMLv2 Providers”を選択します。

openam_7_createSAMLprov.png

“Created Hosted Identity Provider”を選択します。

openam_8_idp.png

以下のような画面が出力されるので、それぞれ入力します(IdP側の名前は今回FQDN形式にしておりますが、デフォルトでも問題はありません)。今回は試験用のため、署名鍵にはtestを用いています。また新しいCoT(Circle of Trust)を”aws”という名前を入力し、右上の”設定”を入力します。

openam_9_idp-fqdn.png

以上でIdP側の初期設定は完了です。この後以下の画面が出力されるので、このままSP側の設定を実施します。

openam_10_sp.png

上記画面を閉じてしまった場合は、もう一度初期画面からRealmを選択し、”Create SAMLv2 Providers”を選択します。その後、一番右に表示されている”Register Remote Service Provider”を選択します。


3-2. SP(AWS)側の設定

SAML 2.0 ベースのフェデレーションについて - AWS Identity and Access Management を参考にSAMLmetadataを取得し、AWSをSPとして登録します。


1. SAMLmetadataの取得

下記URLよりAWS側のSAMLmetadataを取得し、これをsaml-metadata.xmlとして保存します。

https://signin.aws.amazon.com/static/saml-metadata.xml


2. OpenAM側でSAMLmetadataの登録

下記内容にしたがって、上記で取得したsaml-metadata.xmlをuploadします。CoTには先ほど作成した”aws”を選択します。

openam_11_registerSpSaml.png

ここからはAWSマネジメントコンソール(以下AWS-MCと呼びます)側で設定を行います。


3. SAMLproviderの作成

基本的に SAML ID プロバイダーの作成 - AWS Identity and Access Management の内容に従います。

まずは下記URLより、IdP側のSAMLmetadataを取得し、これをexportmetadata.jsp.xmlとして保存します。

http://www.example.com/openam/saml2/jsp/exportmetadata.jsp

次にAWS-MCにログインし、IAMコンソールを開きます。左側のナビゲーションペインより”IDプロバイダ”を選択し、”プロバイダの作成”よりSAMLプロバイダを作成します。

以下の画面で、”SAML”を選択します。

openam_12_1_createSamlProvider.png

次にProviderの設定において、”プロバイダ名”を任意に設定し、先ほど取得したexportmetadata.jsp.xmlをuploadします。

openam_12_2_createSamlProvider.png


4. IAMroleの作成

上記プロバイダーを使用するには、IAMroleを作成し、SAMLproviderと信頼関係を設定する必要があります。

(参考) SAML 2.0 フェデレーション用のロールの作成 (コンソール) - AWS Identity and Access Management

IAMコンソールより左側のナビゲーションペインから、”ロール”を選択し、”ロールの作成”よりIAMroleを作成します。

以下の内容でRoleを設定します(今回はSAMLresponseの確認のためコンソールへのログインも実施できるように設定しております)。

openam_13_1_role.png

次にSAML認証を実施したユーザーのAWSリソースへのアクセス権限を行います。今回は簡単のため”AmazonS3FullAccess”を設定しました。そして、Role名を”saml-provider-role”(任意)とし、設定内容を確認します。

🤖 ~  ⌚ 21:26:08

⚡ aws iam get-role --role-name saml-provider-role
{
"Role": {
"Path": "/",
"RoleName": "saml-provider-role",
"RoleId": "<Role-ID>",
"Arn": "arn:aws:iam::<AccountID>:role/saml-provider-role",
"CreateDate": "2018-03-04T12:23:41Z",
"AssumeRolePolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::<AccountID>:saml-provider/openanm-saml-provider"
},
"Action": "sts:AssumeRoleWithSAML",
"Condition": {
"StringEquals": {
"SAML:aud": "https://signin.aws.amazon.com/saml"
}
}
}
]
},
"Description": "For SAMLfederation"
}
}

これでAWS-MCでの設定は完了です。


3-3. Provider, Userの設定


1. Attribute Mapperの設定

AWSログインに必要な属性値についてここで設定します。

まず、もう一度Forgerockのtopページに戻り、以下のように”Federation”を選択します。

openam_14_fedaration.png

ここでCoTの設定について確認できます。CoTには

* 名前: aws, Entity: urn:amazon:webservices|saml2 及び、www.example.com が確認できます

Entity Prviderには以下の内容が確認できます。

* www.example.com, IdP, ホスト

* urn:amazon:webservices, SP, リモート

Entity Providerにおける”urn:amazon:webservices”を選択します。

openam_15_1_entityProviderSetting.png

次に上部のタブより、”表明処理”(Attribute Processing)を選択します

openam_15_2_entityProviderSetting.png

“属性マッパー”に以下の内容を追加します。

* https://aws.amazon.com/SAML/Attributes/Role=employeeNumber

* https://aws.amazon.com/SAML/Attributes/RoleSessionName=uid

ここの設定を誤るとAWS-MCにSSO経由でログインする際にSAMLassertionの受け渡しが失敗して、Your request included an invalid SAML response.が出力されます。AWS での SAML 2.0 フェデレーションのトラブルシューティング - AWS Identity and Access Management にも記載があります。


このエラーは、ID プロバイダからの SAML レスポンスに、Name が https://aws.amazon.com/SAML/Attributes/RoleSessionName に設定された属性が含まれない場合に発生することがあります。属性値は、ユーザーの ID で、通常は ID または E メールアドレスです。


openam_15_3_entityProviderSetting.png

上記設定を確認後、”保存”します。


2. ログインUserの作成

もう一度Forgerockのtopページに戻り、Realmを選択します。そして画面左側の”subjects”を選択し、Userを追加します。

openam_16_1_LoginUser.png

既にamAdmin, anonymous, demoUserは作成されております。なお汎用IDがAWS-MCにログインする際に必要なIDです。

openam_16_2_LoginUser.png

“新規”より下記のようなUser”login-user”を作成します(入力内容は任意)。

openam_16_3_LoginUser.png

Userが作成されているか確認します。

openam_16_4_LoginUser.png

その後この”openam”を選択し、下記内容でemployeeNumberにペアで設定します。先ほど設定した属性値にこのペアで権限等が渡されます。

arn:aws:iam::<AccountID>:role/saml-provider-role,arn:aws:iam::<AccountID>:saml-provider/openanm-saml-provider

上記内容で設定後”保存”します。ここまででIdP及びSPの設定は完了です。いよいよAWS-MCにログインします。


3-4. AWS-MCへのログイン

下記URLにアクセスすると、ログイン画面となります。(この時”amAdmin”でログアウトしておきます。しないでおくと、上記で登録したemployeeNumberの属性値に合致せず、Your request included an invalid SAML response.が出力されます)。

http://www.example.com/openam/saml2/jsp/idpSSOInit.jsp?metaAlias=/idp&spEntityID=urn:amazon:webservices

補足ですが、このidpSSOInit.jspは実際に対象のインスタンスにSSH経由でログインし、<openamのディレクトリ>/saml2/jspより確認できます。OpenAMのVersionが古い場合は下記URLにアクセスします。

http://www.example.com/openam/idpssoinit?metaAlias=/idp&spEntityID=urn:amazon:webservices

ここで、先ほど登録したUser情報を入力します。

* Username: login-user

* Password: <設定したPassword>

openam_17_login.png

SAMLresponseがうまく渡せると、下記のようにログインできます。

openam_18_completeLogin.png

これでSAMLv2により、一時認証情報を取得し、AWS-MCにログインできることが確認されました。次にSAMLassertionを取り出し、AWS CLIコマンドを実行します。


4. SAMLresponseの抽出及びAWS CLI実行

今回はブラウザとしてGoogle Chromeを使用し、デベロッパツールを利用します。下記ドキュメントを参考に実施します。

トラブルシューティングのためにブラウザで SAML レスポンスを表示する方法 - AWS Identity and Access Management


4-1. デベロッパツールの立ち上げ

以下のように、デベロッパーツールの上部における"Network"タブよりより、"Preserve log"を選択します

openam_19_1_samlassertion.png


4-2. SAMLresponseの取得

“4-1”にてUsername及びPasswordを入力し、SSOでAWS-MCにログインします。”saml”でfilterをかけ、SAMLreponseを取り出します。

openam_19_2_samlassertion.png

以下のようにSAMLResponseを取得できます。

openam_19_3_samlassertion.png

このSAMLresponseをローカル上にsamlresp.txtの名前で保存します。

🤖 ~  ⌚ 23:46:53

⚡ cat samlresp.txt| head -2
PHNhbWxwOlJlc3BvbnNlIHhtbG5zOnNhbWxwPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6
cHJvdG9jb2wiIElEPSJzMjFlODEyMTEzODgwMTE1Y2VjZDU0ODM1NjFhMjNhNDVkZTRlMmQyODIi


4-3. 一時認証情報の取得

下記AWS CLIコマンドによりSAMLresponseを利用し、一時認証情報を取得します。本コマンドの詳細はassume-role-with-saml — AWS CLI 1.14.50 Command Referenceに記載がございます。

🤖 ~  ⌚ 23:47:22

⚡ aws sts assume-role-with-saml --role-arn arn:aws:iam::<AccountID>:role/saml-provider-role --principal-arn arn:aws:iam::<AccountID>:saml-provider/openanm-saml-provider --saml-assertion file://samlresp.txt
{
"Credentials": {
"AccessKeyId": "<AccessKeyID>",
"SecretAccessKey": "<SecretKey>",
"SessionToken": "<一時認証token>",
"Expiration": "2018-03-04T15:50:09Z"
},
"AssumedRoleUser": {
"AssumedRoleId": "<AssumeRoleID>:login-user",
"Arn": "arn:aws:sts::<AccountID>:assumed-role/saml-provider-role/login-user"
},
"Subject": "**************",
"SubjectType": "transient",
"Issuer": "www.example.com",
"Audience": "https://signin.aws.amazon.com/saml",
"NameQualifier": "******************"
}


4-4. 一時認証情報の記載

~/.aws/credentialsに一時認証情報を記載します。

[saml]

aws_access_key_id = <AccessKeyID>
aws_secret_access_key = <SecretKey>
aws_session_token = <一時認証token>


4-5. 権限の確認

saml-provider-roleにはS3のフルアクセス権限のみあるので、実際に反映されているか確認します。

🤖 ~  ⌚ 23:51:41

⚡ aws s3api list-buckets --profile saml | head -10
{
"Buckets": [
{
"Name": "<BucketA>",
"CreationDate": "<Date>"
},
{
"Name": "<BucketB>",
"CreationDate": "<Date>"
},

🤖 ~  ⌚ 23:53:00

⚡ aws ec2 describe-instances --profile saml --region ap-northeast-1

An error occurred (UnauthorizedOperation) when calling the DescribeInstances operation: You are not authorized to perform this operation.

以上より、S3アクセス権限があり、EC2等にはAPIcallできないことが確認できます。