これまでにも繰り返しお伝えしてきたように、ランサムウェアやボットによる攻撃が横行する今日、アプリとAPIのセキュリティを確保することは極めて重要です。Webアプリケーションファイアウォール(WAF)などの仕組みに加え、ユーザーIDの認証と認可制御の適用も、ビジネスアプリケーションを保護するうえで重要な手段です。
認証と認可を実装する最も直接的な方法は、アプリケーション自体に組み込むことです。ユーザー数が少なく、アプリを頻繁に更新する必要がない場合は、この方法でも対応できますが、規模が拡大するとすぐに維持が困難になります。たとえば、多数のアプリごとに異なるアカウント名とパスワードを覚えなければならないと、ログイン時に「ユーザー名またはパスワードが正しくありません」という煩わしいメッセージが頻繁に表示されるようになり、推測されやすい「abc123」のような安全性の低いパスワードに頼りがちです。パスワードのメモを書いたPost-it®が、モニターの周りにずらりと貼られている光景も、誰もが目にしたことがあるでしょう。
シングルサインオン(SSO)テクノロジーでは、個別のユーザー名とパスワードを1組の認証情報に集約することで、こうした問題の一部に対処できます。ユーザーは、Identity Provider(IdP)で一度サインインするだけで、複数のアプリにアクセスできます。ただし、開発者はSSOシステムと連携するためのコードをアプリに組み込む必要があります。これは、アプリケーションが複雑になるほど非常に困難になる可能性があります。
組織の規模が拡大し、急増するユーザーの要件に対応する必要が生じると、認証や認可など、アプリの機能に固有ではない要件をアプリケーション層から切り離すことが重要になります。Kubernetesで認証と認可を一元化するのに適しているのは、Ingressコントローラーです。Ingressコントローラーは、クラスターに入るすべてのトラフィックを精査し、適切なサービスにルーティングできます。これにより、開発者は認証ロジックの構築、保守、複製という負担から解放され、KubernetesネイティブAPIを使用して、Ingress層でSSOテクノロジーを容易に活用できます。
このブログでは、NGINX PlusベースのNGINX Ingress Controllerをリライングパーティとして動作させ、OIDC認可コードフローをサポートする本格的なSSOソリューションの実装方法を紹介します。事前設定済みのアイデンティティプロバイダー(IdP)にはOktaを使用します。
注: この機能は、NGINX Open SourceベースのNGINX Ingress Controllerでは利用できません。
前提条件
このブログでは、Kubernetes環境の運用経験があることを前提としています。また、以下が必要です。
- Kubernetes環境 – NGINX Ingress Controllerは、標準のKubernetesに加え、Amazon Elastic Kubernetes(EKS)、ベアメタル、Google Kubernetes Engine(GKE)、Microsoft Azure Kubernetes Service(AKS)、Rancher Kubernetes Engine、Red Hat OpenShiftなど、多数のKubernetesプラットフォームでサポートされています。
- NGINX PlusベースのNGINX Ingress Controller – NGINX Ingress ControllerのNGINX Plusベース版を使用するには、有効なライセンスが必要です。今すぐ30日間の無料トライアルをお申し込みいただくと、ライセンスの利用を開始できます。詳しくは、ドキュメントをご覧ください。
- Okta開発者アカウント – OktaをIdPとして設定するには、まず開発者アカウントに登録します。または、Okta Command Line Interface(CLI)をダウンロードし、
oktaregisterコマンドを実行して新しいアカウントに登録します。本稿執筆時点では、Okta CLIはベータ版であり、本番環境での使用は推奨されていません。
IdPの事前構成
クラウドサービスでは、ユーザーIDの取得元と検証先を把握する必要があるため、IdPが必要になります。IdPはデジタルIDを安全に管理・保存し、攻撃者によるIDの窃取やユーザーへのなりすましを防ぎます。
このセクションでは、Okta CLIを使用してOktaをIdPとして事前構成し、Oktaで「app integration」と呼ばれるものを作成します。
- Run the
oktaloginコマンドを実行し、Okta Developer AccountでOkta CLIを認証します。プロンプトが表示されたら、OktaドメインとAPIトークンを入力します。
$ okta login Okta Org URL: https://your-okta-domain
Okta API token: your-api-token- アプリ統合を作成します:
$ okta apps create --app-name=mywebapp --redirect-uri=http[s]://ingress-controller-hostname/_codexch- ここで
--app-nameはアプリケーション名(ここでは mywebapp)を定義します--redirect-uriは、サインインのリダイレクト先URIを定義します(ここでは、ingress-controller-hostname/_codexch)
- プロンプトに従ってアプリケーションタイプを指定します。まず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...OrfQAg5d7NGINX Ingress Controllerの設定
NGINX PlusベースのNGINX Ingress Controllerを、ユーザーを認証するリレーパーティとして構成します。
クライアント認証情報シークレットの定義
セキュリティ上の理由から、OIDC Policy Objectにクライアントシークレットをハードコーディングすることはサポートされていません。代わりに、クライアントシークレットの値をbase64でエンコードし、その値をデータとして格納したKubernetes Secretを作成します。
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認証エンドポイントの取得
Oktaが認可サーバーで公開しているエンドポイントに関する情報を取得するには、OAuth 2.0およびOpenID Connect APIを使用します。
ローカルマシンで次のコマンドを実行し、Oktaエンドポイントに関する情報を出力します。サンプル出力に示されている「authorization_endpoint」、「token_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ベースの認証がサポートされるようになりました。詳しくは、F5のブログ記事「OpenID ConnectとNGINX Ingress Controllerで簡単かつ堅牢なシングルサインオンを実現」をご覧ください。
NGINX Ingress ControllerのOIDC認証実装では、KubernetesのPolicyオブジェクト(カスタムリソース)を使用して、NGINX Ingress ControllerのOIDCポリシーを定義します。
- 前のセクションで取得した情報を、
authEndpoint、tokenEndpoint、およびjwksURIの各フィールドに挿入します。対象となるのはPolicyオブジェクトです。
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- ポリシー(ここではoidc.yamlで定義)を適用します:
$ kubectl apply -f oidc.yaml- (任意)ポリシーの有効性を確認します:
$ kubectl get policy
NAME STATE AGE
oidc-policy Valid 2mVirtualServerオブジェクトの定義
VirtualServerとVirtualServerRouteは、NGINX Ingressリソースであり、Kubernetesクラスター内のバックエンドアプリケーションに受信トラフィックをルーティングするためのルールをプロビジョニングします。OIDCポリシーを有効にするには、VirtualServerまたはVirtualServerRouteリソースからそのポリシーを参照する必要があります。
- Reference an OIDC policy under the /パスプレフィックスの配下でOIDCポリシーを参照し、このプレフィックスに一致するパスをリクエストしたユーザーが、リクエストを
app-server-payloadServiceにプロキシする前に認証されるようにします。
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- VirtualServerリソース(ここではapp-virtual-server.yamlで定義)を適用します:
$ kubectl apply -f app-virtual-server.yaml- (任意)リソースが有効であることを確認します:
$ 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 ConsoleのPeopleページ(Directoryカテゴリ内)で各ユーザーを追加します。

複数のアプリ向けSSO統合の作成
OktaをIdP、NGINX Ingress ControllerをリレーイングパーティとしてSSOを構成することで、1つのアプリケーションから認証プロセスを切り離しました。実際には、1組の認証情報で多数のアプリケーションにアクセスできるようにすることが一般的です。また、ユーザーごとにアクセス可能なアプリケーションを柔軟に変更したい場合もあります。これを実現するには、前述のセクションの手順を繰り返します。
- IdPの事前設定により、他のアプリケーションをOktaと統合
- NGINX Ingress OIDCポリシーの定義(他のOIDCポリシーを定義するため)
- VirtualServerオブジェクトの定義(追加のポリシーを参照するため)
次の図に示す例では、NGINX Ingress Controllerの外部IPアドレスに解決される2つのサブドメイン、unit-demo.marketing.netとunit-demo.engineering.netがあります。NGINX Ingress Controllerは、サブドメインに基づいてリクエストをMarketingアプリまたはEngineeringアプリにルーティングします。ユーザーにアクセス権を付与するには、Okta GUIの[Assignments]タブで、ユーザーを該当する各アプリケーションに関連付けます。その後、Oktaは認証済みユーザーに、それらのアプリケーションへのアクセスに使用する有効期間の短いセッションCookieを付与します。

まとめ
KubernetesでNGINX Ingress Controllerをリライングパーティ、OktaをIdPとして使用するOIDCベースのSSOを実装すると、開発者が認証と認可を担う必要がなくなり、アプリのビジネスロジックの最適化に集中できるようになります。NGINX PlusベースのNGINX Ingress Controllerを使い始めるには、今すぐ30日間の無料トライアルをお申し込みいただくか、ユースケースについてご相談ください。
著者について

関連するブログ記事
チュートリアル:NGINXを使用してアプリケーション向けにOpenTelemetryを構成する
OpenTelemetryを使用してNGINXサーバーの状態と健全性をより明確に把握することで、問題のトラブルシューティングを行い、Webアプリケーションのパフォーマンスを向上できます。
AkitaのNGINX Plus認定モジュールでAPIエンドポイントの問題を特定・修正
Akita SoftwareのAPIオブザーバビリティ向け新しいNGINX Plus Certified Moduleを活用して、APIエンドポイントの問題をより迅速に特定し、修正できます。
JavaプロジェクトをスキャフォールディングしてKubernetesネイティブアプリを構築する方法
Red HatのシニアプリンシパルデベロッパーアドボケイトであるDaniel Oh氏が、Javaプロジェクトをゼロから構築するためのひな形を作成し、Kubernetesネイティブアプリケーションとしてビルドする方法を解説します。
F5 NGINXaaS for Azureのご紹介:Microsoft Azureでネイティブに利用できるSaaS型ロードバランシング
NGINXaaS for Azureは、NGINX PlusをAzureネイティブのSaaSとして利用できるサービスです。NGINXの設定を容易にリフト&シフトできるため、クラウド導入とモダンアプリの展開を加速できます。

SELinuxでNGINXおよびNGINX Plusを使用する
Red Hat Enterprise Linux(RHEL)および関連ディストリビューションでSecurity-Enhanced Linux(SELinux)を有効にすると、デフォルト設定によりNGINXとNGINX Plusの一部の操作が制限されます。この記事では、すべての機能を利用できるようにSELinuxの設定を変更する方法について説明します。
NGINX PlusによるAWS Auto Scalingグループの負荷分散
新しいnginx-asg-sync統合ソフトウェアにより、NGINX PlusはAWS Auto Scalingグループの負荷を直接分散できるため、クラウドでの負荷分散がさらに柔軟になります