Rundeck を Google 認証で使う
Rundeck は認証周りが弱い
リバースプロキシで認証して資格情報を渡す機能がある
Google アカウントを使って認証できるようにする
httpd + Let's Encrypt で TLS
適当な FQDN を割り当て: rundeck.example.com
バーチャルホスト設定: /etc/httpd/vhosts.d/rundeck.example.com.conf
httpd & firewalld
code:bash
sudo yum -y httpd mod_ssl
sudo systemctl start httpd
sudo firewall-cmd --add-service=http --add-service=https --permanent
sudo firewall-cmd --reload
code:/etc/httpd/vhosts.d/rundeck.example.com.conf
省略
Certbot
code:bash
sudo yum install python2-certbot-apache
sudo certbot --apache
# 1: rundeck.example.com
# 2: Redirect
リバースプロキシ
リバースプロキシ設定
code:/etc/httpd/vhosts.d/rundeck.example.com.conf
...
ProxyPass / http://localhost:4440/ retry=60
ProxyPassReverse / http://localhost:4440/
...
https://rundeck.example.com/ にアクセスしてログインできることを確認
Preauthenticated Mode にする
Apache 側から資格を渡して自動ログインする
一時的に管理者権限が筒抜けになるので 443 を閉じる
ssh tunnel + hosts 等でアクセス手段を確保する
code:bash
sudo firewall-cmd --remove-service=https
Apache からリクエストヘッダで適当な資格情報を渡す
code:/etc/httpd/vhosts.d/rundeck.example.com.conf
...
RequestHeader set X-Auth-User foobar
RequestHeader set X-Auth-Roles admin
...
code:bash
sudo systemctl reload httpd
Rundeck 側を Preauthenticated Mode に
code:/etc/rundeck/rundeck-config.properties
# Preauthenticated Mode
rundeck.security.authorization.preauthenticated.enabled=true
rundeck.security.authorization.preauthenticated.userNameHeader=X-Auth-User
rundeck.security.authorization.preauthenticated.userRolesHeader=X-Auth-Roles
code:bash
sudo systemctl restart rundeckd
https://rundeck.example.com/ にアクセスすると管理権限を持つ foobar ユーザーでログイン済みになっている
設定を変更して X-Auth-Roles を渡さなかった場合は Preauthenticated は効かない
この場合元々の JAAS 認証にフォールバックしてログイン画面が表示される
先ほど生成した super でログインすることが可能
JAAS 側で JettyRolePropertyFileLoginModule などを使ってロールだけ認可できないか試したけどダメだった
ポリシー未設定の適当な X-Auth-Roles を渡した場合
そのロールではアクセスでないよという画面になる
例外的に以下のページにはアクセスできる
User Profile
Key Storage
Installed Plugins
Password Utility
ヘッダを正しく管理しないときわめて危険
Google アカウントで認証
Apache HTTP Server で Google 認証を導入
Google アカウントを OP として認証
example.jp ドメインに属しているユーザーのみログイン可能とする
Googleアカウントのメールアドレスを Rundeck のユーザー名とする
ひとまず全ユーザーに admin ロールを与える(!)
Google Cloud Console で Credentials を発行
code:/etc/httpd/vhosts.d/rundeck.example.com.conf
...
# Cookie 暗号化用キー
OIDCCryptoPassphrase <任意の文字列>
# モジュールが維持するブラウザセッションの Cookie 名。既定だと mod_auth_openidc_session なので何となく変える
OIDCCookie session
OIDCProviderMetadataURL https://accounts.google.com/.well-known/openid-configuration
OIDCClientID <Client ID>
OIDCClientSecret <Client Secret>
# mod_auth_openidc のために割り当てた専用の URL
# Rundeck では /auth/redirect が使われていないことを確認
OIDCRedirectURI https://rundeck.example.com/auth/redirect
# Google 側で認証画面を example.com ドメインに絞り込む
OIDCAuthRequestParams hd=example.com
# email claim をユーザー名にするのでスコープに含める
OIDCScope "openid email"
# email claim を REMOTE_USER に設定
OIDCRemoteUserClaim email
# REMOTE_USER をヘッダとしてバックエンドに渡す
OIDCAuthNHeader X-Auth-User
# Rundeck のセッションタイムアウトに合わせる
OIDCSessionInactivityTimeout 900
# 全てのアクセスに認証を要求する
<Location />
AuthType openid-connect
# 認可するドメインを必ず確認する
Require claim hd:example.com
</Location>
# 全ての認証済みユーザーに admin 権限を付与する
RequestHeader set X-Auth-Roles admin
...
code:bash
sudo systemctl reload httpd
443 を戻す
code:bash
sudo firewall-cmd --add-service=https
https://rundeck.example.com/ にアクセスすると Google のアカウント選択画面に
ログインすると Google のメールアドレスで Rundeck に自動ログインしている
ユーザーとロール
このままだと組織のメンバーが全員管理者になる
メールアドレスを参照してログイン可能なユーザーを制限したい
ユーザー毎にロールを管理したい
Authz の領域でユーザーがアクセスできるか認可する
ユーザーに基づいてロールを決めてヘッダを出力する
ユーザー名が必要なので Apache の authorization フェーズより後で処理する必要がある
簡単にユーザーとロールを制限する
数名のユーザー user (/etc/rundeck/user.aclpolicy 作成済み)
数名の管理者 admin
設定ファイルで完結
code:/etc/httpd/vhosts.d/rundeck.example.com.conf
...
# ユーザーとロールの定義
<IfDefine !RUNDESK_USER_EXPR>
Define RUNDESK_USER_EXPR "%{REMOTE_USER} =~ /^(foo|bar|baz|quux)@/i"
</IfDefine>
<IfDefine !RUNDESK_ADMIN_EXPR>
Define RUNDESK_ADMIN_EXPR "%{REMOTE_USER} =~ /^(qux|quux)@/i"
</IfDefine>
<Location />
AuthType openid-connect
# アクセス認可
<RequireAll>
Require claim hd:example.com
<RequireAny>
Require expr ${RUNDESK_USER_EXPR}
Require expr ${RUNDESK_ADMIN_EXPR}
</RequireAny>
</RequireAll>
</Location>
# API は除外
<Location /api/>
Require all granted
</Location>
# ロールをバックエンドに通知
RequestHeader unset X-Auth-Roles early
RequestHeader merge X-Auth-Roles user "expr=${RUNDESK_USER_EXPR}"
RequestHeader merge X-Auth-Roles admin "expr=${RUNDESK_ADMIN_EXPR}"
...
ロール条件式は名前定義しておく。こうすれば Apache 起動パラメータからも挿入可能
RequestHeader の early フェーズで X-Auth-Roles を落とし、ユーザーエージェント側の偽装を防ぐ
RequestHeader merge で保持ロールを積み上げていく
merge はカンマ区切りで Rundeck のロールもカンマ区切り
一応 Rundeck 側の区切り文字は rundeck.security.authorization.preauthenticated.delimiter で設定可能
何かしらの設定ミスでアクセスが通ってロールが空っぽになった場合は組み込み JAAS 認証画面になる
ロールを OP から連携する
id_token にカスタム属性を付与できる OP なら OP で設定して claim で受けることができる (Keycloak など)
その場合は rundeck.security.authorization.preauthenticated.userRolesHeader=OIDC_CLAIM_role みたいに簡単
がっつりユーザーとロールを管理する
TODO
ログアウト
TODO