0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

IngressでWebアプリの認証を実現する方法

Last updated at Posted at 2025-12-06

はじめに

KubernetesのIngressは、外部からのHTTP/HTTPSリクエストをホスト名やパスに応じて適切なServiceへ振り分けるリソースです。Ingressは標準のYAML設定に加え、annotationを設定することでコントローラー固有の多様な機能を利用できます。
今回は、NGINX Ingress Controllerのannotationを活用し、Webアプリへのアクセスに認証機能を組み込む手順を紹介します。

要約

Ingressで提供するWebアプリに認証機能を導入するには、annotationに以下のような設定を追加します。

metadata:
  ...
  annotations:
    nginx.ingress.kubernetes.io/auth-signin: "https://[hostname][:port]/login"
    nginx.ingress.kubernetes.io/auth-url: "https://[hostname(または別名)][:port(または別ポート)]/auth-check"
    ...
  • [hostname] は、Webアプリのホスト名と一致する必要があります
    • ただし、nginx.ingress.../auth-url のannotationに指定するホスト名は、NGINX Ingress Controllerが到達可能であれば、Webアプリと異なっていても問題ありません
  • nginx.ingress.kubernetes.io/auth-url
    • リクエストするクライアントが認証済かどうかをチェックするパスを指定します
  • nginx.ingress.kubernetes.io/auth-signin
    • ログインするパスを指定します

全体構成の説明

図のように、リバースプロキシとしてNGINX Ingress Controllerを用い、認証用WebアプリとメインのWebアプリへ転送します。

85.drawio.png

クライアントがメインのWebアプリにアクセスした際、NGINX Ingress Controllerはまず認証用Webアプリの認証確認用パスへリクエストを送信します。認証済みであれば通常通りメインのWebアプリのレスポンスが返され、未認証の場合にはログインページへ誘導されます。この仕組みを動かすには、認証用Webアプリが「認証チェック用エンドポイント」と「ログインページ」を提供していることが必要です。

外部のIdPが利用できる場合は、以下の記事で紹介されているように OAuth2 Proxy を使うことで、自前で認証機能を実装せずに済みます。

しかし本記事では外部IdPは使用せず、筆者が自前で作成した簡易的なフォーム認証アプリを利用して仕組みを説明します。

とりあえず動かしてみたい方

以下の ingress-auth-with-tilt リポジトリをcloneしてセットアップし、tilt up を実行してみてください。

事前準備

前提条件

  • Kubernetesクラスターが構築済であること
  • kubectl, helm, helmfile コマンドが使えること

認証用Webアプリの準備

以下のパスを用意している認証用Webアプリが必要です。

  • ログイン用(例:/login
    • ログインに成功したらセッションCookieをクライアントに返す
  • 認証チェック用(例:/auth-check
    • クライアントの認証状態を確認する。認証されていない場合はUnauthorized(401)を返す

今回は、私が作成した以下の「なんちゃってフォーム認証アプリ」をDockerコンテナで起動します。

以下は実行コマンドの例です。

docker run -d \
--name ts-form-auth-webapp-web \
-p 3000:3000 \
ghcr.io/showchan33/ts-form-auth-webapp-web:v1.0

Dockerが使えない場合は、ts-form-auth-webapp-webのGitHubリポジトリのREADMEをもとにセットアップして、Webアプリを起動してください。

Webブラウザで、
http://localhost:3000/login

にアクセスすると、ログインページが表示されます。

login-form.png

User ID は user1、Password は pass1 と入力して Login ボタンを押下すると、ログインを完了します。

after-login.png

ちなみに、http://localhost:3000/auth-check にアクセスすると現在の認証状態がわかります。Webブラウザには出てきませんが、認証OKならば200、NGなら401のステータスコードがクライアントに返されています。

注意点

以後に記載する内容を実現するには、認証用WebアプリはKubernetesクラスターと同じホストで起動する必要があります。例えばEKS等のマネージドなクラスターを利用する場合、上記の方法だと同じホストに認証用Webアプリを起動するのは難しいはずです。その場合、本記事での説明は割愛しますが、認証用WebアプリをKubernetesのPodで起動して、ServiceやIngress等のリソースを使ってクライアントからアクセスできる状態にしてください。

NGINX ingress controller のインストール

続いて、Kubernetesクラスターに NGINX ingress controller をインストールします。本記事では、Helmfileを使ってインストールする方法を紹介します。

まずは、以下のHelmfileを用意します。

helmfile-ingress-nginx.yaml
repositories:

- name: ingress-nginx
  url: https://kubernetes.github.io/ingress-nginx

releases:

- name: ingress-nginx
  namespace: ingress-nginx
  createNamespace: true
  chart: ingress-nginx/ingress-nginx
  version: 4.14.0

以下がインストールコマンドです。

helmfile apply -f helmfile-ingress-nginx.yaml

しばらくすると、各種リソースがデプロイされます。

$ kubectl get ingressclasses
NAME    CONTROLLER             PARAMETERS   AGE
nginx   k8s.io/ingress-nginx   <none>       81s
$ kubectl get deploy -n ingress-nginx
NAME                       READY   UP-TO-DATE   AVAILABLE   AGE
ingress-nginx-controller   1/1     1            1           25s
$ kubectl get svc -n ingress-nginx
NAME                                 TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)                      AGE
ingress-nginx-controller             LoadBalancer   10.108.38.178   <pending>     80:32553/TCP,443:32142/TCP   47s
ingress-nginx-controller-admission   ClusterIP      10.98.178.88    <none>        443/TCP                      47s

この例では、以下で NGINX ingress のエンドポイントにアクセス可能です。

  • http://[hostname]:32553
  • https://[hostname]:32142 (今回は使わない)

メインのWebアプリのデプロイ

続いて、認証を必要とするメインのWebアプリをデプロイします。本記事ではnginxのコンテナをデプロイしますが、お好きなWebアプリのコンテナを使っていただいて問題ないです。

kubectl create deployment nginx --image=nginx --replicas=1
kubectl expose deployment nginx --port=80 --target-port=80 --name=nginx

全体構成の図を再掲すると、ここまでで真ん中のing(Ingressリソース)以外が出来ている状態です。

85.drawio.png

認証用WebアプリにプロキシするIngressリソースの作成

仕上げに、以下のマニフェストでIngressリソースを作成します。

auth-check.ing.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: auth-check-ingress
  annotations:
    nginx.ingress.kubernetes.io/auth-url: "http://[hostname]:3000/auth-check"
    nginx.ingress.kubernetes.io/auth-signin: "http://[hostname]:3000/login"
spec:
  ingressClassName: nginx
  rules:
  - http:
      paths:
      - backend:
          service:
            name: nginx
            port:
              number: 80
        path: /
        pathType: ImplementationSpecific

以下の2つのannotationを付与しているのがポイントです。

  • nginx.ingress.kubernetes.io/auth-url
    • リクエストするクライアントが認証済かどうかをチェックするパスを指定します
  • nginx.ingress.kubernetes.io/auth-signin
    • ログインするパスを指定します

両方とも、「認証用Webアプリの準備」でデプロイしたWebアプリにアクセスするパスです。

このマニフェストを元に、Ingressリソースをデプロイします。

kubectl apply -f auth-check.ing.yaml

リソースが正常に作成されたことを確認します。

$ kubectl describe ingress auth-check-ingress
Name:             auth-check-ingress
Labels:           <none>
Namespace:        default
Address:
Ingress Class:    nginx
Default backend:  <default>
Rules:
  Host        Path  Backends
  ----        ----  --------
  *
              /   nginx:80 (10.0.0.157:80)
Annotations:  nginx.ingress.kubernetes.io/auth-signin: http://[hostname]:3000/login
              nginx.ingress.kubernetes.io/auth-url: http://[hostname]:3000/auth-check
Events:
  Type    Reason  Age   From                      Message
  ----    ------  ----  ----                      -------
  Normal  Sync    17s   nginx-ingress-controller  Scheduled for sync

試しに、Ingressのエンドポイント
http://[hostname]:32553
にアクセスしてみます。

本来ならばNGINXのサンプルページが表示されますが、annotationの設定が効いて、以下のように認証ページにリダイレクトされます。

login-redirect.png

リダイレクトURLには、以下のように rd のクエリが付いています。

http://[hostname]:3000/login?rd=http://[hostname]:32553%2F

これは「認証後にどのURLへ戻すか」を示すためのパラメータで、その値は先ほどアクセスを試みた http://[hostname]:32553%2F になっています。どうやら、NGINX Ingressのデフォルトでこのクエリ文字列をつけてくれるようです。

ユーザID(user1)とパスワード(pass1)を入力すると、

login-redirect-input.png

認証が完了してNGINXのサンプルページにリダイレクトされます。

nginx.png

これで、認証を必要とするWebアプリケーションが作れているのを確認できました。

注意点ですが、クエリ rd に書かれたURLにリダイレクトするには、認証用Webアプリ側の実装でクエリ文字列をパースして値を取得し、リダイレクト先として指定する必要があります。私が作った「なんちゃってWeb認証アプリ」では、以下の箇所(55,59,71,77行目あたり)でこれを実装しています。

おわりに

NGINXの設定ファイルで同様の仕組みを実現する場合は、auth_request ディレクティブなどを用いた細かな設定が必要になります。一方、Ingressを利用すれば、必要なannotationを2つ追加するだけで同じ構成を簡潔に実現できます。機会があれば、ぜひIngressのannotationを活用してみてください。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?