• Egress TLS 流量中的 SNI 监控及策略
    • 开始之前
    • SNI 监控和访问策略
      • 清理监控和策略定义
    • 监控 SNI 和源身份,并据此作出访问控制
      • 清理基于 SNI 和源身份的监控和访问策略对象
    • 清理
    • 相关内容

    Egress TLS 流量中的 SNI 监控及策略

    在使用通配符主机配置 Egress 流量示例中描述了为 *.wikipedia.org 这样的域名启用 Egress 流量 TLS 支持的方法。本示例中将演示的是如何为 Egress TLS 流量配置 SNI 监控并应用策略。

    开始之前

    • 按照安装指南中的说明安装 Istio。

    • 启动 sleep 示例,以获取发送请求的测试源。

    如果您启用了自动 sidecar 注入,请执行

    Zip

    1. $ kubectl apply -f @samples/sleep/sleep.yaml@

    否则,在部署 sleep 应用程序前,您必须手动注入 sidecar:

    Zip

    1. $ kubectl apply -f <(istioctl kube-inject -f @samples/sleep/sleep.yaml@)

    您可以使用任何安装了 curl 的 pod 作为测试源。

    • 为了发送请求,您需要创建 SOURCE_POD 环境变量来存储源 pod 的名称:
    1. $ export SOURCE_POD=$(kubectl get pod -l app=sleep -o jsonpath={.items..metadata.name})
    • 在 Istio 中部署 Egress 网关

    • 根据使用通配符主机配置 Egress 流量示例中的步骤 为流向 *.wikipedia.org 的流量进行配置,启用 TLS 支持。

    SNI 监控和访问策略

    通过配置,让 Egress 流量流入 Egress 网关之后,就可以对其实施安全的监控和策略管理了。在本节中,会为 *.wikipedia.org 定义一个 LogEntry 以及访问策略。

    • 创建 logentryruleshandlers
    1. $ kubectl apply -f - <<EOF
    2. # Egress 访问的日志定义
    3. apiVersion: "config.istio.io/v1alpha2"
    4. kind: logentry
    5. metadata:
    6. name: egress-access
    7. namespace: istio-system
    8. spec:
    9. severity: '"info"'
    10. timestamp: context.time | timestamp("2017-01-01T00:00:00Z")
    11. variables:
    12. connectionEvent: connection.event | ""
    13. source: source.labels["app"] | "unknown"
    14. sourceNamespace: source.namespace | "unknown"
    15. sourceWorkload: source.workload.name | ""
    16. sourcePrincipal: source.principal | "unknown"
    17. requestedServerName: connection.requested_server_name | "unknown"
    18. destinationApp: destination.labels["app"] | ""
    19. monitored_resource_type: '"UNSPECIFIED"'
    20. ---
    21. # 用于访问日志记录的 Handler
    22. apiVersion: "config.istio.io/v1alpha2"
    23. kind: stdio
    24. metadata:
    25. name: egress-access-logger
    26. namespace: istio-system
    27. spec:
    28. severity_levels:
    29. info: 0 # output log level as info
    30. outputAsJson: true
    31. ---
    32. # 处理对 *.wikipedia.org 访问的 Rule
    33. apiVersion: "config.istio.io/v1alpha2"
    34. kind: rule
    35. metadata:
    36. name: handle-wikipedia-access
    37. namespace: istio-system
    38. spec:
    39. match: source.labels["app"] == "istio-egressgateway-with-sni-proxy" && destination.labels["app"] == "" && connection.event == "open"
    40. actions:
    41. - handler: egress-access-logger.stdio
    42. instances:
    43. - egress-access.logentry
    44. EOF
    • 向 https://en.wikipedia.org 和 https://de.wikipedia.org 发起 HTTPS 访问:
    1. $ kubectl exec -it $SOURCE_POD -c sleep -- sh -c 'curl -s https://en.wikipedia.org/wiki/Main_Page | grep -o "<title>.*</title>"; curl -s https://de.wikipedia.org/wiki/Wikipedia:Hauptseite | grep -o "<title>.*</title>"'
    2. <title>Wikipedia, the free encyclopedia</title>
    3. <title>Wikipedia Die freie Enzyklopädie</title>
    • 检查 Mixer 日志。如果 Istio 部署在 istio-system 命名空间,可以用如下命令:
    1. $ kubectl -n istio-system logs -l istio-mixer-type=telemetry -c mixer | grep 'egress-access.logentry.istio-system'
    • 定义一条策略,允许访问主机名符合 *.wikipedia.org 规则的主机,但是排除英文版:
    1. $ cat <<EOF | kubectl create -f -
    2. apiVersion: "config.istio.io/v1alpha2"
    3. kind: listchecker
    4. metadata:
    5. name: wikipedia-checker
    6. namespace: istio-system
    7. spec:
    8. overrides: ["en.wikipedia.org"] # 用静态列表作为黑名单
    9. blacklist: true
    10. ---
    11. apiVersion: "config.istio.io/v1alpha2"
    12. kind: listentry
    13. metadata:
    14. name: requested-server-name
    15. namespace: istio-system
    16. spec:
    17. value: connection.requested_server_name
    18. ---
    19. # 检查对 *.wikipedia.org 的访问
    20. apiVersion: "config.istio.io/v1alpha2"
    21. kind: rule
    22. metadata:
    23. name: check-wikipedia-access
    24. namespace: istio-system
    25. spec:
    26. match: source.labels["app"] == "istio-egressgateway-with-sni-proxy" && destination.labels["app"] == ""
    27. actions:
    28. - handler: wikipedia-checker.listchecker
    29. instances:
    30. - requested-server-name.listentry
    31. EOF
    • 向黑名单中的英文版 Wikipedia:
    1. $ kubectl exec -it $SOURCE_POD -c sleep -- sh -c 'curl -v https://en.wikipedia.org/wiki/Main_Page'
    2. ...
    3. curl: (35) Unknown SSL protocol error in connection to en.wikipedia.org:443
    4. command terminated with exit code 35

    对英文版 Wikipedia 的访问会被策略拒绝。

    • 向其它 Wikipedia 站点发送 HTTPS 请求,例如 https://es.wikipedia.org 或 https://de.wikipedia.org:
    1. $ kubectl exec -it $SOURCE_POD -c sleep -- sh -c 'curl -s https://es.wikipedia.org/wiki/Wikipedia:Portada | grep -o "<title>.*</title>"; curl -s https://de.wikipedia.org/wiki/Wikipedia:Hauptseite | grep -o "<title>.*</title>"'
    2. <title>Wikipedia, la enciclopedia libre</title>
    3. <title>Wikipedia Die freie Enzyklopädie</title>

    和我们计划的一样,其它语言的 Wikipedia 站点是可以访问的。

    清理监控和策略定义

    1. $ kubectl delete rule handle-wikipedia-access check-wikipedia-access -n istio-system
    2. $ kubectl delete logentry egress-access -n istio-system
    3. $ kubectl delete stdio egress-access-logger -n istio-system
    4. $ kubectl delete listentry requested-server-name -n istio-system
    5. $ kubectl delete listchecker wikipedia-checker -n istio-system

    监控 SNI 和源身份,并据此作出访问控制

    因为已经在 Sidecar 之间、Sidecar 和 Egress 网关之间启用了双向 TLS,所以就有办法对访问外部的应用的服务身份进行监控和策略控制了。在 Kubernetes 上运行的 Istio,其身份是建立在 Service Accounts 基础之上的。这一节中将会部署两个 sleep 容器,sleep-ussleep-canada,各自用不同的 Service account 运行。然后定义一个策略,允许 sleep-us 的身份访问英文和西班牙文版本的维基百科,而 sleep-canada 身份的应用可以访问英文和法文版。

    • 部署两个 sleep 容器,sleep-ussleep-canada,各自使用各自的同名 Service account 运行:

    ZipZip

    1. $ sed 's/: sleep/: sleep-us/g' @samples/sleep/sleep.yaml@ | kubectl apply -f -
    2. $ sed 's/: sleep/: sleep-canada/g' @samples/sleep/sleep.yaml@ | kubectl apply -f -
    3. serviceaccount "sleep-us" created
    4. service "sleep-us" created
    5. deployment "sleep-us" created
    6. serviceaccount "sleep-canada" created
    7. service "sleep-canada" created
    8. deployment "sleep-canada" created
    • 创建 logentryruleshandlers
    1. $ kubectl apply -f - <<EOF
    2. # Egress 访问的日志定义
    3. apiVersion: "config.istio.io/v1alpha2"
    4. kind: logentry
    5. metadata:
    6. name: egress-access
    7. namespace: istio-system
    8. spec:
    9. severity: '"info"'
    10. timestamp: context.time | timestamp("2017-01-01T00:00:00Z")
    11. variables:
    12. connectionEvent: connection.event | ""
    13. source: source.labels["app"] | "unknown"
    14. sourceNamespace: source.namespace | "unknown"
    15. sourceWorkload: source.workload.name | ""
    16. sourcePrincipal: source.principal | "unknown"
    17. requestedServerName: connection.requested_server_name | "unknown"
    18. destinationApp: destination.labels["app"] | ""
    19. monitored_resource_type: '"UNSPECIFIED"'
    20. ---
    21. # Egress 访问日志的 Handler
    22. apiVersion: "config.istio.io/v1alpha2"
    23. kind: stdio
    24. metadata:
    25. name: egress-access-logger
    26. namespace: istio-system
    27. spec:
    28. severity_levels:
    29. info: 0 # output log level as info
    30. outputAsJson: true
    31. ---
    32. # 访问 *.wikipedia.org 时应用的 Rule
    33. apiVersion: "config.istio.io/v1alpha2"
    34. kind: rule
    35. metadata:
    36. name: handle-wikipedia-access
    37. namespace: istio-system
    38. spec:
    39. match: source.labels["app"] == "istio-egressgateway-with-sni-proxy" && destination.labels["app"] == "" && connection.event == "open"
    40. actions:
    41. - handler: egress-access-logger.stdio
    42. instances:
    43. - egress-access.logentry
    44. EOF
    • sleep-us 向英文、德文、西班牙文和法文版本的维基百科分别发送 HTTPS 请求:
    1. $ kubectl exec -it $(kubectl get pod -l app=sleep-us -o jsonpath='{.items[0].metadata.name}') -c sleep-us -- sh -c 'curl -s https://en.wikipedia.org/wiki/Main_Page | grep -o "<title>.*</title>"; curl -s https://de.wikipedia.org/wiki/Wikipedia:Hauptseite | grep -o "<title>.*</title>"; curl -s https://es.wikipedia.org/wiki/Wikipedia:Portada | grep -o "<title>.*</title>"; curl -s https://fr.wikipedia.org/wiki/Wikip%C3%A9dia:Accueil_principal | grep -o "<title>.*</title>"'
    2. <title>Wikipedia, the free encyclopedia</title>
    3. <title>Wikipedia Die freie Enzyklopädie</title>
    4. <title>Wikipedia, la enciclopedia libre</title>
    5. <title>Wikipédia, l'encyclopédie libre</title>
    • 查看 Mixer 日志。如果 Istio 部署在 istio-system 命名空间,可以使用如下命令:
    1. $ kubectl -n istio-system logs -l istio-mixer-type=telemetry -c mixer | grep 'egress-access.logentry.istio-system'
    2. {"level":"info","time":"2019-01-10T17:33:55.559093Z","instance":"egress-access.logentry.istio-system","connectionEvent":"open","destinationApp":"","requestedServerName":"en.wikipedia.org","source":"istio-egressgateway-with-sni-proxy","sourceNamespace":"default","sourcePrincipal":"cluster.local/ns/default/sa/sleep-us","sourceWorkload":"istio-egressgateway-with-sni-proxy"}
    3. {"level":"info","time":"2019-01-10T17:33:56.166227Z","instance":"egress-access.logentry.istio-system","connectionEvent":"open","destinationApp":"","requestedServerName":"de.wikipedia.org","source":"istio-egressgateway-with-sni-proxy","sourceNamespace":"default","sourcePrincipal":"cluster.local/ns/default/sa/sleep-us","sourceWorkload":"istio-egressgateway-with-sni-proxy"}
    4. {"level":"info","time":"2019-01-10T17:33:56.779842Z","instance":"egress-access.logentry.istio-system","connectionEvent":"open","destinationApp":"","requestedServerName":"es.wikipedia.org","source":"istio-egressgateway-with-sni-proxy","sourceNamespace":"default","sourcePrincipal":"cluster.local/ns/default/sa/sleep-us","sourceWorkload":"istio-egressgateway-with-sni-proxy"}
    5. {"level":"info","time":"2019-01-10T17:33:57.413908Z","instance":"egress-access.logentry.istio-system","connectionEvent":"open","destinationApp":"","requestedServerName":"fr.wikipedia.org","source":"istio-egressgateway-with-sni-proxy","sourceNamespace":"default","sourcePrincipal":"cluster.local/ns/default/sa/sleep-us","sourceWorkload":"istio-egressgateway-with-sni-proxy"}

    注意 requestedServerName 属性,以及 sourcePrincipal,应取值为 cluster.local/ns/default/sa/sleep-us

    • 定义一条策略,允许 sleep-us Service account 访问英文和西班牙版本的维基百科;而 sleep-canada 则可以访问英文和法文版本的维基百科。对其它语言的访问会被拦截。
    1. $ cat <<EOF | kubectl create -f -
    2. apiVersion: "config.istio.io/v1alpha2"
    3. kind: listentry
    4. metadata:
    5. name: requested-server-name
    6. namespace: istio-system
    7. spec:
    8. value: connection.requested_server_name
    9. ---
    10. apiVersion: "config.istio.io/v1alpha2"
    11. kind: listchecker
    12. metadata:
    13. name: us-wikipedia-checker
    14. namespace: istio-system
    15. spec:
    16. overrides: ["en.wikipedia.org", "es.wikipedia.org"]
    17. blacklist: false
    18. ---
    19. # 访问 *.wikipedia.org 时应用的 Rule
    20. apiVersion: "config.istio.io/v1alpha2"
    21. kind: rule
    22. metadata:
    23. name: check-us-wikipedia-access
    24. namespace: istio-system
    25. spec:
    26. match: source.labels["app"] == "istio-egressgateway-with-sni-proxy" && destination.labels["app"] == "" && source.principal == "cluster.local/ns/default/sa/sleep-us"
    27. actions:
    28. - handler: us-wikipedia-checker.listchecker
    29. instances:
    30. - requested-server-name.listentry
    31. ---
    32. apiVersion: "config.istio.io/v1alpha2"
    33. kind: listchecker
    34. metadata:
    35. name: canada-wikipedia-checker
    36. namespace: istio-system
    37. spec:
    38. overrides: ["en.wikipedia.org", "fr.wikipedia.org"]
    39. blacklist: false
    40. ---
    41. # 访问 *.wikipedia.org 时应用的 Rule
    42. apiVersion: "config.istio.io/v1alpha2"
    43. kind: rule
    44. metadata:
    45. name: check-canada-wikipedia-access
    46. namespace: istio-system
    47. spec:
    48. match: source.labels["app"] == "istio-egressgateway-with-sni-proxy" && destination.labels["app"] == "" && source.principal == "cluster.local/ns/default/sa/sleep-canada"
    49. actions:
    50. - handler: canada-wikipedia-checker.listchecker
    51. instances:
    52. - requested-server-name.listentry
    53. EOF
    • sleep-us 发送 HTTPS 流量到英文、德文、西班牙文和法文版本的维基百科:
    1. $ kubectl exec -it $(kubectl get pod -l app=sleep-us -o jsonpath='{.items[0].metadata.name}') -c sleep-us -- sh -c 'curl -s https://en.wikipedia.org/wiki/Main_Page | grep -o "<title>.*</title>"; curl -s https://de.wikipedia.org/wiki/Wikipedia:Hauptseite | grep -o "<title>.*</title>"; curl -s https://es.wikipedia.org/wiki/Wikipedia:Portada | grep -o "<title>.*</title>"; curl -s https://fr.wikipedia.org/wiki/Wikip%C3%A9dia:Accueil_principal | grep -o "<title>.*</title>";:'
    2. <title>Wikipedia, the free encyclopedia</title>
    3. <title>Wikipedia, la enciclopedia libre</title>

    会看到 sleep-us 身份允许访问英文和西班牙版本。

    Mixer 策略的同步可能会花几分钟,如果想要快速演示新的策略,可以删除 Mixer Policy Pod:

    1. $ kubectl delete pod -n istio-system -l istio-mixer-type=policy
    • sleep-canada 发送 HTTPS 流量到英文、德文、西班牙文和法文版本的维基百科:
    1. $ kubectl exec -it $(kubectl get pod -l app=sleep-canada -o jsonpath='{.items[0].metadata.name}') -c sleep-canada -- sh -c 'curl -s https://en.wikipedia.org/wiki/Main_Page | grep -o "<title>.*</title>"; curl -s https://de.wikipedia.org/wiki/Wikipedia:Hauptseite | grep -o "<title>.*</title>"; curl -s https://es.wikipedia.org/wiki/Wikipedia:Portada | grep -o "<title>.*</title>"; curl -s https://fr.wikipedia.org/wiki/Wikip%C3%A9dia:Accueil_principal | grep -o "<title>.*</title>";:'
    2. <title>Wikipedia, the free encyclopedia</title>
    3. <title>Wikipédia, l'encyclopédie libre</title>

    会看到 sleep-us 身份允许访问英文和法文版本。

    清理基于 SNI 和源身份的监控和访问策略对象

    1. $ kubectl delete serviceaccount sleep-us sleep-canada
    2. $ kubectl delete service sleep-us sleep-canada
    3. $ kubectl delete deployment sleep-us sleep-canada
    4. $ kubectl delete rule handle-wikipedia-access check-us-wikipedia-access check-canada-wikipedia-access -n istio-system
    5. $ kubectl delete logentry egress-access -n istio-system
    6. $ kubectl delete stdio egress-access-logger -n istio-system
    7. $ kubectl delete listentry requested-server-name -n istio-system
    8. $ kubectl delete listchecker us-wikipedia-checker canada-wikipedia-checker -n istio-system

    清理

    • 执行 使用通配符主机配置 Egress 流量例子中的清理任意域名的通配符配置步骤。

    • 停止 sleep 服务:

    相关内容

    Egress gateway 性能测试

    评估加入 Egress gateway 对性能造成的影响。

    使用外部 MongoDB 服务

    描述了一个基于 Istio 的 Bookinfo 示例的简单场景。

    HTTP Egress 流量监控和访问策略

    描述如何配置 Istio 进行 HTTP Egress 流量监控和访问策略。

    使用外部 TCP 服务

    描述基于 Istio 的 Bookinfo 示例的简单场景。

    使用外部 Web 服务

    描述基于 Istio Bookinfo 示例的简单场景。

    Mixer 适配器模型

    概要说明 Mixer 的插件架构。