在ASM中實現(xiàn)動態(tài)更新OPA策略
服務(wù)網(wǎng)格ASM集成了開放策略代理(OPA)插件,通過OPA定義訪問控制策略,可以使您的應(yīng)用實現(xiàn)細(xì)粒度的訪問控制。v1.8.6.41及以上版本的ASM還支持通過配置ConfigMap將OPA策略自動推送到容器中,實現(xiàn)動態(tài)更新OPA策略。本文介紹如何在ASM中實現(xiàn)動態(tài)更新OPA策略。
前提條件
已創(chuàng)建ASM實例,且ASM實例為v1.8.6.41-gb1d8f288-aliyun及以上版本。具體操作,請參見創(chuàng)建ASM實例。
- 已創(chuàng)建Kubernetes托管版集群。具體操作,請參見創(chuàng)建Kubernetes托管版集群。
- 已添加集群到ASM實例。具體操作,請參見添加集群到ASM實例。
背景信息
作為由CNCF托管的一個孵化項目,開放策略代理(OPA)是一個策略引擎,可用于為您的應(yīng)用程序?qū)崿F(xiàn)細(xì)粒度的訪問控制。OPA作為通用策略引擎,可以與微服務(wù)一起部署為獨立服務(wù)。為了保護應(yīng)用程序,必須先授權(quán)對微服務(wù)的每個請求,然后才能對其進行處理。為了檢查授權(quán),微服務(wù)對OPA進行API調(diào)用,以確定請求是否被授權(quán)。
步驟一:啟用OPA插件
登錄ASM控制臺。
在左側(cè)導(dǎo)航欄,選擇 。
在網(wǎng)格管理頁面,找到待配置的實例,單擊實例的名稱或在操作列中單擊管理。
在基本信息頁面單擊右上角的功能設(shè)置。
在功能設(shè)置更新頁面中選中啟用OPA插件。
單擊確定。
在基本信息頁面可以看到OPA插件的狀態(tài)變?yōu)?b data-tag="uicontrol" id="uicontrol-3gc-s0y-fv4" class="uicontrol">開啟。
步驟二:設(shè)置ConfigMap
服務(wù)網(wǎng)格ASM支持動態(tài)更新OPA策略,您可以配置包含openpolicyagent.org/policy=rego
標(biāo)簽的ConfigMap,該策略會被自動推送到所有命名空間中注入了OPA代理容器的Pod。移除該ConfigMap時,策略也會從Pod中移除。
OPA定義一個Pod的OPA策略時,只允許有一條
default allow
字段。如果多個OPA策略相關(guān)的ConfigMap生效于一個Pod,且每個策略中都定義了default allow
字段,則多條default allow
字段會導(dǎo)致動態(tài)更新失敗。OPA代理容器啟動時需要依賴名為opa-policy的ConfigMap。如果該ConfigMap被刪除,相應(yīng)的OPA策略也會在OPA代理容器中被移除。重建該ConfigMap并不會使之生效,只能重建Pod。
創(chuàng)建名為opa-policy的ConfigMap。
OPA代理容器啟動時需要依賴名為opa-policy的ConfigMap。該ConfigMap有動態(tài)更新功能,推薦該ConfigMap只做基礎(chǔ)的策略配置,后續(xù)復(fù)雜策略配置通過其他ConfigMap動態(tài)添加。
使用以下內(nèi)容,創(chuàng)建名為opa-policy的YAML文件。
apiVersion: v1 kind: ConfigMap metadata: name: opa-policy data: policy.rego: | ### 該策略配置內(nèi)容所允許的path為opa策略動態(tài)推送依賴的,如不配置將導(dǎo)致動態(tài)更新策略失敗。 package istio.authz import input.parsed_path allow { parsed_path[0] = "v1" parsed_path[1] = "policies" }
執(zhí)行以下命令,創(chuàng)建ConfigMap。
kubectl apply -f opa-policy.yaml
創(chuàng)建名為opa-policy-add的ConfigMap。
使用該ConfigMap定義OPA策略。
使用以下內(nèi)容,創(chuàng)建名為opa-policy-add的YAML文件。
apiVersion: v1 kind: ConfigMap metadata: name: opa-policy-add labels: ### 請注意配置label,只有該帶label的ConfigMap才會作為policy進行動態(tài)更新。 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:為用戶授予角色權(quán)限。本例設(shè)置guest1擁有g(shù)uest角色權(quán)限,admin1擁有admin角色權(quán)限。
role_perms:設(shè)置角色擁有的權(quán)限。本文設(shè)置guest角色可以通過/productpage訪問應(yīng)用,admin角色可以通過/productpage和/api/v1/products訪問應(yīng)用。
執(zhí)行以下命令,創(chuàng)建ConfigMap。
kubectl apply -f opa-policy-add.yaml
執(zhí)行以下命令,查看策略推送結(jié)果。
策略推送結(jié)果會更新在ConfigMap的
annotations
。kubectl get configmap opa-policy-add -o yaml
在返回結(jié)果中查看ConfigMap:
如果推送成功,則會在ConfigMap中看到以下信息。
openpolicyagent.org/policy-status: '{"status":"ok"}'
如果推送失敗,則會有相應(yīng)錯誤信息。
步驟三:注入OPA代理
部署示例應(yīng)用Bookinfo到ASM實例,確認(rèn)每個Pod都注入了OPA代理。
部署示例應(yīng)用Bookinfo到ASM實例,請參見部署應(yīng)用到ASM實例。
定義相應(yīng)的Istio虛擬服務(wù)和入口網(wǎng)關(guān),請參見使用Istio資源實現(xiàn)版本流量路由。
檢查每個應(yīng)用是否都注入OPA代理。
- 登錄容器服務(wù)管理控制臺。
- 在控制臺左側(cè)導(dǎo)航欄,單擊集群。
- 在集群列表頁面,單擊目標(biāo)集群名稱或者目標(biāo)集群右側(cè)操作列下的詳情。
- 在集群管理頁左側(cè)導(dǎo)航欄,選擇 。
在容器組頁面,從命名空間下拉列表中選擇default,單擊目標(biāo)應(yīng)用容器組的名稱。
在容器頁簽下可以看到容器被注入了Sidecar代理(istio-proxy)和OPA代理(opa-istio)。依次檢查每個應(yīng)用的容器,確保每個容器都被注入了Sidecar代理和OPA代理。
步驟四:驗證使用OPA定義訪問控制策略是否成功。
執(zhí)行以下命令,可以看到guest1被授予guest角色,并且可以使用帶有/productpage的URL訪問應(yīng)用,但不能使用帶有/v1/api/products的URL訪問應(yīng)用。
curl -X GET http://<入口網(wǎng)關(guān)服務(wù)的IP地址>/productpage --user guest1:password -I
預(yù)期輸出:
HTTP/1.1 200 OK
curl -X GET http://<入口網(wǎng)關(guān)服務(wù)的IP地址>/api/v1/products --user guest1:password -I
預(yù)期輸出:
HTTP/1.1 403 Forbidden
執(zhí)行以下命令,可以看到admin1被授予admin角色,并且可以使用帶有/productpage和/v1/api/products的URL訪問應(yīng)用。
curl -X GET http://<入口網(wǎng)關(guān)服務(wù)的IP地址>/productpage --user admin1:password -I
預(yù)期輸出:
HTTP/1.1 200 OK
curl -X GET http://<入口網(wǎng)關(guān)服務(wù)的IP地址>/api/v1/products --user admin1:password -I
預(yù)期輸出:
HTTP/1.1 200 OK
根據(jù)以上結(jié)果,可以看到OPA定義訪問控制策略是成功的。
步驟五:動態(tài)更新OPA策略
在ACK集群上執(zhí)行以下命令,更新名為opa-policy-add的ConfigMap。
kubectl replace -n {替換成實際的namespace} -f - <<EOF apiVersion: v1 kind: ConfigMap metadata: name: opa-policy-add labels: ### 請注意配置label,只有該帶label的ConfigMap才會作為policy進行動態(tài)更新。 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:為用戶授予角色權(quán)限。本例設(shè)置guest1同時擁有g(shù)uest和admin角色權(quán)限,admin1擁有admin角色權(quán)限。
role_perms:設(shè)置角色擁有的權(quán)限。本例設(shè)置guest角色可以通過/productpage訪問應(yīng)用,admin角色可以通過/productpage和/api/v1/products訪問應(yīng)用。
執(zhí)行以下命令,查看策略推送結(jié)果。
策略推送結(jié)果會更新在ConfigMap的
annotations
。kubectl get configmap opa-policy-add -o yaml
在返回結(jié)果中查看ConfigMap:
如果推送成功,則會在ConfigMap中看到以下信息。
openpolicyagent.org/policy-status: '{"status":"ok"}'
如果推送失敗,則會有相應(yīng)錯誤信息。
步驟六:驗證動態(tài)更新OPA策略是否成功
執(zhí)行以下命令,可以看到guest1被授予了admin角色,此時可以使用/productpage和/v1/api/products訪問應(yīng)用。
curl -X GET http://<入口網(wǎng)關(guān)服務(wù)的IP地址>/productpage --user guest1:password -I
預(yù)期輸出:
HTTP/1.1 200 OK
curl -X GET http://<入口網(wǎng)關(guān)服務(wù)的IP地址>/api/v1/products --user guest1:password -I
預(yù)期輸出:
HTTP/1.1 200 OK
在沒有更新OPA策略之前,guest1只能使用帶有/productpage的URL訪問應(yīng)用,但不能使用帶有/v1/api/products的URL訪問應(yīng)用。更新OPA策略之后,guest1可以使用帶有/productpage和/v1/api/products的URL訪問應(yīng)用。說明動態(tài)更新OPA策略成功。