使用授权策略管理外部服务访问

服务网格中的资源主要通过授权策略(AuthorizationPolicy)资源来完成授权配置。在Ambient模式下,您可以为应用开启4层和7层授权。本文介绍如何使用授权策略限制集群内服务访问集群外服务。

阅读前提示

阅读本文前,请确保您已经了解:

  • 授权策略(Authorization Policy)

  • Ambient模式下,如果您只需要4层授权(限制客户端身份、端口等),则无需启用Waypoint即可实现;如果您需要7层授权能力(基于请求路径、方法等),需要为指定的服务开启Waypoint。更多信息,请参见为应用配置授权策略

继续了解本文内容前,请确保您已完成管理集群内客户端访问集群外服务中的通过Waypoint访问aliyun.com的操作。

部署测试应用

部署not-sleep应用,用于区分不同的集群内客户端。

  1. 创建nosleep.yaml。

    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: not-sleep
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: not-sleep
      labels:
        app: not-sleep
        service: not-sleep
    spec:
      ports:
      - port: 80
        name: http
      selector:
        app: not-sleep
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: not-sleep
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: not-sleep
      template:
        metadata:
          labels:
            app: not-sleep
        spec:
          terminationGracePeriodSeconds: 0
          serviceAccountName: not-sleep
          containers:
          - name: not-sleep
            image:  registry-cn-hangzhou.ack.aliyuncs.com/ack-demo/curl:asm-sleep
            command: ["/bin/sleep", "infinity"]
            imagePullPolicy: IfNotPresent
            volumeMounts:
            - mountPath: /etc/sleep/tls
              name: secret-volume
          volumes:
          - name: secret-volume
            secret:
              secretName: sleep-secret
              optional: true
    ---
  2. 部署not-sleep应用。

    kubectl apply -f nosleep.yaml

场景一:对于HTTP请求,只允许通过GET方法访问外部服务

  1. 创建授权策略。

    kubectl -n istio-egress apply -f - <<EOF
    apiVersion: security.istio.io/v1
    kind: AuthorizationPolicy
    metadata:
      name: aliyun-policy
    spec:
      targetRefs:
      - group: networking.istio.io
        kind: ServiceEntry
        name: external-svc-aliyun
      action: ALLOW
      rules:
      - to:
        - operation:
            methods: ["GET"]
    EOF
  2. 验证访问。

    1. 使用GET方法访问。

      kubectl exec deployment/sleep -- curl aliyun.com -s

      预期输出:

      HTTP/1.1 301 Moved Permanently
      server: envoy
      date: Mon, 18 Aug 2025 09:36:30 GMT
      content-type: text/html
      content-length: 239
      location: https://aliyun.com/
      eagleeye-traceid: 0be3e0ac17555097903637743e684e
      timing-allow-origin: *
      x-envoy-upstream-service-time: 27
    2. 使用DELETE方法访问。

      kubectl exec deployment/sleep -- curl aliyun.com -XDELETE -s -v

      预期输出:

      * Host aliyun.com:80 was resolved.
      * IPv6: 2001:2::7
      * IPv4: 240.xxx.xxx.7
      *   Trying 240.xxx.xxx.7:80...
      * Connected to aliyun.com (240.xxx.xxx.7) port 80
      > DELETE / HTTP/1.1
      > Host: aliyun.com
      > User-Agent: curl/8.8.0
      > Accept: */*
      > 
      * Request completely sent off
      < HTTP/1.1 403 Forbidden
      < content-length: 19
      < content-type: text/plain
      < date: Wed, 20 Aug 2025 08:10:58 GMT
      < server: istio-envoy
      < 
      { [19 bytes data]
      * Connection #0 to host aliyun.com left intact
      RBAC: access denied%  

      可以看到使用GET方法访问时返回码为301,使用DELETE方法访问时返回了403.说明授权策略已经生效。

场景二:对于HTTPS请求,只允许sleep访问外部服务

  1. 创建授权策略。

    kubectl -n istio-egress apply -f - <<EOF
    apiVersion: security.istio.io/v1
    kind: AuthorizationPolicy
    metadata:
      name: aliyun-policy
    spec:
      targetRefs:
      - group: networking.istio.io
        kind: ServiceEntry
        name: external-svc-aliyun
      action: ALLOW
      rules:
      - from:
        - source:
            principals:
            - cluster.local/ns/default/sa/sleep
    EOF
  2. 验证访问。

    1. 使用sleep应用访问。

      kubectl exec deployment/sleep -- curl https://aliyun.com -s

      预期输出:

      <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
      <html>
      <head><title>301 Moved Permanently</title></head>
      <body bgcolor="white">
      <h1>301 Moved Permanently</h1>
      <p>The requested resource has been assigned a new permanent URI.</p>
      <hr/>Powered by Tengine</body>
      </html>
    2. 使用not-sleep应用访问。

      kubectl exec deployment/not-sleep -- curl https://aliyun.com -s

      预期输出:

      command terminated with exit code 35