-
Notifications
You must be signed in to change notification settings - Fork 1
Description
Why authentication and authorization
假定你有一个数据库服务(mongo-db)在你的本地kubernete集群中提供服务。你是希望所有其他的服务都能开心地访问它,还是只有直接和数据库交互的服务能访问它?如果是后者,那么你需要给服务授权(authorization)。
而认证(authentication)是授权的基础。先得知道服务的身份,才能基于身份给予相应的授权。现在问题来了,如何定义一个服务的身份呢?
每个服务都要有个身份
Istio用服务的service account来标识服务的身份。但是,仅仅用service account的名字还不足以标识不同的服务。因为Istio经常用于异构系统的服务治理。也就是说,如果Istio要同时管理两个kubernete集群,或者要处理本地kubernete集群与GKE的统一管理问题,就很有可能出现service account名字冲突的问题。
Istio使用SPIFFE(Secure Production Identity Framework for Everyone)来解决这个异构系统中的身份问题。SPIFFE提供了标准化的在异构系统中生成身份的规范和API,可以想象成身份证号生成器。istio给服务分配的身份证号格式如下:
spiffe://\<trust domain \>/ns/\<namespace\>/sa/\<serviceaccount\>
在kubernete环境中,这个身份证号格式就是
spiffe://<k8s cluster domain>/ns/<k8s namespace>/sa/<serviceaccount>
每个服务都要有张证书
有了身份证号以后,下一个问题是,如何制作身份证。Istio用X.509证书来当身份证。毕竟经过CA认证,假一罚十。每个服务都找外面的CA来申请一个证书显然是不现实的。所以Istio中的Citadel组件提供了一个内置的CA并负责所有证书的签发管理工作。
Citadel会监控Kubernete API server,每当一个新的service account被创建时, Citadel会为service account制作一个私钥和对应的SPIFFE证书,证书的SAN(Subject Alternative Name)字段是service account的SPIFFE ID。私钥与证书对会被作为kubernete secret存储。
当一个pod被创建时,私钥与证书对会作为Kubernetes secret volume挂载到对应的service account中去。
身份证颁发完毕!
交换证书
我们已经有了证书。那么如何才能安全地交换证书呢?答案是双向TLS(mTLS)。
默认情况下,TLS只提供单向校验,也就是客户端(发起TLS连接的服务)会校验服务端(接收TLS连接的服务)的证书,保证服务端是可以信任的一方。而mTLS也要求客户端在建立TLS连接时提供自己的证书给服务器,这下双方都能知道对方的身份啦。
开启服务间认证
那么,如何在istio中开启mTLS呢?
首先,为了保证安全,我们决定制定一个policy把所有没有启用mTLS的request都禁用掉(先破后立)。启用下面的Policy之后,istio-tls这个namespace中的Istio sidecar会检查每一个进入sidecar的请求(incoming request)。如果这不是一个mTLS请求,就把它拒掉。(没带身份证禁止入内)
apiVersion: "authentication.istio.io/v1alpha1"
kind: "Policy"
metadata:
name: "default"
namespace: istio-tls
spec:
peers:
- mtls:
mode: STRICT
Policy决定了哪些请求会被禁掉,现在所有的请求都会收到503 error code。显然这不是我们想要的结果。下一件需要做的事是提示所有的请求启用mTLS连接。
DestinationRule决定了发起对服务的访问时,哪些情况下要带上身份证。例如,启用下面的DestinationRule后,istio-tls这个namespace中的sidecar会知道,如果要发起对别的服务的访问(outcoming request),我最好每次都启用mTLS连接。
apiVersion: "networking.istio.io/v1alpha3"
kind: "DestinationRule"
metadata:
name: "default"
namespace: istio-tls
spec:
host: "*.local"
trafficPolicy:
tls:
mode: ISTIO_MUTUAL
DestinationRule启用后,服务之间的访问又恢复正常了,并且启用了mTLS!好了,故事讲到这里,服务之间终于互相知道对方是谁了。下一篇将是如何使用服务的身份信息进行进一步的权限控制。