Identity サービスとのフェデレーション
Red Hat Single Sign-On を使用した Identity サービスとのフェデレーション
OpenStack Documentation Team
rhos-docs@redhat.com概要
多様性を受け入れるオープンソースの強化
Red Hat では、コード、ドキュメント、Web プロパティーにおける配慮に欠ける用語の置き換えに取り組んでいます。まずは、マスター (master)、スレーブ (slave)、ブラックリスト (blacklist)、ホワイトリスト (whitelist) の 4 つの用語の置き換えから始めます。この取り組みは膨大な作業を要するため、今後の複数のリリースで段階的に用語の置き換えを実施して参ります。詳細は、Red Hat CTO である Chris Wright のメッセージ をご覧ください。
Red Hat ドキュメントへのフィードバック (英語のみ)
Red Hat ドキュメントに対するご意見をお聞かせください。ドキュメントの改善点があればお知らせください。
ドキュメントへのダイレクトフィードバック (DDF) 機能の使用 (英語版のみ)
特定の文章、段落、またはコードブロックに対して直接コメントを送付するには、DDF の Add Feedback 機能を使用してください。なお、この機能は英語版のドキュメントでのみご利用いただけます。
- Multi-page HTML 形式でドキュメントを表示します。
- ドキュメントの右上隅に Feedback ボタンが表示されていることを確認してください。
- コメントするテキスト部分をハイライト表示します。
- Add Feedback をクリックします。
- Add Feedback フィールドにコメントを入力します。
- (オプション) ドキュメントチームが連絡を取り問題についてお伺いできるように、ご自分のメールアドレスを追加します。
- Submit をクリックします。
第1章 はじめに
現時点では、Red Hat はフェデレーションをサポートしていません。これはテスト目的にのみご利用いただく機能で、実稼働環境にデプロイすべきではありません。
高可用性 Red Hat OpenStack Platform director 環境でフェデレーションを設定するには、以下を設定する必要があります。
- Red Hat Identity Management
- Red Hat Single Sign-On (RH-SSO)
- Red Hat OpenStack Platform オーバークラウド
1.1. 概要
フェデレーション認証は、複数の異なるサービス間で認証を提供する方法です。この認証ソリューションは、アイデンティティープロバイダー (IdP)、サービスプロバイダー (SP) に依存し、Security Assertion Language (SAML) に基づいています。
OpenStack がフェデレーション認証ソリューションのサービスプロバイダーの場合、Red Hat Identity Management (IdM) グループ openstack-users のメンバーは、プロジェクトアクセス用の Member ロールで OpenStack Keystone グループ federated_users にマッピングされます。その結果、そのユーザーを IdM グループ openstack-users に追加して、OpenStack へのアクセス権限を付与することができます。
1.2. 前提条件
フェデレーションされた認証をデプロイする前に、以下を完了する必要があります。
Red Hat OpenStack Platform director とオーバークラウドを、以下の属性でデプロイしている。
- SSH を使用して、Red Hat OpenStack Platform director と各オーバークラウドノードに接続することができます。
- 全ノードには完全修飾ドメイン名 (FQDN) があります。
- TLS 暗号化は、すべての外部通信に使用されます。
- HAProxy は TLS フロントエンド接続を終了し、HAProxy の背後で実行しているサーバーは TLS を使用しません。
- RH-SSO サーバーが存在し、サーバーに管理者権限があるか、RH-SSO 管理者が独自のレルムを作成し、そのレルムに対する管理者権限をユーザーに付与している。フェデレーションされた IdP は定義によって外部にあるため、RH-SSO サーバーは Red Hat OpenStack Platform director オーバークラウドの外部にあることを前提とします。詳細は、Installing and configuring RH-SSO および Creating a realm and user を参照してください。
- IdM サーバーが存在し、ユーザーおよびグループが管理される Red Hat OpenStack Platform director オーバークラウド外にも存在します。RH-SSO は、IdM をユーザーフェデレーションバッキングストアとして使用します。
- Keystone Federation Configuration Guide に記載の例に従います。
-
undercloud-0ノードで、ヘルパーファイルをstackユーザーのホームディレクトリーにインストールし、stackユーザーのホームディレクトリーで操作します。 -
controller-0ノードで、ヘルパーファイルをheat-adminユーザーのホームディレクトリーにインストールし、heat-adminユーザーのホームディレクトリーで動作します。 -
mod_auth_mellonがコントローラーノードに以前にインストールされている場合は、Puppet Apache クラスにより Puppet の管理下でない Apache 設定ファイルが削除されるため、再インストールが必要になります。
Red Hat OpenStack オーバークラウドでは、フェデレーションのみが有効化されています。Director はフェデレーションされていません。
1.3. Red Hat OpenStack Platform ノードへのアクセス
デフォルトでは、オーバークラウドノードにアクセスするには、Red Hat OpenStack Platform director にログインする必要があります。
SSH を使用して Red Hat OpenStack director に接続します。
# ssh undercloud-0
stackユーザーになります。$ su - stack
source コマンドで
stackrc設定を読み込み、必要な OpenStack 環境変数を有効にします。$ source stackrc
source コマンドで
stackrcを読み込んだあと、Red Hat OpenStack Platform director に対して動作するopenstackコマンドラインツールを使用してコマンドを発行することができます。オーバークラウドノードのいずれかに直接アクセスするには、openstack server listを使用して IP アドレスを取得し、SSH を使用して接続します。(undercloud) [stack@director ~]$ openstack server list -c Name -c Networks +----------------------+-----------------------+ | Name | Networks | +----------------------+-----------------------+ | rhosp-controller-0 | ctlplane=10.94.101.11 | | rhosp-controller-1 | ctlplane=10.94.101.14 | | rhosp-controller-2 | ctlplane=10.94.101.17 | | rhosp-hypervisor-0 | ctlplane=10.94.101.18 | | rhosp-hypervisor-1 | ctlplane=10.94.101.20 | +----------------------+-----------------------+ $ ssh heat-admin@10.94.101.11
1.4. テクノロジーの概要
以下のテクノロジーは、Red Hat OpenStack Platform の一部です。
1.4.1. 高可用性
Red Hat OpenStack Platform director は、オーバークラウドのデプロイメント全体にわたって、さまざまな OpenStack サービスの冗長コピーを配信します。これらの冗長サービスは、Red Hat OpenStack Platform director が設定されたコントローラーノードの数に応じて、director がノード controller-0、controller-1、controller-2 などの命名を行い、オーバークラウドのコントローラーノードにデプロイされます。
コントローラーノードで実行中のサービスは HAProxy バックエンドサーバーであるため、コントローラーノードの IP アドレスは外部では表示されません。コントローラーノードのセットに公開されている IP アドレスが 1 つあります。これは HAProxy のフロントエンドです。要求がパブリック IP アドレスでサービスに到達すると、HAProxy は要求に対応するバックエンドサーバーを選択します。
オーバークラウドは高可用性クラスターとして編成されます。Pacemaker はクラスターを管理し、ヘルスチェックを実行し、リソースが機能停止した場合に別のクラスターリソースにフェイルオーバーすることができます。Pacemaker を使用して、これらのリソースを起動および停止します。
高可用性に関する詳しい情報は、High Availability Deployment and Usage ガイドを参照してください。
1.4.1.1. Pacemaker サービスの管理
Pacemaker が管理するサービスについては、コントローラーノードで podman コマンドを使用して管理しないでください。Pacemaker pcs コマンドを使用します。
sudo pcs resource restart haproxy-bundle
リソース名を確認するには、Pacemaker status コマンドを使用します。
sudo pcs status
...
* Container bundle set: haproxy-bundle [cluster.common.tag/openstack-haproxy:pcmklatest]:
* haproxy-bundle-podman-0 (ocf::heartbeat:podman): Started rhosp13-controller-0
* haproxy-bundle-podman-1 (ocf::heartbeat:podman): Started rhosp13-controller-1
* haproxy-bundle-podman-2 (ocf::heartbeat:podman): Started rhosp13-controller-2
...1.4.2. HAProxy の概要
HAProxy は Pacemaker に同様のロールを提供します。バックエンドサーバーでヘルスチェックを実行し、機能しているバックエンドサーバーに要求を転送します。すべてのコントローラーノードで HAProxy が実行している。
実行中の HAProxy のコピーは N 個ありますが、実際には 1 つのみで、要求に対するフィールドが設定されます。このアクティブな HAProxy インスタンスは Pacemaker によって管理されます。この手法により競合が発生するのを防ぎ、HAProxy の複数のコピーが複数のバックエンド間で要求の分散を調整できるようにします。Pacemaker は HAProxy が失敗したことを検知すると、フロントエンドの IP アドレスを別の HAProxy インスタンスに再割り当てします。その後、この HAProxy インスタンスは制御する HAProxy インスタンスになります。
1.5. 設定スクリプトの使用
フェデレーション認証を設定するには、長くて複雑なコマンドを実行する必要があります。このタスクを容易にし、反復性を確保するために、コマンドは configure-federation と呼ばれるシェルスクリプトに保存されます。configure-federation にステップの名前を渡すと、特定のステップを実行できます。使用できるコマンドの一覧を表示するには、help オプション (-h または --help) を使用します。
スクリプトの内容に関する詳しい情報は、6章configure-federation ファイル を参照してください。
変数の置き換え後に実行されるコマンドを表示するには、以下のオプションを使用します。
- -n
- このオプションは、システムに変更せずに操作を標準出力に書き込むドライランモードを提供します。
- -v
- このオプションは、実行前にその操作を stdout に書き込む詳細モードを提供します。これはロギングに役立ちます。
1.6. プロキシーまたは SSL 用語の使用
プロキシーの背後にある環境について、以下の主要な機能について検討してください。
バックエンドサーバーには異なるホスト名が設定されるか、別のポートでリッスンするか、またはプロキシーのフロントエンドにクライアントに表示されるプロトコルとは異なるプロトコルを使用する可能性があります。
サーバーが自己参照 URL を生成する際に問題が発生する場合があります。たとえば、サーバーが同じサーバー上の別の URL にクライアントをリダイレクトする場合などです。サーバーが生成する URL は、クライアントが確認できるパブリックアドレスおよびポートと一致させる必要があります。
HTTP や HTTPS などの認証プロトコルは、特定のサーバー、ポート、およびセキュアなトランスポート用に要求がターゲットとなっていることを確認する必要があるため、ホスト、ポート、プロトコルの影響を受けやすくなります。プロキシーはこの情報に干渉する可能性があります。
- プロキシーは、公開フロントエンドで受信する要求を変換してから、バックエンドのパブリック以外のサーバーにディスパッチします。
パブリック以外のバックエンドサーバーからの応答には、プロキシーのパブリックフロントエンドからの応答であるかのように調整が必要になる場合があります。
この問題には、さまざまなアプローチがあります。SAML はホスト、ポート、およびプロトコル情報を区別し、高可用性プロキシー (HAProxy) の背後で SAML を設定しているため、これらの問題に対処する必要があります。そうしないと、設定が失敗する可能性が高くなります。
第2章 Red Hat Identity Management の設定
以下の機能を使用して、フェデレーションされたユーザー管理で Red Hat OpenStack Platform を設定することができます。
- Red Hat Identity Management(IdM) は Red Hat OpenStack Platform の外部にあります。
- Red Hat IdM は、すべてのユーザーおよびグループ情報のソースです。
- Red Hat Single Signon (RH-SSO) は、ユーザーのフェデレーションに Red Hat IdM を使用するように設定されています。
2.1. RH-SSO 用の IdM サービスアカウントの作成
匿名バインドを使用する場合、セキュリティー上の理由から十分な情報が Red Hat Single Sign-On (RH-SSO) に不可欠となる一部情報は非表示になっています。その結果、IdM LDAP サーバーにこの情報を照会するには、専用アカウントの形式で RH-SSO に適切な特権を指定する必要があります。
LDAP_URL="ldaps://$FED_IPA_HOST"
DIR_MGR_DN="cn=Directory Manager"
SERVICE_NAME="rhsso"
SERVICE_DN="uid=$service_name,cn=sysaccounts,cn=etc,$FED_IPA_BASE_DN"
$ ldapmodify -H "${LDAP_URL}" -x -D "${DIR_MGR_DN}" -w <_FED_IPA_ADMIN_PASSWD_> <<EOF
dn: ${SERVICE_DN}
changetype: add
objectclass: account
objectclass: simplesecurityobject
uid: ${SERVICE_NAME}
userPassword: <_FED_IPA_RHSSO_SERVICE_PASSWD_>
passwordExpirationTime: 20380119031407Z
nsIdleTimeout: 0
EOF
上記の手順は、configure-federation スクリプトで実行できます ($ ./configure-federation create-ipa-service-account)。
2.2. テストユーザーの作成
IdM でユーザーアカウントを作成してテストします。
手順
IdM でユーザー
jdoeを作成します。$ipa user-add --first John --last Doe --email jdoe@example.com jdoe
ユーザーにパスワードを割り当てます。
$ipa passwd jdoe
2.3. OpenStack ユーザー向けの IdM グループの作成
Keystone グループ federated_users にマッピングするには、IdM グループ openstack-users が必要です。テストユーザーをこのグループにマッピングします。
Red Hat Identity Management (IdM) で openstack-users グループを作成します。
手順
openstack-usersグループが存在しないことを確認します。$ ipa group-show openstack-users ipa: ERROR: openstack-users: group not found
openstack-users グループを IdM に追加します。
ipa group-add openstack-users
テストユーザーを
openstack-usersグループに追加します。ipa group-add-member --users jdoe openstack-users
openstack-usersグループが存在し、test ユーザーをメンバーとして持つことを確認します。$ ipa group-show openstack-users Group name: openstack-users GID: 331400001 Member users: jdoe
第3章 Red Hat Single Sign-On の設定
Red Hat Single Sign-On (RH-SSO) はマルチテナンシーをサポートし、レルムを使用してテナント間の分離を可能にします。その結果、RH-SSO 操作は常にレルムのコンテキスト内で実行されます。レルムは手動で作成することも、RH-SSO サーバーで管理者権限がある場合は keycloak-httpd-client-install ツールを使用して作成することもできます。
前提条件
RH-SSO サーバーが完全にインストールされている必要があります。RH-SSO のインストールに関する詳細は、Server installation and configuration guide を参照してください。
以下に示すように、次の変数の定義が必要です。
| <_RH_RHSSO_URL_> | The Red Hat Single Sign-On URL |
| <_FED_RHSSO_REALM_> | 使用中の RH-SSO レルムを特定します。 |
3.1. RH-SSO レルムの設定
Red Hat Single Sign-On (RH-SSO) レルムが利用できる状態になったら、RH-SSO Web コンソールを使用して、IdM に対してユーザーフェデレーションのレルムを設定します。
手順
- 左上隅のドロップダウンリストから、RH-SSO レルムを選択します。
-
Configureパネルから、User federatedを選択します。 -
User FederationパネルのAdd providerドロップダウンリストから、ldapを選択します。 以下のパラメーターの値を指定します。サイト固有の値はすべて、実際の環境に適した値に置き換えます。
プロパティー 値 コンソール表示名
Red Hat IDM
編集モード
READ_ONLY
登録の同期
Off
Vendor
Red Hat Directory Server
ユーザー名 LDAP 属性
uid
RDN LDAP 属性
uid
UUID LDAP 属性
ipaUniqueID
ユーザーオブジェクトクラス
inetOrgPerson, organizationalPerson
接続 URL
LDAPS://<_FED_IPA_HOST_>
ユーザー DN
cn=users,cn=accounts,<_FED_IPA_BASE_DN_>
認証タイプ
simple
バインド DN
uid=rhsso,cn=sysaccounts,cn=etc,<_FED_IPA_BASE_DN_>
バインド認証情報
<_FED_IPA_RHSSO_SERVICE_PASSWD_>
- Test connection および Test authentication ボタンを使用して、ユーザーのフェデレーションが機能していることを確認します。
-
Saveをクリックして、新規ユーザーフェデレーションプロバイダーを保存します。 -
作成した Red Hat IdM ユーザーフェデレーションページの上部にある
Mappersタブをクリックします。 - デバイスマッパーを作成してユーザーグループ情報を取得します。ユーザーのグループメンバーシップは SAM アサーションを返します。グループメンバーシップを使用して OpenStack で認証を提供します。
-
Mappers ページで
Createをクリックします。 Add user federation mapperページで、Mapper Type ドロップダウンリストからgroup-ldap-mapperを選択し、Group Mapperという名前を付けます。以下のパラメーターの値を指定します。サイト固有の値はすべて、実際の環境に適した値に置き換えます。プロパティー 値 LDAP グループ DN
cn=groups,cn=accounts„<_FED_IPA_BASE_DN_>
グループ名 LDAP 属性
cn
グループオブジェクトクラス
groupOfNames
メンバーシップ LDAP 属性
member
メンバーシップ属性タイプ
DN
Mode
READ_ONLY
ユーザーグループの取得ストラテジー
GET_GROUPS_FROM_USER_MEMBEROF_ATTRIBUTE
-
Saveをクリックします。
3.2. SAML アサーションを使用したユーザー属性の追加
セキュリティーベンダー言語 (SAML) は、アイデンティティープロバイダー (IdP) とサービスプロバイダー (SP) 間のユーザー属性および承認認証情報の通信を可能にするオープン標準です。
Red Hat Single Sign-On(RH-SSO) を設定して、アサーションで必要な属性を返すことができます。OpenStack Identity サービスが SAML アサーションを受信すると、それらの属性を OpenStack ユーザーにマッピングします。IdP 属性を Identity サービスデータにマッピングするプロセスは、Federated Mapping と呼ばれます。詳しくは、「マッピングファイルの作成および Keystone にアップロード」をご覧ください。
以下のプロセスを使用して属性を SAML に追加します。
手順
- RH-SSO 管理 Web コンソールで、左上隅のドロップダウンリストから <_FED_RHSSO_REALM_> を選択します。
-
ConfigureパネルからClientsを選択します。 -
keycloak-httpd-client-install が設定されたサービスプロバイダークライアントを選択します。SAML
EntityIdでクライアントを特定できます。 - タブの水平一覧から Mappers タブを選択します。
-
Mappers パネルで
CreateまたはAdd Builtinを選択し、プロトコルマッパーをクライアントに追加します。
他の属性を追加できますが、必要なのはユーザーがメンバーとなっているグループの一覧だけです。グループメンバーシップはユーザーの承認方法になります。
3.3. グループ情報の SAML アサーションへの追加
手順
-
Mappers パネルの
Createボタンをクリックします。 -
Create Protocol Mapperパネルで、Mapper tpe ドロップダウンリストから Group リストを選択します。 -
Nameフィールドに名前として Group List を入力します。 Group 属性の
Nameフィールドに、グループを SAML 属性の名前として入力します。注記これは、SAML アサーションに表示される属性の名前です。Keystone マッパーがマッピング宣言の
Remoteセクションで名前を検索すると、SAML 属性名を検索します。アサーションに渡す RH-SSO の属性を追加する場合は、SAML 属性名を指定します。RH-SSO プロトコルマッパーで名前を定義します。-
SAML Attribute NameFormat パラメーターで、
Basicを選択します。 -
Single Group Attribute トグルボックスで、
Onを選択します。 -
Saveをクリックします。
keycloak-httpd-client-install ツールを実行すると、プロセスではグループマッパーを追加します。
第4章 Red Hat OpenStack Platform でのフェデレーションの設定
以下のノードには、割り当てられた完全修飾ドメイン名 (FQDN) が必要です。
- Dashboard (horizon) を実行しているホスト。
-
Identity サービス (keystone) を実行中のホスト。本書では
$FED_KEYSTONE_HOSTとして参照されています。複数のホストが高可用性環境でサービスを実行するため、IP アドレスはホストアドレスではなく、サービスにバインドされる IP アドレスであることに注意してください。 - RH-SSO を実行するホスト。
- IdM を実行するホスト。
Red Hat OpenStack Platform director のデプロイメントでは DNS が設定されていないか、FQDN をノードに割り当てます。ただし、認証プロトコル (および TLS) には FQDN を使用する必要があります。
4.1. IP アドレスの取得
Red Hat OpenStack Platform には、ポート番号で区切られた、すべての OpenStack サービスに共通するパブリック IP アドレスが 1 つあります。オーバークラウドサービスのパブリック IP アドレスを確認するには、openstack endpoint list コマンドを使用します。
(overcloud) [stack@director ~]$ openstack endpoint list -c "Service Name" -c Interface -c URL | grep public | swift | public | http://10.0.0.101:8080/v1/AUTH_%(tenant_id)s | | panko | public | http://10.0.0.101:8977 | | nova | public | http://10.0.0.101:8774/v2.1 | | glance | public | http://10.0.0.101:9292 | | neutron | public | http://10.0.0.101:9696 | | keystone | public | http://10.0.0.101:5000 | | cinderv2 | public | http://10.0.0.101:8776/v2/%(tenant_id)s | | placement | public | http://10.0.0.101:8778/placement | | cinderv3 | public | http://10.0.0.101:8776/v3/%(tenant_id)s | | heat | public | http://10.0.0.101:8004/v1/%(tenant_id)s | | heat-cfn | public | http://10.0.0.101:8000/v1 | | gnocchi | public | http://10.0.0.101:8041 | | aodh | public | http://10.0.0.101:8042 | | cinderv3 | public | http://10.0.0.101:8776/v3/%(tenant_id)s |
4.2. ホスト変数の設定およびホストの命名
使用する IP アドレスとポートを判断する必要があります。この例では、IP アドレスは 10.0.0.101 で、ポートは 13000 です。
overcloudrc でこの値を確認します。
export OS_AUTH_URL=https://10.0.0.101:13000/v2.0
IP アドレスに完全修飾ドメイン名 (FQDN) を割り当て、これを
/etc/hostsファイルに書き込みます。以下の例では、overcloud.localdomain を使用しています。10.0.0.101 overcloud.localdomain # FQDN of the external VIP
注記Red Hat OpenStack Platform director はオーバークラウドノードの host ファイルを設定しますが、参加する外部ホストにホストのエントリーを追加しなければならない場合があります。
fed_variables ファイルに $FED_KEYSTONE_HOST および $FED_KEYSTONE_HTTPS_PORT を設定します。この例では、同じ値を使用します。
FED_KEYSTONE_HOST="overcloud.localdomain" FED_KEYSTONE_HTTPS_PORT=13000
Mellon は Identity サービス (keystone) をホストする Apache サーバーで実行するため、Mellon の host:port と keystone の host:port の値が一致する必要があります。
コントローラーノードの 1 つで hostname コマンドを実行すると、出力が controller-0.localdomain のようになります。これは内部クラスター名ですが、そのパブリック名ではありません。代わりにパブリック IP アドレスを使用してください。
4.3. ヘルパーファイルのインストール
設定の一部としてヘルパーファイルをインストールする必要があります。
-
「設定スクリプトの使用」 の一部として作成した
configure-federationおよびfed_variablesファイルを、undercloud-0のstackホームディレクトリーにコピーします。
4.4. デプロイメント変数の設定
ファイル fed_variables には、フェデレーションのデプロイメントに固有の変数が含まれます。これらの変数は、本書および configure-federation ヘルパースクリプトで参照されます。サイト固有のフェデレーション変数には、FED_ の接頭辞が付けられます。fed_variables のすべての FED_ 変数に値が指定されていることを確認します。
4.5. ヘルパーファイルのコピー
続行するには、controller-0 に設定ファイルおよび変数ファイルが必要です。
-
configure-federation と、編集した fed_variables を
undercloud-0の~/stackホームディレクトリーからcontroller-0の~/heat-adminホームディレクトリーにコピーします。
$ scp configure-federation fed_variables heat-admin@controller-0:/home/heat-admin
上記の手順は、configure-federation スクリプトで実行できます ($ ./configure-federation copy-helper-to-controller)。
4.6. 作業環境の初期化
アンダークラウドノードで、
stackユーザーとしてfed_deploymentディレクトリーを作成します。この場所はファイル stash です。$ su - stack $ mkdir fed_deployment
注記configure-federationスクリプトを使用して、直前の手順を実行できます。$ ./configure-federation initialize
SSH を使用して
controller-0に接続し~/fed_deploymentディレクトリーをhead-adminユーザーとして作成します。この場所はファイル stash です。$ ssh heat-admin@controller-0 $ mkdir fed_deployment
注記configure-federationスクリプトを使用して、直前の手順を実行できます。controller-0ノードから以下を実行します。$ ./configure-federation initialize
4.7. mod_auth_mellon のインストール
環境内の各コントローラーに mod_auth_mellon をインストールする必要があります。
各コントローラーで以下を実行します。
$ ssh heat-admin@controller-n # replace n with controller number $ sudo dnf install mod_auth_mellon
4.8. 各コントローラーへの RH-SSO FQDN の追加
すべてのコントローラーが完全修飾ドメイン名 (FQDN) で到達可能であることを確認します。
mellon サービスは各コントローラーノードで実行され、RH-SSO IdP に接続します。RH-SSO IdP の FQDN が DNS 経由で解決できない場合には、
Heat Hostsセクションの後に、すべてのコントローラーノードの/etc/hostsファイルに FQDN を手動で追加します。$ ssh heat-admin@controller-n $ sudo vi /etc/hosts # Add this line (substituting the variables) before this line: # HEAT_HOSTS_START - Do not edit manually within this section! ... # HEAT_HOSTS_END $FED_RHSSO_IP_ADDR $FED_RHSSO_FQDN
4.9. コントローラーノードでの Mellon のインストールと設定
keycloak-httpd-client-install ツールは、mod_auth_mellon を設定し、RH-SSO IdP に対して認証するのに必要な多くの手順を実行します。mellon が実行するノードで keycloak-httpd-client-install ツールを実行します。以下の例では、mellon は、Identity サービス (keystone) を保護するオーバークラウドコントローラー上で実行します。
Red Hat OpenStack Platform は、複数のオーバークラウドコントローラーノードを持つ高可用性デプロイメントで、それぞれ同一コピーを実行します。したがって、各コントローラーノードで mellon 設定を複製する必要があります。これを実行するには、controller-0 に mellon をインストールおよび設定し、keycloak-httpd-client-install ツールで作成した設定ファイルを tar ファイルに収集します。Object Storage (swift) を使用して各コントローラーにアーカイブをコピーし、アーカイブに含まれるファイルを解凍します。
RH-SSO クライアントのインストールを実行します。
$ ssh heat-admin@controller-0 $ dnf -y install keycloak-httpd-client-install $ sudo keycloak-httpd-client-install \ --client-originate-method registration \ --mellon-https-port $FED_KEYSTONE_HTTPS_PORT \ --mellon-hostname $FED_KEYSTONE_HOST \ --mellon-root /v3 \ --keycloak-server-url $FED_RHSSO_URL \ --keycloak-admin-password $FED_RHSSO_ADMIN_PASSWORD \ --app-name v3 \ --keycloak-realm $FED_RHSSO_REALM \ -l "/v3/auth/OS-FEDERATION/websso/mapped" \ -l "/v3/auth/OS-FEDERATION/identity_providers/rhsso/protocols/mapped/websso" \ -l "/v3/OS-FEDERATION/identity_providers/rhsso/protocols/mapped/auth"
注記上記の手順は、configure-federation スクリプトで実行できます (
$ ./configure-federation client-install)。
クライアント RPM のインストール後に、以下のような出力が表示されるはずです。
[Step 1] Connect to Keycloak Server [Step 2] Create Directories [Step 3] Set up template environment [Step 4] Set up Service Provider X509 Certificates [Step 5] Build Mellon httpd config file [Step 6] Build Mellon SP metadata file [Step 7] Query realms from Keycloak server [Step 8] Create realm on Keycloak server [Step 9] Query realm clients from Keycloak server [Step 10] Get new initial access token [Step 11] Creating new client using registration service [Step 12] Enable saml.force.post.binding [Step 13] Add group attribute mapper to client [Step 14] Add Redirect URIs to client [Step 15] Retrieve IdP metadata from Keycloak server [Step 16] Completed Successfully
4.10. Mellon 設定の編集
IdP-assertion-to-Keystone マッピングフェーズ中は、グループを区切りリストにする必要があります。以下の手順に従い、属性に複数の値を受け取る場合に、区切りの 1 つの値に統合するように mellon を設定します。
手順
-
v3_mellon_keycloak_openstack.conf設定ファイルを開いて編集します。
$ vi /var/lib/config-data/puppet-generated/keystone/etc/httpd/conf.d/v3_mellon_keycloak_openstack.conf
MellonMergeEnvVarsパラメーターを <Location /v3> ブロックに追加します。<Location /v3> ... MellonMergeEnvVars On ";" </Location>
4.11. 生成された設定ファイルのアーカイブの作成
すべてのコントローラーノードで mellon 設定を複製するには、各コントローラーノードにインストールするファイルのアーカイブを作成します。アーカイブを ~/fed_deployment サブディレクトリーに保存します。
圧縮されたアーカイブを作成します。
mkdir fed_deployment && cd fed_deployment tar -czvf rhsso_config.tar.gz \ --exclude '*.orig' \ --exclude '*~' \ /var/lib/config-data/puppet-generated/keystone/etc/httpd/federation \ /var/lib/config-data/puppet-generated/keystone/etc/httpd/conf.d/v3_mellon_keycloak_openstack.conf
configure-federation スクリプトを使用して、直前の手順を実行できます。
$ ./configure-federation create-sp-archive
4.12. Mellon 設定アーカイブの取得
undercloud-0ノードで、作成したアーカイブを取得してファイルを展開し、後続のステップで必要に応じてデータにアクセスできるようにします。$ scp heat-admin@controller-0:/home/heat-admin/fed_deployment/rhsso_config.tar.gz ~/fed_deployment $ tar -C fed_deployment -xvf fed_deployment/rhsso_config.tar.gz
上記の手順は、configure-federation スクリプトで実行できます ($ ./configure-federation fetch-sp-archive)。
4.13. Puppet が管理外の HTTPD ファイルを削除しない
デフォルトでは、Puppet Apache モジュールは、管理しない Apache 設定ディレクトリーのファイルをパージします。これにより、Apache が Puppet が実施する設定に対して動作しなくなります。ただし、これは HTTPD 設定ディレクトリーの mellon の手動設定と競合します。Apache Puppet の apache::purge_configs フラグはデフォルトで有効になっています。このフラグにより、Puppet は mod_auth_mellon RPM に属するファイルを削除することを指示します。Puppet は、keycloak-httpd-client-install が生成する設定ファイルも削除します。Puppet が mellon ファイルを制御するまでは、apache::purge_configs フラグを無効にします。
apache::purge_configs フラグを無効にすると、コントローラーノードが脆弱性に対して開きます。Puppet が mellon の管理機能を追加したら、再度有効にします。
apache::purge_configs フラグを上書きするには、オーバーライドが含まれる Puppet ファイルを作成し、overcloud_deploy.sh スクリプトを実行する際に使用する Puppet ファイルの一覧にオーバーライドファイルを追加します。
fed_deployment/puppet_override_apache.yaml環境ファイルを作成して、以下の内容を追加します。parameter_defaults: ControllerExtraConfig: apache::purge_configs: falseovercloud_deploy.sh スクリプトの最後の環境ファイルとして
puppet_override_apache.yamlを追加します。... -e /home/stack/fed_deployment/puppet_override_apache.yaml \ --log-file overcloud_deployment_14.log &> overcloud_install.log
上記の手順は、configure-federation スクリプトで実行できます ($ ./configure-federation puppet-override-apache)。
4.14. Identity サービス (keystone) でのフェデレーションの設定
Keystone ドメインには追加の設定が必要です。ただし、keystone Puppet モジュールが有効な場合は、この追加の設定ステップを実施することができます。
Puppet YAML ファイルで、以下を追加します。
keystone::using_domain_config: true
/etc/keystone/keystone.conf で以下の値を設定してフェデレーションを有効にします。
auth:methods-
許可される認証方法の一覧。デフォルトでは、一覧は
['external', 'password', 'token', 'oauth1']です。mappedメソッドを使用して SAML を有効にする必要があります。さらに、externalメソッドも除外する必要があります。値をpassword,token,oauth1,mappedに設定します。 federation:trusted_dashboard-
信頼済みダッシュボードホストの一覧。トークンを返すためのシングルサインオン要求を受け入れる前に、元のホストはこの一覧のメンバーである必要があります。異なる値に、この設定オプションを複数回使用することができます。これを Web ベースの SSO フローを使用するように設定する必要があります。このデプロイメントでは、値は
https://$FED_KEYSTONE_HOST/dashboard/auth/websso/です。Red Hat OpenStack Platform director は keystone と horizon の両方が同じホストに配置されているため、ホストは $FED_KEYSTONE_HOST になります。horizon を keystone とは異なるホスト上で実行する場合は、適宜調整する必要があります。 federation:sso_callback_template- Single Sign-On コールバックハンドラーとして使用される HTML ファイルへの絶対パス。このページでは、POST リクエストでトークンをフォームエンコードすることにより、ユーザーを Identity Service から信頼できるダッシュボードホストにリダイレクトします。デフォルト値は、ほとんどのデプロイメントで十分です。
federation:remote_id_attributeアイデンティティープロバイダーのエンティティー ID の取得に使用される値。
mod_auth_mellonについては、Mellon_IDPを使用します。Mellon IDP ディレクティブを使用して、この値を mellon 設定ファイルに設定します。以下の内容で fed_deployment/puppet_override_keystone.yaml ファイルを作成します。
parameter_defaults: controllerExtraConfig: keystone::using_domain_config: true keystone::config::keystone_config: identity/domain_configurations_from_database: value: true auth/methods: value: external,password,token,oauth1,mapped federation/trusted_dashboard: value: https://$FED_KEYSTONE_HOST/dashboard/auth/websso/ federation/sso_callback_template: value: /etc/keystone/sso_callback_template.html federation/remote_id_attribute: value: MELLON_IDPovercloud_deploy.shスクリプトの最後に作成した環境ファイルを追加します。... -e /home/stack/fed_deployment/puppet_override_keystone.yaml \ --log-file overcloud_deployment_14.log &> overcloud_install.log
上記の手順は、configure-federation スクリプトで実行できます ($ ./configure-federation puppet-override-keystone)。
4.15. Mellon 設定アーカイブのデプロイ
Object Storage (swift) アーティファクトを使用して、各コントローラーノードに mellon 設定ファイルをインストールします。
$ source ~/stackrc $ upload-swift-artifacts -f fed_deployment/rhsso_config.tar.gz
上記の手順は、configure-federation スクリプトで実行できます (`./configure-federation deploy-mellon-configuration `)。
4.16. オーバークラウドの再デプロイ
Puppet YAML 設定ファイルおよび Object Storage アーティファクトから変更を適用するには、deploy コマンドを実行します。
./overcloud_deploy.sh
重要: Puppet を再度実行してコントローラーノードに追加の変更を加えると、overcloud_deploy.sh スクリプトにより以前の設定が上書きされる可能性があります。この手順の後には、Puppet 設定を適用しないでください。これにより、オーバークラウドのコントローラーノード上の設定ファイルに対する手動編集が失われるのを防ぐことができます。
4.17. 各コントローラーで Identity サービス (keystone) にプロキシーの永続性を使用する
mod_auth_mellon がセッションを確立すると、複数のサーバーでその状態情報を共有することはできません。SAML で使用されるリダイレクト数が多いため、同じサーバーがすべてのトランザクションを処理する必要があります。そのため、HAProxy を、毎回各クライアントの要求を同じサーバーに転送するように設定する必要があります。
HAProxy が同じサーバーにクライアントをバインドする方法は 2 つあります。
- Affinity
- アプリケーション層下のレイヤーからの情報を使用して、クライアント要求を 1 つのサーバーに固定する場合は、アフィニティーを使用します。
- 永続性
- アプリケーション層の情報がクライアントを 1 つのサーバースティッキーセッションにバインドする場合は、永続性を使用します。永続性はアフィニティーよりもはるかに正確です。永続を実装するには、以下の手順を使用します。
HAProxy クッキーディレクティブは、永続化のために Cookie およびそのパラメーターに名前を付けます。HAProxy サーバーのディレクティブには、クッキーの値をサーバー名に設定する cookie オプションがあります。受け取った要求にバックエンドサーバーを識別する cookie がない場合、HAProxy はその設定済みの分散アルゴリズムに基づいてサーバーを選択します。
手順
/var/lib/config-data/puppet-generated/haproxy/etc/haproxy/haproxy.cfg設定ファイルのkeystone_publicブロックで永続性を有効にするには、以下の行を追加します。cookie SERVERID insert indirect nocache
この設定は、
SERVERIDが永続 Cookie の名前です。各
server行を編集し、追加オプションとしてcookie <server-name>を追加します。server controller-0 cookie controller-0 server controller-1 cookie controller-1
4.18. フェデレーションリソースの作成
アイデンティティープロバイダー (IdP) が使用する Identity サービス (keystone) のターゲット、ユーザー、およびグループを作成します。
手順
source コマンドでアンダークラウド上の
overcloudrcファイルを stack ユーザーとして読み込み、以下のコマンドを実行します。$ openstack domain create federated_domain $ openstack project create --domain federated_domain federated_project $ openstack group create federated_users --domain federated_domain $ openstack role add --group federated_users --group-domain federated_domain --domain federated_domain _member_ $ openstack role add --group federated_users --group-domain federated_domain --project federated_project _member_
上記の手順は、configure-federation スクリプトで実行できます ($ ./configure-federation create-federated-resources)。
4.19. Red Hat OpenStack Platform でのアイデンティティープロバイダーの作成
IdP は Identity サービス (keystone) に登録する必要があります。これにより、SAML アサーションの entityID と Identity サービスの IdP の名前間にバインディングが作成されます。
手順
-
IdP メタデータにある RH-SSO IdP の
entityIDを見つけます。IdP メタデータは、/var/lib/config-data/puppet-generated/keystone/etc/httpd/saml2/v3_keycloak_$FED_RHSSO_REALM_idp_metadata.xml ファイルに保存されます。また、IdP メタデータは、fed_deployment/var/lib/config-data/puppet-generated/keystone/etc/httpd/saml2/v3_keycloak_$FED_RHSSO_REALM_idp_metadata.xml ファイルにも確認することができます。 -
EntityID 属性の値に注意してください。これは、
<EntityDescriptor>要素内の IdP メタデータファイルにあります。この値には$FED_IDP_ENTITY_ID変数を割り当てます。 変数
$FED_OPENSTACK_IDP_NAMEに割り当てられた IdPrhssoに名前を付けます。$ openstack identity provider create --remote-id $FED_IDP_ENTITY_ID $FED_OPENSTACK_IDP_NAME
上記の手順は、configure-federation スクリプトで実行できます ($ ./configure-federation openstack-create-idp)。
4.20. マッピングファイルの作成および Keystone にアップロード
Keystone は、IdP の SAML アサーションを keystone が理解できる形式に一致させるマッピングを実行します。このマッピングは keystone のマッピングエンジンによって実行され、IdP にバインドされる一連のマッピングに基づいています。
以下の例で使用しているマッピングは、以下で説明します (導入部分で説明)。
[ { "local": [ { "user": { "name": "{0}" }, "group": { "domain": { "name": "federated_domain" }, "name": "federated_users" } } ], "remote": [ { "type": "MELLON_NAME_ID" }, { "type": "MELLON_groups", "any_one_of": ["openstack-users"] } ] } ]
このマッピングファイルには、1 つのルールのみが含まれます。ルールは、local と remote の 2 つの部分に分類されます。マッピングエンジンは、1 つが一致するまでルールの一覧を反復処理し、実行します。ルールは、ルールの remote 部分の すべての 条件が一致する場合にのみ一致とみなされます。この例では、remote 条件は以下を指定します。
-
アサーションには
MELLON_NAME_IDという値が含まれている必要があります。 -
アサーションには
MELLON_groupsという名前の値が含まれ、グループ一覧の 1 つ以上のグループはopenstack-usersである必要があります。
ルールが一致する場合は、以下を実行します。
-
keystone
userユーザー名には、MELLON_NAME_IDからの値が割り当てられます。 -
ユーザーは、
federated_domainドメインの keystone グループfederated_usersに割り当てられます。
要約すると、IdP がユーザーの認証に成功し、IdP がそのユーザーが openstack-users グループに所属していることをアサートすると、keystone は keystone の federated_users グループにバインドされている権限で OpenStack にアクセスできます。
4.20.1. マッピングを作成する
keystone でマッピングを作成するには、マッピングルールが含まれるファイルを作成してから keystone にアップロードし、参照名を提供します。
fed_deploymentディレクトリー (例:fed_deployment/mapping_${FED_OPENSTACK_IDP_NAME}_saml2.json) にマッピングファイルを作成し、名前$FED_OPENSTACK_MAPPING_NAMEをマッピングルールに割り当てます。以下に例を示します。$ openstack mapping create --rules fed_deployment/mapping_rhsso_saml2.json $FED_OPENSTACK_MAPPING_NAME
configure-federation スクリプトを使用して、上記の手順を 2 つの手順として実行することができます。
$ ./configure-federation create-mapping $ ./configure-federation openstack-create-mapping
-
create-mapping- マッピングファイルを作成します。 -
openstack-create-mapping- ファイルのアップロードを実行します。
4.21. Keystone フェデレーションプロトコルの作成
Keystone は、
Mappedプロトコルを使用して IdP をマッピングにバインドします。このバインディングを確立するには、以下を実行します。$ openstack federation protocol create \ --identity-provider $FED_OPENSTACK_IDP_NAME \ --mapping $FED_OPENSTACK_MAPPING_NAME \ mapped"
上記の手順は、configure-federation スクリプトで実行できます ($ ./configure-federation openstack-create-protocol)。
4.22. Keystone 設定を完全に修飾します。
各コントローラーノードで
/var/lib/config-data/puppet-generated/keystone/etc/httpd/conf.d/10-keystone_wsgi_main.confを編集して、VirtualHost内のServerNameディレクティブに HTTPS スキーム、パブリックホスト名、およびパブリックポートが含まれていることを確認します。UseCanonicalNameディレクティブも有効にする必要があります。以下に例を示します。<VirtualHost> ServerName https:$FED_KEYSTONE_HOST:$FED_KEYSTONE_HTTPS_PORT UseCanonicalName On ... </VirtualHost>
$FED_ 変数をデプロイメントに固有の値に置き換えてください。
4.23. Horizon がフェデレーションを使用するように設定する
各コントローラーノードで
/var/lib/config-data/puppet-generated/horizon/etc/openstack-dashboard/local_settingsを編集して、以下の設定値が設定されていることを確認します。OPENSTACK_KEYSTONE_URL = "https://$FED_KEYSTONE_HOST:$FED_KEYSTONE_HTTPS_PORT/v3" OPENSTACK_KEYSTONE_DEFAULT_ROLE = "_member_" WEBSSO_ENABLED = True WEBSSO_INITIAL_CHOICE = "mapped" WEBSSO_CHOICES = ( ("mapped", _("RH-SSO")), ("credentials", _("Keystone Credentials")), )
$FED_ 変数をデプロイメントに固有の値に置き換えてください。
4.24. X-Forwarded-Proto HTTP ヘッダーを使用するように設定する
各コントローラーノードで
/var/lib/config-data/puppet-generated/horizon/etc/openstack-dashboard/local_settingsを編集して、行のコメントを解除します。#SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
設定の変更を有効にするには、コンテナーを再起動する必要があります。
第5章 トラブルシューティング
5.1. Keystone マッピングルールのテスト
マッピングルールが予想通りに機能することを確認することが推奨されます。keystone-manage コマンドラインツールを使用すると、ファイルからも読み取られるアサーションデータに対して一連のマッピングルール (ファイルから読み込み) を実行できます。以下に例を示します。
mapping_rules.jsonファイルには以下の内容が含まれます。[ { "local": [ { "user": { "name": "{0}" }, "group": { "domain": { "name": "Default" }, "name": "federated_users" } } ], "remote": [ { "type": "MELLON_NAME_ID" }, { "type": "MELLON_groups", "any_one_of": ["openstack-users"] } ] } ]assertion_data.txtファイルには以下の内容が含まれます。MELLON_NAME_ID: 'G-90eb44bc-06dc-4a90-aa6e-fb2aa5d5b0de MELLON_groups: openstack-users;ipausers
その場合は、以下のコマンドを実行します。
$ keystone-manage mapping_engine --rules mapping_rules.json --input assertion_data.txt
このマップされた結果が表示されるはずです。
{ "group_ids": [], "user": { "domain": { "id": "Federated" }, "type": "ephemeral", "name": "'G-90eb44bc-06dc-4a90-aa6e-fb2aa5d5b0de" }, "group_names": [ { "domain": { "name": "Default" }, "name": "federated_users" } ] }
--engine-debug コマンドライン引数を含めることもできます。これにより、マッピングルールが評価される方法を説明する診断情報が出力されます。
5.2. Keystone で受信されるアサート値を確認する
keystone が使用する マッピングされた アサーション値は環境変数として渡されます。これらの環境変数のダンプを取得するには、以下を実行します。
以下の内容で、以下のテストスクリプトを
/var/www/cgi-bin/keystone/testに作成します。import pprint import webob import webob.dec @webob.dec.wsgify def application(req): return webob.Response(pprint.pformat(req.environ), content_type='application/json')WSGIScriptAliasディレクティブを一時的に変更して、/var/lib/config-data/puppet-generated/keystone/etc/httpd/conf.d/10-keystone_wsgi_main.confファイルを編集し、testスクリプトを実行するように設定します。WSGIScriptAlias "/v3/auth/OS-FEDERATION/websso/mapped" "/var/www/cgi-bin/keystone/test"
コンテナーを再起動します。
podman restart keystone
-
ログインを試行し、スクリプトがダンプする情報を確認します。終了したら、
WSGIScriptAliasディレクティブを復元し、HTTPD サービスを再び再起動します。
5.3. SP と IdP の間で交換される SAML メッセージを確認します。
SAMLTracer Firefox アドオンは、SP と IdP の間で交換される SAML メッセージをキャプチャーし、表示するのに役立つツールです。
-
URL https://addons.mozilla.org/en-US/firefox/addon/saml-tracer/ から
SAMLTracerをインストールします。 -
Firefox メニューから
SAMLTracerを有効にします。すべてのブラウザー要求が表示されるSAMLTracerのポップアップウィンドウが表示されます。要求が SAML メッセージとして検出される場合は、特別なSAMLアイコンが要求に追加されます。 - Firefox ブラウザーから SSO ログインを開始します。
-
SAMLTracerウィンドウで最初のSAMLメッセージを見つけ、これをクリックします。ウィンドウでSAMLタブを使用して、デコードされた SAML メッセージを表示します (ツールはメッセージの本文の暗号化されたコンテンツを復号化できません。暗号化されたコンテンツを表示する必要がある場合は、メタデータの暗号化を無効にする必要があります)。最初の SAML メッセージは、SP によって IdP に送信されるAuthnRequestである必要があります。2 番目の SAML メッセージは、IdP によって送信されるアサーション応答である必要があります。SAML HTTP-Redirect プロファイルが使用されているため、アサーション応答は POST でラップされます。SAMLタブをクリックして、アサーションの内容を表示します。
第6章 configure-federation ファイル
#!/bin/sh
prog_name=`basename $0`
action=
dry_run=0
verbose=0
base_dir=$(pwd)
stage_dir="${base_dir}/fed_deployment"
mellon_root="/v3"
mellon_endpoint="mellon"
mellon_app_name="v3"
overcloud_deploy_script="overcloud_deploy.sh"
overcloudrc_file="./overcloudrc"
function cmd_template {
local status=0
local cmd="$1"
if [ $verbose -ne 0 -o $dry_run -ne 0 ]; then
echo $cmd
fi
if [ $dry_run -ne 0 ]; then
return $status
fi
$cmd
status=$?
if [ $status -ne 0 ]; then
(>&2 echo -e "ERROR cmd \"$cmd\" failed\nstatus = $status")
fi
return $status
}
function cmds_template {
local return_status=0
declare -a cmds=(
"date"
"ls xxx"
"head $0"
)
if [ $dry_run -ne 0 ]; then
for cmd in "${cmds[@]}"; do
echo $cmd
done
else
for cmd in "${cmds[@]}"; do
if [ $verbose -ne 0 ]; then
echo $cmd
fi
$cmd
status=$?
if [ $status -ne 0 ]; then
(>&2 echo -e "ERROR cmd \"$cmd\" failed\nstatus = $status")
return_status=$status
fi
done
fi
return $return_status
}
function show_variables {
echo "base_dir: $base_dir"
echo "stage_dir: $stage_dir"
echo "config_tar_filename: $config_tar_filename"
echo "config_tar_pathname: $config_tar_pathname"
echo "overcloud_deploy_script: $overcloud_deploy_script"
echo "overcloudrc_file: $overcloudrc_file"
echo "puppet_override_apache_pathname: $puppet_override_apache_pathname"
echo "puppet_override_keystone_pathname: $puppet_override_keystone_pathname"
echo
echo "FED_RHSSO_URL: $FED_RHSSO_URL"
echo "FED_RHSSO_ADMIN_PASSWORD: $FED_RHSSO_ADMIN_PASSWORD"
echo "FED_RHSSO_REALM: $FED_RHSSO_REALM"
echo
echo "FED_KEYSTONE_HOST: $FED_KEYSTONE_HOST"
echo "FED_KEYSTONE_HTTPS_PORT: $FED_KEYSTONE_HTTPS_PORT"
echo "mellon_http_url: $mellon_http_url"
echo "mellon_root: $mellon_root"
echo "mellon_endpoint: $mellon_endpoint"
echo "mellon_app_name: $mellon_app_name"
echo "mellon_endpoint_path: $mellon_endpoint_path"
echo "mellon_entity_id: $mellon_entity_id"
echo
echo "FED_OPENSTACK_IDP_NAME: $FED_OPENSTACK_IDP_NAME"
echo "openstack_mapping_pathname: $openstack_mapping_pathname"
echo "FED_OPENSTACK_MAPPING_NAME: $FED_OPENSTACK_MAPPING_NAME"
echo
echo "idp_metadata_filename: $idp_metadata_filename"
echo "mellon_httpd_config_filename: $mellon_httpd_config_filename"
}
function initialize {
local return_status=0
declare -a cmds=(
"mkdir -p $stage_dir"
)
if [ $dry_run -ne 0 ]; then
for cmd in "${cmds[@]}"; do
echo $cmd
done
else
for cmd in "${cmds[@]}"; do
if [ $verbose -ne 0 ]; then
echo $cmd
fi
$cmd
status=$?
if [ $status -ne 0 ]; then
(>&2 echo -e "ERROR cmd \"$cmd\" failed\nstatus = $status")
return_status=$status
fi
done
fi
return $return_status
}
function copy_helper_to_controller {
local status=0
local controller=${1:-"controller-0"}
local cmd="scp configure-federation fed_variables heat-admin@${controller}:/home/heat-admin"
if [ $verbose -ne 0 -o $dry_run -ne 0 ]; then
echo $cmd
fi
if [ $dry_run -ne 0 ]; then
return $status
fi
$cmd
status=$?
if [ $status -ne 0 ]; then
(>&2 echo -e "ERROR cmd \"$cmd\" failed\nstatus = $status")
fi
return $status
}
function install_mod_auth_mellon {
local status=0
local cmd="sudo dnf -y install mod_auth_mellon"
if [ $verbose -ne 0 -o $dry_run -ne 0 ]; then
echo $cmd
fi
if [ $dry_run -ne 0 ]; then
return $status
fi
$cmd
status=$?
if [ $status -ne 0 ]; then
(>&2 echo -e "ERROR cmd \"$cmd\" failed\nstatus = $status")
fi
return $status
}
function create_ipa_service_account {
# Note, after setting up the service account it can be tested
# by performing a user search like this:
# ldapsearch -H $ldap_url -x -D "$service_dn" -w "$FED_IPA_RHSSO_SERVICE_PASSWD" -b "cn=users,cn=accounts,$FED_IPA_BASE_DN"
local status=0
local ldap_url="ldaps://$FED_IPA_HOST"
local dir_mgr_dn="cn=Directory Manager"
local service_name="rhsso"
local service_dn="uid=$service_name,cn=sysaccounts,cn=etc,$FED_IPA_BASE_DN"
local cmd="ldapmodify -H \"$ldap_url\" -x -D \"$dir_mgr_dn\" -w \"$FED_IPA_ADMIN_PASSWD\""
read -r -d '' contents <<EOF
dn: $service_dn
changetype: add
objectclass: account
objectclass: simplesecurityobject
uid: $service_name
userPassword: $FED_IPA_RHSSO_SERVICE_PASSWD
passwordExpirationTime: 20380119031407Z
nsIdleTimeout: 0
EOF
if [ $verbose -ne 0 -o $dry_run -ne 0 ]; then
echo $cmd
echo -e "$contents"
fi
if [ $dry_run -ne 0 ]; then
return $status
fi
sh <<< "$cmd <<< \"$contents\""
status=$?
if [ $status -ne 0 ]; then
(>&2 echo -e "ERROR cmd \"$cmd\" failed\nstatus = $status")
fi
return $status
}
function client_install {
local status=0
local cmd_client_install="sudo dnf -y install keycloak-httpd-client-install"
local cmd="sudo keycloak-httpd-client-install \
--client-originate-method registration \
--mellon-https-port $FED_KEYSTONE_HTTPS_PORT \
--mellon-hostname $FED_KEYSTONE_HOST \
--mellon-root $mellon_root \
--keycloak-server-url $FED_RHSSO_URL \
--keycloak-admin-password $FED_RHSSO_ADMIN_PASSWORD \
--app-name $mellon_app_name \
--keycloak-realm $FED_RHSSO_REALM \
-l "/v3/auth/OS-FEDERATION/websso/mapped" \
-l "/v3/auth/OS-FEDERATION/identity_providers/rhsso/protocols/mapped/websso" \
-l "/v3/OS-FEDERATION/identity_providers/rhsso/protocols/mapped/auth"
"
if [ $verbose -ne 0 -o $dry_run -ne 0 ]; then
echo $cmd_client_install
echo $cmd
fi
if [ $dry_run -ne 0 ]; then
return $status
fi
$cmd_client_install
status=$?
if [ $status -ne 0 ]; then
(>&2 echo -e "ERROR cmd \"$cmd_client_install\" failed\nstatus = $status")
else
$cmd
status=$?
if [ $status -ne 0 ]; then
(>&2 echo -e "ERROR cmd \"$cmd\" failed\nstatus = $status")
fi
fi
return $status
}
function create_sp_archive {
# Note, we put the exclude patterns in a file because it is
# insanely difficult to put --exclude patttern in the $cmd shell
# variable and get the final quoting correct.
local status=0
local cmd="tar -cvzf $config_tar_pathname --exclude-from $stage_dir/tar_excludes /var/lib/config-data/puppet-generated/keystone/etc/httpd/federation /var/lib/config-data/puppet-generated/keystone/etc/httpd/conf.d/$mellon_httpd_config_filename"
if [ $verbose -ne 0 -o $dry_run -ne 0 ]; then
echo $cmd
fi
if [ $dry_run -ne 0 ]; then
return $status
fi
cat <<'EOF' > $stage_dir/tar_excludes
*.orig
*~
EOF
$cmd
status=$?
if [ $status -ne 0 ]; then
(>&2 echo -e "ERROR cmd \"$cmd\" failed\nstatus = $status")
fi
return $status
}
function fetch_sp_archive {
local return_status=0
declare -a cmds=(
"scp heat-admin@controller-0:/home/heat-admin/fed_deployment/$config_tar_filename $stage_dir"
"tar -C $stage_dir -xvf $config_tar_pathname"
)
if [ $dry_run -ne 0 ]; then
for cmd in "${cmds[@]}"; do
echo $cmd
done
else
for cmd in "${cmds[@]}"; do
if [ $verbose -ne 0 ]; then
echo $cmd
fi
$cmd
status=$?
if [ $status -ne 0 ]; then
(>&2 echo -e "ERROR cmd \"$cmd\" failed\nstatus = $status")
return_status=$status
fi
done
fi
return $return_status
}
function deploy_mellon_configuration {
local status=0
local cmd="upload-swift-artifacts -f $config_tar_pathname"
if [ $verbose -ne 0 -o $dry_run -ne 0 ]; then
echo $cmd
fi
if [ $dry_run -ne 0 ]; then
return $status
fi
$cmd
status=$?
if [ $status -ne 0 ]; then
(>&2 echo -e "ERROR cmd \"$cmd\" failed\nstatus = $status")
fi
return $status
}
function idp_entity_id {
local metadata_file=${1:-$idp_metadata_filename}
# Extract the entitID from the metadata file, should really be parsed
# with an XML xpath but a simple string match is probably OK
entity_id=`sed -rne 's/^.*entityID="([^"]*)".*$/\1/p' ${metadata_file}`
status=$?
if [ $status -ne 0 -o "$entity_id"x = "x" ]; then
(>&2 echo -e "ERROR search for entityID in ${metadata_file} failed\nstatus = $status")
return 1
fi
echo $entity_id
return 0
}
function append_deploy_script {
local status=0
local deploy_script=$1
local extra_line=$2
local count
count=$(grep -c -e "$extra_line" $deploy_script)
if [ $count -eq 1 ]; then
echo -e "SKIP appending:\n$extra_line"
echo "already present in $deploy_script"
return $status
elif [ $count -gt 1 ]; then
status=1
(>&2 echo -e "ERROR multiple copies of line in ${deploy_script}\nstatus = $status\nline=$extra_line")
return $status
fi
if [ $verbose -ne 0 -o $dry_run -ne 0 ]; then
echo "appending $deploy_script with:"
echo -e $extra_line
fi
if [ $dry_run -ne 0 ]; then
return $status
fi
# insert line after last -e line already in script
#
# This is not easy with sed, we'll use tac and awk instead. Here
# is how this works: The logic is easier if you insert before the
# first line rather than trying to find the last line and insert
# after it. We use tac to reverse the lines in the file. Then the
# awk script looks for the candidate line. If found it outputs the
# line we're adding, sets a flag (p) to indicate it's already been
# printed. The "; 1" pattern always output the input line. Then we
# run the output through tac again to set things back in the
# original order.
local tmp_file=$(mktemp)
tac $deploy_script | awk "!p && /^-e/{print \"${extra_line} \\\\\"; p=1}; 1" | tac > $tmp_file
count=$(grep -c -e "${extra_line}" $tmp_file)
if [ $count -ne 1 ]; then
status=1
fi
if [ $status -ne 0 ]; then
rm $tmp_file
(>&2 echo -e "ERROR failed to append ${deploy_script}\nstatus = $status\nline=$extra_line")
else
mv $tmp_file $deploy_script
fi
return $status
}
function puppet_override_apache {
local status=0
local pathname=${1:-$puppet_override_apache_pathname}
local deploy_cmd="-e $pathname"
read -r -d '' contents <<'EOF'
parameter_defaults:
ControllerExtraConfig:
apache::purge_configs: false
EOF
if [ $verbose -ne 0 -o $dry_run -ne 0 ]; then
echo "writing pathname = $pathname with contents"
echo -e "$contents"
fi
if [ $dry_run -ne 0 ]; then
return $status
fi
echo -e "$contents" > $pathname
status=$?
if [ $status -ne 0 ]; then
(>&2 echo -e "ERROR failed to write ${pathname}\nstatus = $status")
fi
append_deploy_script $overcloud_deploy_script "$deploy_cmd"
status=$?
return $status
}
function puppet_override_keystone {
local status=0
local pathname=${1:-$puppet_override_keystone_pathname}
local deploy_cmd="-e $pathname"
read -r -d '' contents <<EOF
parameter_defaults:
controllerExtraConfig:
keystone::using_domain_config: true
keystone::config::keystone_config:
identity/domain_configurations_from_database:
value: true
auth/methods:
value: external,password,token,oauth1,mapped
federation/trusted_dashboard:
value: https://$FED_KEYSTONE_HOST/dashboard/auth/websso/
federation/sso_callback_template:
value: /etc/keystone/sso_callback_template.html
federation/remote_id_attribute:
value: MELLON_IDP
EOF
if [ $verbose -ne 0 -o $dry_run -ne 0 ]; then
echo "writing pathname = $pathname with contents"
echo -e "$contents"
fi
if [ $dry_run -ne 0 ]; then
return $status
fi
echo -e "$contents" > $pathname
status=$?
if [ $status -ne 0 ]; then
(>&2 echo -e "ERROR failed to write ${pathname}\nstatus = $status")
fi
append_deploy_script $overcloud_deploy_script "$deploy_cmd"
status=$?
return $status
}
function create_federated_resources {
# follow example in Keystone federation documentation
# http://docs.openstack.org/developer/keystone/federation/federated_identity.html#create-keystone-groups-and-assign-roles
local return_status=0
declare -a cmds=(
"openstack domain create federated_domain"
"openstack project create --domain federated_domain federated_project"
"openstack group create federated_users --domain federated_domain"
"openstack role add --group federated_users --group-domain federated_domain --domain federated_domain _member_"
"openstack role add --group federated_users --project federated_project Member"
)
if [ $dry_run -ne 0 ]; then
for cmd in "${cmds[@]}"; do
echo $cmd
done
else
for cmd in "${cmds[@]}"; do
if [ $verbose -ne 0 ]; then
echo $cmd
fi
$cmd
status=$?
if [ $status -ne 0 ]; then
(>&2 echo -e "ERROR cmd \"$cmd\" failed\nstatus = $status")
return_status=$status
fi
done
fi
return $return_status
}
function create_mapping {
# Matches documentation
# http://docs.openstack.org/developer/keystone/federation/federated_identity.html#create-keystone-groups-and-assign-roles
local status=0
local pathname=${1:-$openstack_mapping_pathname}
read -r -d '' contents <<'EOF'
[
{
"local": [
{
"user": {
"name": "{0}"
},
"group": {
"domain": {
"name": "federated_domain"
},
"name": "federated_users"
}
}
],
"remote": [
{
"type": "MELLON_NAME_ID"
},
{
"type": "MELLON_groups",
"any_one_of": ["openstack-users"]
}
]
}
]
EOF
if [ $verbose -ne 0 -o $dry_run -ne 0 ]; then
echo "writing pathname = $pathname with contents"
echo -e "$contents"
fi
if [ $dry_run -ne 0 ]; then
return $status
fi
echo -e "$contents" > $pathname
status=$?
if [ $status -ne 0 ]; then
(>&2 echo -e "ERROR failed to write ${pathname}\nstatus = $status")
fi
return $status
}
function create_v3_rcfile {
local status=0
local input_file=${1:-$overcloudrc_file}
local output_file="${input_file}.v3"
source $input_file
#clear the old environment
NEW_OS_AUTH_URL=`echo $OS_AUTH_URL | sed 's!v2.0!v3!'`
read -r -d '' contents <<EOF
for key in \$( set | sed 's!=.*!!g' | grep -E '^OS_') ; do unset $key ; done
export OS_AUTH_URL=$NEW_OS_AUTH_URL
export OS_USERNAME=$OS_USERNAME
export OS_PASSWORD=$OS_PASSWORD
export OS_USER_DOMAIN_NAME=Default
export OS_PROJECT_DOMAIN_NAME=Default
export OS_PROJECT_NAME=$OS_TENANT_NAME
export OS_IDENTITY_API_VERSION=3
EOF
if [ $verbose -ne 0 -o $dry_run -ne 0 ]; then
echo "writing output_file = $output_file with contents:"
echo -e "$contents"
fi
if [ $dry_run -ne 0 ]; then
return $status
fi
echo -e "$contents" > $output_file
status=$?
if [ $status -ne 0 ]; then
(>&2 echo -e "ERROR failed to write ${output_file}\nstatus = $status")
fi
return $status
}
function openstack_create_idp {
local status=0
local metadata_file="$stage_dir/var/lib/config-data/puppet-generated/keystone/etc/httpd/federation/$idp_metadata_filename"
local entity_id
entity_id=$(idp_entity_id $metadata_file)
status=$?
if [ $status -ne 0 ]; then
return $status
fi
local cmd="openstack identity provider create --remote-id $entity_id $FED_OPENSTACK_IDP_NAME"
if [ $verbose -ne 0 -o $dry_run -ne 0 ]; then
echo $cmd
fi
if [ $dry_run -ne 0 ]; then
return $status
fi
$cmd
status=$?
if [ $status -ne 0 ]; then
(>&2 echo -e "ERROR cmd \"$cmd\" failed\nstatus = $status")
fi
return $status
}
function openstack_create_mapping {
local status=0
local mapping_file=${1:-$openstack_mapping_pathname}
local mapping_name=${2:-$FED_OPENSTACK_MAPPING_NAME}
cmd="openstack mapping create --rules $mapping_file $mapping_name"
if [ $verbose -ne 0 -o $dry_run -ne 0 ]; then
echo $cmd
fi
if [ $dry_run -ne 0 ]; then
return $status
fi
$cmd
status=$?
if [ $status -ne 0 ]; then
(>&2 echo -e "ERROR cmd \"$cmd\" failed\nstatus = $status")
fi
return $status
}
function openstack_create_protocol {
local status=0
local idp_name=${1:-$FED_OPENSTACK_IDP_NAME}
local mapping_name=${2:-$FED_OPENSTACK_MAPPING_NAME}
cmd="openstack federation protocol create --identity-provider $idp_name --mapping $mapping_name mapped"
if [ $verbose -ne 0 -o $dry_run -ne 0 ]; then
echo $cmd
fi
if [ $dry_run -ne 0 ]; then
return $status
fi
$cmd
status=$?
if [ $status -ne 0 ]; then
(>&2 echo -e "ERROR cmd \"$cmd\" failed\nstatus = $status")
fi
return $status
}
function usage {
cat <<EOF
$prog_name action
-h --help print usage
-n --dry-run dry run, just print computed command
-v --verbose be chatty
action may be one of:
show-variables
initialize
copy-helper-to-controller
install-mod-auth-mellon
create-ipa-service-account
client-install
create-sp-archive
fetch-sp-archive
deploy-mellon-configuration
puppet-override-apache
puppet-override-keystone
create-federated-resources
create-mapping
create-v3-rcfile
openstack-create-idp
openstack-create-mapping
openstack-create-protocol
EOF
}
#-----------------------------------------------------------------------------
# options may be followed by one colon to indicate they have a required argument
if ! options=$(getopt -o hnv -l help,dry-run,verbose -- "$@")
then
# something went wrong, getopt will put out an error message for us
exit 1
fi
eval set -- "$options"
while [ $# -gt 0 ]
do
case $1 in
-h|--help) usage; exit 1 ;;
-n|--dry-run) dry_run=1 ;;
-v|--verbose) verbose=1 ;;
# for options with required arguments, an additional shift is required
(--) shift; break;;
(-*) echo "$0: error - unrecognized option $1" 1>&2; exit 1;;
(*) break;;
esac
shift
done
#-----------------------------------------------------------------------------
source ./fed_variables
# Strip leading and trailing space and slash from these variables
mellon_root=`echo ${mellon_root} | perl -pe 's!^[ /]*(.*?)[ /]*$!\1!'`
mellon_endpoint=`echo ${mellon_endpoint} | perl -pe 's!^[ /]*(.*?)[ /]*$!\1!'`
mellon_root="/${mellon_root}"
mellon_endpoint_path="${mellon_root}/${mellon_endpoint}"
mellon_http_url="https://${FED_KEYSTONE_HOST}:${FED_KEYSTONE_HTTPS_PORT}"
mellon_entity_id="${mellon_http_url}${mellon_endpoint_path}/metadata"
openstack_mapping_pathname="${stage_dir}/mapping_${FED_OPENSTACK_IDP_NAME}_saml2.json"
idp_metadata_filename="${mellon_app_name}_keycloak_${FED_RHSSO_REALM}_idp_metadata.xml"
mellon_httpd_config_filename="${mellon_app_name}_mellon_keycloak_${FED_RHSSO_REALM}.conf"
config_tar_filename="rhsso_config.tar.gz"
config_tar_pathname="${stage_dir}/${config_tar_filename}"
puppet_override_apache_pathname="${stage_dir}/puppet_override_apache.yaml"
puppet_override_keystone_pathname="${stage_dir}/puppet_override_keystone.yaml"
#-----------------------------------------------------------------------------
if [ $# -lt 1 ]; then
echo "ERROR: no action specified"
exit 1
fi
action="$1"; shift
if [ $dry_run -ne 0 ]; then
echo "Dry Run Enabled!"
fi
case $action in
show-var*)
show_variables ;;
initialize)
initialize ;;
copy-helper-to-controller)
copy_helper_to_controller "$1" ;;
install-mod-auth-mellon)
install_mod_auth_mellon ;;
create-ipa-service-account)
create_ipa_service_account ;;
client-install)
client_install ;;
create-sp-archive)
create_sp_archive ;;
fetch-sp-archive)
fetch_sp_archive ;;
deploy-mellon-configuration)
deploy_mellon_configuration ;;
create-v3-rcfile)
create_v3_rcfile "$1" ;;
puppet-override-apache)
puppet_override_apache "$1" ;;
puppet-override-keystone)
puppet_override_keystone "$1" ;;
create-federated-resources)
create_federated_resources ;;
create-mapping)
create_mapping "$1" ;;
openstack-create-idp)
openstack_create_idp "$1" ;;
openstack-create-mapping)
openstack_create_mapping "$1" "$2" ;;
openstack-create-protocol)
openstack_create_protocol "$1" "$2" ;;
*)
echo "unknown action: $action"
usage
exit 1
;;
esac第7章 fed_variables ファイル
# FQDN of IPA server
FED_IPA_HOST="jdennis-ipa.example.com"
# Base DN of IPA server
FED_IPA_BASE_DN="dc=example,dc=com"
# IPA administrator password
FED_IPA_ADMIN_PASSWD="FreeIPA4All"
# Password used by RH-SSO service to authenticate to IPA
# when RH-SSO obtains user/group information from IPA as part of
# RH-SSO's User Federation.
FED_IPA_RHSSO_SERVICE_PASSWD="rhsso-passwd"
# RH-SSO server IP address
FED_RHSSO_IP_ADDR="10.0.0.12"
# RH-SSO server FQDN
FED_RHSSO_FQDN="jdennis-rhsso-7"
# URL used to access the RH-SSO server
FED_RHSSO_URL="https://$FED_RHSSO_FQDN"
# Administrator password for RH-SSO server
FED_RHSSO_ADMIN_PASSWORD=FreeIPA4All
# Name of the RH-SSO realm
FED_RHSSO_REALM="openstack"
# Host name of the mellon server
# Note, this is identical to the Keystone server since Keystone is
# being front by Apache which is protecting it's resources with mellon.
FED_KEYSTONE_HOST="overcloud.localdomain"
# Port number mellon is running on the FED_KEYSTONE_HOST
# Note, this is identical to the Keystone server port
FED_KEYSTONE_HTTPS_PORT=13000
# Name assigned in OpenStack to our IdP
FED_OPENSTACK_IDP_NAME="rhsso"
# Name of our Keystone mapping rules
FED_OPENSTACK_MAPPING_NAME="${FED_OPENSTACK_IDP_NAME}_mapping"