智匯華云 | Istio中雙向TLS認(rèn)證功能詳解

??一、概述

??Istio中實(shí)現(xiàn)了從客戶端到服務(wù)器端的全鏈路加密功能,首先從外部的客戶端發(fā)起請(qǐng)求,到達(dá)Istio的Ingress?Proxy,后者作為整個(gè)集群的邊界網(wǎng)關(guān),會(huì)再將請(qǐng)求轉(zhuǎn)發(fā)到集群內(nèi)部的微服務(wù),在集群內(nèi)部,一般會(huì)涉及到多個(gè)微服務(wù)之間的交互,形成一個(gè)調(diào)用鏈。

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

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

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

??在Envoy?Proxy?A與Envoy?Proxy?B之間認(rèn)證的過(guò)程對(duì)于Pod?A或者Pod?B而言都是無(wú)感知的。

??Istio中雙向tls認(rèn)證的基本對(duì)象是

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

??kind:?PeerAuthentication

??二、認(rèn)證配置的策略類型

??在具體進(jìn)行配置的時(shí)候,有四種基本的策略

??DISABLE

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

??STRICT

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

??PERMISSIVE

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

??UNSET

??即沒(méi)有進(jìn)行設(shè)置,這種情況下會(huì)繼承上級(jí)策略,比如當(dāng)前namespace的或者整個(gè)系統(tǒng)的。如果上級(jí)策略都為空,則會(huì)默認(rèn)設(shè)置為PERMISSIVE

??三、認(rèn)證配置的范圍

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

??全局

??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級(jí)別,即某個(gè)namespace中所有服務(wù)

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

??kind:?PeerAuthentication

??metadata:

??name:?default

??namespace:?foo

??spec:

??mtls:

??mode:?PERMISSIVE

??負(fù)載級(jí)別,即某個(gè)namespace中某些具體的Pod

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

??kind:?PeerAuthentication

??metadata:

??name:?default

??namespace:?foo

??spec:

??selector:

??matchLabels:

??app:?finance

??mtls:

??mode:?STRICT

??會(huì)將帶有"app:?finance"label的Pod所在的Envoy實(shí)行STRICT模式。

??端口級(jí)別

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

??kind:?PeerAuthentication

??metadata:

??name:?default

??namespace:?foo

??spec:

??selector:

??matchLabels:

??app:?finance

??mtls:

??mode:?STRICT

??portLevelMtls:

??8080:

??mode:?DISABLE

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

??四、認(rèn)證配置的具體方法

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

??服務(wù)器端配置,給服務(wù)B對(duì)應(yīng)的負(fù)載配置PeerAuthentication策略,這里配置的是服務(wù)B所有關(guān)聯(lián)Pod對(duì)應(yīng)的Envoy?Proxy。

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

??kind:?PeerAuthentication

??metadata:

??name:?default

??namespace:?foo

??spec:

??selector:

??matchLabels:

??app:?B

??mtls:

??mode:?STRICT

??2.?客戶端配置,給服務(wù)B配置DestinationRule策略。這里配置的是所有訪問(wèn)服務(wù)B的Pod對(duì)應(yīng)的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

??也就是說(shuō)客戶端配置的時(shí)候需要配置目的服務(wù)的DestinationRule對(duì)象,而服務(wù)器端配置的時(shí)候需要配置服務(wù)器端對(duì)應(yīng)負(fù)載的PeerAuthentication對(duì)象。

??五、測(cè)試case1:默認(rèn)配置

??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個(gè)namespace:foo,?bar和legacy,每個(gè)namespace分別創(chuàng)建了sleep和httpbin兩種應(yīng)用,作為客戶端和服務(wù)器端。在foo和bar中的Pod有對(duì)應(yīng)的Envoy?Proxy,而在legacy中則沒(méi)有。下面是創(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

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

??[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

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

??[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訪問(wèn)foo中的httpbin,header中帶有"X-Forwarded-Client-Cert"表明使用了雙向tls認(rèn)證。

??[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訪問(wèn)legacy中的httpbin,header中則不會(huì)帶有"X-Forwarded-Client-Cert",因?yàn)榭蛻舳撕头?wù)器端都沒(méi)有Envoy?Proxy,只能進(jìn)行沒(méi)有任何加密的明文傳輸。

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

??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

??六、測(cè)試case2:針對(duì)特定服務(wù)的配置

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

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

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

??kind:?"PeerAuthentication"

??metadata:

??name:?"default"

??namespace:?"istio-system"

??spec:

??mtls:

??mode:?DISABLE

??EOF

??然后創(chuàng)建一個(gè)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

??這時(shí)進(jìn)行測(cè)試,會(huì)發(fā)現(xiàn)他們之間可以正常訪問(wèn),但沒(méi)有使用雙向tls認(rèn)證,這符合預(yù)期,說(shuō)明全局策略生效。

??[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]#

??接下來(lái)為服務(wù)器端配置PeerAuthentication策略,讓其強(qiáng)制執(zhí)行雙向tls認(rèn)證

??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

??這時(shí)再次進(jìn)行測(cè)試

??[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錯(cuò)誤,這其實(shí)是一個(gè)tls沖突,因?yàn)榻刂聊壳盀橹刮覀優(yōu)榉?wù)器端設(shè)置了強(qiáng)制使用雙向tls認(rèn)證,但是客戶端還未設(shè)置。

??接下來(lái)設(shè)置客戶端。

??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

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

??[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

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