なんか監査的なアレでMySQLの共通アカウントを卒業したい的な需要があるようだったのでkikumotoさんのスライドと公式マニュアルをChromeに翻訳してもらいながらガン見しつついつもどおりググりまくりつつやってみましたので備忘録しておきます。
hashicorpvaultの詳しい話はほかのサイトを見たらいいと思いますがザックリいうと暗号化データを管理してくれる仕組みです。
ansibleのvaultやgoogleのvaultとは違うやつです。
参考
http://kikumoto.hatenablog.com/entry/2016/07/30/112618
http://qiita.com/chroju/items/5f982bafecd3a1c36a9b
http://qiita.com/yunano/items/bfaac7868ce4fb946ee5
https://github.com/hachiojipm/yapcasia-8oji-2016mid-timetable/issues/26
http://kiririmode.hatenablog.jp/entry/20150429/1430279218
https://www.vaultproject.io/docs/secrets/index.html
https://www.vaultproject.io/docs/secrets/databases/index.html
RDSまわりのアカウント権限のマニュアル
今回試した構成
- ストレージバックエンド:ローカルストレージ(filesystem)、HAなし
(HAサポートしてるのは、Consul、DynamoDB、Etcd、Zookeeper) - 認証バックエンド:ldap(今回はテストのためだけのシングル構成でデータもグループ1個用意しただけ)
- SecretBackend:MySQL(RDS)。ldapのグループに基づいたpolicyからMySQLアカウントに権限を割り当てられる
というかんじ。ちなみにhttpで待ち受けてるのでHA仕込んだらスレーブはマスタに更新をリダイレクトする挙動らしい。
vaultのinstall
hashicorp製品はGoで作られてるのでアーキテクチャに合ったバイナリをダウンロードしてきてpathを通すと使える。
/usr/local/sbinあたりに置く。
$ wget https://releases.hashicorp.com/vault/0.8.2/vault_0.8.2_linux_amd64.zip
$ file vault_0.8.2_linux_amd64.zip
$ unzip vault_0.8.2_linux_amd64.zip
$ sudo ln -s /usr/local/src/vault /usr/local/sbin/vault
$ sudo which vault
$ file vault
$ vault -help
vaultのストレージバックエンドの設定と起動
centos6だったのでこちらの参考サイトからたどって落ちてた起動スクリプトを保存してつかわせていただきました。
# vi /etc/init.d/vault
# chmod +x /etc/init.d/vault
# chkconfig --add vault
# chkconfig --list vault
起動スクリプトに定義されてるpathに設定ファイルを定義して起動
# vi /etc/vault.d/vault.hcl
storage "file" {
path = "/root/vault/data"
}
listener "tcp" {
address = "127.0.0.1:8200"
tls_disable = 1
}
# service vault start
filesystemならEBSなどディスク分離してマウントしたとこがいいのかもしれない
※クイックスタートのvault server -dev
だとメモリにしか保存されない
vaultの環境変数の定義
export VAULT_ADDR='http://127.0.0.1:8200'
これ↑をやらないとvaultコマンド打ってもエラーになる。
vaultのunseal
# vault init
と打つとunsealkeyとrootのトークンなどが表示されて後で使うので必ず記録する
# vault unseal
これを3回打って3つの鍵を持ち寄ってシールド解除する
# vault status
Sealed: false #シールド解除された状態
rootのトークンで初回のauth
# vault auth 359ac453-53e5-b289-4dc9-5d9838773***
ldapのデータのグループの仕込みなど
オブジェクトクラスposixGroupにしてたのでmemberUidを定義。
https://fumiyas.github.io/2015/12/12/group-access.openldap-advent-calendar.html
# ldapsearch -x -D "cn=Manager,dc=hoge,dc=local" -W -b "cn=test01,ou=Group,dc=hoge,dc=local"
dn: cn=test01,ou=Group,dc=hoge,dc=local
objectClass: posixGroup
objectClass: top
cn: system
cn: test01
gidNumber: 1000
# vi add_group_20170914.ldif
dn: cn=test01,ou=Group,dc=hoge,dc=local
changetype: modify
add: memberUid
memberUid: test02
memberUid: test
# ldapmodify -x -D "cn=Manager,dc=hoge,dc=local" -w `cat /root/.ldap_pass` -f add_group_20170914.ldif
modifying entry "cn=test01,ou=Group,dc=hoge,dc=local"
# ldapsearch -x -D "cn=Manager,dc=hoge,dc=local" -W -b "cn=test01,ou=Group,dc=hoge,dc=local"
dn: cn=test01,ou=Group,dc=hoge,dc=local
objectClass: posixGroup
objectClass: top
cn: system
cn: test01
gidNumber: 1000
memberUid: test02
memberUid: test
mysql(RDS)側のGrantOptionつきユーザの作成
作成できるアカウント以上の権限を必要とする模様。
GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, PROCESS, REFERENCES, INDEX, ALTER, SHOW DATABASES, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER ON *.* TO 'vault'@'%' IDENTIFIED BY 'xxxxxxxx' WITH GRANT OPTION;
RDSはALLはつかえなくて制限されており以下のリンク先に可能な権限がかいてありました。
http://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/UsingWithRDS.MasterAccounts.html
使用するAuth Backendを有効化、ldapを有効にする・接続設定
# vault auth-enable ldap
Successfully enabled 'ldap' at 'ldap'!
(ldapsは実際やるなら必須だけどもテストなので389で失礼。)
# vault write auth/ldap/config binddn="cn=Manager,dc=hoge,dc=local" bindpass="********" url="ldap://ldap01" userattr=uid userdn="ou=People,dc=hoge,dc=local" groupdn="ou=Group,dc=hoge,dc=local" upndomain="HOGE.LOCAL" insecure_tls=true starttls=false discoverdn=true
Success! Data written to: auth/ldap/config
# vault read auth/ldap/config
Key Value
--- -----
binddn cn=Manager,dc=hoge,dc=local
bindpass ********
certificate
deny_null_bind true
discoverdn true
groupattr cn
groupdn ou=Group,dc=hoge,dc=local
groupfilter (|(memberUid={{.Username}})(member={{.UserDN}})(uniqueMember={{.UserDN}}))
insecure_tls true
starttls false
tls_max_version tls12
tls_min_version tls12
upndomain HOGE.LOCAL
url ldap://ldap01
userattr uid
userdn ou=People,dc=hoge,dc=local
The following warnings were returned from the Vault server:
* Read access to this endpoint should be controlled via ACLs as it will return the configuration information as-is, including any passwords.
データベースのSecretBackendのマウント
# vault mount database
Successfully mounted 'database' at 'database'!
# vault mounts
Path Type Accessor Plugin Default TTL Max TTL Force No Cache Replication Behavior Description
cubbyhole/ cubbyhole cubbyhole_e74259bf n/a n/a n/a false local per-token private secret storage
database/ database database_7c483728 n/a system system false replicated
secret/ generic generic_5203937e n/a system system false replicated generic secret storage
sys/ system system_81574fb0 n/a n/a n/a false replicated system endpoints used for control, policy and debugging
MySQLのSecretBackendを実装
DBへの接続設定とroleの登録とポリシーの登録
さっき作ったアカウントの接続情報を設定する。role名がアカウントに含まれて長くなるので短めに指定。
# vault write database/config/mysql \
> plugin_name=mysql-rds-database-plugin \
> connection_url="vault:xxxxxxxx@tcp(vault-rds01:3306)/" \
> allowed_roles="read, mngr"
# vault read database/config/mysql
Key Value
--- -----
allowed_roles [read mngr]
connection_details map[connection_url:vault:xxxxxxxx@tcp(vault-rds01:3306)/]
plugin_name mysql-rds-database-plugin
※plugin_nameの指定は専用のやつでないとRDSならmysql-rds-database-plugin指定しないとDBアカウント名の字数制限のための刈込を勝手にやってくれる挙動にならなさそうであった。
※接続先増加したときの挙動は確かめてみないとフメイ
ldapグループとvaultPolicyを紐づける設定
読み込み専用のroleを定義
# vault write database/roles/read \
> db_name=mysql \
> creation_statements="CREATE USER '{{name}}'@'%' IDENTIFIED BY '{{password}}';GRANT SELECT ON *.* TO '{{name}}'@'%';" \
> default_ttl="1h" \
> max_ttl="24h"
Success! Data written to: database/roles/read
ホストの定義は固定で@'%'
以外にはできない模様です。
それ以外のパワーユーザーのroleを定義
# vault write database/roles/mngr \
> db_name=mysql \
> creation_statements="CREATE USER '{{name}}'@'%' IDENTIFIED BY '{{password}}';GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, PROCESS, REFERENCES, INDEX, ALTER, SHOW DATABASES, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER ON *.* TO '{{name}}'@'%';" \
> default_ttl="1h" \
> max_ttl="24h"
Success! Data written to: database/roles/mngr
定義されたroleを確認
# vault read database/roles/read
Key Value
--- -----
creation_statements CREATE USER '{{name}}'@'%' IDENTIFIED BY '{{password}}';GRANT SELECT ON *.* TO '{{name}}'@'%';
db_name mysql
default_ttl 3600
max_ttl 86400
renew_statements
revocation_statements
rollback_statements
# vault read database/roles/mngr
Key Value
--- -----
creation_statements CREATE USER '{{name}}'@'%' IDENTIFIED BY '{{password}}';GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, PROCESS, REFERENCES, INDEX, ALTER, SHOW DATABASES, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER ON *.* TO '{{name}}'@'%';
db_name mysql
default_ttl 3600
max_ttl 86400
renew_statements
revocation_statements
rollback_statements
ポリシーの登録
https://www.vaultproject.io/docs/concepts/policies.html
defaultポリシーをみてみる
# vault read sys/policy/default
ポリシーのリストをみてみる
# vault read sys/policy
Key Value
--- -----
keys [default root]
policies [default root]
ポリシーを定義して登録
# vi db-read.hcl
---
path "database/creds/read" {
capabilities = ["read"]
}
---
# vi db-mngr.hcl
---
path "database/creds/mngr" {
capabilities = ["read"]
}
---
# vault policy-write dbread db-read.hcl
# vault policy-write dbmngr db-mngr.hcl
# vault read sys/policy
Key Value
--- -----
keys [dbmngr default dbread root]
policies [dbmngr default dbread root]
vaultからldap認証してmysqlアカウント発行
# vault auth -method=ldap username=test02
Password (will be hidden):
Successfully authenticated! You are now logged in.
The token below is already saved in the session. You do not
need to "vault auth" again with the token.
token: 7f0702b4-5b54-c819-f1d2-80baedb1****
token_duration: 2764800
token_policies: [db-poweruser default]
アカウントデータ取得
一回rootのトークンで認証しなおしてからアカウントデータを取得する
# vault auth 359ac453-53e5-b289-4dc9-5d9838773***
# vault read database/creds/mngr
Key Value
--- -----
lease_id database/creds/mngr/37e0f265-f0d9-1731-c4f4-2eb723cd7xxx
lease_duration 1h0m0s
lease_renewable true
password A1a-2907p9y23xu7qxxx
username v-mngr-v7s8s4ww6
vault read
した時点でアカウントが作成される仕様。
ログイン、期限切れとrenew
取得できたid/passでDBに接続する
$ mysql -u v-mngr-v7s8s4ww6 -p -h vault-rds01
lease_durationを過ぎるとアカウントは容赦なく削除される
期限が切れる前ならrenewで更新
期限が切れたらもう一回authとreadして再発行、となる模様(同じ名前にはならない)
# vault renew database/creds/mngr/85732db5-d8b6-d267-3768-a51e58a8fe4d 30
※renewのあとにreadで出てきたlease_idと伸ばしたい秒数を指定する。
期限変えたい場合はroleの設定しなおすときに一緒にdefault_ttlとmax_ttlを指定する。
とりあえず以上です。
(複数DBの場合のDBアカウントの共有方法の確認とストレージバックエンドのHAなどの残課題有)