共用方式為


使用 PowerShell 佈建 Always Encrypted 金鑰

適用於:SQL ServerAzure SQL 資料庫Azure SQL 受控執行個體

本文提供使用 SqlServer PowerShell 模組佈建永遠加密金鑰的步驟。 您可以使用 PowerShell 佈建永遠加密金鑰, 用不用角色隔離皆可,控制能夠存取金鑰存放區中實際加密金鑰以及能夠存取資料庫的人員。

如需 Always Encrypted 金鑰管理概觀,包括一些高階的最佳做法建議,請參閱 Always Encrypted 金鑰管理概觀。 如需如何開始針對永遠加密使用 SqlServer PowerShell 模組的詳細資訊,請參閱 Configure Always Encrypted using PowerShell(使用 PowerShell 設定永遠加密)。

沒有角色分隔的金鑰佈建

本節中所述金鑰佈建方法不支援安全性系統管理員與 DBA 之間的角色隔離。 本節中的一些步驟會結合實體密鑰的作業與金鑰元數據上的作業。 因此,使用 DevOps 模型的組織,或如果資料庫裝載於雲端且主要目標是限制雲端管理員 (而不是內部部署 DBA) 存取敏感性資料,則建議使用這種方法來佈建金鑰。 如果潛在對手包括 DBA,或是 DBA 不應該存取敏感性資料,那麼就不建議使用。

在執行任何牽涉到存取純文本金鑰或金鑰存放區的步驟之前,請確定 PowerShell 環境是在與裝載資料庫之電腦不同的安全計算機上執行。在下表的 Accesses 純文本金鑰/金鑰存放區 數據行中識別。 如需詳細資訊,請參閱 金鑰管理的安全性考量

任務 文章 存取純文字金鑰/金鑰存放區 存取資料庫
步驟 1: 在金鑰存放區中建立欄位主金鑰。

注意: SqlServer PowerShell 模組不支援此步驟。 若要從命令列完成這項工作,請使用所選金鑰存放區的特有工具。
建立與儲存 Always Encrypted 的欄主金鑰
步驟 2: 啟動 PowerShell 環境並匯入 SqlServer PowerShell 模組。 使用 PowerShell 設定 Always Encrypted
步驟 3: 連接到您的伺服器和資料庫。 連線至資料庫
步驟 4: 建立包含資料行主要金鑰位置相關資訊的 SqlColumnMasterKeySettings 物件。 SqlColumnMasterKeySettings 是存在於 PowerShell 記憶體中的物件。 使用金鑰存放區特有的 Cmdlet。 New-SqlAzureKeyVaultColumnMasterKeySettings(建立 SQL Azure 金鑰保存庫欄位主金鑰設定)

New-SqlCertificateStoreColumnMasterKeySettings

New-SqlCngColumnMasterKeySettings

New-SqlCspColumnMasterKeySettings(新建-SqlCsp欄主鍵設定)
步驟 5。 在資料庫中建立欄主金鑰的中繼資料。

注意: 我們不會驗證用來產生數據行主要密鑰的金鑰或憑證的有效性。
[New-SqlColumnMasterKey](/powershell/sqlserver/sqlserver/vlatest/new-sqlcolumnmasterkey

注意: 實際上,cmdlet 會發出 CREATE COLUMN MASTER KEY 語句來建立密鑰元數據。
步驟 6. 如果您的資料行主鍵儲存在 Azure Key Vault 中,請對 Azure 進行驗證。 Connect-AzAccount
步驟 7: 如果您的資料行主要金鑰儲存在 Azure Key Vault 中,請取得 Azure Key Vault 的存取權杖。 Get-AzAccessToken
步驟 8。 產生新的資料行加密金鑰,並使用資料行主要金鑰將它加密,然後在資料庫中建立資料行加密金鑰中繼資料。 New-SqlColumnEncryptionKey

注意: 請使用用來在內部產生並加密資料行加密金鑰的指令小程序。

注意: 實際上,Cmdlet 會發出 CREATE COLUMN ENCRYPTION KEY 語句來建立密鑰元數據。

沒有角色分離的 Windows 憑證儲存(範例)

此指令碼是產生資料行主要金鑰 (此金鑰為 Windows 憑證存放區中的憑證)、產生並加密資料行加密金鑰,以及在 SQL Server 資料庫中建立金鑰中繼資料的端對端範例。

# Create a column master key in Windows Certificate Store.
$cert = New-SelfSignedCertificate -Subject "AlwaysEncryptedCert" -CertStoreLocation Cert:CurrentUser\My -KeyExportPolicy Exportable -Type DocumentEncryptionCert -KeyUsage DataEncipherment -KeySpec KeyExchange

# Import the SqlServer module.
Import-Module "SqlServer"

# Connect to your database.
$serverName = "<server name>"
$databaseName = "<database name>"
# Change the authentication method in the connection string, if needed.
$connStr = "Server = " + $serverName + "; Database = " + $databaseName + "; Integrated Security = True; TrustServerCertificate = True"
$database = Get-SqlDatabase -ConnectionString $connStr

# Create a SqlColumnMasterKeySettings object for your column master key.
$cmkSettings = New-SqlCertificateStoreColumnMasterKeySettings -CertificateStoreLocation "CurrentUser" -Thumbprint $cert.Thumbprint

# Create column master key metadata in the database.
$cmkName = "CMK1"
New-SqlColumnMasterKey -Name $cmkName -InputObject $database -ColumnMasterKeySettings $cmkSettings

# Generate a column encryption key, encrypt it with the column master key and create column encryption key metadata in the database.
$cekName = "CEK1"
New-SqlColumnEncryptionKey -Name $cekName  -InputObject $database -ColumnMasterKey $cmkName

沒有角色分離的 Azure Key Vault(範例)

此指令碼是佈建和設定 Azure Key Vault、在保存庫產生資料行主要金鑰、產生並加密資料行加密金鑰,以及在 Azure SQL 資料庫中建立金鑰中繼資料的端對端範例。

# Create a column master key in Azure Key Vault.
Import-Module Az
Connect-AzAccount
$SubscriptionId = "<Azure SubscriptionId>"
$resourceGroup = "<resource group name>"
$azureLocation = "<datacenter location>"
$akvName = "<key vault name>"
$akvKeyName = "<key name>"
$azureCtx = Set-AzConteXt -SubscriptionId $SubscriptionId # Sets the context for the below cmdlets to the specified subscription.
New-AzResourceGroup -Name $resourceGroup -Location $azureLocation # Creates a new resource group - skip, if your desired group already exists.
New-AzKeyVault -VaultName $akvName -ResourceGroupName $resourceGroup -Location $azureLocation # Creates a new key vault - skip if your vault already exists.
Set-AzKeyVaultAccessPolicy -VaultName $akvName -ResourceGroupName $resourceGroup -PermissionsToKeys get, create, delete, list, wrapKey,unwrapKey, sign, verify -UserPrincipalName $azureCtx.Account
$akvKey = Add-AzKeyVaultKey -VaultName $akvName -Name $akvKeyName -Destination "Software"

# Connect to your database (Azure SQL database).
Import-Module "SqlServer"

$serverName = "<Azure SQL server name>.database.windows.net"
$databaseName = "<database name>"
# Change the authentication method in the connection string, if needed.
$connStr = "Server = " + $serverName + "; Database = " + $databaseName + "; Authentication = Active Directory Integrated; TrustServerCertificate = True"
$database = Get-SqlDatabase -ConnectionString $connStr

# Create a SqlColumnMasterKeySettings object for your column master key.
$cmkSettings = New-SqlAzureKeyVaultColumnMasterKeySettings -KeyURL $akvKey.Key.Kid

# Create column master key metadata in the database.
$cmkName = "CMK1"
New-SqlColumnMasterKey -Name $cmkName -InputObject $database -ColumnMasterKeySettings $cmkSettings -KeyVaultAccessToken $keyVaultAccessToken

# Obtain an access token for key vaults.
$keyVaultAccessToken = (Get-AzAccessToken -ResourceUrl https://vault.azure.net).Token

# Generate a column encryption key, encrypt it with the column master key and create column encryption key metadata in the database.
$cekName = "CEK1"
New-SqlColumnEncryptionKey -Name $cekName -InputObject $database -ColumnMasterKey $cmkName -KeyVaultAccessToken $keyVaultAccessToken

沒有角色分離的 CNG/KSP (範例)

下列指令碼是在執行新一代密碼編譯 API (CNG) 的金鑰存放區中產生資料行主要金鑰、產生並加密資料行加密金鑰,以及在 SQL Server 資料庫中建立金鑰中繼資料的端對端範例。

此範例使用Microsoft軟體密鑰儲存提供者的金鑰存放區。 您可以選擇修改範例以使用另一個存放區,例如您的硬體安全性模組。 為此,您必須確保對您的裝置實作 CNG 的金鑰存放區提供者 (KSP) 已經正確地安裝和配置在您的電腦上。 您必須以裝置的 KSP 名稱取代 Microsoft Software Key Storage Provider

# Create a column master key in a key store that has a CNG provider, a.k.a key store provider (KSP).
$cngProviderName = "Microsoft Software Key Storage Provider" # If you have an HSM, you can use a KSP for your HSM instead of a Microsoft KSP
$cngAlgorithmName = "RSA"
$cngKeySize = 2048 # Recommended key size for Always Encrypted column master keys
$cngKeyName = "AlwaysEncryptedKey" # Name identifying your new key in the KSP
$cngProvider = New-Object System.Security.Cryptography.CngProvider($cngProviderName)
$cngKeyParams = New-Object System.Security.Cryptography.CngKeyCreationParameters
$cngKeyParams.provider = $cngProvider
$cngKeyParams.KeyCreationOptions = [System.Security.Cryptography.CngKeyCreationOptions]::OverwriteExistingKey
$keySizeProperty = New-Object System.Security.Cryptography.CngProperty("Length", [System.BitConverter]::GetBytes($cngKeySize), [System.Security.Cryptography.CngPropertyOptions]::None);
$cngKeyParams.Parameters.Add($keySizeProperty)
$cngAlgorithm = New-Object System.Security.Cryptography.CngAlgorithm($cngAlgorithmName)
$cngKey = [System.Security.Cryptography.CngKey]::Create($cngAlgorithm, $cngKeyName, $cngKeyParams)

# Import the SqlServer module.
Import-Module "SqlServer"

# Connect to your database.
$serverName = "<server name>"
$databaseName = "<database name>"
# Change the authentication method in the connection string, if needed.
$connStr = "Server = " + $serverName + "; Database = " + $databaseName + "; Integrated Security = True; TrustServerCertificate = True"
$database = Get-SqlDatabase -ConnectionString $connStr

# Create a SqlColumnMasterKeySettings object for your column master key.
$cmkSettings = New-SqlCngColumnMasterKeySettings -CngProviderName $cngProviderName -KeyName $cngKeyName

# Create column master key metadata in the database.
$cmkName = "CMK1"
New-SqlColumnMasterKey -Name $cmkName -InputObject $database -ColumnMasterKeySettings $cmkSettings

# Generate a column encryption key, encrypt it with the column master key and create column encryption key metadata in the database.
$cekName = "CEK1"
New-SqlColumnEncryptionKey -Name $cekName -InputObject $database -ColumnMasterKey $cmkName

密鑰供應與角色分離

對於安全性管理員不能存取資料庫,而資料庫管理員不能存取金鑰存放區或純文字金鑰,本節提供加密設定步驟。

安全性系統管理員

在執行涉及明文金鑰或金鑰存放區的任何步驟之前(在下表的 Accesses 明文金鑰/金鑰存放區 列中識別),請確定:

  • PowerShell 環境運行於一台安全的機器上,該機器與裝載您資料庫的電腦不同。
  • 貴組織的 DBA 沒有電腦存取權 (會破壞的角色隔離的目的)。

如需詳細資訊,請參閱 金鑰管理的安全性考量

任務 文章 存取純文字金鑰/金鑰存放區 存取資料庫
步驟 1: 在金鑰存放區中建立欄位主金鑰。

注意: SqlServer 模組不支援此步驟。 若要從命令列完成這項工作,您需要使用金鑰存放區類型特有的工具。
建立與儲存 Always Encrypted 的欄主金鑰
步驟 2: 啟動 PowerShell 工作階段並匯入 SqlServer 模組。 匯入 SqlServer 模組
步驟 3: 建立包含資料行主要金鑰位置相關資訊的 SqlColumnMasterKeySettings 物件。 SqlColumnMasterKeySettings 是存在於 PowerShell 記憶體中的物件。 使用金鑰存放區特有的 Cmdlet。 New-SqlAzureKeyVaultColumnMasterKeySettings(建立 SQL Azure 金鑰保存庫欄位主金鑰設定)

New-SqlCertificateStoreColumnMasterKeySettings

New-SqlCngColumnMasterKeySettings

New-SqlCspColumnMasterKeySettings(新建-SqlCsp欄主鍵設定)
步驟 4: 如果您的資料行主鍵儲存在 Azure Key Vault 中,請對 Azure 進行驗證。 Connect-AzAccount
步驟 5。 如果您的資料行主要金鑰儲存在 Azure Key Vault 中,請取得 Azure Key Vault 的存取權杖。 Get-AzAccessToken
步驟 6. 產生資料行加密金鑰,使用資料行主要金鑰加密,以產生資料行加密金鑰的加密值。 新建-Sql資料列加密金鑰加密值
步驟 7: 將資料行主金鑰的位置(提供者名稱和資料行主金鑰的鍵路徑)以及資料行加密金鑰的加密值提供給 DBA。 請參閱本文結尾的範例。

資料庫管理員

DBA 使用接收自安全性系統管理員的資訊 (前文步驟 7),在資料庫中建立和管理永遠加密金鑰中繼資料。

任務 文章 存取純文字金鑰 存取資料庫
步驟 1: 從安全性系統管理員處取得資料行主要金鑰位置以及資料行加密金鑰的加密值。 請參閱本文結尾的範例。
步驟 2: 啟動 PowerShell 環境並匯入 SqlServer 模組。 使用 PowerShell 設定 Always Encrypted
步驟 3: 連接到您的伺服器和資料庫。 連線至資料庫
步驟 4: 建立包含資料行主要金鑰位置相關資訊的 SqlColumnMasterKeySettings 物件。 SqlColumnMasterKeySettings 是存在於記憶體中的物件。 新建-SqlColumn主鍵設置
步驟 5。 在資料庫中建立欄主金鑰的中繼資料。

注意: 我們不會驗證用來產生數據行主要密鑰的金鑰或憑證的有效性。
New-SqlColumnMasterKey
注意︰ 實際上,這個 Cmdlet 發出 CREATE COLUMN MASTER KEY (Transact-SQL) 陳述式來建立資料行主要金鑰中繼資料。
步驟 6. 在資料庫中建立欄位加密金鑰的中繼資料。 New-SqlColumnEncryptionKey
注意:資料庫管理員會使用一種 Cmdlet 的變體,只建立資料行加密金鑰中繼資料。
命令在後台會發出 CREATE COLUMN ENCRYPTION KEY (Transact-SQL) 陳述式,以建立資料行加密金鑰中繼資料。

具有角色分離的 Windows 憑證儲存(範例)

安全性系統管理員

# Create a column master key in Windows Certificate Store.
$storeLocation = "CurrentUser"
$certPath = "Cert:" + $storeLocation + "\My"
$cert = New-SelfSignedCertificate -Subject "AlwaysEncryptedCert" -CertStoreLocation $certPath -KeyExportPolicy Exportable -Type DocumentEncryptionCert -KeyUsage DataEncipherment -KeySpec KeyExchange

# Import the SqlServer module
Import-Module "SqlServer"

# Create a SqlColumnMasterKeySettings object for your column master key.
$cmkSettings = New-SqlCertificateStoreColumnMasterKeySettings -CertificateStoreLocation "CurrentUser" -Thumbprint $cert.Thumbprint

# Generate a column encryption key, encrypt it with the column master key to produce an encrypted value of the column encryption key.
$encryptedValue = New-SqlColumnEncryptionKeyEncryptedValue -TargetColumnMasterKeySettings $cmkSettings

# Share the location of the column master key and an encrypted value of the column encryption key with a DBA, via a CSV file on a share drive
$keyDataFile = "Z:\keydata.txt"
"KeyStoreProviderName, KeyPath, EncryptedValue" > $keyDataFile
$cmkSettings.KeyStoreProviderName + ", " + $cmkSettings.KeyPath + ", " + $encryptedValue >> $keyDataFile

# Read the key data back to verify
$keyData = Import-Csv $keyDataFile
$keyData.KeyStoreProviderName
$keyData.KeyPath
$keyData.EncryptedValue

資料庫管理員

# Obtain the location of the column master key and the encrypted value of the column encryption key from your Security Administrator, via a CSV file on a share drive.
$keyDataFile = "Z:\keydata.txt"
$keyData = Import-Csv $keyDataFile

# Import the SqlServer module
Import-Module "SqlServer"

# Connect to your database.
$serverName = "<server name>"
$databaseName = "<database name>"
$connStr = "Server = " + $serverName + "; Database = " + $databaseName + "; Integrated Security = True; TrustServerCertificate = True"
$database = Get-SqlDatabase -ConnectionString $connStr

# Create a SqlColumnMasterKeySettings object for your column master key.
$cmkSettings = New-SqlColumnMasterKeySettings -KeyStoreProviderName $keyData.KeyStoreProviderName -KeyPath $keyData.KeyPath

# Create column master key metadata in the database.
$cmkName = "CMK1"
New-SqlColumnMasterKey -Name $cmkName -InputObject $database -ColumnMasterKeySettings $cmkSettings

# Generate a  column encryption key, encrypt it with the column master key and create column encryption key metadata in the database.
$cekName = "CEK1"
New-SqlColumnEncryptionKey -Name $cekName -InputObject $database -ColumnMasterKey $cmkName -EncryptedValue $keyData.EncryptedValue