应用服务网格

自定义授权服务

2025-08-14 02:40:36

前提条件:

1. 开通云容器引擎

2. 开通服务网格实例

 

操作步骤:

1. 创建测试命名空间

kubectl create ns foo

# 打开sidecar自动注入

kubectl label ns foo istio-injection=enabled

2. 部署sleep和httpbin应用

apiVersion: v1

kind: ServiceAccount

metadata:

  name: sleep

---

apiVersion: v1

kind: Service

metadata:

  name: sleep

  labels:

    app: sleep

    service: sleep

spec:

  ports:

  - port: 80

    name: http

  selector:

    app: sleep

---

apiVersion: apps/v1

kind: Deployment

metadata:

  name: sleep

spec:

  replicas: 1

  selector:

    matchLabels:

      app: sleep

  template:

    metadata:

      labels:

        app: sleep

    spec:

      terminationGracePeriodSeconds: 0

      serviceAccountName: sleep

      containers:

      - name: sleep

        image: registry-vpc-crs-huadong1.cnsp-internal.ctyun.cn/library/curl

        command: ["/bin/sleep", "infinity"]

        imagePullPolicy: IfNotPresent

        volumeMounts:

        - mountPath: /etc/sleep/tls

          name: secret-volume

      volumes:

      - name: secret-volume

        secret:

          secretName: sleep-secret

          optional: true

---

 

3. 部署外部授权服务

apiVersion: v1

kind: Service

metadata:

  name: ext-authz

  labels:

    app: ext-authz

spec:

  ports:

  - name: http

    port: 8000

    targetPort: 8000

  - name: grpc

    port: 9000

    targetPort: 9000

  selector:

    app: ext-authz

---

apiVersion: apps/v1

kind: Deployment

metadata:

  name: ext-authz

spec:

  replicas: 1

  selector:

    matchLabels:

      app: ext-authz

  template:

    metadata:

      labels:

        app: ext-authz

    spec:

      containers:

      - image:registry-vpc-crs-huadong1.cnsp-internal.ctyun.cn/library/ext-authz:1.16.2

        imagePullPolicy: IfNotPresent

        name: ext-authz

        ports:

        - containerPort: 8000

        - containerPort: 9000

---

apiVersion: v1

kind: ServiceAccount

metadata:

  name: httpbin

---

apiVersion: v1

kind: Service

metadata:

  name: httpbin

  labels:

    app: httpbin

    service: httpbin

spec:

  ports:

  - name: http

    port: 8000

    targetPort: 80

  selector:

    app: httpbin

---

apiVersion: apps/v1

kind: Deployment

metadata:

  name: httpbin

spec:

  replicas: 1

  selector:

    matchLabels:

      app: httpbin

      version: v1

  template:

    metadata:

      labels:

        app: httpbin

        version: v1

    spec:

      serviceAccountName: httpbin

      containers:

      - image: registry-vpc-crs-huadong1.cnsp-internal.ctyun.cn/library/httpbin

        imagePullPolicy: IfNotPresent

        name: httpbin

        ports:

        - containerPort: 80

 

部署完成后,在foo命名空间下看到3个服务

不使用授权策略的情况下,验证从sleep应用访问httpbin应用没有被拦截(返回状态码200):

kubectl exec "$(kubectl get pod -l app=sleep -n foo -o jsonpath={.items..metadata.name})" -c sleep -n foo -- curl http://httpbin.foo:8000/ip -s -o /dev/null -w "%{http_code}\n"

 

200

 

查看外部授权服务已经启动,HTTP和gRPC授权服务分别监听80009000端口:

kubectl logs "$(kubectl get pod -l app=ext-authz -n foo -o jsonpath={.items..metadata.name})" -n foo -c ext-authz

 

2023/08/14 11:26:54 Starting HTTP server at [::]:8000

2023/08/14 11:26:54 Starting gRPC server at [::]:9000

 

1. 添加外部授权服务

将上面的HTTP和gRPC服务添加到服务网格的外部授权服务内

 

2. 定义授权策略&验证访问

定义如下授权策略,对httpbin应用的/headers路径的请求将被转发到第三方授权服务进行验证:

apiVersion: security.istio.io/v1beta1

kind: AuthorizationPolicy

metadata:

  name: ext-authz

spec:

  selector:

    matchLabels:

      app: httpbin

  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: sample-ext-authz-grpc

  rules:

  # The rules specify when to trigger the external authorizer.

  - to:

    - operation:

        paths: ["/headers"]

 

sleep应用请求httpbin的/headers路径,由于请求头带了"x-ext-authz: deny",请求被拦截:

kubectl exec "$(kubectl get pod -l app=sleep -n foo -o jsonpath={.items..metadata.name})" -c sleep -n foo -- curl "http://httpbin.foo:8000/headers" -H "x-ext-authz: deny" -s

denied by ext_authz for not found header `x-ext-authz: allow` in the request

 

修改请求,带上"x-ext-authz: allow"头部,请求放行:

kubectl exec "$(kubectl get pod -l app=sleep -n foo -o jsonpath={.items..metadata.name})" -c sleep -n foo -- curl "http://httpbin.foo:8000/headers" -H "x-ext-authz: allow" -s

 

{

  "headers": {

    "Accept": "*/*",

    "Host": "httpbin.foo:8000",

    "User-Agent": "curl/8.2.1",

    "X-B3-Parentspanid": "eb42a8165099e7db",

    "X-B3-Sampled": "1",

    "X-B3-Spanid": "cd6540ba1cfd9e8c",

    "X-B3-Traceid": "e7e15cc10dc66630eb42a8165099e7db",

    "X-Envoy-Attempt-Count": "1",

    "X-Ext-Authz": "allow",

    "X-Ext-Authz-Additional-Header-Override": "grpc-additional-header-override-value",

    "X-Ext-Authz-Check-Received": "source:{address:{socket_address:{address:\"10.1.0.25\"  port_value:37654}}  principal:\"spiffe://cluster.local/ns/foo/sa/sleep\"}  destination:{address:{socket_address:{address:\"10.1.0.24\"  port_value:80}}  principal:\"spiffe://cluster.local/ns/foo/sa/httpbin\"}  request:{time:{seconds:1692015383  nanos:990298000}  http:{id:\"7462237371770661564\"  method:\"GET\"  headers:{key:\":authority\"  value:\"httpbin.foo:8000\"}  headers:{key:\":method\"  value:\"GET\"}  headers:{key:\":path\"  value:\"/headers\"}  headers:{key:\":scheme\"  value:\"http\"}  headers:{key:\"accept\"  value:\"*/*\"}  headers:{key:\"user-agent\"  value:\"curl/8.2.1\"}  headers:{key:\"x-b3-sampled\"  value:\"1\"}  headers:{key:\"x-b3-spanid\"  value:\"eb42a8165099e7db\"}  headers:{key:\"x-b3-traceid\"  value:\"e7e15cc10dc66630eb42a8165099e7db\"}  headers:{key:\"x-envoy-attempt-count\"  value:\"1\"}  headers:{key:\"x-ext-authz\"  value:\"allow\"}  headers:{key:\"x-forwarded-client-cert\"  value:\"By=spiffe://cluster.local/ns/foo/sa/httpbin;Hash=c32db24acfa670a8bbe46f0897ebb70b9ccc0e630ee32afcd1ec037d6616e6c5;Subject=\\\"\\\";URI=spiffe://cluster.local/ns/foo/sa/sleep\"}  headers:{key:\"x-forwarded-proto\"  value:\"http\"}  headers:{key:\"x-request-id\"  value:\"aba7b68c-6bee-9d58-b163-7454075c6ece\"}  path:\"/headers\"  host:\"httpbin.foo:8000\"  scheme:\"http\"  protocol:\"HTTP/1.1\"}}  metadata_context:{}",

    "X-Ext-Authz-Check-Result": "allowed",

    "X-Forwarded-Client-Cert": "By=spiffe://cluster.local/ns/foo/sa/httpbin;Hash=c32db24acfa670a8bbe46f0897ebb70b9ccc0e630ee32afcd1ec037d6616e6c5;Subject=\"\";URI=spiffe://cluster.local/ns/foo/sa/sleep"

  }

}

 





cWtSKUdaQuYo