Ansible AWX でSAML SSO してみた

概要

Ansible AWX でSAML SSOしたときにちょっとつまずいたのでメモを残す。

環境

docker を利用して構築しました。バージョンは2.1.0 イメージは

普通に上記イメージを利用して構築すると、AWX のWebUIはコンテナ内で8052ポートで待ち受けます。

ここに443ポートで待ち受けるロードバランサから接続する割と一般的かな?と思う構成です。

つまずいた点

とても単純で、IdP側に設定をして、いざSSOしてみると https://<awxhost>:8052 instead of https://<awxhost> とメッセージが出るわけです。 つまり、 443ポートに着信してしかるべきなのに、8052ポートに着信してるからおかしいよと警告が出るんですね。

解決策

これを修正すべく、docker run時に -p<外部公開ポート>:443 とし、コンテナ内のnginxの設定を 443ポートでhttpを待ち受けるように設定しkill -HUP nginx で設定をリロードすることで、コンテナ内に着信したとき、ちゃんと443ポートが利用され、事なきを得る事が出来ました。

中期的にはDockerfileを作成し、上記修正をいれたイメージをビルドして利用することで解決できそうです。

根本的には、ちゃんと原因をつかんで修正することが大事だと思いつつ、時間がないのでそこは手を出せていません。

ちなみになんですが、ポート番号が変になることを承知の上で awx/nginx.conf at devel · ansible/awx · GitHub X-Forwarded-Port 443が設定されているのですよね。

この設定をアプリケーション側がちゃんと読んでいないのでは?と疑っております。

ansible module mysql_user について

これは Ansible Blogger 2018 (sponsored by Red Hat) Advent Calendar 2018 - Qiita 2日目の記事です。

ansible module mysql_user

DBもちゃんと管理したい! という話は当然のようにあって、 複数DBに同じユーザがいてほしい! だとか、 残念ながらあの人いなくなるので、全DBから確実にユーザ削除したい! だとか、 よくある話だと思います。

そんなよくある話を(mysqlに限って)解決してくれるのが ansible の mysql_user モジュールです。

詳しいドキュメントは mysql_user - Adds or removes a user from a MySQL database. — Ansible Documentation をみましょう。

で終わってはあんまり意味がないので、便利ポイントを絞って説明します。

option update_password

update_password というオプションがあります。

通常、個人ユーザを作成したら、パスワードの管理はその個人に任せます。というか任せてないとなんかおかしい気がします。

そんな時はこのオプションを on_create に設定することで、既にユーザが作成されている場合は、パスワードを変更しないようにできます。

こうすることで、初期パスワードを適当に設定して、ユーザに通知し、パスワード変更を含め、ユーザに管理をゆだねることができるようになります。

とても便利。

ユーザがパスワードを忘れてしまった場合は、ここをデフォルトのalwaysにして、パスワードを初期化することで再設定を促せます。

とても便利。

more security

ところで、上述のパスワード、ユーザごとのものであれば、ユーザがパスワードを変更するまでが寿命ですが、 例えばアプリケーションが利用するユーザなどは、設定するパスワードは一定期間有効となります。

そんなデータはきちんと扱わないと危険ですよね、そんな重要なデータはまずは ansible-vaultを使って暗号化して保管しておきましょう。

Ansible Vault — Ansible Documentation

また、そんな重要なデータが実行時にログとして出てくると、とても、つらいですよね、 そんな時はno_log という実行時にログ出力しなくなるオプションがあるのでそれを利用しましょう。 no_logオプションはmysql_user固有のオプションではなく、registerなどと同じく一般的なオプションです。

なので

- name: "sample user"
  no_log: true
  mysql_user:
    user: sample
    password: "{{ vault-sample-password }}"
    state: present
    host: localhost

たとえばこんな風に書きます。

まだ実装されてない、実装されると便利そうな機能

そもそもDBで個別にパスワード管理したくないよね?pluginって仕組みあるし! というのは割と誰しも考える事なのではないかと思いますが、今のところ認証pluginを利用する方法は実装されていません。

認証pluginを利用するためには with を用いるのですが、 mysql_user モジュールは mariadb でも利用されることを想定しています。 mariadbにも認証pluginを利用する仕組みはあるのですが、withではなくvia を利用します。

というような事情があったりするのが原因の一つです。

add support for auth_socket by verwilst · Pull Request #3587 · ansible/ansible-modules-core · GitHub

Add plugin as parameter for mysql_user, to allow use of auth_socket plugin · Issue #27179 · ansible/ansible · GitHub

バージョンをチェックして、どのバージョンであればどの記載方法を受け付けるのか といったことを網羅的に調べて、 モジュール内で適切に分岐させるという必要があり 割と面倒ですし、テストも結構大変そうだなぁという気はしていますが、 求めてる人はそこそこいそうなので、挑戦すると喜ばれるのでは?

ISC Kea 1.1 を冗長構成で使ってみる

ISC Kea の 1.4で冗長化のための設定が増えました。

しかし、主要なディストリビューションでは、パッケージマネージャによりインストールされるKeaのバージョンは1.1です。

そこで、そもそもKeaではバックエンドにRDBMSが指定できるので、冗長化しなくても何となく冗長化できるのではないか?と試してみました。

具体的には、Kea を2台たてて、別にMySQLを用意し、2台のKeaがともに同じMySQLを見に行くように設定します。

ルータ等では、DHCPのRelay先として2台のKeaを両方とも指定します。

こうしておくと

クライアントからのDISCOVERは2台のKeaに届き、2台のKeaからOFFERがクライアントに送られますが、

クライアント側では早く届いたほうのOFFERに反応し、REQUESTを送信します。

REQUESTは2台のKeaに届きますが、REQUESTにはサーバ指定が入っているので、片方のKeaのみがACKを返します。

またACKを返す際にしかMySQLには書き込まれないので、結果、Lease情報にはちゃんとクライアント1台につき1つのエントリしか作成されません。

負荷分散されるわけではありませんので、処理能力は1台分ですが、ひとまず、片方が倒れてもクライアント側でIPアドレスが取得できない、という事態にはならずに済みそうです。

Kea のバックエンドをRDBMSにする注意点として、RDBMSとの接続が切れると、再接続をするのではなく、そのままKeaがエラーにより終了してしまいます。

ですので、エラーにより終了した際は、自動で再起動するような対処をしておかないと辛いことになります。

これを書いた後でレポートを見つけてしまった。