Secrets Management(機密管理)
是什麼?
Secrets Management 是管理應用程式中敏感資訊(API Key、資料庫密碼、加密金鑰、Certificate)的完整生命週期:產生、儲存、存取、輪替、撤銷。
ℹ️什麼算是 Secret?
任何洩漏後會造成安全風險的資訊:API Key、Database Connection String、JWT Signing Key、OAuth Client Secret、TLS Certificate Private Key、Encryption Key。
核心觀念
儲存方式比較
| 方式 | 安全性 | 適用場景 | |------|--------|----------| | 硬編碼在程式碼中 | 極危險 | 永遠不要這樣做 | | .env 檔案(不 commit) | 低 | 本地開發 | | 環境變數 | 中 | 容器化部署 | | Cloud Secret Manager | 高 | AWS/GCP/Azure 雲端服務 | | HashiCorp Vault | 最高 | 企業級集中管理 |
Key Rotation 策略
- 自動輪替:設定排程自動產生新金鑰,舊金鑰在寬限期後失效
- Grace Period:新舊金鑰並存期間,確保部署中的服務不中斷
- 輪替頻率:依據合規要求與風險等級,通常 30-90 天
零信任原則
- 最小權限:每個服務只能存取自己需要的 secret
- 審計日誌:記錄誰在什麼時候存取了什麼 secret
- 動態 Secret:用完即棄,不使用長期有效的靜態憑證
常見誤區
⚠️常犯錯誤
- 把
.env檔案 commit 到 Git(即使之後刪除,Git history 中仍然存在) - 在 log 中印出 secret(即使是 debug 模式)
- 所有服務共用同一個 API Key(一個洩漏全部完蛋)
- Secret 從不輪替(洩漏時影響範圍無限擴大)
執行流程
產生 Secret
用密碼學安全的隨機數產生器建立 secret
安全儲存
存入 Vault 或 Cloud Secret Manager,加密靜態儲存
存取控制
透過 IAM Policy 或 ACL 控制誰能讀取
注入應用
啟動時從 Vault 取得,注入環境變數或記憶體
輪替與撤銷
定期自動輪替,緊急時立即撤銷
流程解讀:Secret 的生命週期從安全產生開始,絕對不能使用可預測的值。儲存時必須加密(encryption at rest),存取時透過嚴格的權限控制。應用程式啟動時從 Vault 動態取得 secret,避免寫死在設定檔中。定期輪替確保即使 secret 洩漏,攻擊視窗也是有限的。
程式碼範例
C# 版本
// ASP.NET Core — 使用 Azure Key Vault
using Azure.Identity;
using Azure.Security.KeyVault.Secrets;
var builder = WebApplication.CreateBuilder(args);
// 從 Azure Key Vault 載入 secrets
builder.Configuration.AddAzureKeyVault(
new Uri("https://my-vault.vault.azure.net/"),
new DefaultAzureCredential()
);
// 使用時直接從 Configuration 取得
var dbConnection = builder.Configuration["DatabaseConnection"];
// 絕對不要這樣做
// var apiKey = "sk-hardcoded-key-12345"; // 硬編碼
// HashiCorp Vault 整合
using VaultSharp;
var vaultClient = new VaultClient(new VaultClientSettings(
"https://vault.mycompany.com",
new TokenAuthMethodInfo("hvs.token")
));
var secret = await vaultClient.V1.Secrets.KeyValue.V2
.ReadSecretAsync("myapp/database");
var password = secret.Data.Data["password"].ToString();TypeScript 版本
import { SecretManagerServiceClient } from "@google-cloud/secret-manager";
// Google Cloud Secret Manager
const client = new SecretManagerServiceClient();
async function getSecret(secretName: string): Promise<string> {
const [version] = await client.accessSecretVersion({
name: `projects/my-project/secrets/${secretName}/versions/latest`,
});
return version.payload?.data?.toString() ?? "";
}
// 應用啟動時載入所有需要的 secrets
async function loadSecrets() {
const dbPassword = await getSecret("db-password");
const apiKey = await getSecret("external-api-key");
return {
database: { password: dbPassword },
externalApi: { key: apiKey },
};
}
// .env 只用於本地開發,搭配 .gitignore
// .env 檔案內容:
// DB_PASSWORD=local-dev-password
// API_KEY=test-key-not-realPython 版本
import boto3
import json
from functools import lru_cache
# AWS Secrets Manager
def get_secret(secret_name: str) -> dict:
client = boto3.client("secretsmanager", region_name="ap-northeast-1")
response = client.get_secret_value(SecretId=secret_name)
return json.loads(response["SecretString"])
# 快取 secret,避免每次請求都呼叫 API
@lru_cache(maxsize=32)
def get_db_credentials() -> dict:
return get_secret("myapp/database")
# HashiCorp Vault
import hvac
client = hvac.Client(url="https://vault.mycompany.com",
token="hvs.token")
# 讀取 KV secret
secret = client.secrets.kv.v2.read_secret_version(
path="myapp/database"
)
db_password = secret["data"]["data"]["password"]
# 動態 Secret — 用完即棄的資料庫憑證
creds = client.secrets.database.generate_credentials(
name="myapp-readonly"
)
temp_username = creds["data"]["username"]
temp_password = creds["data"]["password"]
# 這組憑證會在 TTL 到期後自動失效結構圖
圖中 Application 向 Vault 請求 secret,Vault 先透過 IAM 檢查權限,通過後從 Encrypted Storage 取出 secret 並回傳,同時在 Audit Log 記錄存取行為。Key Rotation 定期觸發更新 secret,確保即使洩漏也只在有限時間內有效。
面試常見問題
Q: 如果發現 secret 被 commit 到 Git 了,該怎麼處理?
A: 第一步立即撤銷該 secret(不是刪除 commit,因為可能已經被 clone)。第二步產生新的 secret 並部署。第三步用 git filter-branch 或 BFG Repo-Cleaner 從 Git history 中移除。第四步檢查審計日誌確認是否已被未授權存取。
Q: 環境變數比硬編碼好,但仍有什麼風險?
A: 環境變數可能出現在 process listing(/proc/PID/environ)、crash dump、子程序繼承、container inspection(docker inspect)中。更安全的做法是使用 Vault SDK 在記憶體中管理 secret,用完立即清除。
Q: 什麼是 Dynamic Secret?為什麼比 Static Secret 更安全?
A: Dynamic Secret 是 Vault 根據請求動態產生的短期憑證(例如 15 分鐘有效的資料庫帳密)。好處是:每個 client 拿到的憑證不同(可追溯來源)、自動過期(不需手動撤銷)、洩漏影響範圍極小。
理解測驗
🤔 以下哪種 secret 儲存方式最安全?
🤔 Key Rotation 的主要目的是什麼?
🤔 發現 secret 被 commit 到 Git 後,第一步該做什麼?
重點整理
💡一句話記住
Secrets Management = 不硬編碼 + 集中管理 + 定期輪替。 口訣:「密鑰放 Vault,存取要審計,定期要換鎖」
| 概念 | 說明 | |------|------| | Secret | API Key、密碼、金鑰等敏感資訊 | | Vault | 集中管理 secret 的安全儲存服務 | | Key Rotation | 定期自動更換 secret,限制洩漏風險 | | Dynamic Secret | 用完即棄的短期憑證 | | 核心原則 | 最小權限、加密儲存、完整審計 |