使用ASM安全策略接入外部OPA執(zhí)行引擎
ASM對(duì)Istio原生安全資源的場(chǎng)景進(jìn)行封裝,提供ASM安全策略功能,便于一站式配置常見的安全場(chǎng)景。ASM集成了開放策略代理(OPA)插件,通過OPA定義訪問控制策略,可以使您的應(yīng)用實(shí)現(xiàn)細(xì)粒度的訪問控制。本文介紹如何使用ASM安全策略接入外部OPA執(zhí)行引擎。
前提條件
已添加Kubernetes托管版集群到ASM實(shí)例,且ASM實(shí)例版本為1.15.3.25及以上。具體操作,請(qǐng)參見添加集群到ASM實(shí)例和升級(jí)ASM實(shí)例。
已部署httpbin應(yīng)用,且可以正常訪問。具體操作,請(qǐng)參見部署httpbin應(yīng)用。
default命名空間已開啟Sidecar自動(dòng)注入。具體操作,請(qǐng)參見開啟Sidecar自動(dòng)注入。
功能介紹
ASM目前默認(rèn)的OPA部署方式為Sidecar模式。當(dāng)開啟OPA之后,重啟應(yīng)用Pod,ASM就會(huì)在應(yīng)用Pod中注入一個(gè)OPA容器。此后,業(yè)務(wù)容器所有的請(qǐng)求都會(huì)經(jīng)過OPA Sidecar校驗(yàn)。Sidecar模式是完全的Pod內(nèi)部訪問,因此可以實(shí)現(xiàn)較低的延遲,適用于一些對(duì)延遲比較敏感的業(yè)務(wù)。
但是Sidecar模式存在一些弊端,例如資源占用、應(yīng)用接入需要重啟Pod、接入方式不夠靈活等。集中式OPA在這些方面可以和Sidecar模式的OPA形成互補(bǔ)。集中式OPA可以實(shí)現(xiàn)更低的資源占用、應(yīng)用無需重啟即可接入、自由決定到達(dá)應(yīng)用的哪些請(qǐng)求執(zhí)行OPA策略等。下文將介紹如何部署一個(gè)集中式的OPA授權(quán)服務(wù)并將其接入應(yīng)用。
步驟一:部署OPA
使用以下內(nèi)容,創(chuàng)建asm-opa.yaml文件。
YAML文件部署了一個(gè)OPA Service、OPA Deployment和Secret。
Kind
說明
Deployment
鏡像
registry-vpc.cn-hangzhou.aliyuncs.com/acs/opa:0.46.1-istio-3-static
請(qǐng)?zhí)鎿Q為您實(shí)際的集群地域。該OPA引擎默認(rèn)打開了日志
--set=decision_logs.console=true
,方便進(jìn)行調(diào)試。
Secret
Secret定義了OPA策略,含義如下:
如果請(qǐng)求路徑是
health
,放行請(qǐng)求。如果請(qǐng)求的方法是
HEAD
,放行請(qǐng)求。如果用戶名稱是
alice
,放行請(qǐng)求。說明用戶名稱來自請(qǐng)求的
Authorization
Header,形式為Authorization: Basic ${用戶名:密碼字符串的base64編碼}
。
apiVersion: v1 kind: Service metadata: name: asm-opa labels: app: opa spec: ports: - name: grpc port: 9191 targetPort: 9191 protocol: TCP - name: http port: 8181 targetPort: 8181 protocol: TCP selector: app: opa --- kind: Deployment apiVersion: apps/v1 metadata: name: opa labels: app: opa spec: replicas: 1 selector: matchLabels: app: opa template: metadata: labels: app: opa annotations: sidecar.istio.io/inject: "false" spec: containers: - name: opa image: registry-vpc.cn-hangzhou.aliyuncs.com/acs/opa:0.46.1-istio-3-static securityContext: runAsUser: 1111 volumeMounts: - readOnly: true mountPath: /policy name: opa-policy args: - "run" - "--server" - "--addr=0.0.0.0:8181" - "--diagnostic-addr=0.0.0.0:8282" - "--set=plugins.envoy_ext_authz_grpc.addr=:9191" - "--set=plugins.envoy_ext_authz_grpc.path=asm/authz/allow" - "--set=decision_logs.console=true" - "--ignore=.*" - "/policy/policy.rego" ports: - containerPort: 9191 protocol: TCP resources: limits: cpu: "0" memory: "0" volumes: - name: opa-policy secret: secretName: opa-policy --- apiVersion: v1 kind: Secret metadata: name: opa-policy type: Opaque stringData: policy.rego: | package asm.authz import future.keywords import input.attributes.request.http as http_request import input.parsed_path default allow := false allow if { parsed_path[0] == "health" } allow if { http_request.method == "HEAD" } allow if { user_name == "alice" } user_name := parsed if { [_, encoded] := split(http_request.headers.authorization, " ") [parsed, _] := split(base64url.decode(encoded), ":") }
使用ACK集群的KubeConfig,執(zhí)行以下命令,部署OPA。
kubectl apply -f asm-opa.yaml
步驟二:使用ASM安全策略接入OPA
登錄ASM控制臺(tái),在左側(cè)導(dǎo)航欄,選擇 。
在網(wǎng)格管理頁面,單擊目標(biāo)實(shí)例名稱,然后在左側(cè)導(dǎo)航欄,選擇 。
在ASM安全策略頁面,單擊創(chuàng)建,在創(chuàng)建ASM安全策略對(duì)話框,單擊自定義授權(quán)服務(wù)卡片,然后單擊確定。
配置自定義授權(quán)相關(guān)信息。
在創(chuàng)建自定義授權(quán)服務(wù)頁面,配置步驟一部署的OPA授權(quán)服務(wù)信息,然后單擊下一步。
在工作負(fù)載和匹配規(guī)則配置向?qū)В瑔螕?b data-tag="uicontrol" id="19afc0702d2ip" class="uicontrol">添加工作負(fù)載組,然后在新建工作負(fù)載組對(duì)話框,輸入工作負(fù)載組名稱,單擊添加工作負(fù)載。
在添加工作負(fù)載對(duì)話框,選中工作負(fù)載生效,命名空間選擇default,工作負(fù)載類型選擇Service,在選擇負(fù)載區(qū)域選中httpbin,單擊圖標(biāo),然后單擊確定。
在新建工作負(fù)載組對(duì)話框的匹配規(guī)則列表區(qū)域,匹配模式選擇選中請(qǐng)求必須經(jīng)過鑒權(quán),匹配規(guī)則選擇自定義匹配規(guī)則,打開HTTP路徑(Path)開關(guān)并配置為
/status/*
,然后單擊確定。在工作負(fù)載和匹配規(guī)則配置向?qū)В瑔螕?b data-tag="uicontrol" id="657a5a902d1q5" class="uicontrol">提交。
創(chuàng)建成功后,界面顯示如下。
步驟三:對(duì)httpbin應(yīng)用進(jìn)行訪問測(cè)試
執(zhí)行以下命令,訪問
/
路徑。curl ${ASM網(wǎng)關(guān)IP}/ -I -X GET
預(yù)期輸出:
HTTP/1.1 200 OK server: istio-envoy date: Tue, 25 Jul 2023 08:30:58 GMT content-type: text/html; charset=utf-8 content-length: 9593 access-control-allow-origin: * access-control-allow-credentials: true x-envoy-upstream-service-time: 2
預(yù)期輸出表明該路徑不需要鑒權(quán),直接通過。
執(zhí)行以下命令,未攜帶合法參數(shù),訪問
/status/201
路徑。curl ${ASM網(wǎng)關(guān)IP}/status/201 -I -X GET
預(yù)期輸出:
HTTP/1.1 403 Forbidden date: Tue, 25 Jul 2023 08:31:18 GMT server: istio-envoy content-length: 0 x-envoy-upstream-service-time: 1
預(yù)期輸出表明未攜帶合法參數(shù),請(qǐng)求被拒絕。
執(zhí)行以下命令,攜帶合法參數(shù),訪問
/status/201
路徑。curl ${ASM網(wǎng)關(guān)IP}/status/201 -I -X GET --user alice:testpassword
預(yù)期輸出:
HTTP/1.1 201 Created server: istio-envoy date: Tue, 25 Jul 2023 08:31:38 GMT content-type: text/html; charset=utf-8 access-control-allow-origin: * access-control-allow-credentials: true content-length: 0 x-envoy-upstream-service-time: 3
預(yù)期輸出表明攜帶合法參數(shù),請(qǐng)求通過。
步驟四:更新OPA策略
調(diào)用OPA引擎的HTTP接口,更新OPA策略。
執(zhí)行以下命令,要求只有bob用戶才可以正常訪問HTTP,之前的alice用戶不能訪問。
kubectl exec deployment/httpbin -c istio-proxy -- curl asm-opa:8181/v1/policies/policy/policy.rego -XPUT --data-binary 'package asm.authz import future.keywords import input.attributes.request.http as http_request import input.parsed_path default allow := false allow if { parsed_path[0] == "health" } allow if { http_request.method == "HEAD" } allow if { user_name == "bob" } user_name := parsed if { [_, encoded] := split(http_request.headers.authorization, " ") [parsed, _] := split(base64url.decode(encoded), ":") }'
執(zhí)行以下命令,使用bob用戶訪問httpbin。
curl ${ASM網(wǎng)關(guān)IP}/status/201 -I -X GET --user bob:testpassword
預(yù)期輸出:
HTTP/1.1 201 Created server: istio-envoy date: Tue, 25 Jul 2023 08:32:16 GMT content-type: text/html; charset=utf-8 access-control-allow-origin: * access-control-allow-credentials: true content-length: 0 x-envoy-upstream-service-time: 3
預(yù)期輸出表明bob用戶訪問成功。
執(zhí)行以下命令,使用alice用戶訪問httpbin。
curl ${ASM網(wǎng)關(guān)IP}/status/201 -I -X GET --user alice:testpassword
預(yù)期輸出:
HTTP/1.1 403 Forbidden date: Tue, 25 Jul 2023 08:32:49 GMT server: istio-envoy content-length: 0 x-envoy-upstream-service-time: 1
預(yù)期輸出表明alice用戶訪問被禁止。