Anthos Service Mesh のユーザー認証の構成

Anthos Service Mesh のユーザー認証は、デプロイされたワークロードへのブラウザベースのエンドユーザー認証とアクセス制御のための統合ソリューションです。このソリューションにより、ユーザー認証の既存の ID プロバイダ(IDP)と統合できます。アクセス管理には、Istio API と認証ポリシーが使用されます。これは、Istio JSON Web Token(JWT)認証に代わる、ユーザー フレンドリーな代替手段です。

代表的な使用例は、従業員がウェブブラウザからアクセスできるように、組織が Anthos Service Mesh を使用して、ウェブ アプリケーションをホストする場合です。また、組織では既存の ID プロバイダを使用してユーザー ID を管理する必要があります。Anthos Service Mesh のユーザー認証では、ユーザーは標準のウェブベースの OpenID Connect(OIDC)ログインと同意フローを使用して簡単に認証できます。ユーザーが認証されると、Anthos Service Mesh によって Istio の認証ポリシーが適用されます。認証が正常に完了すると、安全な認証情報形式で ID がワークロードに送信されます。

仕組み

Anthos Service Mesh のユーザー認証では、新しいコンポーネント authservice が導入されています。このコンポーネントは、すべての受信認証リクエストをインターセプトする外部承認サービスとして Envoy ベースの Ingress と統合します。authservice は OIDC プロトコルのクライアント側を実装し、ユーザーがブラウザからアプリケーションにアクセスできるようにします。この際、ユーザーはインタラクティブな認証および同意フローを完了して、有効期間の短いセッションを確立します。authservice は、OIDC 認証サーバーとして機能できる ID プロバイダと統合するための業界標準プロトコルを実装します。ユーザーが認証されると、主要な情報は RCToken に JWT 形式でカプセル化され、authservice によって署名されてから Ingress の Istio 認証レイヤに転送されます。このモデルは、メッシュへのトラフィックの境界アクセス制御を提供します。ユーザーがリソースへのアクセスを承認されている場合は、この RCToken もマイクロサービスに転送されるため、主要な情報を取得してきめ細かいアクセス制御を行えます。

次の図は、メッシュ内の authservice の場所と、Ingress、ワークロード、ユーザーのブラウザ、既存の IDP など、メッシュの他の部分との関連を示しています。

エンドユーザー認証

管理者は、Anthos Service Mesh インストール時にアドオンとして authservice をインストールできます。authservice をインストールすると、UserAuth カスタム リソースで定義されている OIDC エンドポイント構成と他の関連設定が読み取られます。管理者は、Anthos Service Mesh ExternalAuthorization API を使用して、auth_server を Ingress のフィルタとして構成できます。

ユーザー認証サービスをインストールする

次の手順では、authservice の構成方法について説明します。

前提条件

次の手順に沿って、前提条件を満たしていることを確認してください。

ユーザー認証オーバーレイを使用してインストールをカスタマイズする

ユーザー認証サービスをインストールするには、ASM のインストールをカスタマイズして、メッシュレベルの外部認証プロバイダを追加する必要があります。

  1. サンプルのユーザー認証オーバーレイを取得し、メッシュにカスタマイズがある場合は更新します。このオーバーレイ ファイルをソース コントロール内で管理することをおすすめします。

    curl https://raw.githubusercontent.com/GoogleCloudPlatform/asm-user-auth/release-1.0/overlay/user-auth-overlay.yaml > user-auth-overlay.yaml
    
  2. オーバーレイを使用して ASM をインストールするの手順に沿って、Google 提供のスクリプトを使用してユーザー認証オーバーレイで Anthos Service Mesh をインストールします。次に例を示します。

    /install_asm \
     --project_id "PROJECT_ID" \
     --cluster_name "CLUSTER_NAME" \
     --cluster_location "CLUSTER_LOCATION" \
     --mode install \
     --enable_all \
     --custom_overlay user-auth-overlay.yaml
    

    ユーザー認証の kpt パッケージが AuthorizationPolicy を作成し、pkg/ext-authz.yaml で指定された外部認証プロバイダを参照します。

OIDC クライアントの構成を準備する

次の手順で OIDC クライアント構成を設定します。このガイドでは Google を IDP として使用しますが、OIDC 認証をサポートする任意の IDP を使用できます。

  1. Google Cloud コンソールで、[API とサービス] > [認証情報] に移動します。

    [認証情報] に移動

  2. [認証情報を作成] に移動し、[OAuth クライアント ID] を選択します。必要に応じて、[OAuth 同意画面] オプションを設定し、次のオプションを構成します。

    • [アプリケーションの種類] を [ウェブ アプリケーション] に設定します。
    • [承認済みのリダイレクト URI] を https://localhost:8443/_gcp_anthos_callback に設定します。

    最後に [保存] をクリックします。

  3. さらに、後で使用するために OIDC クライアントの構成を保存します。

    export OIDC_CLIENT_ID='<your-client-id>'
    export OIDC_CLIENT_SECRET='<your-client-secret>'
    export OIDC_ISSUER_URI='https://accounts.google.com'
    # The host where your application is served from, such as https://example.com
    export OIDC_REDIRECT_HOST='<your-oidc-redirect-host>'
    export OIDC_REDIRECT_PATH='<your-oidc-redirect-path>'
    

kpt パッケージを入手する

公開リポジトリから推奨の authservice 構成をインストールするには、次の手順を行います。これらのコマンドは、最新の authservice コンテナを取得し、asm-user-auth 名前空間の Pod として起動します。また、すべてのリクエストをインターセプトするように Ingress を構成します。

  1. kpt パッケージを取得します。

    kpt pkg get https://github.com/GoogleCloudPlatform/asm-user-auth@release-1.0 .
    cd asm-user-auth/
    

Ingress ゲートウェイのリダイレクト URL とシークレットを設定する

OAuth2 には、HTTPS で保護されたエンドポイントでホストされているリダイレクト URL が必要です。これらのコマンドはサンプル用途であり、Istio Ingress ゲートウェイの自己署名証明書を生成することで簡単に設定できます。本番環境デプロイでは、自己署名証明書は使用しません。

  1. 自己署名証明書を生成します。

    openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem \
     -days 365 -nodes -subj '/CN=localhost'
    
  2. HTTPS トラフィックをホストする Ingress ゲートウェイのシークレットを作成します。

    kubectl create -n istio-system secret tls userauth-tls-cert --key=key.pem \
    --cert=cert.pem
    

暗号鍵と署名鍵を適用する

authservice が正しく動作するには、2 つの鍵セットが必要です。1 つ目は、暗号化と復号の対称鍵です。この鍵は、セッションの状態を Cookie として設定する前に、セッションの暗号化に使用します。

2 つ目は、公開鍵/秘密鍵のペアです。この鍵は、RCToken として JWT 形式で認証されたユーザー情報に署名するために使用されます。このペアの公開鍵は、サイドカーが JWT の検証に使用できる事前定義されたエンドポイントで公開されます。

ユーザー認証の kpt パッケージには、簡単に設定できるように 2 つのサンプルキーが含まれています。ただし、任意の鍵管理システムを使用して、これらの鍵を生成することもできます。

  1. 鍵を生成した後、同じ形式で鍵データを入力します。

    cat ./samples/rctoken_signing_key.json
    {
      "keys":[
         {
            "kty":"RSA",
            "kid":"rsa-signing-key",
            "K":"YOUR_KEY", # k contains a Base64 encoded PEM format RSA signing key.
            "useAfter": 1612813735, # unix timestamp
         }
      ]
    }
    
    cat ./samples/cookie_encryption_key.json
    {
      "keys":[
         {
            "kty":"oct",
            "kid":"key-0",
            "K":"YOUR_KEY",
            "useAfter": 1612813735
         }
      ]
    }
    
  2. authservice が独自のファイル システムにマウントする Kubernetes Secret を作成します。

    REVISION ラベルの値は、Istiod deployment で確認できます。

    kubectl create namespace asm-user-auth
    kubectl label namespace asm-user-auth istio.io/rev=REVISION --overwrite
    kubectl create secret generic secret-key  \
        --from-file="session_cookie.key"="./samples/cookie_encryption_key.json" \
        --from-file="rctoken.key"="./samples/rctoken_signing_key.json"  \
        --namespace=asm-user-auth
    

ユーザー認証サービスをデプロイする

次のコマンドは、ユーザー認証サービスとデプロイを asm-user-auth 名前空間に作成します。

  1. oauth 変数を設定します。クライアント ID とシークレットは Kubernetes Secret として保存されるため、Base64 を使用してエンコードします。

    kpt cfg set pkg anthos.servicemesh.user-auth.oidc.clientID $(echo -n ${OIDC_CLIENT_ID} | base64 -w0)
    kpt cfg set pkg anthos.servicemesh.user-auth.oidc.clientSecret $(echo -n ${OIDC_CLIENT_SECRET} | base64 -w0)
    kpt cfg set pkg anthos.servicemesh.user-auth.oidc.issuerURI ${OIDC_ISSUER_URI}
    kpt cfg set pkg anthos.servicemesh.user-auth.oidc.redirectURIHost ${OIDC_REDIRECT_HOST}
    kpt cfg set pkg anthos.servicemesh.user-auth.oidc.redirectURIPath ${OIDC_REDIRECT_PATH}
    
  2. kpt パッケージを適用します。

    # Remove the potential alpha version CRD if exists.
    kubectl delete crd userauthconfigs.security.anthos.io
    kubectl apply -f ./pkg/asm_user_auth_config_v1beta1.yaml
    kubectl apply -f ./pkg
    

authserviceUserAuthConfig CRD を使用してエンドユーザー認証を行います。UserAuthConfig は実行時に構成可能で、authservice の動作を変更し、任意の OIDC 認証サーバーのエンドポイントで構成するように更新できます。次のフィールドが含まれています。

cat pkg/user_auth_config.yaml

apiVersion: security.anthos.io/v1beta1
kind: UserAuthConfig
metadata:
  name: user-auth-config
  namespace: asm-user-auth
spec:
  authentication:
    oidc:
      certificateAuthorityData: ""
      oauthCredentialsSecret:
        name: "oauth-secret"
        namespace: "asm-user-auth"
      issuerURI: "https://accounts.google.com"
      redirectURIHost: ""
      redirectURIPath: "/_gcp_asm/authenticate"

user_auth_config.yaml フィールドの詳細については、ユーザー認証構成の詳細をご覧ください。

インストール後のタスクを行う

前述のインストール手順が完了した後は、以下のタスクが必要になります。

アプリケーションのユーザー認証を有効にする

このセクションでは、Online Boutique のサンプル アプリケーションを例に使い、ユーザー認証を有効にする方法を説明します。

Anthos Service Mesh ユーザー認証では、CUSTOM タイプの認証ポリシーを使用して OIDC フローをトリガーします。

また、インストール プロセスでは、前記の手順で作成した TLS 証明書 userauth-tls-cert を使用して、HTTPS トラフィックを処理する Istio ゲートウェイが作成されます。pkg/gateway.yaml の構成は次のとおりです。

apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
  name: userauth
  namespace: asm-user-auth
spec:
  selector:
    istio: ingressgateway
  servers:
  - hosts:
    - '*'
    port:
      name: https
      number: 443
      protocol: HTTPS
    tls:
      mode: SIMPLE
      credentialName: userauth-tls-cert
---
# This ensures the OIDC endpoint has at least some route defined.
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: userauth-oidc
  namespace: asm-user-auth
spec:
  gateways:
  - userauth
  hosts:
  - '*'
  http:
  - match:
    - uri:
        prefix: /status
    - uri:
        prefix: "your-oidc-redirect-path"
    name: user-auth-route
    route:
    - destination:
        host: authservice
        port:
          number: 10004
  1. Online Boutique アプリケーションを更新して、このゲートウェイを使って HTTPS トラフィックを処理し、ポート転送を使用してローカルでアプリケーションにアクセスします。

    kubectl apply -f./samples/boutique-route.yaml -n demo
    kubectl port-forward service/istio-ingressgateway 8443:443 -n istio-system
    

    ポート 8443 の Ingress ゲートウェイが localhost に転送され、アプリケーションはローカルでアクセス可能になります。

  2. Online Boutique サンプル アプリケーションが https://localhost:8443/ でアクセスできることを確認します。

ユーザー認証を確認する

続いて、Online Boutique のアプリケーション サービスで、エンドユーザーが Google アカウントを使用してログインする必要があります。

  1. https://localhost:8443/ にアクセスして、OIDC ログインページが表示されることを確認します。

  2. ログイン後、[次へ] をクリックして、Online Boutique のホームページにリダイレクトすることを確認します。

認証ポリシーを構成する

前の手順で構成を完了すると、各ユーザーはウェブベースの認証フローにリダイレクトされます。フローが完了すると、authservice によって JWT 形式の RCToken が生成されます。これを使用して、認証されたユーザー情報が転送されます。

  1. Ingress で Istio の認証ポリシーを追加して、認証されたユーザーごとに認証チェックが行われるようにします。

    kubectl apply -f ./samples/rctoken-authz.yaml
    
  2. rctoken-authz.yaml ファイルは、Ingress ゲートウェイを構成して authservice が発行した RC トークンを検証し、JWT にオーディエンスや発行者などの目的のフィールドが含まれている場合にのみ承認します。

    次の認証ポリシーの例をご覧ください。

    apiVersion: security.istio.io/v1beta1
    kind: RequestAuthentication
    metadata:
     name: require-rc-token
     namespace: istio-system
    spec:
     selector:
       matchLabels:
         istio: ingressgateway
     jwtRules:
     - issuer: "authservice.asm-user-auth.svc.cluster.local"
       audiences:
       - "test_audience"
       jwksUri: "http://authservice.asm-user-auth.svc.cluster.local:10004/_gcp_user_auth/jwks"
       fromHeaders:
       - name: X-ASM-RCTOKEN
       forwardOriginalToken: true
    ---
    apiVersion: security.istio.io/v1beta1
    kind: AuthorizationPolicy
    metadata:
     name: require-rc-token
     namespace: istio-system
    spec:
     selector:
       matchLabels:
         istio: ingressgateway
     action: ALLOW
     rules:
     - when:
       - key: request.auth.claims[iss]
         values:
         - authservice.asm-user-auth.svc.cluster.local
       - key: request.auth.claims[aud]
         values:
         - test_audience
    

環境固有の設定を構成する

前のステップでは、簡単にセットアップするため、localhost と自己署名 HTTPS 証明書を使用しました。本番環境用に使用する場合は、example.com などの実際のドメインを使用します。

さらに、UserAuthConfig CRD で構成された tokenEndpointauthorizationEndpoint に、VirtualService で構成されているルートが設定されていることを確認します。前回のインストール手順では、asm-user-auth/userauth-oidc VirtualService に設定されています。

鍵の管理とローテーションを行う

authservice で使用されるキーのセットは 2 つあります。各鍵を個別にローテーションできます。ただし、鍵をローテーションする前に、ローテーションの仕組みを理解しておくことが重要です。

どちらの鍵も JSON 形式です。useAfter フィールドには、鍵の使用が開始されると考えられる期間のタイムスタンプを指定します。鍵のローテーション中は、JSON に古い鍵と新しい鍵の両方を含める必要があります。たとえば、次の例では、new-key はタイムスタンプ 1712813735 の後にのみ使用されます。

{
   "keys":[
      {
         "kty":"RSA",
         "kid":"old-key",
         "K":"...", # k contains a Base64 encoded PEM format RSA signing key.
         "useAfter": 1612813735, # unix timestamp
      }
      {
      "kty":"RSA",
         "kid":"new-key",
         "K":"...", # k contains a Base64 encoded PEM format RSA signing key.
         "useAfter": 1712813735, # unix timestamp
      }
   ]
}

Anthos Service Mesh では、ブラウザの Cookie に保存されるセッション データを暗号化するために対称鍵を使用します。既存のセッションの有効性を確保するため、authservice は鍵セット内のすべての鍵で復号を試みます。ローテーション時には、authservice は新しいセッションの暗号化に新しい鍵を使用し、引き続き古い鍵による復号を試みます。

公開鍵/秘密鍵ペアは、RCToken の署名に使用されます。公開鍵は、JWT 検証のために istiod によってサイドカーに送信されます。authservice が新しい秘密鍵を使用して RCToken に署名する前に、サイドカーが新しい公開鍵を受け取ることが重要です。この目的を達成するため、authservice は、鍵が追加された直後に公開鍵の公開を開始します。ただし、その鍵を使用して RCToken に署名するまではかなりの時間待機します。

要約すると、鍵のローテーションを行うときは、次のことをおすすめします。

  1. 定期的に、または必要に応じて、鍵のローテーションを実行します。
  2. JSON 形式で、現在の鍵と新しい鍵の両方を指定します。新しい鍵は、将来のタイムスタンプに関連付ける必要があります。タイムスタンプは現在の時刻の少なくとも数時間前に指定することをおすすめします。
  3. 新しい鍵が使用された後でもサービスが正常であるかをモニタリングし確認します。新しい鍵が使用されてから 1 日以上待って、次の手順に進みます。
  4. JSON エントリから古い鍵を削除します。今後それらの鍵は不要です。

ユーザー認証構成の詳細

次の表に、CRD の各フィールドの説明を示します。

フィールド名 説明
authentication.oidc このセクションには、OIDC エンドポイントの構成と、OIDC フローで使用されるパラメータが含まれます。
authentication.oidc.certificateAuthorityData これは、OIDC 認証サーバーのドメインの SSL 証明書です。
authentication.oidc.clientSecret Tsecret は、JSON ペイロードに OAuth2 OIDC client_id と client_secret を含む Kubernetes Opaque タイプのシークレットを参照します。
authentication.oidc.issuerURI 出力 RCToken の発行者として使用する URI。
authentication.oidc.redirectURIHost OAuth 終了 URI に使用するホスト。空白のままにすると、ターゲット URL からのホストが使用され、リダイレクト URI が動的に構成されます。
この値は、より高いレベルのドメインでユーザー認証 SSO セッションが必要な場合に使用できます。たとえば、profile.example.com/ と admin.example.com/ の間で SSO を有効にするには、この値を example.com に設定します。これにより、すべてのサブドメイン間で共有されるユーザー認証セッションを example.com で確立できます。注: 同じメッシュから複数のドメイン(example1.com と example2.com)が提供されている場合、この機能は使用できないため、空白のままにすることをおすすめします。
authentication.oidc.redirectURIPath 「authservice」が OAuth フローを終了するエンドポイントのパス。authentication.oidc.clientID の承認サーバーで、この URI パスとホストを承認済みのリダイレクト URI として登録する必要があります。
また、この URI は、「authservice」が有効になっている同じサービス メッシュと Ingress から提供される必要があります。
authentication.oidc.scopes 認証リクエストでリクエストする必要がある OAuth スコープ。
authentication.oidc.groupsClaim 「idtoken」にグループ クレームが含まれている場合は、このフィールドを使用して名前を指定します。指定すると、サービスは、このリクエストのデータを出力 RCToken の「groups」クレームに渡します。
authentication.outputJWTAudience 「authservice」によって生成された RCToken の対象デバイス。サイドカーは、この対象デバイス値に対して受信 RCToken を検証できます。

マルチクラスタ デプロイ

Anthos Service Mesh のユーザー認証では、マルチクラスタのデプロイをサポートしています。前記のように、各クラスタにユーザー認証をデプロイする必要があります。UserAuth カスタム リソース、OIDC クライアント シークレット、暗号鍵などのユーザー認証構成は、すべて各クラスタに複製する必要があります。

デフォルトでは、Ingress ゲートウェイはいずれかの authservice インスタンスへの認証リクエストを負荷分散します。宛先ルールを使用すると、同じクラスタ内の authservice にリクエストを送信し、他のクラスタの authservice にのみフェイル オーバーするように Ingress ゲートウェイを構成できます。

apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: authservice-fail-over
  namespace: asm-user-auth
spec:
  host: authservice.asm-user-auth.svc.cluster.local
  trafficPolicy:
    loadBalancer:
      localityLbSetting:
        enabled: true
        failover:
        - from:  us-east
          to: us-west
        - from: us-west
          to: us-east

他の構成と同様に、各クラスタで構成する必要があります。

よくある質問

  1. ユーザー認証を有効にした Anthos Service Mesh をアップグレードするにはどうすればよいですか?

    Anthos Service Mesh のアップグレード プロセスに従って、コマンドラインで user-auth.yaml オーバーレイ ファイルを install_asm に指定します。

  2. authservice にはどれくらいのリソースをプロビジョニングすればよいですか。1 秒あたりいくつのリクエストを処理できますか?

    デフォルトでは、authservice は 2.0 vCPU、256Mi メモリで構成されています。このような構成では、authservice は 1 秒あたり 500 件のリクエストを処理できます。大量のリクエストを処理するには、CPU を追加する必要があります。CPU は、そのリクエストの処理能力にほぼ比例します。また、認証サービスの複数のレプリカを構成して、水平方向のスケーラビリティを高めることもできます。