授權政策總覽

Cloud Service Mesh 的授權政策可讓您控管應用程式 (L7) 和傳輸 (L3/4) 層的工作負載存取權。您可以設定 AuthorizationPolicy 自訂資源 (CR),指定精細權限,定義服務或使用者可執行的動作。

由於 Kubernetes Pod 使用暫時性 IP 位址,因此傳統以 IP 為基礎的防火牆規則,不足以保護分散式微服務之間的流量。授權政策以 Kubernetes 服務帳戶和 Istio 安全性政策為基礎,可跨網路邊界強制執行以身分為準的存取控管。

授權政策

根據預設,網格中服務之間 (以及使用者與服務之間) 的要求皆可通過。您可以使用 AuthorizationPolicy CR 為工作負載定義精細政策。套用授權政策後,Cloud Service Mesh 會將政策發布至 Sidecar Proxy。當要求進入工作負載時,Sidecar Proxy 會檢查授權政策,判斷是否應允許或拒絕要求。

如要進一步瞭解平台支援 AuthorizationPolicy CR 的哪些欄位,請參閱「支援的功能」。

政策範圍

您可以將政策套用至整個服務網格、命名空間或個別工作負載。

  • 如要套用網格層級政策,請在 metadata:namespace 欄位中指定根命名空間 istio-system:

    apiVersion: "security.istio.io/v1beta1"
    kind: "AuthorizationPolicy"
    metadata:
      name: "mesh-wide"
      namespace: istio-system
    spec:
    ...
    
  • 如要將政策套用至命名空間,請在 metadata:namespace 欄位中指定命名空間:

    apiVersion: "security.istio.io/v1beta1"
    kind: "AuthorizationPolicy"
    metadata:
      name: "currencyservice"
      namespace: currencyservice
    spec:
    ...
    
  • 如要將政策限制在特定工作負載,請加入 selector 欄位。

    apiVersion: "security.istio.io/v1beta1"
    kind: "AuthorizationPolicy"
    metadata:
      name: "frontend"
      namespace: demo
    spec:
      selector:
        matchLabels:
          app: frontend
       ...
    

基本結構

授權政策包含政策範圍、action 和 rules 清單:

  • 如上一節所述,政策範圍可以是整個網格、命名空間或特定工作負載。如果加入這個欄位,selector 欄位會指定政策的目標。

  • action 欄位指定要ALLOW還是DENY要求。如未指定動作,系統預設會將動作設為 ALLOW。為求明確,建議您一律指定動作。(授權政策也支援 AUDIT 和 CUSTOM 動作。只有部分平台支援AUDIT動作。詳情請參閱「支援的功能」。)

  • rules 指定觸發動作的時間。

    • rules 中的 from 欄位會指定要求的來源。

    • rules 中的 to 欄位會指定要求的作業。

    • when 欄位會指定套用規則所需的其他條件。

在下列範例中:

  • 這項政策會套用至 demo 命名空間中傳送至 frontend 服務的要求。

  • 如果要求標頭中包含「hello:world」,系統就會允許要求,否則會拒絕要求。

apiVersion: "security.istio.io/v1beta1"
kind: "AuthorizationPolicy"
metadata:
  name: "hello-world"
  namespace: demo
spec:
  selector:
    matchLabels:
      app: frontend
  action: ALLOW
  rules:
  - when:
    - key: request.headers[hello]
      values: ["world"]

要求作業的存取控管

您可以在 rules 下方新增 to 區段,控管特定要求作業 (例如 HTTP 方法或 TCP 通訊埠) 的存取權。在以下範例中,只有 GET 和 POST HTTP 方法可以存取 demo 命名空間中的 currencyservice。

apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
 name: currencyservice
 namespace: demo
spec:
 selector:
   matchLabels:
     app: currencyservice
 action: ALLOW
 rules:
 - to:
   - operation:
       methods: ["GET", "POST"]

對已驗證身分進行存取控管

在上述範例中,政策允許來自未經驗證工作負載的要求。如果您已啟用STRICT雙向 TLS (mTLS),則可在source部分,根據要求來源的工作負載或命名空間身分限制存取權。

  • 使用 principals 或 notPrincipal 欄位,在工作負載層級控管存取權。

  • 使用 namespaces 或 notNamespaces 欄位,在命名空間層級控管存取權。

上述所有欄位都必須啟用 STRICT mTLS。如果無法設定 STRICT mTLS,請參閱「拒絕明文要求」一節,瞭解替代解決方案。

找到的工作負載

在以下範例中,只有 frontend 服務可以向 currencyservice 傳送要求。來自其他工作負載的 currencyservice 要求會遭到拒絕。

apiVersion: "security.istio.io/v1beta1"
kind: "AuthorizationPolicy"
metadata:
  name: "currencyservice"
  namespace: demo
spec:
  selector:
    matchLabels:
      app: currencyservice
  action: ALLOW
  rules:
  - from:
    - source:
        principals: ["example-project-1234.svc.id.goog/ns/demo/sa/frontend-sa"]

如要指定服務帳戶,principals 必須採用下列格式:

principals: ["PROJECT_ID.svc.id.goog/ns/NAMESPACE/sa/SERVICE_ACCOUNT_NAME"]

如果您使用叢集內 Cloud Service Mesh 搭配 Citadel CA,則 cluster.local 是信任網域。在所有其他情況下,PROJECT_ID.svc.id.goog是網格的信任網域。

信任網域對應至系統的信任根,是 Workload Identity 的一部分。Cloud Service Mesh 會使用信任網域,在網格中建立所有身分。舉例來說,在 SPIFFE ID spiffe://mytrustdomain.com/ns/default/sa/myname 中,子字串 mytrustdomain.com 指定工作負載來自名為 mytrustdomain.com 的信任網域。

使用 Cloud Service Mesh 憑證授權單位時,Cloud Service Mesh 會自動產生信任網域。這項設定是根據叢集的工作負載集區而定。

只要叢集共用相同的信任根,多叢集網格中就能有一或多個信任網域。

已識別的命名空間

以下範例顯示的政策會拒絕來源不是 foo 命名空間的要求:

apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
 name: httpbin-deny
 namespace: foo
spec:
 selector:
   matchLabels:
     app: httpbin
     version: v1
 action: DENY
 rules:
 - from:
   - source:
       notNamespaces: ["foo"]

值比對

授權政策中的多數欄位都支援下列所有比對結構定義:

  • 完全比對:完全比對字串。
  • 使用 "*" 萬用字元進行萬用字元比對:
    • 前置字元比對:以 "*" 結尾的字串。舉例來說,"test.example.*" 與 "test.example.com" 或 "test.example.com.cn" 相符。
    • 後置字串比對:以 "*" 開頭的字串。舉例來說,"*.example.com" 與 "eng.example.com" 或 "test.eng.example.com" 相符。
  • 存在比對:如要指定欄位必須存在且不得為空白,請使用 fieldname: ["*"] 格式。這與不指定欄位不同,不指定欄位代表比對任何內容,包括空白。

但有幾種情況例外。舉例來說,下列欄位僅支援完全比對:

  • 「when」部分下方的「key」欄位
  • 「source」部分下方的「ipBlocks」
  • 「to」部分下方的「ports」欄位

以下範例政策允許存取前置字串為 /test/* 或後置字串為 */info 的路徑:

apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: tester
  namespace: default
spec:
  selector:
    matchLabels:
      app: products
  action: ALLOW
  rules:
  - to:
    - operation:
        paths: ["/test/*", "*/info"]

排除條件比對

如要比對 when 欄位中的 notValues、source 欄位中的 notIpBlocks、to 欄位中的 notPorts 等負面條件,Cloud Service Mesh 支援排除比對。如果要求路徑不是 /healthz,下列範例需要有效的要求 principals,該要求衍生自 JWT 驗證。因此,這項政策會將傳送至 /healthz 路徑的要求排除在 JWT 驗證之外:

apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: disable-jwt-for-healthz
  namespace: default
spec:
  selector:
    matchLabels:
      app: products
  action: ALLOW
  rules:
  - to:
    - operation:
        notPaths: ["/healthz"]
    from:
    - source:
        requestPrincipals: ["*"]

拒絕明文要求

Cloud Service Mesh 預設會啟用自動 mTLS。啟用自動 mTLS 後,用戶端 Sidecar Proxy 會自動偵測伺服器是否有 Sidecar。用戶端 Sidecar 會將 mTLS 傳送至具有 Sidecar 的工作負載,並將純文字傳送至沒有 Sidecar 的工作負載。為確保最佳安全性,建議您啟用 STRICT mTLS。

如果無法為工作負載或命名空間啟用 STRICT 模式的 mTLS,可以採取下列做法:

  • 建立授權政策,明確允許 namespaces 或 principals 非空白的流量,或
  • 拒絕 namespaces 或 principals 為空的流量。

由於 namespaces 和 principals 只能透過 mTLS 要求擷取,因此這些政策會有效拒絕任何純文字流量。

如果要求中的主體為空白 (明文要求即是如此),下列政策會拒絕要求。如果主體不為空白,政策就會允許要求。["*"] 表示非空白比對,與 notPrincipals 搭配使用則表示比對空白主體。

apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: require-mtls
  namespace: NAMESPACE
spec:
  action: DENY
  rules:
  - from:
    - source:
        notPrincipals: ["*"]

授權政策優先順序

您可以分別設定 ALLOW 和 DENY 授權政策,但必須瞭解政策優先順序和預設行為,確保政策能發揮預期效果。下圖說明政策優先順序。

授權政策優先順序

以下各節的範例政策說明瞭一些預設行為,以及可能適用的情況。

全部禁止

以下範例顯示不符合任何項目的 ALLOW 政策。根據預設,如果沒有其他 ALLOW 政策,要求一律會遭拒。

apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: allow-nothing
spec:
  action: ALLOW

建議您先採用「不允許任何項目」政策,然後逐步新增更多 ALLOW 政策,開放更多工作負載存取權,這是良好的安全性做法。

拒絕所有存取權

以下範例顯示比對所有項目的 DENY 政策。由於系統會在評估 ALLOW 政策前先評估 DENY 政策,因此即使有與要求相符的 ALLOW 政策,所有要求仍會遭拒。

apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: deny-all
spec:
  action: DENY
  rules:
  - {}

如要暫時停用工作負載的所有存取權,可以使用「全部拒絕」政策。

允許超級 VIP

以下範例顯示比對所有項目的 ALLOW 政策,並允許完整存取工作負載。「全部允許」政策一律會允許要求,因此其他 ALLOW 政策會失效。

apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: allow-all
spec:
  action: ALLOW
  rules:
  - {}

如要暫時公開工作負載的完整存取權,可以使用「全部允許」政策。如果存在任何 DENY 政策,系統會先評估 DENY 政策,再評估 ALLOW 政策,因此要求仍可能遭到拒絕。

最佳做法

  1. 為每項服務建立 Kubernetes 服務帳戶,並在 Deployment 中指定服務帳戶。例如:

    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: frontend-sa
      namespace: demo
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: frontend
      namespace:demo
    spec:
      selector:
        matchLabels:
          app: frontend
      template:
        metadata:
          labels:
            app: frontend
        spec:
          serviceAccountName: frontend-sa
        ...
    
  2. 首先,請採用不允許任何存取權的政策,然後逐步新增更多 ALLOW 政策,開放更多工作負載存取權。

  3. 如果服務使用 JWT:

    1. 建立 DENY 政策來封鎖未經驗證的要求,例如:

      apiVersion: security.istio.io/v1beta1
      kind: AuthorizationPolicy
      metadata:
        name: requireJWT
        namespace: admin
      spec:
        action: DENY
        rules:
        -  from:
          - source:
              notRequestPrincipals: ["*"]
      
    2. 套用「不允許任何項目」政策。

    3. 為每個工作負載定義 ALLOW 政策。如需範例,請參閱「JWT 權杖」。

後續步驟

進一步瞭解 Cloud Service Mesh 安全防護功能:

如要進一步瞭解授權政策,請參閱 Istio 說明文件: