iT邦幫忙

2018 iT 邦幫忙鐵人賽
DAY 25
1
DevOps

k8s 不自賞系列 第 25

Day 25 - 保護你的系統:套用 SSL

  • 分享至 

  • xImage
  •  

Day 25 - 保護你的系統:套用 SSL

本日共賞

  • 認證、授權與加密
  • 加入 SSL

希望你知道

認證、授權與加密

認證 (Authentication)、授權 (Authorization) 與加密 (Encryption),對於 Cloud Security 來說一直是很重要的議題。簡單來說

  • 認證:確認是否為合法使用者 (Authenticated User)
  • 授權:確認是否有權限 (Permission) 能存取
  • 加密:確保資料在傳輸中的安全性

參考文章 Understanding Authentication, Authorization, and Encryption

針對部署在 k8s 中的應用程式,我們可以套用 SSL (Secure Sockets Layer) 來加強應用程式的安全性,今天將分享如何加入 SSL

加入 SSL

開始前,這裡先說明加入 SSL 的大略步驟

  1. 建立自我簽署憑證 (self-signed certificates)
  2. 建立 Secret 物件
  3. 為應用程式加入 SSL

建立自我簽署憑證

憑證選擇

要套用 SSL 需要有一份公正第三方簽署的憑證 (certificates) 而網路上可以找到很多 SSL 供應商提供不同等級與方案的憑證。當然也有提供免費 SSL 憑證的供應商,例如 Letsencrypt, sslforfree 等等。

付費的憑證效期長但是就是要付錢,而免費的憑證通常只會提供較短期 (三個月) 的期限,缺點是需要常常更新。需要使用哪一種方案請自行斟酌。

這裡用的憑證,是透過 openssl 產生的自我簽署憑證。雖無第三方認證機構的效力,不過使用上與第三方憑證無異。

首先透過指令建立金鑰與憑證

$ openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt
  • req:使用 X.509 Certificate Signing Request(CSR) Management 產生憑證
  • -x509:建立自我簽署的憑證
  • -nodes:不使用密碼保護
  • -days 365:設定憑證期限為 365 天
  • -newkey rsa:2048:產生新的 RSA 金鑰
  • -keyout:金鑰名稱與儲存位置
  • -out:憑證名稱與儲存位置

接著會提示輸入憑證相關資訊。因為是測試用,只要填入 Email Address 即可,其他可以直接按 Enter 忽略。順利的話會產生 tls.key 與 tls.crt 這兩個檔案。
接下來我們要將 key 與 crt 部署到 k8s 中,k8s 就可以利用這兩個檔案來啟用加密

建立 Secret 物件

透過指令建立 Secret 物件

$ kubectl create secret generic tls-certificate --from-file=./tls.key --from-file=./tls.crt
secret "tls-certificate" created

--from-file:會需要使用金鑰與憑證

觀察一下名為 tls-certificate 的 Secret 物件

$ kubectl describe secret tls-certificate
Name:         tls-certificate
Namespace:    default
Labels:       <none>
Annotations:  <none>

Type:  Opaque

Data
====
tls.key:  1704 bytes
tls.crt:  1021 bytes

我們可以看到 tls-certificate 包含兩個 Data 欄位即 tls.key 與 tls.crt 。

為應用程式加入 SSL

接著我們需要部署可以提供 SSL 服務的應用程式。我已經預先做好了 docker 映像檔,位置在 jlptf/ssl-nginx。照著之後的說明,如果一切順利無誤,則透過瀏覽器可存取以下畫面。

這邊顯示 “不安全”是正常的,因為我們是使用自我簽署憑證,就好像詐騙集團自己寫了一張“我們是合法機構”的告示貼在門口的意思是一樣的。

底下我先來解釋一下在映像檔中做了哪些事情。

首先修改 nginx 的 default.conf 設定檔,讓 nginx 能夠支援 SSL

# default.conf

server{
listen 80 default_server;
listen [::]:80 default_server;

listen 443 ssl default_server;
listen [::]:443 ssl default_server;

ssl_certificate /etc/nginx/ssl/tls.crt;
ssl_certificate_key /etc/nginx/ssl/tls.key;
}

其中 ssl_certificatessl_certificate_key 分別是憑證與金鑰的名稱與存放的位置。在部署到 k8s 後,我們會需要將上述的 tls-certificate (Secret 物件) ,放置到對應的位置上即 /etc/nginx/ssl/,因此名稱與路徑都十分重要。

接著攥寫部署需要用到的 .yaml 檔,這邊需要兩個檔案,分別是 deploy.ssl.yamlservice.ssl.yaml 內容如下

# deploy.ssl.yaml

---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: ssl-nginx
spec:
  replicas: 1
  template:
    metadata:
      labels: 
        app: ssl-nginx
    spec:
      containers:
      - name: ssl-nginx
        image: jlptf/ssl-nginx   <=== 使用預先做好的映像檔
        ports:
        - containerPort: 443   <=== SSL port 為 443
        volumeMounts:
        - name: nginx-ssl    <=== 將 Volume 掛載到 /etc/nginx/ssl 目錄下
          mountPath: /etc/nginx/ssl
          readOnly: true
      volumes:
      - name: nginx-ssl    <=== 掛載一個 Volume 並綁定名為 tls-certificate 的 Secret 物件
        secret:
          secretName: tls-certificate

大部分的內容已在前面文章解釋說明過,請參考之前文章內容。需要特別注意的是

  • image: jlptf/ssl-nginx:記得換成支援 SSL 的映像檔
  • containerPort:SSL 預設 port 為 443
  • volumes.secret.secretName:將名稱為 tls-certificate 的 Secret 物件掛載成名稱為 nginx-ssl 的 volume
  • spec.containers.volumeMounts:將名稱為 nginx-ssl 的 volume 掛載到 /etc/nginx/ssl 並設定成唯讀
# service.ssl.yaml

---
apiVersion: v1
kind: Service
metadata:
  name: ssl-web
spec:
  type: NodePort
  selector:
    app: ssl-nginx
  ports:
    - protocol: TCP
      port: 443
      targetPort: 443

這裡的設定只要注意 selector, port 與 targetPort 即可

接下來執行指令部署物件

$ kubectl apply -f deploy.ssl.yaml
deployment "ssl-nginx" created

$ kubectl apply -f service.ssl.yaml 
service "ssl-web" created

查看新增的 Service

$ kubectl get service
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)         AGE
kubernetes   ClusterIP   10.0.0.1     <none>        443/TCP         5d
ssl-web      NodePort    10.0.0.227   <none>        443:32525/TCP   1m

ssl-web 即為新增加的 Service 物件,我們可以透過 32525 port 存取 SSL server。還記得怎麼取得 minikube IP 嗎?取得 IP 後,打開瀏覽器輸入 https://[minikubeIP]:32525 就能存取有提供 SSL 服務的 nginx。

注意 port 會不同

本文與部署檔案同步發表於 https://jlptf.github.io/ironman2018-day25/


上一篇
Day 24 - 常見問題與建議 (5)
下一篇
Day 26 - 部署多階層應用:簡易通訊錄 SAB
系列文
k8s 不自賞32
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言