官方文档:node
Istio 1.5 的安全更新:git
安全发现服务(SDS):github
接下来咱们配置一个安全网关,为外部提供 HTTPS 的访问方式。首先,确认 curl
命令是否经过LibreSSL去编译的:docker
$ curl --version |grep LibreSSL
为服务建立根证书和私钥:json
$ openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -subj '/O=example Inc./CN=example.com' -keyout example.com.key -out example.com.crt
为 httpbin.example.com 域名建立证书和私钥:api
$ openssl req -out httpbin.example.com.csr -newkey rsa:2048 -nodes -keyout httpbin.example.com.key -subj "/CN=httpbin.example.com/O=httpbin organization" $ openssl x509 -req -days 365 -CA example.com.crt -CAkey example.com.key -set_serial 0 -in httpbin.example.com.csr -out httpbin.example.com.crt
完成以上操做后,当前目录会建立以下证书和密钥文件:安全
[root@m1 ~]# ls |grep example example.com.crt example.com.key httpbin.example.com.crt httpbin.example.com.csr httpbin.example.com.key [root@m1 ~]#
部署 httpbin 服务:bash
apiVersion: v1 kind: Service metadata: name: httpbin labels: app: httpbin spec: ports: - name: http port: 8000 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: containers: - image: docker.io/citizenstig/httpbin imagePullPolicy: IfNotPresent name: httpbin ports: - containerPort: 8000
而后为入口网关建立k8s的secret,将 httpbin.example.com 域名的密钥和证书挂载到secret中:app
$ kubectl create -n istio-system secret tls httpbin-credential --key=httpbin.example.com.key --cert=httpbin.example.com.crt
建立入口网关,并指定外部以 https 方式访问:curl
apiVersion: networking.istio.io/v1alpha3 kind: Gateway metadata: name: mygateway spec: selector: istio: ingressgateway servers: - port: # 使用https访问方式 number: 443 name: https protocol: HTTPS tls: mode: SIMPLE # 简单模式,单向TLS credentialName: httpbin-credential # k8s secret的名称 hosts: - httpbin.example.com
建立虚拟服务,配置 TLS 网关和路由规则:
apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: httpbin spec: hosts: - "httpbin.example.com" gateways: - mygateway http: - match: - uri: prefix: /status - uri: prefix: /delay route: - destination: port: number: 8000 host: httpbin
curl
测试,请求验证是否生效:
$ curl -HHost:httpbin.example.com \ --resolve httpbin.example.com:443:${INGRESS_HOST} \ --cacert example.com.crt "https://httpbin.example.com:443/status/418"
若是 istio-ingressgateway 组件是以 nodePort 方式开放端口的,那么这里的 443 端口须要替换成对应的 nodePort 端口。示例:
[root@m1 ~]# kubectl get po -l istio=ingressgateway -n istio-system -o jsonpath='{.items[0].status.hostIP}' 192.168.243.140 # istio-ingressgateway 组件所在的虚拟机IP [root@m1 ~]# kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="https")].nodePort}' 32155 # https的nodePort端口 [root@m1 ~]# curl -HHost:httpbin.example.com --resolve httpbin.example.com:32155:192.168.243.140 --cacert example.com.crt "https://httpbin.example.com:32155/status/418" -=[ teapot ]=- _...._ .' _ _ `. | ."` ^ `". _, \_;`"---"`|// | ;/ \_ _/ `"""` [root@m1 ~]#
配置选项:
mTLS 简介:
接下来咱们尝试为应用设置不一样级别的双向TLS。首先,建立一个用于测试的命令空间:
[root@m1 ~]# kubectl create ns testaut namespace/testaut created [root@m1 ~]#
在该命名空间下建立测试用的客户端(sleep):
[root@m1 ~]# kubectl apply -f /usr/local/istio-1.8.1/samples/sleep/sleep.yaml -n testaut serviceaccount/sleep created service/sleep created deployment.apps/sleep created [root@m1 ~]#
咱们使用上一小节的 httpbin 服务做为服务端,注意 httpbin 是在 default 命名空间下的。咱们经过 sleep 访问一下 httpbin 的接口:
[root@m1 ~]# kubectl get po -n testaut NAME READY STATUS RESTARTS AGE sleep-854565cb79-tk586 1/1 Running 0 2m4s [root@m1 ~]# kubectl exec -it sleep-854565cb79-tk586 -n testaut -c sleep -- curl http://httpbin.default:8000/ip { "origin": "127.0.0.1" } [root@m1 ~]#
目前它们的通信方式是没有采用TLS的,接下来咱们配置一个对等认证策略:
$ kubectl apply -f - <<EOF apiVersion: "security.istio.io/v1beta1" kind: "PeerAuthentication" metadata: name: "default" namespace: "default" # 给default添加命名空间策略 spec: mtls: # 采用对等认证 mode: PERMISSIVE # 兼容模式 EOF
此时,依旧能够采用非TLS方式进行通信,由于兼容模式能够同时经过非TLS和TLS方式进行通信:
[root@m1 ~]# kubectl exec -it sleep-854565cb79-tk586 -n testaut -c sleep -- curl http://httpbin.default:8000/ip { "origin": "127.0.0.1" } [root@m1 ~]#
如今咱们将策略改成严格模式,以下:
$ kubectl apply -f - <<EOF apiVersion: "security.istio.io/v1beta1" kind: "PeerAuthentication" metadata: name: "default" namespace: "default" spec: mtls: mode: STRICT # 严格模式 EOF
改成严格模式后,使用非TLS的通信方式就会被拒绝访问了:
[root@m1 ~]# kubectl exec -it sleep-854565cb79-tk586 -n testaut -c sleep -- curl http://httpbin.default:8000/ip curl: (56) Recv failure: Connection reset by peer command terminated with exit code 56 [root@m1 ~]#
此时咱们就要为网格内的服务开启自动 mTLS,开启的方式也比较简单,只须要注入 Sidecar 便可。由于 Istio 已经实现了一个自动的 mTLS ,会帮咱们完成证书和密钥的管理。命令以下:
[root@m1 ~]# kubectl apply -f <(istioctl kube-inject -f /usr/local/istio-1.8.1/samples/sleep/sleep.yaml) -n testaut serviceaccount/sleep unchanged service/sleep unchanged deployment.apps/sleep configured [root@m1 ~]#
并且访问方式也不须要改变,仍是和以前同样:
[root@m1 ~]# kubectl get pods -n testaut NAME READY STATUS RESTARTS AGE sleep-866b7dc94-dqd9p 2/2 Running 0 4m21s [root@m1 ~]# kubectl exec -it sleep-866b7dc94-dqd9p -n testaut -c sleep -- curl http://httpbin.default:8000/ip { "origin": "127.0.0.1" } [root@m1 ~]#
上面示例的认证范围针对的是命名空间,咱们也能够添加全局策略,以下示例:
$ kubectl apply -f - <<EOF apiVersion: "security.istio.io/v1beta1" kind: "PeerAuthentication" metadata: name: "default" spec: mtls: mode: STRICT EOF
配置选项:
与认证相对应的就是受权,简单来讲受权就是授予你作什么事情的权利,例如某个数据只有获得受权的用户才能访问。在 Istio 中咱们能够使用 JWT 来实现身份认证与受权。
什么是 JWT:
经过以下命令建立用于测试的命名空间,以及两个分别做为客户端(sleep)和服务端(httpbin)的应用:
[root@m1 ~]# kubectl create ns testjwt namespace/testjwt created [root@m1 ~]# kubectl apply -f <(istioctl kube-inject -f /usr/local/istio-1.8.1/samples/httpbin/httpbin.yaml) -n testjwt # httpbin做为服务端 serviceaccount/httpbin created service/httpbin created deployment.apps/httpbin created [root@m1 ~]# kubectl apply -f <(istioctl kube-inject -f /usr/local/istio-1.8.1/samples/sleep/sleep.yaml) -n testjwt # sleep做为客户端 serviceaccount/sleep created service/sleep created deployment.apps/sleep created [root@m1 ~]# kubectl get pods -n testjwt NAME READY STATUS RESTARTS AGE httpbin-5b6477fb8-5pn4v 2/2 Running 0 48s sleep-866b7dc94-mrzdg 2/2 Running 0 42s [root@m1 ~]#
测试客户端与服务端之间的连通性:
[root@m1 ~]# kubectl exec "$(kubectl get pod -l app=sleep -n testjwt -o jsonpath={.items..metadata.name})" -c sleep -n testjwt -- curl http://httpbin.testjwt:8000/ip -s -o /dev/null -w "%{http_code}\n" 200 [root@m1 ~]#
接下来配置基于 JWT 的认证策略,建立一个请求认证资源,以下所示:
kubectl apply -f - <<EOF apiVersion: "security.istio.io/v1beta1" kind: "RequestAuthentication" # 资源类型为请求认证 metadata: name: "jwt-example" namespace: testjwt # 做用于哪一个命名空间 spec: selector: matchLabels: app: httpbin # 须要请求认证的服务 jwtRules: - issuer: "testing@secure.istio.io" # JWT的签发人 jwks: "https://raw.githubusercontent.com/istio/istio/release-1.8/security/tools/jwt/samples/jwks.json" # 用于验证JWT签名的提供者公钥集的URL EOF
测试使用不合法的JWT访问,会返回401:
[root@m1 ~]# kubectl exec $(kubectl get pod -l app=sleep -n testjwt -o jsonpath={.items..metadata.name}) -c sleep -n testjwt -- curl "http://httpbin.testjwt:8000/headers" -H "Authorization: Bearer invalidToken" -s -o /dev/null -w "%{http_code}\n" 401 [root@m1 ~]#
测试没有受权策略时,能够直接访问:
[root@m1 ~]# kubectl exec $(kubectl get pod -l app=sleep -n testjwt -o jsonpath={.items..metadata.name}) -c sleep -n testjwt -- curl "http://httpbin.testjwt:8000/headers" -s -o /dev/null -w "%{http_code}\n" 200 [root@m1 ~]#
配置 JWT 的受权策略,实现基于 JWT 的受权访问:
kubectl apply -f - <<EOF apiVersion: security.istio.io/v1beta1 kind: AuthorizationPolicy # 受权策略 metadata: name: require-jwt namespace: testjwt # 做用于哪一个命名空间 spec: selector: matchLabels: app: httpbin # 须要受权访问的服务 action: ALLOW # 符合受权条件时的动做,拒绝或容许 rules: # 定义受权规则 - from: - source: requestPrincipals: ["testing@secure.istio.io/testing@secure.istio.io"] # 来源于此JWT签发人列表的请求知足条件 EOF
解析token,并设置为系统变量:
[root@m1 ~]# TOKEN=$(curl https://raw.githubusercontent.com/istio/istio/release-1.8/security/tools/jwt/samples/demo.jwt -s) && echo "$TOKEN" | cut -d '.' -f2 - | base64 --decode -
而后进行验证,测试带token的请求是否正常:
[root@m1 ~]# kubectl exec $(kubectl get pod -l app=sleep -n testjwt -o jsonpath={.items..metadata.name}) -c sleep -n testjwt -- curl "http://httpbin.testjwt:8000/headers" -s -o /dev/null -H "Authorization: Bearer $TOKEN" -w "%{http_code}\n" 200 [root@m1 ~]#
请求认证配置选项:
受权策略配置选项:
关于安全方面更多的内容能够参考官方文档的使用示例: