本文說明如何透過 mssql-django 後端,在 Django 應用程式中使用 SQL Server Always Encrypted。 Always Encrypted 提供欄位層級加密,保護靜態及傳輸中的敏感資料。
先決條件
- 適用於 SQL Server 的 Microsoft ODBC Driver 17 或 18
- SQL Server 2016 或更新版本,或者 Azure SQL Database
- SQL Server端設定的欄位加密(欄位主金鑰與欄位加密金鑰)
運作原理
Always Encrypted 是由 ODBC 驅動層處理,而非 Django 本身。 啟用 ColumnEncryption ODBC 參數時,驅動程式會在資料在應用程式與 SQL Server 之間傳遞時自動加密與解密。 無論欄位是否加密,Django 模型和查詢的運作方式相同。
Windows 的憑證存放區
當資料行主金鑰儲存在 Windows 憑證存放區時,將 ColumnEncryption=Enabled 新增至 extra_params 以啟用 Always Encrypted:
DATABASES = {
"default": {
"ENGINE": "mssql",
"NAME": "<your-database>",
"USER": "<your-username>",
"PASSWORD": "<your-password>",
"HOST": "<your-server>",
"PORT": "1433",
"OPTIONS": {
"driver": "ODBC Driver 18 for SQL Server",
"extra_params": "ColumnEncryption=Enabled",
},
},
}
這種方法只適用於 Windows。
使用用戶端 ID 和密碼的 Azure 金鑰保存庫
當欄位主金鑰儲存在 Azure Key Vault 時,請在以下欄位提供應用程式憑證:extra_params
DATABASES = {
"default": {
"ENGINE": "mssql",
"NAME": "<your-database>",
"USER": "<your-username>",
"PASSWORD": "<your-password>",
"HOST": "<your-server>",
"PORT": "1433",
"OPTIONS": {
"driver": "ODBC Driver 18 for SQL Server",
"extra_params": (
"ColumnEncryption=Enabled;"
"KeyStoreAuthentication=KeyVaultClientSecret;"
"KeyStorePrincipalId=<application-client-id>;"
"KeyStoreSecret=<client-secret>"
),
},
},
}
將 <application-client-id> 和 <client-secret> 替換為應用程式註冊的 應用程式(用戶端)識別碼 和用戶端密碼值。
Important
不要在 settings.py 中硬編碼機密資訊。 使用環境變數或秘密管理器在執行時提供憑證。
具有受控識別的 Azure Key Vault
在 Azure 上執行時(例如 Azure 虛擬機器 或 Azure App 服務),請使用管理身份來存取 Azure Key Vault。
系統指派的管理身份識別
除了以下 KeyStoreAuthentication 參數外,不需要額外的配置:
DATABASES = {
"default": {
"ENGINE": "mssql",
"NAME": "<your-database>",
"HOST": "<your-server>.database.windows.net",
"PORT": "1433",
"OPTIONS": {
"driver": "ODBC Driver 18 for SQL Server",
"extra_params": (
"ColumnEncryption=Enabled;"
"KeyStoreAuthentication=KeyVaultManagedIdentity"
),
},
},
}
使用者指派的受控識別
加入受控識別的用戶端 ID(也稱為應用程式 ID):
DATABASES = {
"default": {
"ENGINE": "mssql",
"NAME": "<your-database>",
"HOST": "<your-server>.database.windows.net",
"PORT": "1433",
"OPTIONS": {
"driver": "ODBC Driver 18 for SQL Server",
"extra_params": (
"ColumnEncryption=Enabled;"
"KeyStoreAuthentication=KeyVaultManagedIdentity;"
"KeyStorePrincipalId=<managed-identity-client-id>"
),
},
},
}
授與受控識別權限
授與受控識別存取您 Azure SQL 資料庫的權限:
CREATE USER [<identity-name>] FOR EXTERNAL PROVIDER; ALTER ROLE db_datareader ADD MEMBER [<identity-name>]; ALTER ROLE db_datawriter ADD MEMBER [<identity-name>]; GRANT VIEW ANY COLUMN MASTER KEY DEFINITION TO [<identity-name>]; GRANT VIEW ANY COLUMN ENCRYPTION KEY DEFINITION TO [<identity-name>];授權管理身份存取存放欄位主金鑰的 Azure Key Vault,權限列於 Always Encrypted Azure Key Vault 文件中。
讓 Django 管理加密資料表
使用 Django 的 Always Encrypted 時,請先在 SQL Server 上設定加密物件,然後再執行遷移。
建議順序:
- 在 SQL Server 或 Azure SQL 上建立欄位主金鑰(CMK)和欄位加密金鑰(CEK)。
- 在 Django 連線設定中設定
ColumnEncryption=Enabled。 - 執行 Django 遷移。
- 使用 SQL Server Management Studio 或 T-SQL 加密目標欄位。
執行遷移:
python manage.py migrate
mssql-django 不會建立或管理 Always Encrypted 金鑰的元資料。 金鑰建立與欄位加密政策仍屬於 SQL Server 管理任務。
不支援的認證方法
使用者名稱/密碼和 Azure Key Vault 互動式認證不支援 Always Encrypted 金鑰儲存存取。