NGINX Full Version

Kubernetes向けOpenID Connect認証の実装

ランサムウェアやボットによる攻撃が増加傾向にある今日、アプリやAPIの安全性を確保することがいかに重要であるかは、様々な場所で論じられてきました。Webアプリケーションファイアウォール(WAF)のような仕組みとともに、ユーザーIDの認証と認可の実装は、ビジネスアプリケーションを保護するための重要な方法です。

認証と認可を実装する最もシンプルな方法は、アプリケーション自体に実装することです。ユーザー数が少なく、アプリを頻繁に更新する必要がない場合には有効ですが、規模が大きくなるとこの方法では管理が難しくなります。各々のアプリに異なるアカウント名とパスワードを設定すると、覚えられずにログイン時に「ユーザー名またはパスワードが正しくありません」というメッセージが表示され、簡単に推測できる「abc123」のような安全でない解決策に頼るケースがでてきます。また、パスワードが書かれたメモを飾っているモニターを見たことがあります。

シングルサインオン(SSO)の技術は、これらの問題を部分的に解決するために、すべての別々のユーザー名とパスワードを排除し、1つの認証情報のセットを使用することができます。ユーザーは、IDプロバイダー(IdP)に一度サインインするだけで、多くのアプリケーションにアクセスできるようになります。しかし、開発者は、アプリケーションにSSOシステムとのインターフェイスのコードを含める必要があり、特にアプリケーションが複雑化すると、非常に困難になる可能性があります。

組織が規模を拡大し、急増するユーザーベースの要件を満たす必要があるため、認証や認可など、アプリの機能に特化しない要件をアプリケーション層からオフロードすることが重要になります。Kubernetes で認証と認可を集中管理する理想的な場所は Ingress Controllerで、このコントローラーはクラスタに入るすべてのトラフィックを精査し、適切なサービスにルーティングすることができます。これにより、開発者は認証ロジックを構築、維持、複製する負担から解放され、ネイティブのKubernetes APIを使用してIngress層で簡単にSSO技術を活用することができるようになります。

このブログでは、NGINX PlusベースのNGINX Ingress ControllerがOIDCのRelaying Partyとして動作し、事前に設定したOktaをIDプロバイダー(IdP)と連携させたOIDC Authorization Code Flowをサポートする本格的なSSOソリューションの実装方法を紹介します。

注:この機能は、NGINX Open SourceベースのNGINX Ingress Controllerでは使用できません。

前提条件

本ブログでは、Kubernetes環境での運用経験がある方を想定しています。また、以下の環境をご準備いただく必要があります。

IdPの事前設定

クラウドサービスは、どこで取得されたユーザーIDであるか、そしてユーザーの識別情報の確認をしなければなりません。これが、IdPが必要となるポイントです。IdPは、デジタルIDを安全に管理・保管し、攻撃者がIDを盗んでユーザーになりすますことができないようにします。

このセクションでは、Okta CLIを使用して、OktaをIdPとして事前設定し、Oktaの「app integration」を作成します。

  1. okta login コマンドを実行し、Okta Developer AccountでOkta CLIの認証を行います。プロンプトでOktaドメインとAPIトークンを入力します。

    $ okta login
    Okta Org URL: https://your-okta-domain
    Okta API token: your-api-token
  2. 「app integration」アプリ統合を作成します。

    $ okta apps create --app-name=mywebapp --redirect-uri=http[s]://ingress-controller-hostname/_codexch
    • --app-name は、アプリケーション名を定義します(ここでは、mywebapp)。
    • --redirect-uri は、サインインのリダイレクト先URIを定義します(ここでは、ingress-controller-hostname/_codexch)。
  3. プロンプトの表示に従って、まず1(「Webアプリケーション」を表す項目)を選択し、次に5(「その他」を示す項目)を選択し、アプリケーションの種類を指定します。

    Type of Application
    (The Okta CLI only supports a subset of application types and properties):
    > 1: Web
    > 2: Single Page App
    > 3: Native App (mobile)
    > 4: Service (Machine-to-Machine)
    Enter your choice [Web]: 1
    Type of Application
    > 1: Okta Spring Boot Starter
    > 2: Spring Boot
    > 3: JHipster
    > 4: Quarkus
    > 5: Other
    Enter your choice [Other]: 5
    Configuring a new OIDC Application, almost done:
    Created OIDC application, client-id: 0oa1mi...OrfQAg5d7

NGINX Ingress Controllerの設定

NGINX PlusベースのNGINX Ingress Controllerを、ユーザーを認証するOIDCのRelaying Partyとして設定します。

クライアントクレデンシャルのシークレットを定義

セキュリティ上の理由から、OIDCポリシーオブジェクトにクライアントシークレットをハードコードすることはサポートされていません。その代わりに、クライアントシークレットのbase64エンコード値を含むデータでKubernetesシークレットを作成します。

apiVersion: v1
kind: Secret
metadata:
  name: oidc-secret
type: nginx.org/oidc
data:
  client-secret: base64-encoded-value-of-client-secret 

そして、Secretを含むYAMLファイル(ここではclient-secret.yaml)を適用します。:

$ kubectl apply –f client-secret.yaml

Auth Endpointsの取得

OAuth 2.0およびOpenID Connect APIを使用して、Oktaが認証サーバで公開しているエンドポイントに関する情報を取得します。

ローカルマシンで以下のコマンドを実行し、Oktaのエンドポイントに関する情報を出力してください。サンプル出力に示されているauthorization_endpointtoken_endpoint、およびjwks_uriの値に注意してください。これらは次のセクションで使用します。

$ curl -i https://your-okta-domain/.well-known/openid-configuration
{
    "authorization_endpoint": "https://your-okta-domain/oauth2/v1/authorize",
    ...
    "jwks_uri": "https://your-okta-domain/oauth2/v1/keys",
    ...
    "token_endpoint": "https://your-okta-domain/oauth2/v1/token",
 ...
 }

NGINX Ingress OIDCポリシーの定義

NGINX Ingress Controller 1.10.0でOIDCベースの認証がサポートされるようになりました。詳しくは、ブログ「Easy and Robust Single Sign‑On with OpenID Connect and NGINX Ingress Controller」をご覧ください。

NGINX Ingress ControllerのOIDC認証の実装では、Policyオブジェクトを使用します。これは、NGINX Ingress ControllerでOIDCポリシーを定義するKubernetesカスタムリソースとなります。

  1. PolicyオブジェクトのauthEndpointtokenEndpointjwksURIフィールドに、前項で取得した情報を挿入します。

    apiVersion: k8s.nginx.org/v1
    kind: Policy
    metadata:
      name: oidc-policy
    spec:
      oidc:
        clientID: client-id
        clientSecret: oidc-secret
        authEndpoint: https://your-okta-domain/oauth2/v1/authorize
        tokenEndpoint: https://your-okta-domain/oauth2/v1/token
        jwksURI: https://your-okta-domain/oauth2/v1/keys
  2. ポリシーを適用します。(ここでは oidc.yaml)。

    $ kubectl apply -f oidc.yaml
  3. (オプション) ポリシーが有効であることを確認します。

    $ kubectl get policy
    
    NAME          STATE   AGE
    oidc-policy   Valid   2m

VirtualServer オブジェクトの定義

VirtualServerとVirtualServerRouteはNGINX Ingressリソースで、Kubernetesクラスタ内のバックエンドアプリケーションに受信トラフィックをルーティングするためのルールをデプロイします。OIDCポリシーを有効にするには、VirtualServerまたはVirtualServerRouteリソースから参照する必要があります。

  1. URL PATHの “/” というプレフィックスでOIDC ポリシーを参照します。ユーザーがこのプレフィックスに該当するリクエストを行うと、リクエストがapp-server-payload というサービスにプロキシされる前に認証が行われます。

    apiVersion: k8s.nginx.org/v1
    kind: VirtualServer
    metadata:
      name: app-ingress
    spec:
      host: unit-demo.linkpc.net
      upstreams:
      - name: app-server-payload
        service: app-server-svc
        port: 80
      routes:
      - path: /
        policies:
        - name: oidc-policy
        action:
          proxy:
            upstream: app-server-payload
  2. VirtualServerリソース(ここではapp-virtual-server.yamlで定義)を適用します。

    $ kubectl apply -f app-virtual-server.yaml
  3. (オプション) リソースが有効であることを確認します。

    $ kubectl get vs
    
    NAME          STATE   HOST                   IP    PORTS   AGE
    app-ingress   Valid   unit-demo.linkpc.net                 2m

環境のテスト

OIDCが正しくOktaと統合し動作することをテストするため、ブラウザのアドレスバーにNGINX Ingress Controllerのホスト名を入力します。Oktaのログインポータルにリダイレクトされますので、Oktaの開発者アカウントの認証情報を入力することで、バックエンドアプリケーションにアクセス出来ることを確認できます。

認証に成功すると、プロキシされapp-server-payloadサービスにアクセスできるようになります。

アプリケーションにユーザーを追加する

ほとんどの場合、組織内の複数のユーザーがアプリにアクセスする必要があります。Okta AdminコンソールのDirectoryカテゴリにあるPeopleページで、各ユーザーを追加します。

SSO用の複数のアプリ統合を作成する

IdPとしてOkta、OIDCのRelaying PartyとしてNGINX Ingress ControllerでSSOを構成し、1つのアプリケーションから認証処理をオフロードしています。実際には、ユーザーが1つの認証情報を使って多くのアプリケーションにアクセスできるようにしたい場合が多いと思います。また、ユーザーがアクセスできるアプリケーションを柔軟に変更したいと思うかもしれません。

他のアプリケーションをOktaと統合し、他のOIDCポリシーを定義し、VirtualServerリソースでポリシーを参照することで、これを行うことができます。この図の例では、unit-demo.marketing.netunit-demo.engineering.net という 2 つのサブドメインが存在します。これは、NGINX Ingress Controller の外部 IP アドレスとして登録されています。 NGINX Ingress Controllerは、サブドメインに基づいてMarketing アプリまたはEngineering アプリにリクエストをルーティングします。ユーザーにアクセスを許可するには、Okta GUI の Assignments タブで、ユーザーを各適当なアプリケーションに関連付けます。その後、Oktaは認証されたユーザーに、これらのアプリケーションにアクセスするための短時間のセッションクッキーを付与します。

まとめ

NGINX Ingress ControllerをOIDCのRelaying Partyとして、そしてOktaをIdPとしてKubernetesにOIDCベースのSSOを実装することで、開発者から認証・認可をオフロードすることで、開発者はそのリソースをアプリ内のビジネスロジックの最適化に集中することが出来るようになります。NGINX PlusベースのNGINX Ingress Controllerを使い始めるには、今すぐ30日間の無料トライアルをリクエストするか、お客様のユースケースについて弊社までお問合せください。