一、理解授权
为了保障集群中的服务的安全,Istio提供了一系列开箱即用的安全机制,对服务进行访问控制就是其中非常重要的一个部分,这个功能被称为授权。授权功能会按照预定义的配置针对特定的请求进行匹配,匹配成功之后会执行对应的动作,例如放行请求或者拒绝请求。
由于作用的对象是服务,因此,授权功能主要适用于四层至七层(相比较而言,传统的防火墙主要用于二至四层),例如gRPC、HTTP、HTTPS和HTTP2以及TCP协议等等,对基于这些协议的请求进行授权检测,Istio都可以提供原生支持。
从数据流的角度来讲,授权功能可以用于多种场景,包括从集群外部访问集群内部的服务、从集群内部的一个服务访问集群内部的另外一个服务、以及从集群内部访问集群外部的服务。
就像实现流量控制功能一样,Istio中授权功能的实现也是非侵入式的,可以在不影响有业务逻辑的情况下,通过一系列自定义的授权策略在Istio集群中启用授权功能,实现业务的安全加固。
用户可以通过配置授权策略这种CRD对象来实现授权的功能。授权策略按照作用域大小,可以分为三类:
1)作用于整个集群的全局策略
2)作用于某个namespace的局部策略
3)作用于某些pod的具体策略
例如下面的一个授权策略示例:
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: httpbin-policy
namespace: foo
spec:
selector:
matchLabels:
app: httpbin
action: ALLOW
rules:
- from:
- source:
principals: ["cluster.local/ns/default/sa/sleep"]
to:
- operation:
methods: ["GET"]
paths: ["/info*"]
when:
- key: request.auth.claims[iss]
values: ["https://foo.com"]
.
这个授权策略的含义是:筛选出foo这个namespace中含有app:httpbin这个标签的pod,对发送到这些pod的请求进行匹配,如果匹配成功,则放行当前请求,匹配规则如下:发起请求的pod的Service Account需要是cluster.local/ns/default/sa/sleep,请求使用HTTP协议,请求的具体方法类型是GET,请求的URL为/info*,并且请求中需要包含由https://foo.com签发的有效的JWT Token。
从这个例子中可以看出一个授权策略主要包含以下几个部分:
name:授权策略的名称,仅用于标识授权策略本身,不会影响规则的匹配和执行;
namespace:当前策略对象所在的namespace,可以使用这个字段配置不同作用范围的授权策略;
selector:使用label来选择当前授权策略作用于哪些pod上。注意,这里设置的是服务端的pod,因为最终这些规则会转换为Envoy规则由服务端的Envoy Porxy来具体执行。例如有client和server两个service,它们的pod对应的label分别为app:client和app:server,为了针对client到server的请求进行配置授权策略,这里的selector应该设置为app:server;
action:可以为ALLOW(默认值)或者DENY;
rules:匹配规则,如果匹配成功,就会执行对应的action;
二、授权策略的作用范围
授权策略可以按照作用域的大小分成三个不同的类型:全局策略、某个 namespace 内的局部策略和具有明确 match label 的授权策略。下面分别进行说明。
1)全局策略
授权策略位于 istio 的 root namespace 中(例如 istio-system),且匹配所有的 pod。这种规则会作用于整个集群中的所有 pod。下面的例子中有3个全局策略,第一个是全局 ALLOW ,第二个和第三个是全局 DENY ,后面这两个作用类似,但又有重要的区别。
kubectl apply -f - <<EOF
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: global-allow
namespace: istio-system
spec:
action: ALLOW
rules:
- {}
EOF
kubectl apply -f - <<EOF
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: global-deny
namespace: istio-system
spec:
action: DENY
rules:
- {}
EOF
kubectl apply -f - <<EOF
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: global-deny
namespace: istio-system
spec:
{}
EOF
2)某个namespace内的局部策略
授权策略位于除了 root namespace 之外的任何一个 namespace 中,且匹配所有的 pod ,这种情况下,这个策略会作用于当前 namespace 中的所有 pod。下面的例子中是3个 namespace 级别的策略,第一个是 ALLOW ,第二个和第三个是 DENY ,像全局策略一样,后面这两个作用类似,但又有重要的区别。
kubectl apply -f - <<EOF
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: foo-namespace-allow
namespace: foo
spec:
action: ALLOW
rules:
- {}
EOF
kubectl apply -f - <<EOF
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: foo-namespace-de