DevOps CICD K8s Docker今天筆者想介紹K8s中的TLS,也就是Transport Layer Security。K8s中的TLS說實在滿複雜的,所以筆者想先從基礎的TLS開始講起,先有個概念後會比較好延伸。如果你已經了解TLS了,那麼就直接跳過前面的介紹吧!那我們開始囉~
TLS存在的目的只有一個,那就是"確保Client和Server的訊息傳輸是安全的"。這句話看起來像廢話 (事實上就是),但要達到這個目的其實要確實做到兩件事:
Server是非偽造的舉個例子,當有個User要存取某個Web Application,需要輸入帳號密碼等使用者資訊,這些資訊會以明文(plain text)的方式在網路中傳輸,因此Hacker很容易可以取得這些資料。為了預防這個情況發生,我們會將資料加密,例如random產生一個key然後以XOR等方式加密資料後傳輸,如此即使Hacker真的取得傳輸資料,他取得的也是加密後的資料,無法做任何事。但是Web Server收到的資料同時也是加密後的資料,它一樣無法解讀,因此User必須將key也傳給Web Server,Web Server收到加密資料及key後再進行解密。
這種傳送加密資料,並以相同的key進行加密及解密的方法,就是經典的"對稱式加密(Symmetric Encryption)"
但是問題來了,Hacker既然可以取得加密資料,當然也有辦法取得你的key阿,畢竟是在同一個網路上做傳輸的,沒道理他取不到吧。因此,對稱式加密顯而易見的缺點就是,要是這把鑰匙被中間人竊聽到了,那之後所有攔截到的加密訊息,都能被輕易破解,因為它加解密的方法都是同一把key。為了解決這個問題,就有了所謂 "非對稱式加密(Asymmetric Encryption)"。
"非對稱式加密(Asymmetric Encryption)" 就是每個使用者都擁有"一對金鑰",一把
Public Key,一把Private Key。
你可以把Public Key想像成是一個鎖(lock),而Private Key是用來解這把鎖的鑰匙(key)。鎖是大家都可以來解的,所以它是public,而鑰匙卻只有我有,所以是private的。
(這種說法不是很嚴謹,因為事實上兩把都是key,並沒有一定是誰解誰,這樣舉例只是方便大家理解~)
我們以SSH當作例子,當Client想要access目標Server時,Client會產生一對金鑰。輸入ssh-keygen會產生兩個檔案: id_rsa和id_rsa.pub,分別是Private Key 和 Public Key(lock)。
接著將目標Server以Public Key lock住,確保它是安全的。作法通常是在Server的~/.ssh/authorized_keys中用Public Key 加入一個entry。
$ vim ~/.ssh/authorized_keys
ssh-rsa <public key> <user-name>
這時Client即可透過Private Key存取Server
$ ssh -i id_rsa <user-name>@<server-name>
Successfully Logged In!
剛剛我們提到TLS的安全需要確保傳輸的資料是加密且無法被破解的,那麼要如何辦到呢?我們以剛剛的Web Applcation 當作例子,有Client和目標Server,Client產生一把Symmetric Key(以下簡稱CK),Server則產生一對金鑰,即一個Private Key(以下簡稱SK) 和一個 Public Key(以下簡稱PK)。
要注意,
Public Key是公開在網路上的,理論上所有人都知道,而Private Key只有擁有者知道

當Client以https存取網站時,即得到Web Server公開的PK
Client將CK以PK加密,並將加密後的CK傳送至Server 
Server將加密的CK以SK解密,得到原先的CK 
Client將要傳送的機密資料以CK加密後傳送到Server 
Server將資料以CK解密後,即可得到原始資料 
這樣的作法就可以保證Hacker無法破解資料,為啥呢?
因為在整個資料傳輸及金鑰交換的過程中,Hacker只能取得以下東西
Server的PK
PK加密後的CK
CK加密後的資料如此一來,Hacker無法得到CK(Hacker雖然得到加密後的CK,但是沒有SK就無法破解),當然也無法破解原始資料拉~
但是Hacker也不是省油的燈呀,它可能會產生類似的一組SK跟PK,然後將你的目的地位址導到Hacker的Fake Server,然後用一樣的流程得到你的資料。那要怎麼防止這個情況發生呢? 其實就是一開始獲得PK的方式啦,只要我們確認這個PK是來自真實Server而非Fake Server,那就可以確保傳輸的安全性。至於要如何確認,就是讓Server在給Client 這個PK時,不要直接給PK,而是透過Certificate的方式,而PK則放在其中。這個Certificate會包含一些資訊,像是Server的PK、Server的位址等。
但是你可能會想,Hacker也可能會偽造Certificate阿,那不就沒用了?沒錯,所以Certificate的"簽章(signature)"就變得非常重要。誰創建這個Certificate,誰就必須在上面簽章。所以假的Certificate上面就是Hacker的數位簽章喔~
大部分的Web Browser都有 Certificate Validation Mechanism,所以當你在瀏覽https網站時,常常在URL前會有個"Not secure"的提醒,就是因為Browser認為這個Certificate可能是假的,在警告你喔~
那麼,要如何得知那些Certificate是合法的,哪些是不合法的呢?這就是CA(Certificate Authority)的工作啦~
CA通常是世界上知名的組織,他們可以為你的Certificate簽章和認證,藉此保證你Certificate的合法性。著名的CA像是:
Server會先產生CSR(Certificate Singing Request)到CA請求簽章,CA會檢查CSR中的資訊,若認定Server為合法則會為其簽章,並送回Certificate至Server。至此,Server即擁有Browser認定合法的Certificate了。
若Hacker想產生一組相同的合法
Certificate,到CA這關就會卡關啦~
至於CA是如何判定你是不是合法用戶,這就是它們自己的方法了,筆者也不是很清楚,有興趣的朋友再自己研究囉!
可是還有個問題,Browser要怎麼認定這個Certificate是經由合法CA簽章的,而不是Fake CA呢? 答案是CA自己也會有一組金鑰啦~所有合法CA的Public Key會內嵌在Browser中,而Private Key則由CA自己保存。這樣一來Brower就可以透過這一組金鑰來驗證Certificate是不是由真實CA簽章的囉~
綜合以上這些流程,包含CA、Server、Client、Certificate等等的,就是所謂的
PKI(Public Key Infrastructure)。
總結一下上述的流程,我們一共會有三組金鑰:
Server Certificates : 確保傳輸資料安全Root Certificates : 為Server Certificates簽章Server Certificates : Client的認證 
Public Key的檔名通常是*.crt,*.pem,例如:
- server.crt
- server.pem
- client.crt
- client.pem
Private Key的檔名通常是*.key,*-key.pem,例如:
- server.key
- server-key.pem
- client.key
- client-key.pem
在K8s集群中,Control Plane和Node間、Node和Node間及Administrator和Control Plane之間的連線傳輸都必須確保是安全的,因此他們之間都必須建立TLS連線。K8s中會用到的Certificates有 Client Certificates及 Server Certificates。我們分別列出此兩種Certificates會用到的key及crt,以及他們分別屬於那些元件。要記住,一個元件不一定只有Server或Client的身分,它也可能同時兼具。例如apiserver,它既是admin、kube-scheduler、controller-manager及kube-proxy下達指令的對象(作為Server),亦是向etcd發出request的Client。K8s中的Certificates和key一共有下列這些:
觀察
kube-apiserver的設定檔可以發現K8s認證所需的key和csr會放在/etc/kubernetes/pki目錄下
今天算是比較general的介紹一下TLS的流程以及K8s中TLS的元件有哪些,筆者覺得有個概念即可,有機會後面做題目時再講的細一點。好啦,今天就到這裡啦~ 謝謝大家~
簡介 SSL、TLS 協定
基礎密碼學(對稱式與非對稱式加密技術)
Manage TLS Certificates in a Cluster
PKI Bootcamp - What is a PKI?
PKI certificates and requirements
You can find me on