ランサムウェアやボットによる攻撃が増加傾向にある今日、アプリや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環境での運用経験がある方を想定しています。また、以下の環境をご準備いただく必要があります。
- Kubernetes環境 – NGINX Ingress Controllerは、vanilla 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 PlusベースのNGINX Ingress Controller – NGINX Plus をベースとしたNGINX Ingress Controllerを利用する場合、有効なライセンスが必要となります。30日間の無料トライアルをリクエストすることで、今すぐライセンスを取得することができます。その他の情報については、当社のドキュメントを参照してください。
- Okta開発者アカウント – OktaをIdPとして設定するには、開発者アカウントにサインアップすることから始めてください。その他のログイン方法として、Okta Command Line Interface(CLI)をダウンロードし、
okta
register
コマンドを実行して新しいアカウントにサインアップすることも可能です。この記事の執筆時点では、Okta CLIはベータ版であり、実稼働環境での使用は推奨されません。
IdPの事前設定
クラウドサービスは、どこで取得されたユーザーIDであるか、そしてユーザーの識別情報の確認をしなければなりません。これが、IdPが必要となるポイントです。IdPは、デジタルIDを安全に管理・保管し、攻撃者がIDを盗んでユーザーになりすますことができないようにします。
このセクションでは、Okta CLIを使用して、OktaをIdPとして事前設定し、Oktaの「app integration」を作成します。
-
okta
login
コマンドを実行し、Okta Developer AccountでOkta CLIの認証を行います。プロンプトでOktaドメインとAPIトークンを入力します。$ okta login Okta Org URL: https://your-okta-domain Okta API token: your-api-token
-
「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)。
-
プロンプトの表示に従って、まず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_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ベースの認証がサポートされるようになりました。詳しくは、ブログ「Easy and Robust Single Sign‑On with OpenID Connect and NGINX Ingress Controller」をご覧ください。
NGINX Ingress ControllerのOIDC認証の実装では、Policy
オブジェクトを使用します。これは、NGINX Ingress ControllerでOIDCポリシーを定義するKubernetesカスタムリソースとなります。
-
Policy
オブジェクトのauthEndpoint
、tokenEndpoint
、jwksURI
フィールドに、前項で取得した情報を挿入します。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 2m
VirtualServer オブジェクトの定義
VirtualServerとVirtualServerRouteはNGINX Ingressリソースで、Kubernetesクラスタ内のバックエンドアプリケーションに受信トラフィックをルーティングするためのルールをデプロイします。OIDCポリシーを有効にするには、VirtualServerまたはVirtualServerRouteリソースから参照する必要があります。
-
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
-
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コンソールのDirectoryカテゴリにあるPeopleページで、各ユーザーを追加します。
SSO用の複数のアプリ統合を作成する
IdPとしてOkta、OIDCのRelaying PartyとしてNGINX Ingress ControllerでSSOを構成し、1つのアプリケーションから認証処理をオフロードしています。実際には、ユーザーが1つの認証情報を使って多くのアプリケーションにアクセスできるようにしたい場合が多いと思います。また、ユーザーがアクセスできるアプリケーションを柔軟に変更したいと思うかもしれません。
他のアプリケーションをOktaと統合し、他のOIDCポリシーを定義し、VirtualServerリソースでポリシーを参照することで、これを行うことができます。この図の例では、unit-demo.marketing.net と unit-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日間の無料トライアルをリクエストするか、お客様のユースケースについて弊社までお問合せください。