智匯華云 | Istio中雙向TLS認證功能詳解

??一、概述

??Istio中實現(xiàn)了從客戶端到服務器端的全鏈路加密功能,首先從外部的客戶端發(fā)起請求,到達Istio的Ingress?Proxy,后者作為整個集群的邊界網關,會再將請求轉發(fā)到集群內部的微服務,在集群內部,一般會涉及到多個微服務之間的交互,形成一個調用鏈。

??在很多架構模型中,集群內部會被認為是天然安全的,微服務之間的流量也是明文傳輸?shù)?。這種模型現(xiàn)在受到越來越多的質疑,因此諸如很多公有云都實現(xiàn)了"零信任"網絡,全鏈路加密的功能。

??本文會詳細分析在一個集群內部,如何通過Istio實現(xiàn)服務之間通信數(shù)據的加密。Istio中的加密方式是雙向tls的認證,具體是指兩個Envoy?Proxy之間的首先進行雙向tls認證,認證通過后將后續(xù)的數(shù)據流進行加密傳輸。

??例如:Pod?A需要訪問Pod?B,在Istio中,請求都是由Envoy進行代理的,因此完整的流程是Pod?A發(fā)出到Pod?B的請求,然后請求會被Envoy?Proxy?A劫持,接著Envoy?Proxy?A會與Envoy?Proxy?B進行點對點的認證,認證通過后,數(shù)據會進行加密傳輸,請求會由Envoy?Proxy?A發(fā)送給Envoy?Proxy?B,最后再由Envoy?Proxy?B將請求轉發(fā)給Pod?B。

??在Envoy?Proxy?A與Envoy?Proxy?B之間認證的過程對于Pod?A或者Pod?B而言都是無感知的。

??Istio中雙向tls認證的基本對象是

??apiVersion:?security.istio.io/v1beta1

??kind:?PeerAuthentication

??二、認證配置的策略類型

??在具體進行配置的時候,有四種基本的策略

??DISABLE

??即禁用雙向tls認證,這種情況下源Envoy與目的Envoy之間沒有對對方進行身份的安全確認,它們之間發(fā)送的都是明文數(shù)據

??STRICT

??即嚴格的雙向tls認證模式。源Envoy與目的Envoy之間必須對對方進行身份的安全確認,它們之間發(fā)送的都是加密后的數(shù)據。

??PERMISSIVE

??可以進行雙向tls認證、也可以不進行認證從而發(fā)送明文數(shù)據。

??UNSET

??即沒有進行設置,這種情況下會繼承上級策略,比如當前namespace的或者整個系統(tǒng)的。如果上級策略都為空,則會默認設置為PERMISSIVE

??三、認證配置的范圍

??Istio中對雙向tls認證進行配置的時候,可以有幾種不同的范圍,范圍越小優(yōu)先級越高:

??全局

??apiVersion:?security.istio.io/v1beta1

??kind:?PeerAuthentication

??metadata:

??name:?default

??namespace:?istio-system

??spec:

??mtls:

??mode:?STRICT

??注意,全局的安全策略名稱只能是default,namespace則是istio所在的系統(tǒng)namespace,這里是istio-system

??namespace級別,即某個namespace中所有服務

??apiVersion:?security.istio.io/v1beta1

??kind:?PeerAuthentication

??metadata:

??name:?default

??namespace:?foo

??spec:

??mtls:

??mode:?PERMISSIVE

??負載級別,即某個namespace中某些具體的Pod

??apiVersion:?security.istio.io/v1beta1

??kind:?PeerAuthentication

??metadata:

??name:?default

??namespace:?foo

??spec:

??selector:

??matchLabels:

??app:?finance

??mtls:

??mode:?STRICT

??會將帶有"app:?finance"label的Pod所在的Envoy實行STRICT模式。

??端口級別

??apiVersion:?security.istio.io/v1beta1

??kind:?PeerAuthentication

??metadata:

??name:?default

??namespace:?foo

??spec:

??selector:

??matchLabels:

??app:?finance

??mtls:

??mode:?STRICT

??portLevelMtls:

??8080:

??mode:?DISABLE

??會將帶有"app:?finance"label的Pod所在的Envoy實行STRICT模式,但是會將其中的8080端口使用DISABLE模式。

??四、認證配置的具體方法

??在Istio中進行雙向tls認證配置,需要注意的是客戶端和服務器端配置方法是不一樣的。例如在namespace?foo中有兩組服務A和B,每組都有一些Pod,假設服務A的Pod對應的label為"app:?A",而服務B的Pod對應的label為"app:?B"。這時在服務A所在的Pod中訪問服務B,要將這一請求設置為STRICT模式,需要配置兩處

??服務器端配置,給服務B對應的負載配置PeerAuthentication策略,這里配置的是服務B所有關聯(lián)Pod對應的Envoy?Proxy。

??apiVersion:?security.istio.io/v1beta1

??kind:?PeerAuthentication

??metadata:

??name:?default

??namespace:?foo

??spec:

??selector:

??matchLabels:

??app:?B

??mtls:

??mode:?STRICT

??2.?客戶端配置,給服務B配置DestinationRule策略。這里配置的是所有訪問服務B的Pod對應的Envoy?Proxy。

??cat?<<eof |="" kubectl="" apply="" -n="" foo="" -f="" -<="" p=""> ?

??apiVersion:?"networking.istio.io/v1alpha3"

??kind:?"DestinationRule"

??metadata:

??name:?"B"

??spec:

??host:?"B.foo.svc.cluster.local"

??trafficPolicy:

??tls:

??mode:?ISTIO_MUTUAL

??EOF

??也就是說客戶端配置的時候需要配置目的服務的DestinationRule對象,而服務器端配置的時候需要配置服務器端對應負載的PeerAuthentication對象。

??五、測試case1:默認配置

??kubectl?create?ns?foo

??kubectl?apply?-f?<(istioctl?kube-inject?-f?samples/httpbin/httpbin.yaml)?-n?foo

??kubectl?apply?-f?<(istioctl?kube-inject?-f?samples/sleep/sleep.yaml)?-n?foo

??kubectl?create?ns?bar

??kubectl?apply?-f?<(istioctl?kube-inject?-f?samples/httpbin/httpbin.yaml)?-n?bar

??kubectl?apply?-f?<(istioctl?kube-inject?-f?samples/sleep/sleep.yaml)?-n?bar

??kubectl?create?ns?legacy

??kubectl?apply?-f?samples/httpbin/httpbin.yaml?-n?legacy

??kubectl?apply?-f?samples/sleep/sleep.yaml?-n?legacy

??創(chuàng)建了3個namespace:foo,?bar和legacy,每個namespace分別創(chuàng)建了sleep和httpbin兩種應用,作為客戶端和服務器端。在foo和bar中的Pod有對應的Envoy?Proxy,而在legacy中則沒有。下面是創(chuàng)建成功后的Pod情況

??[root@master1?istio-1.6.0]#?kubectl?get?pod?--all-namespaces

??NAMESPACE?NAME?READY?STATUS?RESTARTS?AGE

??bar?httpbin-67576779c-tjl4m?2/2?Running?0?31m

??bar?sleep-7dc44b8d45-rfhpl?2/2?Running?0?31m

??foo?httpbin-67576779c-tw6kl?2/2?Running?0?31m

??foo?sleep-7dc44b8d45-87x2p?2/2?Running?0?31m

??legacy?httpbin-779c54bf49-h5wrw?1/1?Running?0?31m

??legacy?sleep-f8cbf5b76-b8xgd?1/1?Running?0?31m

??在使用默認的default配置部署Istio的情況下,如果沒有設置任何安全策略,默認是PERMISSIVE,即同時允許雙向tls認證和不進行任何認證的明文傳輸兩種方式。注意這只針對有Envoy?Proxy的情況,因為這些策略最終的執(zhí)行者是Envoy,而對于那些沒有Envoy?Proxy的Pod,例如legacy中的Pod,則只能使用明文方式進行收發(fā)數(shù)據。下面來驗證這一點

??[root@master1?istio-1.6.0]#?for?from?in?"foo"?"bar"?"legacy";?do?for?to?in?"foo"?"bar"?"legacy";?do?kubectl?exec?$(kubectl?get?pod?-l?app=sleep?-n?${from}?-o?jsonpath={.items..metadata.name})?-c?sleep?-n?${from}?--?curl?"//httpbin.${to}:8000/ip"?-s?-o?/dev/null?-w?"sleep.${from}?to?httpbin.${to}:?%{http_code}\n";?done;?done

??sleep.foo?to?httpbin.foo:?200

??sleep.foo?to?httpbin.bar:?200

??sleep.foo?to?httpbin.legacy:?200

??sleep.bar?to?httpbin.foo:?200

??sleep.bar?to?httpbin.bar:?200

??sleep.bar?to?httpbin.legacy:?200

??sleep.legacy?to?httpbin.foo:?200

??sleep.legacy?to?httpbin.bar:?200

??sleep.legacy?to?httpbin.legacy:?200

??可以看到任何兩個sleep與httpbin之間都是可以連通的。但是如果進一步觀察,發(fā)現(xiàn)這些認證方式其實是不同的

??[root@master1?istio-1.6.0]#?kubectl?exec?$(kubectl?get?pod?-l?app=sleep?-n?foo?-o?jsonpath={.items..metadata.name})?-c?sleep?-n?foo?--?curl?//httpbin.foo:8000/headers?-s?|?grep?X-Forwarded-Client-Cert

??"X-Forwarded-Client-Cert":?"By=spiffe://cluster.local/ns/foo/sa/httpbin;Hash=41eb8aa0a91782fc1a09df8da85b586c5eaabbca3117f645cdb9df8d998b55f2;Subject=\"\";URI=spiffe://cluster.local/ns/foo/sa/sleep"

??從foo中的sleep訪問foo中的httpbin,header中帶有"X-Forwarded-Client-Cert"表明使用了雙向tls認證。

??[root@master1?istio-1.6.0]#?kubectl?exec?$(kubectl?get?pod?-l?app=sleep?-n?legacy?-o?jsonpath={.items..metadata.name})?-c?sleep?-n?legacy?--?curl?//httpbin.foo:8000/headers?-s?|?grep?X-Forwarded-Client-Cert

??[root@master1?istio-1.6.0]#

??而從legacy中的sleep訪問legacy中的httpbin,header中則不會帶有"X-Forwarded-Client-Cert",因為客戶端和服務器端都沒有Envoy?Proxy,只能進行沒有任何加密的明文傳輸。

??另外,還可以看出sleep.legacy發(fā)出去的請求都是明文數(shù)據,而sleep.httpbin收到的請求也都是明文數(shù)據。而foo和bar里面的Pod發(fā)送請求時則會優(yōu)先使用雙向tls認證方式(即下面四種),這些可以自行測試驗證。

??sleep.foo?to?httpbin.foo:?200

??sleep.foo?to?httpbin.bar:?200

??sleep.bar?to?httpbin.foo:?200

??sleep.bar?to?httpbin.bar:?200

??清理命令

??kubectl?delete?-f?<(istioctl?kube-inject?-f?samples/httpbin/httpbin.yaml)?-n?foo

??kubectl?delete?-f?<(istioctl?kube-inject?-f?samples/sleep/sleep.yaml)?-n?foo

??kubectl?delete?-f?samples/httpbin/httpbin.yaml?-n?legacy

??kubectl?delete?-f?samples/sleep/sleep.yaml?-n?legacy

??kubectl?delete?-f?<(istioctl?kube-inject?-f?samples/httpbin/httpbin.yaml)?-n?bar

??kubectl?delete?-f?<(istioctl?kube-inject?-f?samples/sleep/sleep.yaml)?-n?bar

??kubectl?delete?ns?foo

??kubectl?delete?ns?legacy

??kubectl?delete?ns?bar

??六、測試case2:針對特定服務的配置

??首先,創(chuàng)建一個全局的安全策略,禁用所有的雙向tls認證。

??kubectl?apply?-f?-?< <?p="">? <>

??apiVersion:?"security.istio.io/v1beta1"

??kind:?"PeerAuthentication"

??metadata:

??name:?"default"

??namespace:?"istio-system"

??spec:

??mtls:

??mode:?DISABLE

??EOF

??然后創(chuàng)建一個foo?namespace,并在其中創(chuàng)建帶有Envoy?Proxy的sleep和httpbin

??kubectl?create?ns?foo

??kubectl?apply?-f?<(istioctl?kube-inject?-f?samples/httpbin/httpbin.yaml)?-n?foo

??kubectl?apply?-f?<(istioctl?kube-inject?-f?samples/sleep/sleep.yaml)?-n?foo

??這時進行測試,會發(fā)現(xiàn)他們之間可以正常訪問,但沒有使用雙向tls認證,這符合預期,說明全局策略生效。

??[root@master1?istio-1.6.0]#?kubectl?exec?$(kubectl?get?pod?-l?app=sleep?-n?foo?-o?jsonpath={.items..metadata.name})?-c?sleep?-n?foo?--?curl?"//httpbin.foo:8000/ip"?-s?-o?/dev/null?-w?"sleep.foo?to?httpbin.foo:?%{http_code}\n"

??sleep.foo?to?httpbin.foo:?200

??[root@master1?istio-1.6.0]#?kubectl?exec?$(kubectl?get?pod?-l?app=sleep?-n?foo?-o?jsonpath={.items..metadata.name})?-c?sleep?-n?foo?--?curl?//httpbin.foo:8000/headers?-s?|?grep?X-Forwarded-Client-Cert

??[root@master1?istio-1.6.0]#

??接下來為服務器端配置PeerAuthentication策略,讓其強制執(zhí)行雙向tls認證

??cat?<<eof |="" kubectl="" apply="" -n="" foo="" -f="" -<="" p=""> ?

??apiVersion:?"security.istio.io/v1beta1"

??kind:?"PeerAuthentication"

??metadata:

??name:?"httpbin"

??namespace:?"foo"

??spec:

??selector:

??matchLabels:

??app:?httpbin

??mtls:

??mode:?STRICT

??EOF

??這時再次進行測試

??[root@master1?istio-1.6.0]#?kubectl?exec?$(kubectl?get?pod?-l?app=sleep?-n?foo?-o?jsonpath={.items..metadata.name})?-c?sleep?-n?foo?--?curl?"//httpbin.foo:8000/ip"?-s?-o?/dev/null?-w?"sleep.foo?to?httpbin.foo:?%{http_code}\n"

??sleep.foo?to?httpbin.foo:?503

??[root@master1?istio-1.6.0]#

??出現(xiàn)了503錯誤,這其實是一個tls沖突,因為截至目前為止我們?yōu)榉掌鞫嗽O置了強制使用雙向tls認證,但是客戶端還未設置。

??接下來設置客戶端。

??cat?<<eof |="" kubectl="" apply="" -n="" foo="" -f="" -<="" p=""> ?

??apiVersion:?"networking.istio.io/v1alpha3"

??kind:?"DestinationRule"

??metadata:

??name:?"httpbin"

??spec:

??host:?"httpbin.foo.svc.cluster.local"

??trafficPolicy:

??tls:

??mode:?ISTIO_MUTUAL

??EOF

??然后進行測試,發(fā)現(xiàn)現(xiàn)在已經可以正常訪問,且使用了雙向tls認證,符合預期。

??[root@master1?istio-1.6.0]#?kubectl?exec?$(kubectl?get?pod?-l?app=sleep?-n?foo?-o?jsonpath={.items..metadata.name})?-c?sleep?-n?foo?--?curl?"//httpbin.foo:8000/ip"?-s?-o?/dev/null?-w?"sleep.foo?to?httpbin.foo:?%{http_code}\n"

??sleep.foo?to?httpbin.foo:?200

??[root@master1?istio-1.6.0]#?kubectl?exec?$(kubectl?get?pod?-l?app=sleep?-n?foo?-o?jsonpath={.items..metadata.name})?-c?sleep?-n?foo?--?curl?//httpbin.foo:8000/headers?-s?|?grep?X-Forwarded-Client-Cert

??"X-Forwarded-Client-Cert":?"By=spiffe://cluster.local/ns/foo/sa/httpbin;Hash=b8a73b2655b270e23eda820e49c56cc9b16521d98cb6c1896eff41c58cc32d56;Subject=\"\";URI=spiffe://cluster.local/ns/foo/sa/sleep"

??[root@master1?istio-1.6.0]#

??清理命令

??kubectl?delete?PeerAuthentication?httpbin?-n?foo

??kubectl?delete?DestinationRule?httpbin?-n?foo

??kubectl?delete?-f?<(istioctl?kube-inject?-f?samples/httpbin/httpbin.yaml)?-n?foo

??kubectl?delete?-f?<(istioctl?kube-inject?-f?samples/sleep/sleep.yaml)?-n?foo

??kubectl?delete?ns?foo

(免責聲明:本網站內容主要來自原創(chuàng)、合作伙伴供稿和第三方自媒體作者投稿,凡在本網站出現(xiàn)的信息,均僅供參考。本網站將盡力確保所提供信息的準確性及可靠性,但不保證有關資料的準確性及可靠性,讀者在使用前請進一步核實,并對任何自主決定的行為負責。本網站對有關資料所引致的錯誤、不確或遺漏,概不負任何法律責任。
任何單位或個人認為本網站中的網頁或鏈接內容可能涉嫌侵犯其知識產權或存在不實內容時,應及時向本網站提出書面權利通知或不實情況說明,并提供身份證明、權屬證明及詳細侵權或不實情況證明。本網站在收到上述法律文件后,將會依法盡快聯(lián)系相關文章源頭核實,溝通刪除相關內容或斷開相關鏈接。 )