設定 Cloud Service Mesh 使用者驗證

Cloud Service Mesh 使用者驗證是一項整合式解決方案,可針對已部署的工作負載,提供瀏覽器型使用者驗證和存取控管功能。您可以整合現有的識別資訊提供者 (IDP) 進行使用者驗證,並使用 Istio API 和授權政策管理存取權。這項功能容易使用,可做為 Istio JSON Web Token (JWT) 驗證的替代方案。

常見的使用案例是,組織使用 Cloud Service Mesh 代管網頁應用程式,讓員工透過網路瀏覽器存取。此外,組織必須使用現有的識別資訊提供者來管理使用者身分。Cloud Service Mesh 使用者驗證功能可讓使用者輕鬆透過標準網頁式 OpenID Connect (OIDC) 登入和同意聲明流程進行驗證。使用者驗證時,Cloud Service Mesh 會強制執行 Istio 授權政策,並在授權成功後,以安全憑證格式將身分傳輸至工作負載。

運作方式

Cloud Service Mesh 使用者驗證功能導入了新元件 authservice。這項元件會與 Envoy 型 ingress 整合,做為外部授權服務,攔截所有傳入要求進行驗證。authservice 實作 OIDC 通訊協定的用戶端,並讓使用者透過瀏覽器存取應用程式,使用者在瀏覽器中完成互動式驗證和同意聲明流程,建立短期工作階段。authservice 採用業界標準通訊協定,可與任何能做為 OIDC 授權伺服器的識別資訊提供者整合。使用者通過驗證後,主體資訊會封裝在 JWT 格式的 RCToken 中,並由 authservice 簽署,然後轉送至輸入中的 Istio 授權層。這個模型可對進入網格的流量進行周邊存取控管。如果使用者有權存取資源,這個 RCToken 也會轉送至微服務,以取得主體資訊並強制執行精細的存取控管。

下圖顯示 authservice 在網格中的位置,以及與網格其他部分的關係,例如輸入、工作負載、使用者瀏覽器和任何現有的 IDP。

使用者驗證

管理員可以將 authservice 安裝為 Cloud Service Mesh 安裝項目的外掛程式。安裝後,authservice 會讀取 OIDC 端點設定,以及 UserAuth 自訂資源中定義的其他相關設定。管理員可以使用 Cloud Service Mesh ExternalAuthorization API,將 auth_server 設為輸入篩選器。

安裝使用者驗證服務

下列步驟說明如何設定 authservice。

必要條件

按照「安裝依附元件工具並驗證叢集」中的步驟操作,完成下列事項:
  • 如果您在私人叢集使用代管 Cloud Service Mesh,請確認叢集能將輸出流量傳送至 IDP。

此外,請按照下列步驟確認您符合必要條件。

自訂安裝使用者驗證疊加層

如要安裝使用者驗證服務,您必須自訂 Cloud Service Mesh 安裝作業,新增網格層級的外部授權提供者。所需步驟取決於您使用的是代管或叢集內 Cloud Service Mesh。

受管理

  1. 更新 ConfigMap,加入使用者驗證 MeshConfig。在下列指令中,使用您在佈建代管 Cloud Service Mesh 時使用的 REVISION_LABEL (例如 asm-managed、asm-managed-rapid 或 asm-managed-stable):

    kubectl edit configmap istio-REVISION_LABEL -n istio-system
    
  2. 在 MeshConfig 的 mesh 欄位下方,新增下列文字:

    mesh: |-
    ...
      extensionProviders:
      - name: "asm-userauth-grpc"
        envoyExtAuthzGrpc:
          service: "authservice.asm-user-auth.svc.cluster.local"
          port: "10003"
    
  3. 建立 asm-user-auth 命名空間。

    kubectl create namespace asm-user-auth
    
  4. 啟用命名空間,以便插入。步驟取決於控制層實作。

    代管 (TD)

    將預設插入標籤套用至命名空間:

    kubectl label namespace asm-user-auth \
        istio.io/rev- istio-injection=enabled --overwrite
    

    代管 (Istiod)

    建議做法:執行下列指令,將預設插入標籤套用至命名空間:

    ```sh
    kubectl label namespace asm-user-auth \
        istio.io/rev- istio-injection=enabled --overwrite
    ```
    

    如果您是使用代管 Istiod 控制層的現有使用者:建議您使用預設插入,但系統支援以修訂版本為基礎的插入。請按照下列操作說明進行:

    1. 執行下列指令,找出可用的發布版本:
    kubectl -n istio-system get controlplanerevision
    

    輸出結果會與下列內容相似:

    NAME                AGE
    asm-managed-rapid   6d7h
    

    在輸出內容中,NAME 欄下方的值是修訂版本標籤,對應至 Cloud Service Mesh 版本的可用發布管道。

    1. 將修訂版本標籤套用至命名空間:

      kubectl label namespace asm-user-auth \
          istio-injection- istio.io/rev=REVISION_LABEL --overwrite
      
  5. 在 asm-user-auth 命名空間中安裝 Istio 閘道。

    kubectl apply -n asm-user-auth -f DIR_PATH/samples/gateways/istio-ingressgateway
    

叢集內

  1. 取得使用者驗證疊加層範例,並根據網格中的自訂項目進行更新。建議您在原始碼控制中維護這個疊加檔案。

    curl https://raw.githubusercontent.com/GoogleCloudPlatform/asm-user-auth/v1.2.5/overlay/user-auth-overlay.yaml > user-auth-overlay.yaml
    
  2. 請按照使用疊加層安裝 Cloud Service Mesh 的步驟,使用 Google 提供的指令碼,安裝具有使用者驗證疊加層的 Cloud Service Mesh。例如:

    ./asmcli install \
      --project_id PROJECT_ID \
      --cluster_name CLUSTER_NAME \
      --cluster_location CLUSTER_LOCATION \
      --fleet_id FLEET_PROJECT_ID \
      --output_dir DIR_PATH \
      --enable_all \
      --custom_overlay user-auth-overlay.yaml
    

    使用者驗證 kpt 套件會建立 AuthorizationPolicy,參照 pkg/ext-authz.yaml 指定的外部授權提供者。

  3. 建立 asm-user-auth 命名空間。

    kubectl create namespace asm-user-auth
    
  4. 啟用命名空間,以便插入。

    建議做法:執行下列指令,將預設插入標籤套用至命名空間:

      kubectl label namespace asm-user-auth \
          istio.io/rev- istio-injection=enabled --overwrite
    

    建議您使用預設插入,但我們也支援修訂版本插入: 請按照下列操作說明:

    1. 使用下列指令,找出 istiod 的修訂版本標籤:

      kubectl get deploy -n istio-system -l app=istiod -o \
        jsonpath={.items[*].metadata.labels.'istio\.io\/rev'}'{"\n"}'
      
    2. 將修訂版本標籤套用至命名空間。在下列指令中,REVISION_LABEL 代表您在上一步記下的 istiod 修訂版本標籤值。

      kubectl label namespace asm-user-auth \
          istio-injection- istio.io/rev=REVISION_LABEL --overwrite
      
  5. 在 asm-user-auth 命名空間中安裝 Istio 閘道。

    kubectl apply -n asm-user-auth -f DIR_PATH/samples/gateways/istio-ingressgateway
    

準備 OIDC 用戶端設定

請按照下列步驟設定 OIDC 用戶端。本指南使用 Google 做為 IDP,但您可以使用任何支援 OIDC 驗證的 IDP。

  1. 在 Google Cloud 控制台中,依序前往「API & Services」(API 和服務) >「Credentials」(憑證)。

    前往「憑證」

  2. 前往「建立憑證」,然後選擇「OAuth 用戶端 ID」。如有需要,請設定 OAuth 同意畫面選項,然後設定下列選項:

    • 將「應用程式類型」設為「網頁應用程式」。
    • 將「Authorized redirect URI」(已授權的重新導向 URI) 設為 https://REDIRECT_HOST/REDIRECT_PATH。舉例來說,如果是 localhost,您可以設為 https://localhost:8443/_gcp_asm_authenticate。

    點選「儲存」。

  3. 此外,請儲存 OIDC 用戶端設定,以便日後使用。

    export OIDC_CLIENT_ID=CLIENT_ID
    export OIDC_CLIENT_SECRET=CLIENT_SECRET
    export OIDC_ISSUER_URI=ISSUER_URI
    export OIDC_REDIRECT_HOST=REDIRECT_HOST
    export OIDC_REDIRECT_PATH=REDIRECT_PATH
    

取得 kpt 套件

請按照下列步驟,從公開存放區安裝建議的 authservice 設定。這些指令會擷取最新的 authservice 容器,並在 asm-user-auth 命名空間中以 Pod 的形式啟動。並設定輸入,攔截所有要求。

取得 kpt 套件:

kpt pkg get https://github.com/GoogleCloudPlatform/asm-user-auth.git/@v1.2.5 .
cd asm-user-auth/

設定 Ingress 閘道的重新導向網址和密鑰

OAuth2 需要託管於受 HTTPS 保護端點的重新導向網址。這些指令僅供示範,並會為 Istio 輸入閘道產生自行簽署憑證,簡化設定程序。

  1. 產生自行簽署的憑證:

    openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem \
     -days 365 -nodes -subj '/CN=localhost'
    
  2. 為 Ingress 閘道建立密鑰,以便託管 HTTPS 流量:

    kubectl create -n asm-user-auth secret tls userauth-tls-cert --key=key.pem \
    --cert=cert.pem
    

套用加密和簽署金鑰

authservice 需要兩組金鑰才能順利運作。第一種是對稱式金鑰,用於加密和解密。這個金鑰用於加密工作階段狀態,然後再將其設為 Cookie。

第二組金鑰是公開/私密金鑰組。這組金鑰會用於簽署 JWT 格式的已驗證使用者資訊,做為 RCToken。這組金鑰的公開金鑰會發布在預先定義的端點,sidecar 可用來驗證 JWT。

使用者驗證 kpt 套件包含兩個範例金鑰,可快速設定。不過,您也可以使用偏好的金鑰管理系統產生這些金鑰。

  1. 請使用下列格式準備工作階段加密金鑰,或使用 pkg 中的範例 (可透過 cat ./samples/cookie_encryption_key.json 查看)。

    {
      "keys":[
         {
            "kty":"oct",
            "kid":"key-0",
            "K":"YOUR_KEY",
            "useAfter": 1612813735
         }
      ]
    }
    

    您可以使用下列指令產生測試 AES 金鑰:

    openssl enc -aes-256-cbc -k mycustomkey -P -md sha1 | grep key
    
  2. 請使用下列格式準備 RCToken 簽署金鑰,或使用 pkg 中的範例 (可透過 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
         }
      ]
    }
    

    您可以使用下列指令,產生測試用的 512 位元 RSA 私密金鑰:

    openssl genpkey -algorithm RSA -out rsa_private.pem -pkeyopt rsa_keygen_bits:512
    
  3. 建立 Kubernetes 密鑰,authservice 會將其掛接至自己的檔案系統。

    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 命名空間中建立使用者驗證服務和部署作業。

設定使用者驗證所需的必要值。用戶端 ID 和密鑰會儲存為 Kubernetes 密鑰,因此我們使用 Base64 進行編碼。請前往公開存放區,查看所有可用的 setter。

kpt fn eval pkg --image gcr.io/kpt-fn/apply-setters:v0.2 --truncate-output=false -- \
  client-id="$(echo -n ${OIDC_CLIENT_ID} | base64 -w0)" \
  client-secret="$(echo -n ${OIDC_CLIENT_SECRET} | base64 -w0)" \
  issuer-uri="${OIDC_ISSUER_URI}" \
  redirect-host="${OIDC_REDIRECT_HOST}" \
  redirect-path="${OIDC_REDIRECT_PATH}"

套用 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

authservice 會使用 UserAuthConfig 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: ""  # kpt-set: ${ca-cert}
      issuerURI: "<your issuer uri>"  # kpt-set: ${issuer-uri}
      proxy: ""  # kpt-set: ${proxy}
      oauthCredentialsSecret:
        name: "oauth-secret"  # kpt-set: ${secret-name}
        namespace: "asm-user-auth"  # kpt-set: ${secret-namespace}
      redirectURIHost: ""  # kpt-set: ${redirect-host}
      redirectURIPath: "/_gcp_asm_authenticate"  # kpt-set: ${redirect-path}
      scopes: ""  # kpt-set: ${scopes}
      groupsClaim: ""  # kpt-set: ${groups}
  outputJWTAudience: "test_audience"  # kpt-set: ${jwt-audience}

如要進一步瞭解 user_auth_config.yaml 欄位,請參閱使用者驗證設定詳細資料。

設定 API 要求 ID

API 要求 ID 是一組一般運算語言 (CEL) 運算式,Cloud Service Mesh 使用者驗證機制會用來識別 API 要求。定義這些 ID 後,Cloud Service Mesh 使用者驗證機制就能以語意方式處理 API 要求驗證失敗。

具體來說,當您提供 CEL 運算式來識別 API 要求時,Cloud Service Mesh 使用者驗證功能會傳回 401-Unauthorized 狀態碼,讓未經驗證的 API 要求失敗。這對 CLI 和服務帳戶等用戶端來說至關重要,因為這些用戶端會預期未經驗證的 API 要求會傳回這個狀態碼。

如果沒有 API 要求 ID,Cloud Service Mesh 使用者驗證會將所有未經驗證的要求重新導向至設定的 OpenID Connect (OIDC) 供應商,並傳回 302-Found 狀態碼。這種重新導向行為通常不適用於 API 要求,因為 API 要求在失敗時應傳回 401-Unauthorized。

如要定義 API 要求 ID,請在 UserAuthConfig CR 中新增 apiRequestIdentifier 區段。這樣一來,您就能新增多個 CEL 運算式。如果提供多個 CEL 運算式,只要要求符合其中至少一個運算式,就會視為 API 要求。

以下範例說明如何將下列要求指定為 API 要求:包含 example-api-header 標頭的要求、導向主機 api.example.com 的要求,或指定 /v1/api/ 底下路徑的要求。

apiVersion: security.anthos.io/v1beta1
kind: UserAuthConfig
metadata:
  name: user-auth-config
  namespace: asm-user-auth
spec:
  authentication:
    oidc:
      certificateAuthorityData: ""  # kpt-set: ${ca-cert}
      issuerURI: "<your issuer uri>"  # kpt-set: ${issuer-uri}
      proxy: ""  # kpt-set: ${proxy}
      oauthCredentialsSecret:
        name: "oauth-secret"  # kpt-set: ${secret-name}
        namespace: "asm-user-auth"  # kpt-set: ${secret-namespace}
      redirectURIHost: ""  # kpt-set: ${redirect-host}
      redirectURIPath: "/_gcp_asm_authenticate"  # kpt-set: ${redirect-path}
      scopes: ""  # kpt-set: ${scopes}
      groupsClaim: ""  # kpt-set: ${groups}
  outputJWTAudience: "test_audience"  # kpt-set: ${jwt-audience}
  apiRequestIdentifier: 
    name: "api-request-identifiers"
    expressions: 
    - "'example-api-header' in http_request.headers"
    - "http_request.host == 'api.example.com'"
    - "matches(http_request.path, '/v1/api/(.*)')"
    # other expressions go here

Cloud Service Mesh 使用者驗證 CEL 運算式可由下列欄位建構:

  1. http_request.headers:HTTP 要求標頭的對應,其中鍵為小寫字串,值為字串向量。

    在 CEL 運算式中使用這個欄位,將具有特定標頭的要求指定為 API 要求。

  2. http_request.host:要求的 HTTP 網址主機 (例如 api.example.com)。

    在 CEL 運算式中使用這個欄位,將傳送至特定主機的要求指定為 API 要求。

  3. http_request.path:要求的 HTTP 網址路徑 (例如 /example-api-path)。開頭一律為「/」,且不含要求網址的查詢元件。

    在 CEL 運算式中使用這個欄位,將具有特定路徑的要求指定為 API 要求。

下一節提供 CEL 運算式範例,說明如何檢查及比對這些欄位的部分內容,讓 Cloud Service Mesh 使用者驗證機制瞭解如何判斷哪些要求是 API 要求。

運算式範例

比對並找出含有 X-API-Key 標頭的所有要求:

"'x-api-key' in http_request.headers"

比對標頭 X-API-Key 設為特定值的所有要求:

"'x-api-key' in http_request.headers && http_request.headers['x-api-key'].values == ['example-value ']"

比對傳送至主機 api.example.com 的所有要求:

"http_request.host == api.example.com"

比對並找出路徑為 /api/query 的所有要求:

"http_request.path == /api/query"

比對 /api/ 下任何路徑的所有要求:

"matches(http_request.path, '/api/(.*)')"

執行安裝後工作

完成上述安裝步驟後,請執行下列工作。

為應用程式啟用使用者驗證

本節以 httpbin 為例,示範如何啟用使用者驗證。

Cloud Service Mesh 使用者驗證會使用 CUSTOM 類型的授權政策,觸發 OIDC 流程。

安裝 Istio 閘道後,請使用您在上方建立的 TLS 憑證 userauth-tls-cert,將閘道設為提供 HTTPS 流量。以下是您剛安裝的 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. 為 default 命名空間加上標籤,為部署作業啟用 istio-proxy 自動插入功能。

    kubectl label namespace default istio.io/rev=REVISION --overwrite
    
  2. 將 httpbin 部署至 default 命名空間。

    kubectl apply -f https://raw.githubusercontent.com/istio/istio/master/samples/httpbin/httpbin.yaml -n default
    
  3. 更新 httpbin,使用這個閘道提供 HTTPS 流量,並使用通訊埠轉送功能在本機存取應用程式:

    kubectl apply -f./samples/httpbin-route.yaml -n default
    kubectl port-forward service/istio-ingressgateway 8443:443 -n asm-user-auth
    
    apiVersion: networking.istio.io/v1alpha3
    kind: VirtualService
    metadata:
      name: httpbin
      namespace: default
    spec:
      gateways:
      - asm-user-auth/userauth
      hosts:
      - '*'
      http:
      - match:
        - uri:
            prefix: /ip
        - uri:
            prefix: /headers
        name: httpbin-routes
        route:
        - destination:
            host: httpbin.default.svc.cluster.local
            port:
              number: 8000
    

    通訊埠 8443 上的輸入閘道會轉送至 localhost,以便在本機存取應用程式。

  4. 部署 samples/rctoken-authz.yaml,啟用 RequestAuthentication 和 AuthorizationPolicy,驗證要求的 RCToken。

    kubectl apply -f ./samples/rctoken-authz.yaml -n asm-user-auth
    

    範例 samples/rctoken-authz.yaml:

    apiVersion: security.istio.io/v1beta1
    kind: RequestAuthentication
    metadata:
      name: require-rc-token
    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
    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
    

驗證使用者

httpbin 提供兩個路徑,/ip 可公開存取,/headers 則要求使用者透過設定的 IDP 登入。

  1. 前往 https://localhost:8443/ip,確認您可以直接存取 /ip。

  2. 前往 https://localhost:8443/headers,確認您看到 OIDC 登入頁面。

  3. 登入後,按一下「Next」(下一步),確認系統會將您重新導向至 /headers 頁面。

設定授權政策

完成上述步驟的設定後,每位使用者都會重新導向至網頁式驗證流程。流程完成後,authservice 會產生 JWT 格式的 RCToken,用於傳輸已驗證的使用者資訊。

  1. 在 ingress 新增 Istio 授權政策,確保每位通過驗證的使用者都會接受授權檢查:

    kubectl apply -f ./samples/httpbin-authz.yaml -n asm-user-auth
    
  2. httpbin-authz.yaml 檔案會設定輸入閘道,驗證 authservice 核發的 RC 權杖,並在 JWT 包含所需欄位 (例如目標對象和核發者) 時才授權。

    請參閱下列授權政策範例:

    apiVersion: security.istio.io/v1beta1
    kind: AuthorizationPolicy
    metadata:
      name: require-rc-token
    spec:
      selector:
        matchLabels:
          istio: ingressgateway
      action: ALLOW
      rules:
      - to:
        - operation:
            paths: ["/ip"]
      - to:
        when:
        - key: request.auth.claims[iss]
          values:
          - authservice.asm-user-auth.svc.cluster.local
        - key: request.auth.claims[aud]
          values:
          - test_audience
        - key: request.auth.claims[sub]
          values:
          - allowed_user_sub_1  # Change this with the "sub" claim in the RC token. Wildcard '*' will match everything.
    

調整環境專屬設定

上述步驟使用 localhost 和自行簽署的 HTTPS 憑證,以便快速設定。如要用於實際工作環境,請使用自己的網域,例如 example.com。

此外,請確認 certificateAuthorityData 包含預期的根憑證內容。舉例來說,如果 IDP 信任系統的根憑證,您可以將其留空。如果 HTTPS Proxy 終止 HTTPS 連線,則應設為 Proxy 的根憑證。

管理及輪替金鑰

authservice 會使用兩組金鑰。您可以個別輪替各個金鑰。不過,在輪替金鑰之前,請務必瞭解輪替的運作方式。

這兩種金鑰都採用 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
      }
   ]
}

Cloud Service Mesh 會使用對稱金鑰,加密儲存在瀏覽器 Cookie 中的工作階段資料。為確保現有工作階段有效,authservice 會嘗試使用金鑰集中的所有金鑰進行解密。輪替時,authservice 會使用新金鑰加密新工作階段,並繼續嘗試使用舊金鑰解密。

公開/私密金鑰組用於簽署 RCToken。公開金鑰會由 istiod 傳輸至 Sidecar,用於 JWT 驗證。在 authservice 開始使用新的私密金鑰簽署 RCToken 之前,sidecar 必須先收到新的公開金鑰。為此,authservice 會在新增公開金鑰後立即發布,但會等待一段時間,才開始使用該金鑰簽署 RCToken。

總結來說,執行金鑰輪替時,建議您:

  1. 定期或視需要輪替金鑰。
  2. 在 JSON 格式中,請同時加入目前和新的金鑰。新金鑰應與未來的時間戳記建立關聯。建議您指定比目前時間早至少幾小時的時間戳記。
  3. 監控並確認使用新金鑰後,服務仍正常運作。使用新金鑰後,請等待至少一天,再進行下一步。
  4. 從 JSON 項目中移除舊金鑰。因為不再需要使用。

多叢集部署

Cloud Service Mesh 使用者驗證支援多叢集部署。您必須按照上述步驟,在每個叢集中部署使用者驗證。使用者驗證設定 (例如 UserAuth 自訂資源、OIDC 用戶端密鑰、加密金鑰) 都必須在每個叢集中複製。

根據預設,輸入閘道會將驗證要求負載平衡至任何一個 authservice 執行個體。您可以使用目的地規則,設定輸入閘道將要求傳送至同一叢集中的 authservice,並僅容錯移轉至其他叢集的 authservice。

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

與其他設定相同,這項設定必須在每個叢集中進行。

自訂權杖附加資訊對應

如要設定自訂權杖附加資訊對應,請設定 spec.authentication.oidc.attributeMapping,定義原始識別資訊提供者 IDToken 的任何對應。鍵是 RCToken 中的宣告名稱,值則是 CEL 運算式,說明如何從 IDToken 剖析宣告,請使用 assertion 參照 IDToken。

範例:

spec:
  authentication:
    oidc:
      attributeMapping:
        aud_copy: assertion.aud
        decision: 'assertion.sub.startsWith("123") ? "success" : "fail"'

在 RCToken 中,巢狀憑證附加資訊 attributes 包含已設定的憑證附加資訊:

"attributes": {
    "aud_copy": "foo.googleusercontent.com",
    "decision": "success"
}

如果 CEL 運算式無法剖析 IDToken 中的值,則會忽略該要求,但不會導致驗證流程失敗。

使用者驗證升級授權

  1. 再次安裝 user-auth 套件,因為其中包含新版 user-auth 的更新二進位檔:

    kpt pkg get https://github.com/GoogleCloudPlatform/asm-user-auth.git/@v1.2.5 .
    cd asm-user-auth/
    
  2. 儲存 OIDC 用戶端設定:

    export OIDC_CLIENT_ID=CLIENT_ID
    export OIDC_CLIENT_SECRET=CLIENT_SECRET
    export OIDC_ISSUER_URI=ISSUER_URI
    export OIDC_REDIRECT_HOST=REDIRECT_HOST
    export OIDC_REDIRECT_PATH=REDIRECT_PATH
    
  3. 部署使用者驗證服務,升級至新版本。

使用者驗證設定詳細資料

下表說明 CRD 中的各個欄位:

欄位名稱 說明
authentication.oidc 這個部分包含 OIDC 端點設定和 OIDC 流程中使用的參數。
authentication.oidc.certificateAuthorityData 這是 OIDC 授權伺服器網域或 HTTPS Proxy (如有) 的 SSL 根憑證。
authentication.oidc.oauthCredentialsSecret Secret 參照 Kubernetes Opaque 類型 Secret,其中包含 JSON 酬載中的 OAuth2 OIDC 用戶端 ID 和用戶端密鑰。
authentication.oidc.issuerURI 在輸出 RCToken 中做為核發者的 URI。
authentication.oidc.proxy OIDC IDP 的 Proxy 伺服器 (如適用),格式為 http://user:password@10.10.10.10:8888。
authentication.oidc.redirectURIHost 用於 OAuth 終止 URI 的主機。如果留空,系統會使用目標網址的主機,並動態組合重新導向 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 範圍。以逗號分隔的 ID 清單,用於指定除了「openid」範圍外,還要要求哪些存取權限,例如 「groups,allatclaim」。
authentication.oidc.groupsClaim 如果 idtoken 包含群組要求,請使用這個欄位指明其名稱。如果指定,服務會將這項憑證附加資訊中的資料,傳遞至輸出 RCToken 的 groups 憑證附加資訊。這項要求應包含逗號分隔的清單字串,例如["group1", "group2"]。
authentication.oidc.attributeMapping 包含一或多個權杖附加資訊對應,後面接著 idtoken CEL 運算式。所有聲明都應由 assertion.X 參照,assertion 則參照原始 IDToken,例如 aud_copy: assertion.aud.
authentication.outputJWTAudience authservice 產生的 RCToken 目標對象。sidecar 可以根據這個目標對象值,驗證傳入的 RCToken。

疑難排解

  1. IDP 的網路存取權。

    可能記錄:error: TLS handshake failed.。

    如要驗證,請從附加至 istio-proxy 的臨時容器執行 curl,呼叫 IDP 核發者 URI。例如,請參閱「收集 Cloud Service Mesh 記錄檔」。

    如果無法連線,請檢查叢集的防火牆規則或其他網路設定。

  2. 根 CA 憑證。

    可能記錄:error: The server's TLS certificate did not match expectations.或error: TLS handshake failed.。

    確認 certificateAuthorityData 含有正確的根 CA 憑證。如果沒有 HTTPS Proxy 終止 HTTPS 流量,這個欄位應包含 IDP 的根 CA 憑證。如果有的話,這應該會保留 Proxy 的。

  3. 重新導向路徑設定。

    可能觀察到的現象:在 OIDC 驗證流程中收到 404 錯誤頁面。

    使用者驗證會傳回「Set-Cookie」標頭,而不使用路徑屬性,瀏覽器預設會將要求網址的目錄做為 Cookie 路徑 (與路徑相關的 Cookie 範圍)。因此,除非您有意為之,否則建議不要在重新導向路徑中加入「/」。

  4. sidecar 無法擷取 jwksUri。

    在某些情況下,sidecar 限制可能會導致無法擷取 jwksUri。如果命名空間未使用萬用字元 (例如 ./* 或 istio-system/*),則無法運作。您必須在輸出 Sidecar 中手動新增其命名空間。

常見問題

  1. 如何升級已啟用使用者驗證的 Cloud Service Mesh?

    按照 Cloud Service Mesh 升級程序操作,並在指令列中新增 --custom_overlay user-auth-overlay.yaml 至 asmcli install,指定疊加檔案。

  2. 我們應該為 authservice 佈建多少資源?每秒可處理多少要求?

    根據預設,authservice 設有 2.0 個 vCPU 和 256 MiB 記憶體。在這種設定下,authservice 每秒可處理 500 個要求。如要處理大量要求,請佈建更多 CPU,這與要求處理能力大致成正比。您也可以設定多個 authservice 副本,提高水平擴充能力。