在 Day 21 的主題中,我們在嘗試讀取敏感資訊的時候都會去找 Secret,但是 Secret 是什麼?為什麼駭客通常都會在容器環境裡面找它?為什麼交由 Secret 管理的敏感資訊,仍可能在容器內被直接讀取?今天讓我們來好好聊聊這個 K8S 的敏感資訊管理機制-Secret,它的功能與運作原理是什麼。
K8S 的官方文件是這麼說明 Secret 的:
從 K8S 的官方文件內容可以知道,Secret 是 K8S 中專門儲存與管理敏感資料的資源物件,讓密碼、Token 與金鑰能與應用程式碼及容器映像檔分開管理。至於這些資料在 etcd 中是否加密,則取決於叢集的靜態加密配置。
但是!官方文件補充了 Secret 的一個大重點:Secret 預設會以未加密的形式,儲存在 etcd 裡面。
接著,官方文件也說明了 Secret 的 data 欄位格式:各個 key 對應的值必須使用 Base64 編碼。
Secret 的 data 欄位在 JSON/YAML 中以 Base64 字串表示;Base64 是編碼,不提供加密保護:

從上述幾點我們可以知道:
接著透過實作,觀察 Secret 在容器內的呈現方式。
在 K8S 官方文件說明,可以在容器設定中透過 envFrom 搭配 secretRef,將指定 Secret 中的鍵值對注入為容器的環境變數:
因此我們可以直接執行 env,列出該指令執行時取得的環境變數。將 Secret 中的密碼與 Token 注入容器環境變數,因此可以直接看到原始值,不需要再做 Base64 解碼。
env

在 K8S 的官方文件說明,Secret 是可以掛載成檔案的:
我們在 Day 22 的 Lab 已將 app-secrets 以檔案形式掛載到容器內的 /etc/app-secrets/。這是 Lab 自訂的掛載目錄,以下使用指令查看目錄與檔案內容:
ls -l /etc/app-secrets/; echo;for f in /etc/app-secrets/*; do echo "$f = $(cat $f)"; done

從輸出可以看到,本實驗的密碼與 Token 在掛載檔中呈現為可直接讀取的明文,不需要再做 Base64 解碼。部分應用程式原本就透過檔案讀取憑證或設定,因此需要這種提供機密的方式。管理時應限制掛載對象、提供必要的 key,並配合適當的檔案權限,落實最小權限原則。
我們先轉移到 Control Node 上面用以下指令查看 app-secrets 的內容。
kubectl -n lab22 get secret app-secrets -o jsonpath='{.data.DB_PASSWORD}'; echo
kubectl -n lab22 get secret app-secrets -o jsonpath='{.data.DB_PASSWORD}' | base64 -d; echo

第一個指令的意思是從 lab23 namespace 讀取名為 app-secrets 的 Secret,取出 data 裡的 DB_PASSWORD 值,最後換行。
第一個指令會輸出 Base64 編碼的值;第二個指令則透過管線 |,將輸出交給 base64 -d,還原出原始密碼。這個結果顯示,API 回傳的 Secret data 值可以透過 Base64 解碼還原。
Secret 的安全防護需要從多個面向著手。靜態加密可以降低 etcd 儲存資料遭竊後的機密外洩風險,前提是攻擊者沒有同時取得解密金鑰或解密能力。然而,權限設定過於寬鬆、應用程式將密碼寫入日誌,或具有 Secret 讀取權限的身分遭竊,仍可能導致敏感資訊外洩。因此,除了靜態加密,還需要落實最小權限原則、保護應用程式的執行環境,並建立憑證輪替與撤銷機制。
除了靜態加密與權限控管,也可以依需求導入 Vault 等機密管理工具,透過支援的整合提供動態憑證、輪替與撤銷能力。不過,交付給容器使用的機密,仍需要由容器與應用程式的安全措施保護。
今天的介紹就到這裡,希望透過這次實驗,讓大家更了解 K8S Secret 的用途與保護範圍。
感謝大家的收看,我們明天見!