官方文檔: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 ~]#
請求認證配置選項:
受權策略配置選項:
關於安全方面更多的內容能夠參考官方文檔的使用示例: