使用 PowerShell 配置原地列加密

适用于:SQL ServerAzure SQL 数据库Azure SQL 托管实例

本文提供使用 Set-SqlColumnEncryption cmdlet(在 SqlServer PowerShell 模块中)来设置数据库列的目标 Always Encrypted 配置的步骤。 Set-SqlColumnEncryption cmdlet 修改目标数据库的架构和存储在选定列中的数据。 可对存储在列中的数据进行加密、重新加密或解密,具体取决于列和当前加密配置的指定目标加密设置。 若要使用安全区域触发原地加密操作,Set-SqlColumnEncryption 必须使用通过包含 Attestation Protocol 关键字且可选择包含 Attestation URL 关键字的连接字符串创建的数据库连接。

先决条件

若要设置目标加密配置,需要确保:

  • 数据库中已配置支持 enclave 的列加密密钥(如果要加密或重新加密某个列)。 有关详细信息,请参阅 管理带安全区域的 Always Encrypted 的密钥
  • 你已连接到启用了 Always Encrypted 且使用连接字符串中指定的认证属性的数据库。
  • 可从运行 PowerShell cmdlet 的计算机上访问要加密、重新加密或解密的每一列的列主密钥。
  • 你使用的是 SqlServer PowerShell 模块 22.0.50 或更高版本。 对于就地联机加密,请使用 SqlServer PowerShell 模块 22.3.0 或更高版本。

注释

Microsoft建议在运行 Always Encrypted PowerShell 脚本时使用 PowerShell 7 或更高版本。 PowerShell 7 提供了改进的跨平台支持、更好的性能和与 SqlServer 模块(v22+)的最新兼容性,这是许多 Always Encrypted 方案所必需的。

安全注意事项

用于配置数据库列加密的 Set-SqlColumnEncryption cmdlet 可处理 Always Encrypted 密钥和存储在数据库列中的数据。 因此,请务必在一台安全的计算机上运行此 cmdlet。 如果你的数据库在 SQL Server 中,请不要在托管 SQL Server 实例的计算机上执行 cmdlet,而是在另一台计算机上执行。 由于 Always Encrypted 的主要目的是确保加密的敏感数据的安全(即使数据库系统遭到入侵),因此执行用于处理 SQL Server 计算机上密钥和/或敏感数据的 PowerShell 脚本可减少或抵消该功能带来的益处。

任务 文章 访问纯文本密钥/密钥存储 访问数据库
步骤 1. 启动 PowerShell 环境并导入 SqlServer 模块。 导入 SqlServer 模块
步骤 2. 连接到您的服务器和数据库 连接到数据库
步骤 3. 如果列主密钥(保护要轮换的列加密密钥)存储在 Azure 密钥保管库中,请对 Azure 进行身份验证 Connect-AzAccount
步骤 4. 获取 Azure 密钥保管库的访问令牌。 Get-AzAccessToken
步骤 5。 构造一组 SqlColumnEncryptionSettings 对象,每个对象对应一个要加密、重新加密或解密的数据库列。 SqlColumnMasterKeySettings 是存在于内存中的对象(在 PowerShell 中)。 它指定列的目标加密方案。 New-SqlColumnEncryptionSettings
步骤 6。 设置所需加密配置,该配置在之前的步骤中创建的一组 SqlColumnMasterKeySettings 对象中指定。 根据指定的目标设置和列的当前加密配置,对列进行加密、重新加密或解密。 Set-SqlColumnEncryption

注意: 此步骤可能需要很长时间。 应用程序无法通过整个操作或其中的一部分访问表,具体取决于你选择的方法(联机与脱机)。

使用 VBS enclave 加密列

下面的示例演示如何为多个列设置目标加密配置。 如果任一列尚未加密,则会将其加密。 如果已使用不同密钥和/或不同加密类型加密了任何列,则将先进行解密,然后按照指定目标密钥/类型进行加密。 VBS enclave 当前不支持证明功能。 EnclaveAttestationProtocol 参数应设置为 None,且不需要 EnclaveAttestationUrl。

# Import modules
Import-Module SqlServer
Import-Module Az.Accounts

# Edit these values.
$serverName = '<your-server>.database.windows.net'
$databaseName = 'ContosoHR'
$cekName = 'CEK'
$subscriptionId = '<your-subscription-id>'

# Columns to encrypt with the CEK.
$columnsToEncrypt = @(
    'dbo.Employees.SSN',
    'dbo.Employees.Salary'
)

# Sign in with Microsoft Entra and select subscription.
Connect-AzAccount
Set-AzContext -SubscriptionId $subscriptionId

# Token needed when CEK uses Azure Key Vault CMK.
$keyVaultAccessToken = (Get-AzAccessToken -ResourceUrl 'https://vault.azure.net').Token

# Connect to Azure SQL Database using Entra auth.
$connStr = "Server=tcp:$serverName,1433;Database=$databaseName;Encrypt=True;TrustServerCertificate=False;Authentication=Active Directory Interactive"
$database = Get-SqlDatabase -ConnectionString $connStr

# Build encryption settings for target columns.
$columnEncryptionSettings = @(
    $columnsToEncrypt | ForEach-Object {
        New-SqlColumnEncryptionSettings -ColumnName $_ -EncryptionType Randomized -EncryptionKey $cekName
    }
)

# Encrypt or re-encrypt the columns.
Set-SqlColumnEncryption -InputObject $database -ColumnEncryptionSettings $columnEncryptionSettings -EnclaveAttestationProtocol None -LogFileDirectory . -KeyVaultAccessToken $keyVaultAccessToken

Write-Host 'Done.'

解密列 - 示例

下面的示例演示如何解密数据库中当前已加密的所有列。

# Import modules
Import-Module SqlServer -MinimumVersion 22.0.50
Import-Module Az.Accounts -MinimumVersion 2.2.0

#Connect to Azure
Connect-AzAccount

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

# Connect to your database.
$serverName = "<server name>"
$databaseName = "<database name>"
# Connect to Azure SQL Database using Entra auth.
$connStr = "Server=tcp:$serverName,1433;Database=$databaseName;Encrypt=True;TrustServerCertificate=False;Authentication=Active Directory Interactive"
$database = Get-SqlDatabase -ConnectionString $connStr

# Find all encrypted columns, and create a SqlColumnEncryptionSetting object for each column.
$ces = @()
$tables = $database.Tables
for($i=0; $i -lt $tables.Count; $i++){
    $columns = $tables[$i].Columns
    for($j=0; $j -lt $columns.Count; $j++) {
        if($columns[$j].isEncrypted) {
            $threeColPartName = $tables[$i].Schema + "." + $tables[$i].Name + "." + $columns[$j].Name 
            $ces += New-SqlColumnEncryptionSettings -ColumnName $threeColPartName -EncryptionType "Plaintext" 
        }
    }
}

# Decrypt all columns.
Set-SqlColumnEncryption -ColumnEncryptionSettings $ces -InputObject $database -LogFileDirectory . -EnclaveAttestationProtocol "None" -KeyVaultAccessToken $keyVaultAccessToken

使用 SGX enclave 加密列

下面的示例演示如何为多个列设置目标加密配置。 如果这两列中有任一列尚未加密,则会将其加密。 如果已使用不同密钥和/或不同加密类型加密了任何列,则将先进行解密,然后按照指定目标密钥/类型进行加密。 若要使用 enclave 触发就地加密操作,则需要 EnclaveAttestationProtocol 和 EnclaveAttestationUrl 参数。

# Import modules
Import-Module SqlServer
Import-Module Az.Accounts

# Edit these values.
$serverName = '<your-server>.database.windows.net'
$databaseName = 'ContosoHR'
$cekName = 'CEK'
$subscriptionId = '<your-subscription-id>'

# Columns to encrypt with the CEK.
$columnsToEncrypt = @(
    'dbo.Employees.SSN',
    'dbo.Employees.Salary'
)

# Sign in with Microsoft Entra and select subscription.
Connect-AzAccount
Set-AzContext -SubscriptionId $subscriptionId

# Token needed when CEK uses Azure Key Vault CMK.
$keyVaultAccessToken = (Get-AzAccessToken -ResourceUrl 'https://vault.azure.net').Token

# Connect to Azure SQL Database using Entra auth.
$connStr = "Server=tcp:$serverName,1433;Database=$databaseName;Encrypt=True;TrustServerCertificate=False;Authentication=Active Directory Interactive"
$database = Get-SqlDatabase -ConnectionString $connStr

# Build encryption settings for target columns.
$columnEncryptionSettings = @(
    $columnsToEncrypt | ForEach-Object {
        New-SqlColumnEncryptionSettings -ColumnName $_ -EncryptionType Randomized -EncryptionKey $cekName
    }
)
# Encrypt or re-encrypt the columns.
Set-SqlColumnEncryption -InputObject $database -ColumnEncryptionSettings $columnEncryptionSettings -EnclaveAttestationProtocol "AAS" -EnclaveAttestationURL "https://<attestationURL>"   -KeyVaultAccessToken $keyVaultAccessToken -LogFileDirectory .

Write-Host 'Done.' 

解密列 - 示例

下面的示例演示如何解密数据库中当前已加密的所有列。

# Import modules
Import-Module "SqlServer" -MinimumVersion 22.0.50
Import-Module Az.Accounts -MinimumVersion 2.2.0

#Connect to Azure
Connect-AzAccount

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

# Connect to your database.
$serverName = "<server name>"
$databaseName = "<database name>"
# Connect to Azure SQL Database using Entra auth.
$connStr = "Server=tcp:$serverName,1433;Database=$databaseName;Encrypt=True;TrustServerCertificate=False;Authentication=Active Directory Interactive"
$database = Get-SqlDatabase -ConnectionString $connStr

# Find all encrypted columns, and create a SqlColumnEncryptionSetting object for each column.
$ces = @()
$tables = $database.Tables
for($i=0; $i -lt $tables.Count; $i++){
    $columns = $tables[$i].Columns
    for($j=0; $j -lt $columns.Count; $j++) {
        if($columns[$j].isEncrypted) {
            $threeColPartName = $tables[$i].Schema + "." + $tables[$i].Name + "." + $columns[$j].Name 
            $ces += New-SqlColumnEncryptionSettings -ColumnName $threeColPartName -EncryptionType "Plaintext" 
        }
    }
}

# Decrypt all columns.
Set-SqlColumnEncryption -ColumnEncryptionSettings $ces -InputObject $database -LogFileDirectory . -EnclaveAttestationProtocol "AAS" -EnclaveAttestationURL "https://<attestationURL>" -KeyVaultAccessToken $keyVaultAccessToken

后续步骤

另请参阅