应用服务网格

使用OPA策略引擎实现访问控制

2025-08-14 02:46:29

3.7.8.3使用OPA策略引擎实现访问控制

前提条件:

1. 开通云容器引擎

2. 开通服务网格实例

开通实例后,系统默认生成OPA相关的ServiceEntry和opa-ext-auth-grpc

 

l验证opa-ext-auth-grpc:

在服务网格控制台->网格安全中心->自定义授权服务。

可以看到产生了一个GRPC协议的授权服务,端口为19191

 

l验证ServiceEntry

在服务网格控制台->集群与工作负载->服务条目中,选定istio-system命名空间,可以看到产生了ext-authz,点击编辑可以查看详情。

 

 

 

 

详情中可以看到端口为19191端口,指向127.0.0.1

 

 

l全局放行18181和18282端口:

sidecar管理->sidecar代理配置菜单下选择命名空间tab,选择我们验证功能要用的命名空间,这里选择default,配置sidecar入流量不拦截18181和18282端口(OPA agent的配置端口和健康检查端口)

 

 

开启OPA功能

操作步骤:

1. 在服务网格控制台->网格管理->OPA功能开关菜单下打开OPA开关,主要是安装OPA控制面组件

 

2. default命名空间打上标签,自动注入istio sidecar和OPA sidecar

kubectl label namespace default opa-istio-injection="enabled"

kubectl label namespace default istio-injection="enabled"

3. 部署bookinfo应用和sleep应用,可以看到pod里除了业务容器之外还有两个容器,分别是istio sidecar和OPA sidecar,OPA sidecar用于实现外部授权服务

 

 

4. 定义AuthorizationPolicy授权策略,注意引用的外部授权服务需要和上面定义的外部授权服务名称一致,可以根据业务的需要执行OPA外部授权策略,如下示例对匹配标签app: productpage的:

apiVersion: security.istio.io/v1beta1

kind: AuthorizationPolicy

metadata:

  name: ext-authz

spec:

  selector:

    matchLabels:

      app: productpage

  action: CUSTOM

  provider:

    # The provider name must match the extension provider defined in the mesh config.

    # You can also replace this with sample-ext-authz-http to test the other external authorizer definition.

    name: opa-ext-authz-grpc

  rules:

  # The rules specify when to trigger the external authorizer.

  - to:

    - operation:

        paths: ["/*"]

5. 上面的配置中,我们通过workloadSelector指定对productpage应用进行访问授权,我们从sleep应用发起请求,访问productpage,此时采用默认OPA策略,请求总是被拒绝

kubectl exec $(kubectl get pod -l app=sleep -o jsonpath={.items..metadata.name} -n default) -c istio-proxy -n default -- curl http://productpage.default:9080/api/v1/products  --user bob:password -o /dev/null -s -w '%{http_code}\n'

403

6. 配置OPA策略:以下OPA策略定义了guest和admin角色,guest和admin可以使用GET方法访问/productpage路径,admin另外还可以使用GET方法访问/api/v1/products路径;外部访问时会先解析出用户名,获取用户角色,进一步获取用户访问权限,并与请求进行比对,满足条件则放过,否则拦截

apiVersion: istio.ctyun.cn/v1beta1

kind: OpaPolicy

metadata:

  name: object-policy

  namespace: default

spec:

  policy: |-

    package istio.authz

    import input.attributes.request.http as http_request

    import input.parsed_path

 

    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 = {

        "alice": ["guest"],

        "bob": ["admin"]

    }

 

    role_perms = {

        "guest": [

            {"method": "GET",  "path": "/productpage"},

        ],

        "admin": [

            {"method": "GET",  "path": "/productpage"},

            {"method": "GET",  "path": "/api/v1/products"},

        ],

    }

  workloadSelector:

    labels:

      version: v1

7. 验证

bob的身份访问/api/v1/products和/productpage,由于bob是admin权限,两个路径都可以访问,返回200

kubectl exec $(kubectl get pod -l app=sleep -o jsonpath={.items..metadata.name} -n default) -c istio-proxy -n default -- curl http://productpage.default:9080/api/v1/products  --user bob:password -o /dev/null -s -w '%{http_code}\

n'

200

kubectl exec $(kubectl get pod -l app=sleep -o jsonpath={.items..metadata.name} -n default) -c istio-proxy -n default -- curl http://productpage.default:9080/productpage  --user bob:password -o /dev/null -s -w '%{http_code}\n'

200

 

alice的身份访问/api/v1/products和/productpage,由于alice是guest权限,所以对/api/v1/products的访问会被拒绝,返回403;对/productpage的访问可以通过,返回200

kubectl exec $(kubectl get pod -l app=sleep -o jsonpath={.items..metadata.name} -n default) -c istio-proxy -n default -- curl http://productpage.default:9080/api/v1/products  --user alice:password -o /dev/null -s -w '%{http_code

}\n'

403

kubectl exec $(kubectl get pod -l app=sleep -o jsonpath={.items..metadata.name} -n default) -c istio-proxy -n default -- curl http://productpage.default:9080/productpage  --user alice:password -o /dev/null -s -w '%{http_code}\n'

200

8. 修改OPA策略,给alice加上admin权限

user_roles = {

    "alice": ["guest", "admin"],

    "bob": ["admin"]

}

重新验证以alice身份访问/api/v1/products,返回200

kubectl exec $(kubectl get pod -l app=sleep -o jsonpath={.items..metadata.name} -n default) -c istio-proxy -n default -- curl http://productpage.default:9080/api/v1/products  --user alice:password -o /dev/null -s -w '%{http_code}\n'

200

 


waMKm5lqTv.r