为工作负载设置访问策略
默认情况下,服务网格内的工作负载可以互相访问。您可以使用授权策略设置工作负载的访问条件,仅符合要求的请求才能访问对应工作负载。本文以限制访问工作负载的请求路径、方法和客户端IP为例,介绍如何为工作负载设置访问策略。
背景信息
授权策略支持CUSTOM、DENY和ALLOW策略类型。规则的判断存在优先级关系,当CUSTOM、DENY和ALLOW策略同时用于同一个工作负载时,将首先验证CUSTOM策略,然后验证DENY策略,最后验证ALLOW策略,并且存在以下关系:
如果任何一个CUSTOM策略匹配了请求并验证结果为拒绝,则拒绝此请求。
如果任何一个DENY策略匹配了请求并验证结果为拒绝,则拒绝此请求。
如果此工作负载上没有配置ALLOW策略,允许此请求(默认允许)。
如果该工作负载配置了ALLOW策略,并且ALLOW策略匹配此请求,允许此请求。
如果都不满足以上要求,则拒绝此请求。
场景示例一:限制访问工作负载的请求路径
本示例中,所有命名空间下的应用仅支持访问foo命名空间下的httpbin应用的/headers路径,访问其他路径都将失败,foo命名空间下的应用访问httpbin应用不受任何限制。
步骤一:为default和foo命名空间注入Sidecar代理
创建default和foo命名空间。具体操作,请参见管理全局命名空间。
为default命名空间注入Sidecar代理。
登录ASM控制台。
在左侧导航栏,选择 。
在网格管理页面,找到待配置的实例,单击实例的名称或在操作列中单击管理。
在网格详情页面左侧导航栏,选择 。
在全局命名空间页面单击default命名空间右侧操作列下的启用Sidecar自动注入。
在确认对话框单击确定。
重复步骤2,为foo命名空间注入Sidecar代理。
步骤二:部署测试应用
在default和foo命名空间部署sleep应用。
使用以下内容,创建sleep.yaml。
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: curlimages/curl command: ["/bin/sleep", "3650d"] imagePullPolicy: IfNotPresent volumeMounts: - mountPath: /etc/sleep/tls name: secret-volume volumes: - name: secret-volume secret: secretName: sleep-secret optional: true ---
执行以下命令,在default命名空间部署sleep应用。
kubectl apply -f sleep.yaml -n default
执行以下命令,在foo命名空间部署sleep应用。
kubectl apply -f sleep.yaml -n foo
在foo命名空间部署httpbin应用。
使用以下内容,创建httpbin.yaml。
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: docker.io/kennethreitz/httpbin imagePullPolicy: IfNotPresent name: httpbin ports: - containerPort: 80
执行以下命令,在foo命名空间部署httpbin应用。
kubectl apply -f httpbin.yaml -n foo
步骤三:创建授权策略
登录ASM控制台。
在左侧导航栏,选择 。
在网格管理页面,找到待配置的实例,单击实例的名称或在操作列中单击管理。
在网格详情页面左侧导航栏,选择 ,然后在右侧页面,单击创建。
在创建页面设置授权策略参数,然后单击创建。
配置项
说明
名称
自定义授权策略名称。
策略类型
设置策略类型为允许。
命名空间
在工作负载生效页签,设置命名空间为foo。
生效范围
选择生效范围为Service。
工作负载
设置工作负载为httpbin。
命名空间(Namespaces)
在添加请求来源区域,打开命名空间(Namespaces)开关,设置值为foo。
以上设置,使得foo命名空间下的应用都能访问httpbin应用。
HTTP路径(Paths)
在添加请求目标区域,打开HTTP路径(Paths)开关,设置值为/headers。
以上设置,使得所有命名空间下的应用仅支持访问foo命名空间下的httpbin应用的/headers路径。
步骤四:验证限制访问请求路径是否成功
使用default命名空间下的sleep应用访问foo命名空间下的httpbin应用。
- 登录容器服务管理控制台。
- 在控制台左侧导航栏,单击集群。
- 在集群列表页面,单击目标集群名称或者目标集群右侧操作列下的详情。
- 在集群管理页左侧导航栏,选择 。
在容器组页面顶部设置命名空间为default,单击sleep右侧操作列下的终端,选择容器:sleep。
在sleep容器终端中执行以下命令,访问httpbin应用的/headers路径。
curl httpbin.foo.svc.cluster.local:8000/headers
预期输出:
{ "headers": { "Accept": "*/*", "Host": "httpbin.foo.svc.cluster.local:8000", "User-Agent": "curl/7.82.0-DEV", "X-Envoy-Attempt-Count": "1", "X-Forwarded-Client-Cert": "By=spiffe://cluster.local/ns/foo/sa/httpbin;Hash=f7ab4985563b5b1986314d5a36c6e46819213e2f38301f534f00afb7cd4b9164;Subject=\"\";URI=spiffe://cluster.local/ns/foo/sa/sleep" } }
在sleep容器终端中执行以下命令,访问httpbin应用的/ip路径。
curl httpbin.foo.svc.cluster.local:8000/ip
返回403,提示访问被拒绝。
使用foo命名空间下的sleep应用访问foo命名空间下的httpbin应用。
- 在集群管理页左侧导航栏,选择 。
在容器组页面顶部设置命名空间为foo,单击sleep右侧操作列下的终端,选择容器:sleep。
在sleep容器终端中执行以下命令,访问httpbin应用的/headers路径。
curl httpbin.foo.svc.cluster.local:8000/headers
预期输出:
{ "headers": { "Accept": "*/*", "Host": "httpbin.foo.svc.cluster.local:8000", "User-Agent": "curl/7.82.0-DEV", "X-Envoy-Attempt-Count": "1", "X-Forwarded-Client-Cert": "By=spiffe://cluster.local/ns/foo/sa/httpbin;Hash=f7ab4985563b5b1986314d5a36c6e46819213e2f38301f534f00afb7cd4b9164;Subject=\"\";URI=spiffe://cluster.local/ns/foo/sa/sleep" } }
在sleep容器终端中执行以下命令,访问httpbin应用的/ip路径。
curl httpbin.foo.svc.cluster.local:8000/ip
预期输出:
{ "headers": { "Accept": "*/*", "Host": "httpbin.foo.svc.cluster.local:8000", "User-Agent": "curl/7.82.0-DEV", "X-Envoy-Attempt-Count": "1", "X-Forwarded-Client-Cert": "By=spiffe://cluster.local/ns/foo/sa/httpbin;Hash=f7ab4985563b5b1986314d5a36c6e46819213e2f38301f534f00afb7cd4b9164;Subject=\"\";URI=spiffe://cluster.local/ns/foo/sa/sleep" } }
可以看到default命名空间中的应用仅能访问foo命名空间下的httpbin应用的/headers路径,访问其他路径失败,foo命名空间中的应用访问httpbin应用不受任何限制,说明限制访问工作负载的请求路径成功。
场景示例二:限制访问工作负载的请求路径和方法
本示例中,所有命名空间下的应用仅支持通过GET请求访问foo命名空间下的httpbin应用的/status路径,访问其他路径或使用其他请求方法都将失败。
步骤一:为default和foo命名空间注入Sidecar代理
创建default和foo命名空间。具体操作,请参见管理全局命名空间。
为default命名空间注入Sidecar代理。
登录ASM控制台。
在左侧导航栏,选择 。
在网格管理页面,找到待配置的实例,单击实例的名称或在操作列中单击管理。
在网格详情页面左侧导航栏,选择 。
在全局命名空间页面单击default命名空间右侧操作列下的启用Sidecar自动注入。
在确认对话框单击确定。
重复步骤2,为foo命名空间注入Sidecar代理。
步骤二:部署测试应用
在default和foo命名空间部署sleep应用。
使用以下内容,创建sleep.yaml。
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: curlimages/curl command: ["/bin/sleep", "3650d"] imagePullPolicy: IfNotPresent volumeMounts: - mountPath: /etc/sleep/tls name: secret-volume volumes: - name: secret-volume secret: secretName: sleep-secret optional: true ---
执行以下命令,在default命名空间部署sleep应用。
kubectl apply -f sleep.yaml -n default
执行以下命令,在foo命名空间部署sleep应用。
kubectl apply -f sleep.yaml -n foo
在foo命名空间部署httpbin应用。
使用以下内容,创建httpbin.yaml。
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: docker.io/kennethreitz/httpbin imagePullPolicy: IfNotPresent name: httpbin ports: - containerPort: 80
执行以下命令,在foo命名空间部署httpbin应用。
kubectl apply -f httpbin.yaml -n foo
步骤三:创建授权策略
登录ASM控制台。
在左侧导航栏,选择 。
在网格管理页面,找到待配置的实例,单击实例的名称或在操作列中单击管理。
在网格详情页面左侧导航栏,选择 ,然后在右侧页面,单击创建。
在创建页面设置授权策略参数,然后单击创建。
配置项
说明
名称
自定义授权策略名称。
策略类型
设置策略类型为允许。
命名空间
在工作负载生效页签,设置命名空间为foo。
生效范围
选择生效范围为Service。
工作负载
设置工作负载为httpbin。
HTTP方法(Methods)
在添加请求目标区域,打开HTTP方法(Methods)开关,设置值为GET。
HTTP路径(Paths)
在添加请求目标区域,打开HTTP路径(Paths)开关,设置值为/status/*。
以上设置,使得所有命名空间下的应用仅支持使用GET方法访问foo命名空间下的httpbin应用的/status路径。
步骤四:验证限制访问工作负载的请求路径和方法是否成功
- 登录容器服务管理控制台。
- 在控制台左侧导航栏,单击集群。
- 在集群列表页面,单击目标集群名称或者目标集群右侧操作列下的详情。
- 在集群管理页左侧导航栏,选择 。
在容器组页面顶部设置命名空间为default,单击sleep右侧操作列下的终端,选择容器:sleep。
在sleep容器终端中执行以下命令,使用POST的方式访问httpbin应用的/status路径。
curl -I -X POST "httpbin.foo.svc.cluster.local:8000/status/200" -H "accept: text/plain"
返回403,访问httpbin应用失败。
执行以下命令,使用GET的方式访问httpbin应用的/IP路径。
curl -I -X GET "httpbin.foo.svc.cluster.local:8000/IP/200" -H "accept: text/plain"
返回403,访问httpbin应用失败。
执行以下命令,使用GET的方式访问httpbin应用的/status路径。
curl -I -X GET "httpbin.foo.svc.cluster.local:8000/status/200" -H "accept: text/plain"
预期输出:
HTTP/1.1 200 OK server: envoy date: Fri, 29 Apr 2022 03:01:16 GMT content-type: text/html; charset=utf-8 access-control-allow-origin: * access-control-allow-credentials: true content-length: 0 x-envoy-upstream-service-time: 5
根据以上结果,可以看到default命名空间下的应用只有使用GET方式访问httpbin应用的/status路径才能成功,说明限制访问工作负载的请求路径和方法成功。
场景示例三:限制访问工作负载的客户端IP
限制foo命名空间中的httpbin应用只能被许可的客户端IP访问。
步骤一:为foo命名空间注入Sidecar代理
创建foo命名空间。具体操作,请参见管理全局命名空间。
为foo命名空间注入Sidecar代理。
登录ASM控制台。
在左侧导航栏,选择 。
在网格管理页面,找到待配置的实例,单击实例的名称或在操作列中单击管理。
在网格详情页面左侧导航栏,选择 。
在全局命名空间页面单击default命名空间右侧操作列下的启用Sidecar自动注入。
在确认对话框单击确定。
步骤二:创建ASM网关
- 登录ASM控制台,在左侧导航栏,选择 。
- 在网格管理页面,单击目标实例名称,然后在左侧导航栏,选择 。
在入口网关页面,单击创建。
设置网关的基本信息,以下介绍重点参数,其他参数采用默认配置。
参数
说明
名称
自定义网关的名称。
部署集群
选择网关部署的集群。
网关类型
选择南北向-入口。
负载均衡类型
选择公网访问。
新建负载均衡
选择负载均衡,可选:
使用已有负载均衡:从已有负载均衡列表中选择。
新建负载均衡:单击新建负载均衡,从下拉列表中选择所需的负载均衡规格。
端口映射
单击添加端口,在新增端口行中,选择协议,输入服务端口。
单击高级选项,设置外部流量策略为Local,单击创建。
步骤三:创建虚拟服务和网关规则
创建虚拟服务。
登录ASM控制台。
在左侧导航栏,选择 。
在网格管理页面,找到待配置的实例,单击实例的名称或在操作列中单击管理。
在网格详情页面左侧导航栏,选择 ,然后在右侧页面,单击使用YAML创建。
设置命名空间为foo,场景模板采用默认设置,将以下内容输入到YAML文本框中,然后单击创建。
apiVersion: networking.istio.io/v1beta1 kind: VirtualService metadata: name: httpbin spec: gateways: - httpbin-gateway hosts: - '*' http: - match: - uri: prefix: /headers route: - destination: host: httpbin port: number: 8000
创建网关规则。
登录ASM控制台。
在左侧导航栏,选择 。
在网格管理页面,找到待配置的实例,单击实例的名称或在操作列中单击管理。
在网格详情页面左侧导航栏,选择 ,然后在右侧页面,单击使用YAML创建。
设置命名空间为foo,场景模板采用默认设置,将以下内容输入到YAML文本框中,然后单击创建。
apiVersion: networking.istio.io/v1beta1 kind: Gateway metadata: name: httpbin-gateway spec: selector: istio: ingressgateway servers: - hosts: - '*' port: name: http number: 80 protocol: HTTP
步骤四:创建授权策略
获取ASM网关IP。具体操作,请参见创建入口网关服务。
获取客户端IP。
在浏览器地址栏中输入http://{ASM网关IP}/headers,获取X-Envoy-External-Address右侧的IP。
创建授权策略。
登录ASM控制台。
在左侧导航栏,选择 。
在网格管理页面,找到待配置的实例,单击实例的名称或在操作列中单击管理。
在网格详情页面左侧导航栏,选择 ,然后在右侧页面,单击创建。
在创建页面设置授权策略参数,然后单击创建。
配置项
说明
名称
自定义授权策略名称。
策略类型
设置策略类型为拒绝。
命名空间
在工作负载生效页签,设置命名空间为foo。
生效范围
选择生效范围为Service。
工作负载
设置工作负载为httpbin。
原始源IP(RemoteIPBlocks)
在添加请求来源区域,打开原始源IP(RemoteIPBlocks)开关,设置值为步骤2获取的客户端IP。
以上设置,使得客户端IP将无法访问httpbin应用。
步骤五:验证限制访问工作负载的客户端IP是否成功
在浏览器地址栏中输入http://{ASM网关IP}/headers,返回RBAC:access denied
,访问httpbin应用失败,说明限制访问工作负载的客户端IP成功。