Quantum周りのたった1つの問題に1週間以上ハマって絶望するも、
絞りだすような勘で生還してブログ再開!!
今回はなんとっ!KeystoneデータをLDAPで管理するという一風変わった情報をお届けします!
LDAPを採用した理由
どうしてわざわざLDAPにしたのか、というと、まず、既にLDAPが存在し、他の複数のソフトウェアのアカウント管理に用いていたため、OpenStackも同様に既存のLDAPユーザでログインしたかった、というのが1つ。
次に、LDAPユーザから削除された(例えば退職したとか)場合に、そのユーザが管理していたVMを自動的に(もしくは一括して)削除できるようにすることで、VMをより管理しやすくしたかったから。Horizonの表示上は見えませんが、実は novadb.instances テーブルには user_id が保存されているし、nova-manage vm list でも確認できるので、実現することは容易いです。
ということで、ユーザデータだけは既存LDAPのデータを使用し、それ以外のテナントやロールは新規に作成。さらに、一部を除いてデータ管理は keystone コマンドではなく、LDAP Account Manager(LAM)で行うというルールの元に構築していっています。
LDAPサーバslapdの構築
テストデータとなる slapd をControllerNodeにでも作成します。パッケージインストール
1 |
apt-get install slapd ldap-utils |
設定は以下のようにしています。
1 2 3 4 |
dpkg-reconfigure slapd # データ確認 slapcat | less |
設定
パスワードのSSHAを取得し、設定ファイルに利用します。
1 2 |
slappasswd {SSHA}PNof4WRW8ckd7bWQRfof1CVmgeQ14B09 |
設定ファイルを作成します。
/etc/ldap/slapd.conf
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
include /etc/ldap/schema/core.schema include /etc/ldap/schema/cosine.schema include /etc/ldap/schema/inetorgperson.schema include /etc/ldap/schema/nis.schema pidfile /var/run/slapd/slapd.pid argsfile /var/run/slapd/slapd.args loglevel 0 modulepath /usr/lib/ldap moduleload back_hdb tool-threads 1 backend hdb database hdb suffix "dc=openstack,dc=org" rootdn "cn=admin,dc=openstack,dc=org" rootpw {SSHA}PNof4WRW8ckd7bWQRfof1CVmgeQ14B09 directory /var/lib/ldap |
今回は slapd.conf で設定したため、slapd.d はどけておく必要があります。
1 |
mv /etc/ldap/slapd.d /etc/ldap/__slapd.d~orig |
schema修正
Keystone+LDAPが必要としている項目 enabled をスキーマに追加します。編集対象が core.schema なのが心苦しいですが、仕方ありません。
/etc/ldap/schema/core.schema
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
# 追加 360行目あたり attributetype ( 2.5.4.66 NAME 'enabled' DESC 'RFC2256: enabled of a group' EQUALITY booleanMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 SINGLE-VALUE ) # 変更 443行目あたり objectclass ( 2.5.6.9 NAME 'groupOfNames' DESC 'RFC2256: a group of names (DNs)' SUP top STRUCTURAL MUST ( member $ cn ) MAY ( businessCategory $ seeAlso $ owner $ ou $ o $ description $ enabled ) ) # MAY ( businessCategory $ seeAlso $ owner $ ou $ o $ description ) ) |
DB_CONFIG
これは好みで設定しておきます。/var/lib/ldap/DB_CONFIG
1 2 3 4 5 6 7 8 |
set_cachesize 0 268435456 2 set_flags DB_TXN_NOSYNC set_lg_regionmax 20971520 set_lg_max 10485760 set_lg_bsize 524288 set_lk_max_objects 5000 set_lk_max_locks 5000 set_lk_max_lockers 5000 |
設定したら再起動します。
1 |
/etc/init.d/slapd restart |
LDAPに基本データを入れる
必要な ou を入れます。domains はGrizzlyから必要になっています。
全て同じ階層に作成していますが、users だけ別の階層にしたりしても、問題なく動作します。
usersのみ既存データを想定しているので、実際は、わかりやすくするためにusers以外は1つdc階層を下げました
suffix を別にすることは slapd において可能ではありますが、1つのLAMで管理できなくなるので不採用にしています
suffix を別にすることは slapd において可能ではありますが、1つのLAMで管理できなくなるので不採用にしています
/etc/keystone/openstack.ldif
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
dn: ou=groups,dc=openstack,dc=org objectClass: top objectClass: organizationalUnit ou: groups dn: ou=users,dc=openstack,dc=org objectClass: top objectClass: organizationalUnit ou: users dn: ou=roles,dc=openstack,dc=org objectClass: top objectClass: organizationalUnit ou: roles dn: ou=machines,dc=openstack,dc=org objectClass: top objectClass: organizationalUnit ou: machines dn: ou=domains,dc=openstack,dc=org objectClass: top objectClass: organizationalUnit ou: domains |
LDIFを作成したら、追加します。
1 2 3 4 5 |
ldapadd -h localhost -x -D "cn=admin,dc=openstack,dc=org" -W -f /etc/keystone/openstack.ldif # データの確認 slapcat | less ldapsearch -x -LLL -h localhost -p 389 -b dc=openstack,dc=org | less |
LAM (LDAP Account Manager) のインストール
パッケージ
1 |
apt-get install ldap-account-manager cronolog |
設定
管理ユーザ や OU を編集します。/var/lib/ldap-account-manager/config/lam.conf
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
# slapdの管理ユーザ serverURL: ldap://localhost:389 admins: cn=admin,dc=openstack,dc=org passwd: {SSHA}PNof4WRW8ckd7bWQRfof1CVmgeQ14B09 treesuffix: dc=openstack,dc=org # 表示言語 defaultLanguage: ja_JP.utf8:UTF-8:日本語 (日本) # ユーザ/グループIDの最小値変更してみたり modules: posixAccount_minUID: 5000 modules: posixGroup_minGID: 5000 # 基本OUのsuffixを変更 types: suffix_user: ou=users,dc=openstack,dc=org types: suffix_group: ou=groups,dc=openstack,dc=org types: suffix_host: ou=machines,dc=openstack,dc=org types: suffix_smbDomain: dc=openstack,dc=org |
Apacheの設定
ログ排除条件を指定して、/etc/apache2/conf.d/logenv.conf
1 |
SetEnvIf Request_URI \.(gif|jpg|png|js|css|ida|exe)$ no_log |
元のサイト設定を削除して
1 |
rm /etc/apache2/conf.d/ldap-account-manager |
VirtualHostでちゃんと指定しておきます。(※プライベートDNSに追加できれば)
/etc/apache2/sites-available/lam
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 |
<VirtualHost *:80> ServerName ldap.openstack.org CustomLog "|/usr/bin/cronolog /var/log/apache2/lam/access/%Y%m/%Y%m.log" combined env=!no_log ErrorLog "|/usr/bin/cronolog /var/log/apache2/lam/error/%Y%m/%Y%m.log" Alias /lam /usr/share/ldap-account-manager <Directory /usr/share/ldap-account-manager> Options +FollowSymLinks AllowOverride All Order allow,deny Allow from all DirectoryIndex index.html </Directory> <Directory /var/lib/ldap-account-manager/tmp> Options -Indexes </Directory> <Directory /var/lib/ldap-account-manager/tmp/internal> Options -Indexes Order allow,deny Deny from all </Directory> <Directory /var/lib/ldap-account-manager/sess> Options -Indexes Order allow,deny Deny from all </Directory> <Directory /var/lib/ldap-account-manager/config> Options -Indexes Order allow,deny Deny from all </Directory> <Directory /usr/share/ldap-account-manager/lib> Options -Indexes Order allow,deny Deny from all </Directory> <Directory /usr/share/ldap-account-manager/help> Options -Indexes Order allow,deny Deny from all </Directory> <Directory /usr/share/ldap-account-manager/locale> Options -Indexes Order allow,deny Deny from all </Directory> </VirtualHost> |
他、security系とか好みで編集したら、
設定を有効にしてリロードします。
1 2 3 |
a2ensite lam apache2ctl configtest /etc/init.d/apache2 reload |
LAMでデータ作成
LAMにアクセスしてみます。LAMでOpenStack管理ユーザと、一般ユーザのグループ/ユーザを作成しておきます。
『業種』は businessCategory の項目となっています
既存ユーザデータに小文字の admin を混ぜるのが嫌だったので OpenStackAdmin を管理者にしています
さらにLAMでdefaultドメインを作成しておきます。
usersデータの businessCategory と紐付いたデータです
お互いの default が一致していないとアカウントは有効になりません
お互いの default が一致していないとアカウントは有効になりません
keystone連携
設定
keystone.conf をLDAP仕様に変更します。設定は関連部のみ、それとメモを書いておきます。
/etc/keystone/keystone.conf
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 64 65 66 67 68 69 70 71 72 73 74 75 76 |
[identity] driver = keystone.identity.backends.ldap.Identity [ldap] url = ldap://192.168.0.11 user = cn=admin,dc=openstack,dc=org password = rootpass #user = uid=OpenStackAdmin,ou=users,dc=drecom,dc=co,dc=jp #password = adminpass suffix = dc=openstack,dc=org use_dumb_member = True dumb_member = cn=dumb,dc=nonexistent allow_subtree_delete = False query_scope = one page_size = 0 alias_dereferencing = default user_tree_dn = ou=users,dc=openstack,dc=org user_objectclass = inetOrgPerson user_filter = user_id_attribute = uid user_name_attribute = cn user_mail_attribute = mail user_pass_attribute = userPassword user_domain_id_attribute = businessCategory user_enabled_attribute = enabled user_enabled_mask = 0 user_enabled_default = True user_attribute_ignore = tenant_id,tenants user_allow_create = False user_allow_update = False user_allow_delete = False user_enabled_emulation = False user_enabled_emulation_dn = tenant_tree_dn = ou=groups,dc=openstack,dc=org tenant_objectclass = groupOfNames tenant_filter = tenant_id_attribute = cn tenant_name_attribute = ou tenant_member_attribute = member tenant_desc_attribute = description tenant_enabled_attribute = enabled tenant_domain_id_attribute = businessCategory tenant_attribute_ignore = tenant_allow_create = True tenant_allow_update = True tenant_allow_delete = True tenant_enabled_emulation = False tenant_enabled_emulation_dn = role_tree_dn = ou=roles,dc=openstack,dc=org role_objectclass = organizationalRole role_filter = role_id_attribute = cn role_name_attribute = ou role_member_attribute = roleOccupant role_attribute_ignore = role_allow_create = True role_allow_update = True role_allow_delete = True domain_tree_dn = ou=domains,dc=openstack,dc=org domain_filter = domain_objectclass = groupOfNames domain_id_attribute = cn domain_name_attribute = ou domain_member_attribute = member domain_desc_attribute = description domain_enabled_attribute = enabled domain_attribute_ignore = domain_allow_create = True domain_allow_update = True domain_allow_delete = True domain_enabled_emulation = False domain_enabled_emulation_dn = |
編集したら再起動します。
1 |
/etc/init.d/keystone restart |
メモ
データ追加
プロジェクトなど最初必要なものを追加していきます。初めて追加する時は、LAMのツリービューを見ながらやるとデータの所在がわかってよいです。
プロジェクト(ou=groups)
1 2 3 |
TENANT_NAME=admin keystone tenant-create --name=$TENANT_NAME keystone tenant-list |
ユーザ(ou=users)
外道運用ルールでは keystone user-create はせず、LAM上での作成とするため実際にはコマンドは不要ですが、動作確認のために書いておきます。
1 2 3 4 5 |
USER_NAME=OpenStackAdmin keystone user-create \ --tenant-id $(keystone tenant-list | grep " $TENANT_NAME " | awk '{print $2}') \ --name $USER_NAME --pass adminpass --email admin@e.mail --enabled true keystone user-list |
ロール(ou=roles)
管理者と一般ユーザ用のロールを追加しておきます。
1 2 3 4 5 |
keystone role-create --name="admin" keystone role-create --name="KeystoneAdmin" keystone role-create --name="KeystoneServiceAdmin" keystone role-create --name="Member" keystone role-list |
プロジェクト/ユーザ/ロールの関連付け(groupsのcnのさらに上にcnが作成される)
管理者ユーザを全ての固定管理ロールに入れておきます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
keystone user-role-add \ --tenant-id $(keystone tenant-list | grep " $TENANT_NAME " | awk '{print $2}') \ --user-id $(keystone user-list | grep " $USER_NAME " | awk '{print $2}') \ --role-id $(keystone role-list | grep " admin " | awk '{print $2}') keystone user-role-add \ --tenant-id $(keystone tenant-list | grep " $TENANT_NAME " | awk '{print $2}') \ --user-id $(keystone user-list | grep " $USER_NAME " | awk '{print $2}') \ --role-id $(keystone role-list | grep " KeystoneAdmin " | awk '{print $2}') keystone user-role-add \ --tenant-id $(keystone tenant-list | grep " $TENANT_NAME " | awk '{print $2}') \ --user-id $(keystone user-list | grep " $USER_NAME " | awk '{print $2}') \ --role-id $(keystone role-list | grep " KeystoneServiceAdmin" | awk '{print $2}') |
データの確認
1 2 3 4 5 6 7 |
# 全データ slapcat | less # 動作確認。取得できなかったら見直し curl -d '{"auth": {"tenantName": "admin", "passwordCredentials":{"username": "OpenStackAdmin", "password": "rootpass" }}}' \ -H "Content-type:application/json" http://192.168.0.11:35357/v2.0/tokens \ | python -mjson.tool | less |
テストプロジェクト追加
基本的に admin プロジェクトはネットワーク設定やスナップショット編集などをするためのものにして普段は放置し、2つ目以降のプロジェクトをガリガリ使うようにしています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
# プロジェクト追加 TENANT_NAME=test keystone tenant-create --name=$TENANT_NAME # ユーザ名定義だけ。実際の追加はLAMで USER_NAME=member # ユーザロールに追加 ROLE_NAME=Member keystone user-role-add \ --tenant-id $(keystone tenant-list | grep " $TENANT_NAME " | awk '{print $2}') \ --user-id $(keystone user-list | grep " $USER_NAME " | awk '{print $2}') \ --role-id $(keystone role-list | grep " $ROLE_NAME " | awk '{print $2}') # 確認 keystone tenant-list keystone user-list curl -d '{"auth": {"tenantName": "test", "passwordCredentials":{"username": "member", "password": "memberpass" }}}' \ -H "Content-type:application/json" http://192.168.0.11:35357/v2.0/tokens \ | python -mjson.tool | less |
ユーザ追加の際にグループ追加する手順
LAMでユーザを追加したら、OpenStackでも認証できるように、手動で user-role のデータを追加する必要があります。LDAPのデータをKeystoneでも有効にするには、ユーザのbusinessCategoryにdefaultが入っていて、かつ、上記 user-role データが存在する必要があります。それ以外のユーザは OpenStack を触ることができない、ということです。
後片付け
色々終わったら、LDAPユーザを切り替えておきます。さきほども書きましたが、これはお好みで、私はできるだけLDAP管理者権限を撒き散らしたくないのでパスワードを消しておき、読み込みのみでKeystoneで利用するようにしています。
/etc/keystone/keystone.conf
1 2 3 4 5 |
[ldap] url = ldap://192.168.0.11 #user = cn=admin,dc=openstack,dc=org user = uid=OpenStackAdmin,ou=users,dc=openstack,dc=org password = adminpass |
編集したら再起動します。
1 |
/etc/init.d/keystone restart |
LDAPをそこそこ知らないと厳しい設定かもしれませんが、やってみると意外に悪くなく、特に問題なく運用できています。
ただ、FolsomからGrizzlyにするとスキーマが変わって古いデータは使えなかったりしたので、その辺の対応は覚悟しておく必要がありそうです。