iT邦幫忙

2026 iThome 鐵人賽

DAY 26
0
Software Development

從零打造邊緣運算閘道器:Raspberry Pi 與 Linux 底層軟硬整合實戰系列 第 26

Day 26:開源前的準備:實戰機敏資訊去敏與自動化發布檢查

  • 分享至 

  • xImage
  •  

🎯 問題情境 (The Problem)

在邊緣運算閘道器 (EdgeNode) 的研發過程中,工程團隊通常會在測試階段將各種伺服器 IP、SFTP 連線帳密、私鑰憑證、甚至是硬體設備的 CPU 序列號 (Serial Number) 硬編碼 (Hardcode) 在程式碼或設定檔中。

當專案從「內部原型階段」準備走向「商業部署」或是「開源 Publish」時,噩夢往往就發生了:

  1. 憑證洩漏:開發者一個不留神,將含有 Cloud Server SFTP 登入密碼或私鑰的 config.json 提交到 Git Remote。
  2. 硬體防拷失效:用來作為綁定晶片的 CPU 序號與加密金鑰以明文存放在樹莓派磁碟中,設備一旦掉落現場被拔掉 SD 卡,憑證即遭複製。
  3. ** Git 歷史殘留**:即便發現後手動刪除該檔案並重新 git commit,機敏資訊依然完好無損地躺在 Git commit history 裡。

在醫療或工業邊緣閘道器的防禦體系中,「資訊安全與去敏 (Sanitization)」是 SRE 穩定度工程的第一道防線


❌ 錯誤嘗試 (The Pitfalls)

許多團隊在處理去敏與憑證管理時,經常犯下以下三個致命錯誤:

1. 單純依賴 .gitignore

工程師以為在 .gitignore 加上 secrets.json 就安全了。然而,只要團隊中某位成員在建立 .gitignore 之前就 git add . 了一次,該檔案就會被納入版控,後續再加 .gitignore 根本無法阻止機敏檔案被推送出去。

2. 事後刪除與強制推送

當發現憑證洩漏後,直覺地執行:

rm config/secrets.json
git commit -m "Remove secrets"
git push

這種做法只是在最新的 Commit 隱藏了檔案,任何人只要 git log -p 或切換到舊 Commit,依然能一覽無遺地看到當年的明文密碼。

3. 將憑證硬編碼在 Python 程式碼中

# ❌ 極度危險的寫法
SFTP_HOST = "10.0.0.5"
SFTP_USER = "admin"
SFTP_PASS = "SuperSecretPassword123"

這種寫法不僅無法隨部署環境動態調整,更會讓所有擁有程式碼存取權的人直接取得核心伺服器的最高存取權限。


🧠 底層原理:機敏防禦與環境變數隔離

要打造商業級的邊緣閘道器,我們必須建立 「三層防禦架構」

https://ithelp.ithome.com.tw/upload/images/20260911/20183645ik9vBxQysm.png

1. 動態金鑰衍生 (Key Derivation Function, KDF)

邊緣設備不應存放明文憑證。我們利用樹莓派獨一無二的硬體 CPU 序號(位於 /proc/cpuinfo),搭配 PBKDF2 衍生出專屬的 AES-256 對稱金鑰。

  • 明文憑證只在「生產線首度燒錄」時存在。
  • 設備開機後,自動將明文加密成 secrets.dat,並強制徹底抹除 (Shred) 原始明文檔。

2. 設定檔與程式碼分離

所有環境相關的設定(如 IP、Port、路徑)一律抽離成外部 JSON 或環境變數,程式碼本身保持 100% 潔淨且不包含任何硬編碼資訊。

3. Git 自動化攔截牆 (Pre-commit Hooks)

在程式碼送出版控前,在本地端自動觸發正則表達式 (Regex) 掃描,強制攔截含有 IP 地址、API Key 或私鑰格式的提交。


💡 最終解決方案:自動化去敏與發布檢查

1. 實作 CPU 序號綁定與明文自動抹除 (security.py)

DataGateway 部署腳本中,我們實作自動化機敏保護機制:

import os
import json
import base64
from cryptography.fernet import Fernet
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
from cryptography.hazmat.primitives import hashes

def get_hardware_cpu_sn() -> str:
    """擷取樹莓派硬體 CPU 獨一無二的序列號"""
    try:
        with open('/proc/cpuinfo', 'r') as f:
            for line in f:
                if line.startswith('Serial'):
                    return line.split(':')[1].strip()
    except Exception:
        pass
    return "0000000000000000"

def derive_fernet_key(salt: bytes) -> bytes:
    """使用 CPU 序號衍生 32-byte Fernet 加密金鑰"""
    cpu_sn = get_hardware_cpu_sn()
    kdf = PBKDF2HMAC(
        algorithm=hashes.SHA256(),
        length=32,
        salt=salt,
        iterations=100000,
    )
    return base64.urlsafe_b64encode(kdf.derive(cpu_sn.encode()))

def secure_provision_secrets(json_path: str, dat_path: str):
    """將明文 secrets.json 加密轉存為 secrets.dat 並安全抹除明文"""
    if not os.path.exists(json_path):
        return
        
    print("[Security] 檢測到明文憑證,啟動硬體加密流程...")
    with open(json_path, 'r', encoding='utf-8') as f:
        raw_data = f.read()

    salt = os.urandom(16)
    key = derive_fernet_key(salt)
    fernet = Fernet(key)
    
    encrypted_bytes = fernet.encrypt(raw_data.encode())
    
    # 寫入包含 Salt + 密文的 binary 檔案
    with open(dat_path, 'wb') as f:
        f.write(salt + encrypted_bytes)
        
    # 安全抹除原始明文檔案 (Shredding)
    with open(json_path, "ba+", buffering=0) as f:
        length = f.tell()
        f.seek(0)
        f.write(os.urandom(length))
    os.remove(json_path)
    print("[Security] 明文憑證已徹底銷毀,已生成 CPU 綁定加密檔。")

2. 實作 Git Pre-commit 自動去敏檢查腳本 (.git/hooks/pre-commit)

為了防止開發人員誤將私密資訊提交至程式庫,我們在 Git Hook 中設定自動化攔截:

#!/bin/bash
# .git/hooks/pre-commit

echo "🔍 執行出貨與開源前機敏資訊去敏檢查 (Pre-commit Check)..."

# 1. 檢查是否有固定的私人內網 IP (例如 192.168.x.x)
FORBIDDEN_IP=$(git diff --cached | grep -E "192\.168\.[0-9]{1,3}\.[0-9]{1,3}" | grep "^+")

if [ -n "$FORBIDDEN_IP" ]; then
    echo "❌ [ERROR] 攔截到未去敏的內網 IP 地址提交!"
    echo "$FORBIDDEN_IP"
    echo "💡 請將 IP 替換為 10.0.0.x 或改用環境變數載入。"
    exit 1
fi

# 2. 檢查是否有明文私鑰或敏感檔名
FORBIDDEN_KEYS=$(git diff --cached --name-only | grep -E "(secrets\.json|\.pem|\.key|id_rsa)")

if [ -n "$FORBIDDEN_KEYS" ]; then
    echo "❌ [ERROR] 攔截到機敏檔案提交:"
    echo "$FORBIDDEN_KEYS"
    echo "💡 請確認該檔案已加入 .gitignore 並從 Index 中移除!"
    exit 1
fi

echo "✅ 機敏檢查通過,允許 Commit!"
exit 0

🎯 小結

邊緣閘道器的安全性絕不能依賴「事後補救」。在 Day 26 中,我們介紹了:

  1. 硬體 CPU 序號綁定:讓密文離開該台樹莓派即無法解密。
  2. 安全檔案抹除 (Shredding):確保隨身碟或 SD 卡被實體拔走時,明文檔已無處尋覓。
  3. 自動化 Pre-commit 攔截:從開發源頭絕後患,確保程式碼具備完美的去敏品質。

在下一篇 Day 27 中,我們將深入探討現場防護的另一個硬核課題:「斷電與拔插救援:如何實作開機自動化 fsck 檢查與壞軌修復?」


上一篇
Day 25:從隱性狀態到嚴謹架構:淺談有限狀態機 (FSM) 如何徹底解決爭奪鬧劇
系列文
從零打造邊緣運算閘道器:Raspberry Pi 與 Linux 底層軟硬整合實戰26
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言