Istio的安全功能十分强大,安全场景包括对网关的加密、服务间的访问控制、认证和授权。网关加密由Ingress Gateway实现,访问控制依赖于Mixer,认证和授权主要由Citadel、Envoy实现。
HTTPS 能最大化地保证信息传输的安全,是当前互联网推荐的通信方式。Istio 为Gateway 提供了HTTPS加密支持。
一般的 We b 应用都采用单向认证,即仅客户端验证服务端证书,无须在通信层做用户身份验证,而是在应用逻辑层保证用户的合法登入。
官方教程:https://istio.io/zh/docs/tasks/traffic-management/ingress/secure-ingress-mount/
SDS方式:https://istio.io/zh/docs/tasks/traffic-management/ingress/secure-ingress-sds/
-
创建一个 Kubernetes secret 以保存服务器的证书和私钥。使用
kubectl
在命名空间istio-system
下创建 secretistio-ingressgateway-certs
。Istio 网关将会自动加载该 secret。$ kubectl create -n istio-system secret tls istio-ingressgateway-certs --key kube-apiserver/apiserver-key.pem --cert kube-apiserver/apiserver.pem
检查 secret 是否挂载好了:
$ kubectl exec -it -n istio-system $(kubectl -n istio-system get pods -l istio=ingressgateway -o jsonpath='{.items[0].metadata.name}') -- ls -al /etc/istio/ingressgateway-certs
-
定义 Gateway 如下:
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
namespace: xujiyou-test
name: hello-gateway
spec:
selector:
istio: ingressgateway
servers:
- port:
number: 443
name: https
protocol: HTTPS
hosts:
- "fueltank-1.cloud.bbdops.com"
tls:
mode: SIMPLE
serverCertificate: /etc/istio/ingressgateway-certs/tls.crt
privateKey: /etc/istio/ingressgateway-certs/tls.key
-
访问如下:
$ curl -v -HHost:fueltank-1.cloud.bbdops.com --cacert /home/admin/k8s-cluster/cert/ca.pem https://fueltank-1.cloud.bbdops.com:31390/api/hello
定义 hello-policy 文件如下:
apiVersion: authentication.istio.io/v1alpha1
kind: Policy
metadata:
name: hello-policy
namespace: xujiyou-test
spec:
peers:
- mtls: {}
targets:
- name: hello-service
创建:
$ kubectl apply -f hello-policy.yaml
创建完成后,再使用上边的 curl 访问就会出错,因为 从 ingress-gateway 到 hello-service 这一块并没有进行认证。
修改 hello-destination-rule.yaml 如下,使用 SDS 自动添加认证:
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: hello
namespace: xujiyou-test
spec:
host: hello-service
subsets:
- name: default
labels:
app: hello
- name: v1
labels:
version: v1
- name: v2
labels:
version: v2
- name: v3
labels:
version: v3
trafficPolicy:
tls:
mode: ISTIO_MUTUAL
ISTIO_MUTUAL
的意思就是通过 SDS 自动添加认证!
提交修改后,通过上边的 curl 通过 ingress-gateway 又可以访问了。但是直接通过 Pod 和 Service 是无法访问的。
mtls
中的 m 就是 MUTUAL
的意思,这个单词是双向的意思,mtls
就是双向认证的意思!!!
这里有一个巨坑!!! kubernetes 的 service 的端口名要指定!!!如下,要指定 name: http
:
apiVersion: v1
kind: Service
metadata:
name: hello-service
namespace: xujiyou-test
labels:
app: hello
spec:
ports:
- port: 8080
name: http
selector:
app: hello
type: NodePort
修改 hello-policy 如下:
apiVersion: authentication.istio.io/v1alpha1
kind: Policy
metadata:
name: hello-policy
namespace: xujiyou-test
spec:
origins:
- jwt:
issuer: "[email protected]"
jwksUri: "http://fueltank-1:81/jwks.json"
principalBinding: USE_ORIGIN
peers:
- mtls: {}
targets:
- name: hello-service
创建:
$ kubectl apply -f hello-policy.yaml
创建之后,再访问:
$ curl -v -HHost:fueltank-1.cloud.bbdops.com --cacert /home/admin/k8s-cluster/cert/ca.pem https://fueltank-1.cloud.bbdops.com:31390/api/hello?version=v2
会发现返回 401,怎么办那,可以这样:
$ TOKEN=$(curl https://raw.githubusercontent.com/istio/istio/release-1.5/security/tools/jwt/samples/demo.jwt -s)
$ curl -v -HHost:fueltank-1.cloud.bbdops.com --cacert /home/admin/k8s-cluster/cert/ca.pem https://fueltank-1.cloud.bbdops.com:31390/api/hello?version=v2 --header "Authorization: Bearer $TOKEN"
Istio 1.4 版本之后,开始使用 AuthorizationPolicy
,不再推荐使用 rbac.istio.io
中的 CRD。
等到 Istio 1.6 版本,rbac.istio.io
将被删除!!!
下来来看看怎么使用。
注意,Kubernetes 的原生 Service 要对端口号进行命名,切记切记
下面先来看 hello-authorization-policy.yaml :
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: hello-authorization-policy
namespace: xujiyou-test
spec:
selector:
app: hello
rules:
- from:
- source:
principals:
- cluster.local/ns/istio-system/sa/istio-ingressgateway-service-account
to:
- operation:
methods:
- GET
- POST
when:
- key: request.headers[User-Agent]
values:
- "curl/*"
principals
中使用的是 Pod 中的 ServiceAccount !!!
这个文件的意思是 :hello 服务只允许名为 istio-ingressgateway-service-account
的 ServiceAccount 对本服务进行 GET 请求,并且在请求的 headers 中要带有 User-Agent: curl/*
,即只允许 curl 访问。
when
中完整的 key 定义请查看:https://istio.io/docs/reference/config/security/conditions/ ,其 value 支持通配符。
只对一个服务进行了授权之后,也会自动为所在命名空间下的其他服务添加禁止访问的权限。
因为 hello 服务还访问了 other 服务,所以这里也要为 other 服务添加授权策略。
编写 other-authorization-policy.yaml :
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: other-authorization-policy
namespace: xujiyou-test
spec:
selector:
app: other
rules:
- from:
- source:
namespaces:
- xujiyou-test
principals:
- "*"
- cluster.local/ns/xujiyou-test/sa/default
to:
- operation:
methods:
- GET
注意看,这里的 source 不仅可以定义 ServiceAccount ,还支持定义命名空间和通配符。
在 Istio 1.5 版本之后,Istio 将不会再有黑名单白名单之类的访问控制,而是同意使用 AuthorizationPolicy
进行访问控制!!!