全部產品
Search
文件中心

:在ASM中實現動態更新OPA策略

更新時間:Jan 13, 2025

Service MeshASM整合了開放策略代理(OPA)外掛程式,通過OPA定義存取控制策略,可以使您的應用實現細粒度的存取控制。v1.8.6.41及以上版本的ASM還支援通過配置ConfigMap將OPA策略自動推送到容器中,實現動態更新OPA策略。本文介紹如何在ASM中實現動態更新OPA策略。

前提條件

背景資訊

作為由CNCF託管的一個孵化專案,開放策略代理(OPA)是一個策略引擎,可用於為您的應用程式實現細粒度的存取控制。OPA作為通用策略引擎,可以與微服務一起部署為獨立服務。為了保護應用程式,必須先授權對微服務的每個請求,然後才能對其進行處理。為了檢查授權,微服務對OPA進行API調用,以確定請求是否被授權。OPA

步驟一:啟用OPA外掛程式

  1. 登入ASM控制台

  2. 在左側導覽列,選擇服務網格 > 網格管理

  3. 網格管理頁面,找到待配置的執行個體,單擊執行個體的名稱或在操作列中單擊管理

  4. 基本資料頁面單擊右上方的功能設定

  5. 功能設定更新頁面中選中啟用OPA外掛程式

  6. 單擊確定

    基本資料頁面可以看到OPA外掛程式的狀態變為開啟

步驟二:設定ConfigMap

Service MeshASM支援動態更新OPA策略,您可以配置包含openpolicyagent.org/policy=rego標籤的ConfigMap,該策略會被自動推送到所有命名空間中注入了OPA代理容器的Pod。移除該ConfigMap時,策略也會從Pod中移除。

重要
  • OPA定義一個Pod的OPA策略時,只允許有一條default allow欄位。如果多個OPA策略相關的ConfigMap生效於一個Pod,且每個策略中都定義了default allow欄位,則多條default allow欄位會導致動態更新失敗。

  • OPA代理容器啟動時需要依賴名為opa-policy的ConfigMap。如果該ConfigMap被刪除,相應的OPA策略也會在OPA代理容器中被移除。重建該ConfigMap並不會使之生效,只能重建Pod。

  1. 步驟二:選擇叢集憑證類型

  2. 建立名為opa-policy的ConfigMap。

    OPA代理容器啟動時需要依賴名為opa-policy的ConfigMap。該ConfigMap有動態更新功能,推薦該ConfigMap只做基礎的策略配置,後續複雜策略配置通過其他ConfigMap動態添加。

    1. 使用以下內容,建立名為opa-policy的YAML檔案。

      apiVersion: v1
      kind: ConfigMap
      metadata:
        name: opa-policy
      data:
        policy.rego: | ### 該策略配置內容所允許的path為opa策略動態推送依賴的,如不配置將導致動態更新策略失敗。
          package istio.authz
      
          import input.parsed_path
          
          allow {
                  parsed_path[0] = "v1"
                  parsed_path[1] = "policies"
          }
    2. 執行以下命令,建立ConfigMap。

      kubectl apply -f opa-policy.yaml
  3. 建立名為opa-policy-add的ConfigMap。

    使用該ConfigMap定義OPA策略。

    1. 使用以下內容,建立名為opa-policy-add的YAML檔案。

      apiVersion: v1
      kind: ConfigMap
      metadata:
        name: opa-policy-add
        labels:
          ### 請注意配置label,只有該帶label的ConfigMap才會作為policy進行動態更新。
          openpolicyagent.org/policy: rego
      data:
        policy.rego: |  ###以下為樣本策略定義,需要替換成實際的策略定義。
          package istio.authz
          import input.attributes.request.http as http_request
          default allow = false
          allow {
              roles_for_user[r]
              required_roles[r]
          }
          roles_for_user[r] {
              r := user_roles[user_name][_]
          }
          required_roles[r] {
              perm := role_perms[r][_]
              perm.method = http_request.method
              perm.path = http_request.path
          }
          user_name = parsed {
              [_, encoded] := split(http_request.headers.authorization, " ")
              [parsed, _] := split(base64url.decode(encoded), ":")
          }
          user_roles = {
              "guest1": ["guest"],
              "admin1": ["admin"]
          }
          role_perms = {
              "guest": [
                  {"method": "GET",  "path": "/productpage"},
              ],
              "admin": [
                  {"method": "GET",  "path": "/productpage"},
                  {"method": "GET",  "path": "/api/v1/products"},
              ],
          }     
      • user_roles:為使用者授予角色許可權。本例設定guest1擁有guest角色許可權,admin1擁有admin角色許可權。

      • role_perms:設定角色擁有的許可權。本文設定guest角色可以通過/productpage訪問應用,admin角色可以通過/productpage/api/v1/products訪問應用。

    2. 執行以下命令,建立ConfigMap。

      kubectl apply -f opa-policy-add.yaml
  4. 執行以下命令,查看策略推送結果。

    策略推送結果會更新在ConfigMap的annotations

    kubectl get configmap  opa-policy-add -o yaml  

    在返回結果中查看ConfigMap:

    • 如果推送成功,則會在ConfigMap中看到以下資訊。

      openpolicyagent.org/policy-status: '{"status":"ok"}'
    • 如果推送失敗,則會有相應錯誤資訊。

步驟三:注入OPA代理

部署樣本應用Bookinfo到ASM執行個體,確認每個Pod都注入了OPA代理。

  1. 部署樣本應用Bookinfo到ASM執行個體,請參見部署應用到ASM執行個體

  2. 定義相應的Istio虛擬服務和入口網關,請參見使用Istio資源實現版本流量路由

  3. 檢查每個應用是否都注入OPA代理。

    1. 登入Container Service管理主控台

    2. 在控制台左側導覽列,單擊叢集

    3. 叢集列表頁面,單擊目的地組群名稱或者目的地組群右側操作列下的詳情

    4. 在叢集管理頁左側導覽列,選擇工作負載 > 容器組

    5. 容器組頁面,從命名空間下拉式清單中選擇default,單擊目標應用程式容器組的名稱。

      容器頁簽下可以看到容器被注入了Sidecar代理(istio-proxy)和OPA代理(opa-istio)。依次檢查每個應用的容器,確保每個容器都被注入了Sidecar代理和OPA代理。注入OPA代理

步驟四:驗證使用OPA定義存取控制策略是否成功。

  • 執行以下命令,可以看到guest1被授予guest角色,並且可以使用帶有/productpage的URL訪問應用,但不能使用帶有/v1/api/products的URL訪問應用。

    curl -X GET http://<入口網關服務的IP地址>/productpage --user guest1:password -I

    預期輸出:

    HTTP/1.1 200 OK
    curl -X GET http://<入口網關服務的IP地址>/api/v1/products --user guest1:password -I

    預期輸出:

    HTTP/1.1 403 Forbidden
  • 執行以下命令,可以看到admin1被授予admin角色,並且可以使用帶有/productpage和/v1/api/products的URL訪問應用。

    curl -X GET http://<入口網關服務的IP地址>/productpage --user admin1:password -I

    預期輸出:

    HTTP/1.1 200 OK
    curl -X GET http://<入口網關服務的IP地址>/api/v1/products --user admin1:password -I

    預期輸出:

    HTTP/1.1 200 OK

    根據以上結果,可以看到OPA定義存取控制策略是成功的。

步驟五:動態更新OPA策略

  1. 在ACK叢集上執行以下命令,更新名為opa-policy-add的ConfigMap。

    kubectl replace -n {替換成實際的namespace} -f - <<EOF
    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: opa-policy-add
      labels:
        ### 請注意配置label,只有該帶label的ConfigMap才會作為policy進行動態更新。
        openpolicyagent.org/policy: rego
    data:
      policy.rego: |  ###以下為樣本策略定義,需要替換成實際的策略定義。
        package istio.authz
        import input.attributes.request.http as http_request
        default allow = false
        allow {
            roles_for_user[r]
            required_roles[r]
        }
        roles_for_user[r] {
            r := user_roles[user_name][_]
        }
        required_roles[r] {
            perm := role_perms[r][_]
            perm.method = http_request.method
            perm.path = http_request.path
        }
        user_name = parsed {
            [_, encoded] := split(http_request.headers.authorization, " ")
            [parsed, _] := split(base64url.decode(encoded), ":")
        }
        user_roles = {
            "guest1": ["guest", "admin"],
            "admin1": ["admin"]
        }
        role_perms = {
            "guest": [
                {"method": "GET",  "path": "/productpage"},
            ],
            "admin": [
                {"method": "GET",  "path": "/productpage"},
                {"method": "GET",  "path": "/api/v1/products"},
            ],
        }
    EOF
    • user_roles:為使用者授予角色許可權。本例設定guest1同時擁有guest和admin角色許可權,admin1擁有admin角色許可權。

    • role_perms:設定角色擁有的許可權。本例設定guest角色可以通過/productpage訪問應用,admin角色可以通過/productpage/api/v1/products訪問應用。

  2. 執行以下命令,查看策略推送結果。

    策略推送結果會更新在ConfigMap的annotations

    kubectl get configmap  opa-policy-add -o yaml  

    在返回結果中查看ConfigMap:

    • 如果推送成功,則會在ConfigMap中看到以下資訊。

      openpolicyagent.org/policy-status: '{"status":"ok"}'
    • 如果推送失敗,則會有相應錯誤資訊。

步驟六:驗證動態更新OPA策略是否成功

執行以下命令,可以看到guest1被授予了admin角色,此時可以使用/productpage和/v1/api/products訪問應用。

curl -X GET http://<入口網關服務的IP地址>/productpage --user guest1:password -I

預期輸出:

HTTP/1.1 200 OK
curl -X GET http://<入口網關服務的IP地址>/api/v1/products --user guest1:password -I

預期輸出:

HTTP/1.1 200 OK

在沒有更新OPA策略之前,guest1隻能使用帶有/productpage的URL訪問應用,但不能使用帶有/v1/api/products的URL訪問應用。更新OPA策略之後,guest1可以使用帶有/productpage和/v1/api/products的URL訪問應用。說明動態更新OPA策略成功。