概要
k8s に web アプリケーションをデプロイし、Basic 認証を設定したいことがあるでしょう。nginx-ingress で簡単に設定する方法について説明します。
前提
- 作業環境は Ubuntu-20.04 です
- apache2-utils パッケージが作業環境にインストール済です
- kubectl コマンドが作業環境にインストール済です
設定方法
パスワードファイルの作成
apache2-utils パッケージがインストール済であれば htpasswd コマンドが利用できます。
htpasswd -nb USER PASSWORD | awk 'NR==1{print "auth="$0}' > tmpfile
kubectl -n NAMESPACE delete secret basic-auth
kubectl -n NAMESPACE create secret generic basic-auth --from-env-file=./tmpfile
rm -f tmpfile
NAMESPACE にはアプリケーションがデプロイされている k8s のネームスペースを、USER, PASSWORD にはベーシック認証のユーザー名、パスワードを入力して下さい。
ここでは Secret リソースの名前として basic-auth を、Secret のデータ名として auth を指定していますが、これらの名前は任意ですので好きなものを指定してください。ただし前者は後で使用しますので、名前を変更したら適宜後述する部分も書き換えて下さい。
nginx-ingress の設定
アプリケーション用としてデプロイ済の Ingress リソースに対して、以下の annotation を追加します。
nginx.ingress.kubernetes.io/auth-realm: Authentication Required - App
nginx.ingress.kubernetes.io/auth-secret: basic-auth
nginx.ingress.kubernetes.io/auth-secret-type: auth-file
nginx.ingress.kubernetes.io/auth-type: basic
auth-realm には認証レルムを設定します。auth-secret には Secret リソースの名前(上で指定したもの)を指定します。auth-type にはベーシック認証である basic を指定します。auth-secret-type には auth-file を指定します。ここを間違って auth-map としてしまうと、Secret リソースが nginx-ingress-controller コンテナにコピーされた時に以下のような中身になってしまいますので注意が必要です。
auth:user:ENCRYPTED_PASSWORD
この場合、ユーザー名は auth、パスワードを暗号化したものが user:ENCRYPTED_PASSWORD になりますが、この文字列は decrypt できないので絶対に認証が通ることはないでしょう。
以上で設定は終了となります。Ingress リソースに設定されているホスト名にアクセスするとベーシック認証がかかっていることを確認することができるでしょう。
おまけ
nginx.conf の状態
上記 annotation を設定すると、nginx-ingress-controller の nginx.conf の該当ドメインに対する部分に次の設定が記載されます。
auth_basic "Authentication Required - App";
auth_basic_user_file /etc/ingress-controller/auth/NAMELIST-b550d251-c940-4823-9ad5-817dbe128777-732ddfae-a1b4-429a-868b-df6b3a8ccc9d.passwd;
なおファイル名のハッシュ値みたいなのは勝手に生成されるものだと思います。
auth_basic には認証レルムが、auth_basic_user_file にはベーシック認証のファイル名が指定されています。なお後者の中身は Secret リソースのデータ部分を Base64 デコードされたものが入っています。
auth-map について
ベーシック認証に複数のアカウントを設定したい場合があるかと思います。この場合、複数行記載された .htpasswd ファイル全体を Secret リソースのデータにし、上記同様に auth-secret-type として auth-file を指定することで設定ができます。
別の方法としては以下のような方法もあります。予めアカウント情報を以下のように用意してあったとします。
USER1:PASSWORD1
USER2:PASSWORD2
:> tmpfile
for row in $(cat auth_file.txt)
do
auth=$(echo ${row} | sed 's/:/ /')
eval "htpasswd -nb ${auth}" | sed 's/:/=/' | grep -v ^$ >> tmpfile
done
kubectl -n NAMESPACE delete secret basic-auth
kubectl -n NAMESPACE create secret generic basic-auth --from-env-file=./tmpfile
こうすると Secret リソースは以下のようになります。
apiVersion: v1
kind: Secret
metadata:
name: basic-auth
namespace: NAMESPACE
type: Opaque
data:
USER1: BASE64ENCRYPTED_ENCRYPTED_PASSWORD1
USER2: BASE64ENCRYPTED_ENCRYPTED_PASSWORD2
このようにデータ部分をユーザー名ごとに設定した Secret リソースとなります。この時 auth-secret-type には以下のように
nginx.ingress.kubernetes.io/auth-secret-type: auth-map
と指定することになります。