文档

L7认证与鉴权

Ambient模式中,由于4层和7层的分离架构,导致认证和授权的配置模型与原Sidecar模式不同。以ASM 1.18版本为例,本文介绍如何使用7层授权策略。

前提条件

已部署ASM网关和应用,且成功验证基本功能。具体操作,请参见入门示例的前提条件和步骤一。

使用限制

  • 授权策略在Waypoint代理中的使用限制如下:

    • action字段不支持CUSTOM,即Waypoint代理不支持自定义授权服务。

    • source字段中不支持ipBlocks

  • 存在Waypoint代理时,Ztunnel代理会允许所有来自Waypoint代理的请求通过。此时,授权策略需要绑定给指定的Waypoint代理。

准备工作

  1. 执行以下命令,为productpage部署Waypoint。

    istioctl x waypoint apply --service-account bookinfo-productpage
  2. 执行以下命令,查看对应的Waypoint Pod。

    kubectl get pod --show-labels | grep waypoint

    预期输出:

    bookinfo-productpage-istio-waypoint-6c579dd48d-l****   1/1     Running   0          91s    gateway.istio.io/managed=istio.io-mesh-controller,istio.io/gateway-name=bookinfo-productpage,pod-template-hash=6c579dd48d,service.istio.io/canonical-name=bookinfo-productpage-istio-waypoint,service.istio.io/canonical-revision=latest,sidecar.istio.io/inject=false

示例一:存在Waypoint时,Ztunnel上的授权策略失效

存在Waypoint时,Ztunnel将会允许所有来自当前服务Waypoint的流量通过,此时再将授权策略应用到Ztunnel上(授权策略的selector选中了业务Pod)时,该授权策略不会生效。

  1. 使用以下内容,创建productpage-viewer.yaml。

    以下授权策略作用于Ztunnel,禁止访问productpage的9080端口。

    apiVersion: security.istio.io/v1beta1
    kind: AuthorizationPolicy
    metadata:
     name: productpage-viewer
     namespace: default
    spec:
     selector:
       matchLabels:
         app: productpage
     action: DENY
     rules:
     - to:
       - operation:
           ports:
           - "9080"
  2. 在ASM实例对应的KubeConfig环境下,执行以下命令,创建授权策略。

    kubectl apply -f productpage-viewer.yaml
  3. 执行以下命令,进行访问测试。

    # 从以下四个测试可以看出,9080的DENY规则完全没有生效。
    
    kubectl exec deploy/sleep -- curl -s "http://$GATEWAY_HOST/productpage" | grep -o "<title>.*</title>"
    # 预期输出:
    <title>Simple Bookstore App</title>
    
    kubectl exec deploy/notsleep -- curl -s "http://$GATEWAY_HOST/productpage" | grep -o "<title>.*</title>"
    # 预期输出:
    <title>Simple Bookstore App</title>
    
    kubectl exec deploy/sleep -- curl -s http://productpage:9080/ | grep -o "<title>.*</title>"
    # 预期输出:
    <title>Simple Bookstore App</title>
    
    kubectl exec deploy/notsleep -- curl -s http://productpage:9080/ | grep -o "<title>.*</title>"
    # 预期输出:
    <title>Simple Bookstore App</title>

    本测试和不存在Waypoint的示例二:禁止访问productpage的9080端口使用了同样的授权策略,但本测试所有访问均成功。

    以上结果说明当配置Waypoint后,之前Ztunnel上的所有策略都会失效。您需要更改selector为productpage对应的Waypoint。

  4. 将授权策略productpage-viewer.yaml修改为如下内容,然后执行kubectl apply -f productpage-viewer.yaml命令进行部署。

    以下YAML修改了selector字段。

    apiVersion: security.istio.io/v1beta1
    kind: AuthorizationPolicy
    metadata:
     name: productpage-viewer
     namespace: default
    spec:
     selector:
       matchLabels:
         istio.io/gateway-name: bookinfo-productpage
     action: DENY
     rules:
     - to:
       - operation:
           ports:
           - "9080"
  5. 执行以下命令,进行访问测试。

    # 9080端口的DENY规则生效。
    kubectl exec deploy/sleep -- curl -s "http://$GATEWAY_HOST/productpage"
    # 预期输出:
    RBAC: access denied%
    
    kubectl exec deploy/notsleep -- curl -s "http://$GATEWAY_HOST/productpage"
    # 预期输出:
    RBAC: access denied%
    
    kubectl exec deploy/sleep -- curl -s http://productpage:9080/
    # 预期输出:
    RBAC: access denied%
    
    kubectl exec deploy/notsleep -- curl -s http://productpage:9080/
    # 预期输出:
    RBAC: access denied%

    此处返回的报错信息RBAC: access denied%和L4鉴权的示例二:禁止访问productpage的9080端口不同。这个错误实际由productpage的Waypoint返回。Waypoint发现9080端口不允许访问,于是返回一个HTTP RBAC错误,实际的状态码应为403。

  6. 执行以下命令,清除授权策略。

    kubectl delete authorizationpolicy productpage-viewer

示例二:禁止sleep Pod的IP直接或通过网关间接访问productpage

目前配置在Waypoint上的授权策略不支持ipBlocks字段,只支持remoteIpBlocks。请求只有经过了网关才可以配置remoteIpBlocks字段进行匹配。因此,只能实现禁止sleep Pod的IP通过网关间接访问productpage,无法实现禁止sleep Pod的IP直接访问productpage。

  1. 使用以下内容,创建productpage-viewer.yaml,禁止sleep Pod通过网关访问productpage。

    apiVersion: security.istio.io/v1beta1
    kind: AuthorizationPolicy
    metadata:
     name: productpage-viewer
     namespace: default
    spec:
     selector:
       matchLabels:
         istio.io/gateway-name: bookinfo-productpage
     action: DENY
     rules:
     - from:
       - source:
           remoteIpBlocks:
           - "${sleep Pod IP}"
  2. 在ASM实例对应的KubeConfig环境下,执行以下命令,创建授权策略。

    kubectl apply -f productpage-viewer.yaml
  3. 执行以下命令,进行访问测试。

    # sleep Pod通过网关访问productpage被禁止。
    kubectl exec deploy/sleep -- curl -s "http://$GATEWAY_HOST/productpage"
    # 预期输出:
    RBAC: access denied%
    
    kubectl exec deploy/sleep -- curl -s http://productpage:9080/ -I
    # 预期输出:
    HTTP/1.1 200 OK
    content-type: text/html; charset=utf-8
    content-length: 1683
    server: istio-envoy
    date: Tue, 15 Aug 2023 02:11:30 GMT
    x-envoy-upstream-service-time: 3

    预期输出表明sleep Pod可以直接访问productpage,不可以通过网关访问。

  4. 执行以下命令,清除授权策略。

    kubectl delete authorizationpolicy productpage-viewer

示例三:productpage禁止被istio-system命名空间下的Pod访问

  1. 使用以下内容,创建productpage-viewer.yaml,禁止istio-system命名空间的Pod访问productpage。

    apiVersion: security.istio.io/v1beta1
    kind: AuthorizationPolicy
    metadata:
     name: productpage-viewer
     namespace: default
    spec:
     selector:
       matchLabels:
         istio.io/gateway-name: bookinfo-productpage
     action: DENY
     rules:
     - from:
       - source:
           namespaces:
           - istio-system
  2. 在ASM实例对应的KubeConfig环境下,执行以下命令,创建授权策略。

    kubectl apply -f productpage-viewer.yaml
  3. 执行以下命令,进行访问测试。

    # 网关无法访问productpage。
    kubectl exec deploy/sleep -- curl -s "http://$GATEWAY_HOST/productpage"
    # 预期输出:
    RBAC: access denied%
    
    kubectl exec deploy/notsleep -- curl -s "http://$GATEWAY_HOST/productpage"
    # 预期输出:
    RBAC: access denied%
    
    kubectl exec deploy/sleep -- curl -s http://productpage:9080/ | grep -o "<title>.*</title>"
    # 预期输出:
    <title>Simple Bookstore App</title>
    
    kubectl exec deploy/notsleep -- curl -s http://productpage:9080/ | grep -o "<title>.*</title>"
    # 预期输出:
    <title>Simple Bookstore App</title>

    预期输出表明sleep和notsleep均无法通过网关访问productpage,但是可以直接访问productpage,因为网关在istio-system命名空间。

  4. 执行以下命令,清除授权策略。

    kubectl delete authorizationpolicy productpage-viewer

示例四:对请求携带的JWT进行认证和鉴权

对请求携带的JWT进行认证和鉴权需要请求认证和授权策略配合使用。本示例要求来自istio-system命名空间的请求必须携带有效JWT,default命名空间不需要携带有效JWT。配置完成之后,通过网关的请求必须携带JWT,sleep或notsleep直接访问productpage则不需要携带JWT。

  1. 创建请求认证。

    1. 使用以下内容,创建jwt-example.yaml。

      apiVersion: security.istio.io/v1beta1
      kind: RequestAuthentication
      metadata:
        name: jwt-example
        namespace: default
      spec:
        selector:
          matchLabels:
            istio.io/gateway-name: bookinfo-productpage
        jwtRules:
        - issuer: "testing@secure.istio.io"
          jwks: '{ "keys":[ {"e":"AQAB","kid":"DHFbpoIUqrY8t2zpA2qXfCmr5VO5ZEr4RzHU_-envvQ","kty":"RSA","n":"xAE7eB6qugXyCAG3yhh7pkDkT65pHymX-P7KfIupjf59vsdo91bSP9C8H07pSAGQO1MV_xFj9VswgsCg4R6otmg5PV2He95lZdHtOcU5DXIg_pbhLdKXbi66GlVeK6ABZOUW3WYtnNHD-91gVuoeJT_DwtGGcp4ignkgXfkiEm4sw-4sfb4qdt5oLbyVpmW6x9cfa7vs2WTfURiCrBoUqgBo_-4WTiULmmHSGZHOjzwa8WtrtOQGsAFjIbno85jp6MnGGGZPYZbDAa_b3y5u-YpW7ypZrvD8BgtKVjgtQgZhLAGezMt0ua3DRrWnKqTZ0BJ_EyxOGuHJrLsn00fnMQ"}]}'
    2. 在ASM实例对应的KubeConfig环境下,执行以下命令,创建请求认证。

      kubectl apply -f jwt-example.yaml
  2. 创建授权策略。

    1. 使用以下内容,创建productpage-viewer.yaml。

      apiVersion: security.istio.io/v1beta1
      kind: AuthorizationPolicy
      metadata:
        name: productpage-viewer
        namespace: default
      spec:
        selector:
          matchLabels:
            istio.io/gateway-name: bookinfo-productpage
        action: ALLOW
        rules:
        - from:
          - source:
              requestPrincipals: ["testing@secure.istio.io/testing@secure.istio.io"]
              namespaces: ["istio-system"]
          - source:
              namespaces: ["default"]
    2. 在ASM实例对应的KubeConfig环境下,执行以下命令,创建授权策略。

      kubectl apply -f productpage-viewer.yaml
  3. 执行以下命令,将TOKEN注册为环境变量。

    export TOKEN=eyJhbGciOiJSUzI1NiIsImtpZCI6IkRIRmJwb0lVcXJZOHQyenBBMnFYZkNtcjVWTzVaRXI0UnpIVV8tZW52dlEiLCJ0eXAiOiJKV1QifQ.eyJleHAiOjQ2ODU5ODk3MDAsImZvbyI6ImJhciIsImlhdCI6MTUzMjM4OTcwMCwiaXNzIjoidGVzdGluZ0BzZWN1cmUuaXN0aW8uaW8iLCJzdWIiOiJ0ZXN0aW5nQHNlY3VyZS5pc3Rpby5pbyJ9.CfNnxWP2tcnR9q0vxyxweaF3ovQYHYZl82hAUsn21bwQd9zP7c-LS9qd_vpdLG4Tn1A15NxfCjp5f7QNBUo-KC9PJqYpgGbaXhaGx7bEdFWjcwv3nZzvc7M__ZpaCERdwU7igUmJqYGBYQ51vr2njU9ZimyKkfDe3axcyiBZde7G6dabliUosJvvKOPcKIWPccCgefSj_GNfwIip3-SsFdlR7BtbVUcqR-yv-XOxJ3Uc1MI0tz3uMiiZcyPV7sNCU4KRnemRIMHVOfuvHsU60_GhGbiSFzgPTAa9WTltbnarTbxudb_YEOx12JiwYToeX0DCPb43W1tzIBxgm8NxUg
  4. 执行以下命令,进行访问测试。

    # 不携带JWT通过网关访问,被禁止。
    kubectl exec deploy/sleep -- curl -s http://$GATEWAY_HOST/productpage
    # 预期输出:
    RBAC: access denied%
    
    # 不携带JWT直接访问productpage,可以正常返回。
    kubectl exec deploy/sleep -- curl -s http://productpage:9080/ | grep -o "<title>.*</title>"
    # 预期输出:
    <title>Simple Bookstore App</title>
    
    # 携带正确的JWT,通过网关访问。
    kubectl exec deploy/sleep -- curl -s http://$GATEWAY_HOST/productpage -H "Authorization: Bearer $TOKEN" -I
    # 预期输出:
    HTTP/1.1 200 OK
    content-type: text/html; charset=utf-8
    content-length: 5290
    server: istio-envoy
    date: Tue, 15 Aug 2023 03:16:21 GMT
    x-envoy-upstream-service-time: 21
    
    # 携带错误的JWT,通过网关访问。
    kubectl exec deploy/sleep -- curl -s http://$GATEWAY_HOST/productpage -H "Authorization: Bearer wrongtoken" -I
    # 预期输出:
    HTTP/1.1 401 Unauthorized
    www-authenticate: Bearer realm="http://istio-ingressgateway.istio-system/productpage", error="invalid_token"
    content-length: 79
    content-type: text/plain
    date: Tue, 15 Aug 2023 03:17:26 GMT
    server: istio-envoy
    x-envoy-upstream-service-time: 0
  5. 执行以下命令,清除授权策略和请求认证。

    kubectl delete authorizationpolicy productpage-viewer
    kubectl delete requestauthentication jwt-example

示例五:限制host为test.com的请求,不能访问9080端口

productpage应用暴露的端口为9080。本示例配置hosttest.com的请求不能访问9080,但其它请求可以。

  1. 使用以下内容,创建productpage-viewer.yaml。

    apiVersion: security.istio.io/v1beta1
    kind: AuthorizationPolicy
    metadata:
      name: productpage-viewer
      namespace: default
    spec:
      selector:
        matchLabels:
          istio.io/gateway-name: bookinfo-productpage
      action: DENY
      rules:
      - to:
        - operation:
            hosts: ["test.com"]
            ports: ["9080"]
  2. 在ASM实例对应的KubeConfig环境下,执行以下命令,创建授权策略。

    kubectl apply -f productpage-viewer.yaml
  3. 执行以下命令,进行访问测试。

    # 使用test.com作为host访问productpage,访问失败。
    kubectl exec deploy/sleep -- curl -s http://$GATEWAY_HOST/productpage -H "Host: test.com"
    # 预期输出:
    RBAC: access denied%
    
    # 使用test1.com作为host访问productpage,访问成功。
    kubectl exec deploy/sleep -- curl -s http://$GATEWAY_HOST/productpage -H "Host: test1.com" -I
    # 预期输出:
    HTTP/1.1 200 OK
    content-type: text/html; charset=utf-8
    content-length: 5290
    server: istio-envoy
    date: Tue, 15 Aug 2023 03:39:29 GMT
    x-envoy-upstream-service-time: 18
  4. 执行以下命令,清除授权策略。

    kubectl delete authorizationpolicy productpage-viewer

示例六:限制不允许使用HEAD方法访问/productpage路径

  1. 使用以下内容,创建productpage-viewer.yaml。

    apiVersion: security.istio.io/v1beta1
    kind: AuthorizationPolicy
    metadata:
      name: productpage-viewer
      namespace: default
    spec:
      selector:
        matchLabels:
          istio.io/gateway-name: bookinfo-productpage
      action: DENY
      rules:
      - to:
        - operation:
            methods: ["HEAD"]
            paths: ["/productpage"]
  2. 在ASM实例对应的KubeConfig环境下,执行以下命令,创建授权策略。

    kubectl apply -f productpage-viewer.yaml
  3. 执行以下命令,进行访问测试。

    # 使用HEAD方法访问/productpage路径,-I选项默认是HEAD方法。
    kubectl exec deploy/sleep -- curl -s http://$GATEWAY_HOST/productpage -I
    #预期输出:
    HTTP/1.1 403 Forbidden
    content-length: 19
    content-type: text/plain
    date: Tue, 15 Aug 2023 03:59:37 GMT
    server: istio-envoy
    x-envoy-upstream-service-time: 0
    
    # 使用GET方法访问/productpage路径。
    kubectl exec deploy/sleep -- curl -s http://$GATEWAY_HOST/productpage -XGET -I
    #预期输出:
    HTTP/1.1 200 OK
    content-type: text/html; charset=utf-8
    content-length: 5290
    server: istio-envoy
    date: Tue, 15 Aug 2023 04:00:48 GMT
    x-envoy-upstream-service-time: 20
    
    # 使用HEAD方法访问/api/v1/products路径。
    kubectl exec deploy/sleep -- curl -s http://$GATEWAY_HOST/api/v1/products -I
    #预期输出:
    HTTP/1.1 200 OK
    content-type: application/json
    content-length: 395
    server: istio-envoy
    date: Tue, 15 Aug 2023 04:02:39 GMT
    x-envoy-upstream-service-time: 2
  4. 执行以下命令,清除授权策略。

    kubectl delete authorizationpolicy productpage-viewer
  • 本页导读 (1)
文档反馈