Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Gilt für:SQL Server
Azure SQL-Datenbank
Azure SQL Managed Instance
Dieser Artikel enthält die Schritte zur Rotation von Always Encrypted-Schlüsseln unter Verwendung des SqlServer PowerShell-Moduls. Informationen darüber, wie Sie mit dem SqlServer PowerShell-Modul für Always Encrypted beginnen können, finden Sie unter Konfigurieren von Always Encrypted mithilfe von PowerShell.
Hinweis
Microsoft empfiehlt die Verwendung von PowerShell 7 oder höher beim Ausführen von Always Encrypted PowerShell-Skripts. PowerShell 7 bietet eine verbesserte plattformübergreifende Unterstützung, bessere Leistung und die neueste Kompatibilität mit dem SqlServer-Modul (v22+), die für viele Always Encrypted-Szenarien erforderlich ist.
Das Drehen von Always Encrypted-Schlüsseln ist der Vorgang, einen vorhandenen Schlüssel durch einen neuen zu ersetzen. Möglicherweise müssen Sie einen Schlüssel drehen, wenn er kompromittiert ist, oder um die Richtlinien oder Compliancebestimmungen Ihrer Organisation einzuhalten, die eine regelmäßige Rotation von kryptografischen Schlüsseln erfordern.
Always Encrypted verwendet zwei Schlüsseltypen, es gibt also zwei allgemeine Schlüsselrotationsworkflows: das Drehen von Spaltenhauptschlüssel und das Drehen von Spaltenverschlüsselungsschlüssel.
- Rotieren des Spaltenverschlüsselungsschlüssels – umfasst das Entschlüsseln von Daten, die mit dem vorhandenen Schlüssel verschlüsselt sind und das erneute Verschlüsseln der Daten mit einem neuen Spaltenverschlüsselungsschlüssel. Da die Drehung eines Spaltenverschlüsselungsschlüssels sowohl Zugriff auf die Schlüssel als auch auf die Datenbank erfordert, kann sie nur ohne Rollentrennung durchgeführt werden.
- Rotation des Spaltenhauptschlüssels – umfasst das Entschlüsseln von Spaltenverschlüsselungsschlüsseln, die mit dem aktuellen Spaltenhauptschlüssel verschlüsselt sind, das erneute Verschlüsseln mit dem neuen Spaltenhauptschlüssel sowie das Aktualisieren der Metadaten für beide Schlüsseltypen. Die Rotation des Spaltenhauptschlüssels kann mit oder ohne Rollentrennung abgeschlossen werden (bei Verwendung des SqlServer PowerShell-Moduls).
Rotation eines Spaltenhauptschlüssels ohne Rollentrennung
Die in diesem Abschnitt beschriebene Methode zum Drehen eines Spaltenmasterschlüssels unterstützt keine Rollentrennung zwischen einem Sicherheitsadministrator und einem DBA. Einige der folgenden Schritte kombinieren Vorgänge für die physischen Schlüssel mit Vorgängen für Schlüsselmetadaten. Verwenden Sie diesen Workflow, wenn Ihre Organisation das DevOps-Modell verwendet oder wenn Ihre Datenbank in der Cloud gehostet wird, und das primäre Ziel besteht darin, Cloudadministratoren (aber nicht lokale DBAs) auf den Zugriff auf vertrauliche Daten zu beschränken. Verwenden Sie diese Methode nicht, wenn potenzielle Angreifer DBAs enthalten oder wenn DBAs keinen Zugriff auf vertrauliche Daten haben sollten.
| Aufgabe | Artikel | Greift auf Klartextschlüssel/Schlüsselspeicher zu | Greift auf Datenbank zu |
|---|---|---|---|
| Schritt 1. Erstellen Sie einen neuen Spaltenhauptschlüssel in einem Schlüsselspeicher. Hinweis: Das PowerShell-Modul SqlServer unterstützt diesen Schritt nicht. Sie müssen Tools verwenden, die für Ihren Schlüsselspeicher spezifisch sind, um diese Aufgabe mithilfe der Befehlszeile durchzuführen. Wenn Sie Azure Key Vault als Schlüsselspeicher verwenden, wird die vom Kunden verwaltete Schlüsselrotation in Multimandantenumgebungen nicht unterstützt. Stellen Sie sicher, dass sich der neue kundenseitig verwaltete Schlüssel im selben Mandanten wie der vorhandene befindet. |
Erstellen und Speichern von Spaltenhauptschlüsseln für Always Encrypted | Ja | Nein |
| Schritt 2. Starten Sie eine PowerShell-Umgebung, und importieren Sie das SqlServer-Modul. | Importieren des SqlServer-Moduls | Nein | Nein |
| Schritt 3. Stellen Sie eine Verbindung mit Ihrem Server und Ihrer Datenbank her. | Herstellen einer Verbindung mit einer Datenbank | Nein | Ja |
| Schritt 4. Erstellen Sie ein SqlColumnMasterKeySettings-Objekt, dass Informationen über den Speicherort Ihres neuen Spaltenhauptschlüssels enthält. SqlColumnMasterKeySettings ist ein Objekt, das im Arbeitsspeicher (in PowerShell) vorhanden ist. Verwenden Sie das Cmdlet, das für Ihren Schlüsselspeicher spezifisch ist, um es zu erstellen. |
New-SqlAzureKeyVaultColumnMasterKeySettings New-SqlCertificateStoreColumnMasterKeySettings New-SqlCngColumnMasterKeySettings New-SqlCspColumnMasterKeySettings |
Nein | Nein |
| Schritt 5. Erstellen Sie die Metadaten über den neuen Spaltenhauptschlüssel in Ihrer Datenbank. |
New-SqlColumnMasterKey Hinweis: Intern führt dieses Cmdlet die CREATE COLUMN MASTER KEY (Transact-SQL)-Anweisung aus, um Schlüsselmetadaten zu erstellen. |
Nein | Ja |
| Schritt 6. Authentifizieren Sie sich bei Azure, wenn Ihr aktueller oder neuer Spaltenhauptschlüssel in einem Schlüsseltresor oder einem verwalteten HSM im Azure Key Vault gespeichert ist. | Connect-AzAccount | Ja | Nein |
| Schritt 7. Rufen Sie ein Zugriffstoken für Azure Key Vaults ab, wenn Ihr Spaltenhauptschlüssel in Azure Key Vault gespeichert ist. | Get-AzAccessToken | Nein | Nein |
| Schritt 8: Starten Sie die Rotation, indem Sie jeden der Spaltenverschlüsselungsschlüssel verschlüsseln, der aktuell mit dem alten Spaltenhauptschlüssel geschützt ist, indem Sie den neuen Spaltenhauptschlüssel verwenden. Nach diesem Schritt ist jeder betroffene Spaltenverschlüsselungsschlüssel (der dem alten Spaltenhauptschlüssel zugeordnet ist, der rotiert wird) jeweils mit dem alten und dem neuen Spaltenhauptschlüssel verschlüsselt und besitzt zwei verschlüsselte Werte in den Datenbankmetadaten. | Invoke-SqlColumnMasterKeyRotation | Ja | Ja |
| Schritt 9 Stimmen Sie mit den Administratoren aller Anwendungen ab, die verschlüsselte Spalten in der Datenbank abfragen (die mit dem alten Spaltenhauptschlüssel geschützt sind), sodass sie sicherstellen können, dass die Anwendungen über Zugriff auf den neuen Spaltenhauptschlüssel verfügen. | Create and Store Column Master Keys (Always Encrypted) (Erstellen und Speichern von Spaltenhauptschlüsseln (Always Encrypted)) | Ja | Nein |
| Schritt 10. Schließen Sie die Rotation ab. Hinweis: Stellen Sie vor der Ausführung dieses Schritts sicher, dass alle Anwendungen, die verschlüsselte Spalten abfragen, die mit dem alten Spaltenhauptschlüssel geschützt sind, so konfiguriert sind, dass sie den neuen Spaltenhauptschlüssel verwenden. Wenn Sie diesen Schritt vorzeitig ausführen, können einige der Anwendungen möglicherweise die Daten nicht verschlüsseln. Schließen Sie die Rotation ab, indem Sie die verschlüsselten Werte aus der Datenbank entfernen, die mit dem alten Spaltenhauptschlüssel generiert wurden. Dadurch wird die Zuordnung zwischen dem alten Spaltenhauptschlüssel und den von ihm geschützten Spaltenverschlüsselungsschlüsseln entfernt. |
Complete-SqlColumnMasterKeyRotation | Nein | Ja |
| Schritt 11 Entfernen Sie die Metadaten aus dem alten Spaltenhauptschlüssel. | Remove-SqlColumnMasterKey | Nein | Ja |
Hinweis
Es wird dringend empfohlen, dass Sie den alten Spaltenhauptschlüssel nach der Rotation nicht dauerhaft löschen. Stattdessen sollten Sie den alten Spaltenhauptschlüssel im aktuellen Schlüsselspeicher oder an einem anderen sicheren Ort archivieren. Wenn Sie die Datenbank aus einer Sicherungsdatei auf einen Zeitpunkt vor der Konfiguration des neuen Spaltenhauptschlüssels wiederherstellen, benötigen Sie den alten Schlüssel für den Datenzugriff.
Rotieren eines Spaltenhauptschlüssels ohne Rollentrennung (Windows-Zertifikat-Beispiel)
Das folgende Skript stellt ein End-to-End-Beispiel dar, das einen vorhandenen Spaltenhauptschlüssel (CMK1) mit einem neuen Spaltenhauptschlüssel (CMK2) ersetzt.
[CmdletBinding()]
param(
[Parameter(Mandatory = $false)]
[string]$ServerName = '<server name>',
[Parameter(Mandatory = $false)]
[ValidateNotNullOrEmpty()]
[string]$DatabaseName = '<database name>',
[Parameter(Mandatory = $false)]
[string]$CertificateSubject = 'AlwaysEncryptedCertNew',
[Parameter(Mandatory = $false)]
[ValidateNotNullOrEmpty()]
[string]$OldCmkName = 'CMK1',
[Parameter(Mandatory = $false)]
[ValidateNotNullOrEmpty()]
[string]$NewCmkName = 'CMK2'
)
Set-StrictMode -Version Latest
$ErrorActionPreference = 'Stop'
Import-Module SqlServer -MinimumVersion 22.0.50 -ErrorAction Stop
Write-Host '[AE] Step 1: Creating a new self-signed certificate for the new CMK'
$cert = New-SelfSignedCertificate `
-Subject $CertificateSubject `
-CertStoreLocation 'Cert:CurrentUser\My' `
-KeyExportPolicy Exportable `
-Type DocumentEncryptionCert `
-KeyUsage KeyEncipherment `
-KeySpec KeyExchange `
-KeyLength 2048
Write-Host "[AE] Certificate created with thumbprint: $($cert.Thumbprint)"
Write-Host "[AE] Step 2: Connecting to SQL Server '$ServerName' / Database '$DatabaseName'"
$connStr = "Server=$ServerName;Database=$DatabaseName;Integrated Security=True;Encrypt=True;TrustServerCertificate=True;Connection Timeout=30"
try {
$database = Get-SqlDatabase -ConnectionString $connStr -ErrorAction Stop
}
catch {
Write-Error "Failed to connect to '$ServerName' / '$DatabaseName'. Verify instance, database, and local permissions."
throw
}
Write-Host "[AE] Step 3: Validating that old CMK '$OldCmkName' exists"
$oldCmk = Get-SqlColumnMasterKey -InputObject $database | Where-Object { $_.Name -eq $OldCmkName }
if (-not $oldCmk) {
throw "Old CMK '$OldCmkName' does not exist. Cannot rotate."
}
Write-Host "[AE] Old CMK '$OldCmkName' found."
Write-Host "[AE] Step 4: Creating CMK settings for new certificate"
$newCmkSettings = New-SqlCertificateStoreColumnMasterKeySettings -CertificateStoreLocation 'CurrentUser' -Thumbprint $cert.Thumbprint
Write-Host "[AE] Step 5: Registering new CMK '$NewCmkName' in the database"
$newCmk = Get-SqlColumnMasterKey -InputObject $database | Where-Object { $_.Name -eq $NewCmkName }
if ($newCmk) {
Write-Host "[AE] New CMK '$NewCmkName' already exists. Skipping creation."
}
else {
New-SqlColumnMasterKey -Name $NewCmkName -InputObject $database -ColumnMasterKeySettings $newCmkSettings | Out-Null
Write-Host "[AE] New CMK '$NewCmkName' registered."
}
Write-Host "[AE] Step 6: Initiating CMK rotation from '$OldCmkName' to '$NewCmkName'"
Write-Host "[AE] (This re-encrypts all associated CEKs under the new CMK...)"
Invoke-SqlColumnMasterKeyRotation `
-SourceColumnMasterKeyName $OldCmkName `
-TargetColumnMasterKeyName $NewCmkName `
-InputObject $database
Write-Host "[AE] Rotation initiated."
Write-Host "[AE] Step 7: Completing the CMK rotation"
Complete-SqlColumnMasterKeyRotation `
-SourceColumnMasterKeyName $OldCmkName `
-InputObject $database
Write-Host "[AE] Rotation completed."
Write-Host "[AE] Step 8: Verifying CEKs are now under '$NewCmkName'"
$query = "SELECT name FROM sys.column_encryption_keys WHERE name = N'$($NewCmkName)'"
$rotatedCeks = Invoke-SqlCmd -ServerInstance $ServerName -Database $DatabaseName -Query $query -TrustServerCertificate -ErrorAction SilentlyContinue
if ($rotatedCeks) {
$cekCount = @($rotatedCeks).Count
if ($cekCount -eq 0) { $cekCount = 1 }
Write-Host "[AE] Verified: $cekCount CEK(s) now under '$NewCmkName'"
@($rotatedCeks) | ForEach-Object { Write-Host " - $($_.name)" }
}
Write-Host "[AE] Step 9: Removing old CMK metadata '$OldCmkName'"
Remove-SqlColumnMasterKey -Name $OldCmkName -InputObject $database
Write-Host "[AE] Old CMK '$OldCmkName' removed."
Write-Host '[AE] ========== Rotation Complete =========='
Write-Host "[AE] Old CMK: $OldCmkName (deleted)"
Write-Host "[AE] New CMK: $NewCmkName (active)"
Write-Host '[AE] All CEKs have been re-encrypted under the new CMK.'
Rotation eines Spaltenhauptschlüssels mit Rollentrennung
Der in diesem Abschnitt beschriebene Workflow der Rotation eines Spaltenhauptschlüssels stellt die Trennung zwischen einem Sicherheitsadministrator und einem DBA sicher.
Wichtig
Stellen Sie vor der Ausführung der Schritte, für die in der nachfolgenden Tabelle Greift auf Klartextschlüssel/Schlüsselspeicher zu=Ja (Schritte, die auf Nur-Text-Schlüssel oder Schlüsselspeicher zugreifen) gilt, sicher, dass die PowerShell-Umgebung auf einem sicheren Computer ausgeführt wird, der nicht der Computer ist, auf dem Ihre Datenbank gehostet wird. Weitere Informationen finden Sie im Abschnitt Security Considerations for Key Management(Überlegungen zur Sicherheit für die Schlüsselverwaltung).
Teil 1: DBA
Ein DBA ruft Metadaten über den Spaltenhauptschlüssel ab, der rotiert werden soll, und über die betroffenen Spaltenverschlüsselungsschlüssel, die dem aktuellen Spaltenhauptschlüssel zugeordnet sind. Der DBA gibt alle Informationen für den Sicherheitsadministrator frei.
| Aufgabe | Artikel | Greift auf Klartextschlüssel/Schlüsselspeicher zu | Greift auf Datenbank zu |
|---|---|---|---|
| Schritt 1. Starten Sie eine PowerShell-Umgebung, und importieren Sie das SqlServer-Modul. | Importieren des SqlServer-Moduls | Nein | Keine |
| Schritt 2. Stellen Sie eine Verbindung mit Ihrem Server und Ihrer Datenbank her. | Herstellen einer Verbindung mit einer Datenbank | Nein | Ja |
| Schritt 3. Rufen Sie die Metadaten über den alten Spaltenhauptschlüssel ab. | Get-SqlColumnMasterKey | Nein | Ja |
| Schritt 4. Rufen Sie die Metadaten über Spaltenverschlüsselungsschlüssel ab, die vom alten Spaltenhauptschlüssel geschützt sind, einschließlich ihrer verschlüsselten Werte. | Get-SqlColumnEncryptionKey | Nein | Ja |
| Schritt 5. Geben Sie den Speicherort des Spaltenhauptschlüssels (den Anbieternamen und einen Schlüsselpfad des Spaltenhauptschlüssels) sowie die verschlüsselten Werte der Spaltenverschlüsselungsschlüssel frei, die mit dem alten Spaltenhauptschlüssel geschützt sind. | Beispiele hierzu finden Sie weiter unten. | Nein | Nein |
Teil 2: Sicherheitsadministrator
Der Sicherheitsadministrator generiert einen neuen Spaltenhauptschlüssel, verschlüsselt den betroffenen Spaltenverschlüsselungsschlüssel erneut mit einem neuen Spaltenhauptschlüssel und gibt die Informationen über den neuen Spaltenhauptschlüssel sowie einen Satz neuer verschlüsselter Werte für die betroffenen Spaltenverschlüsselungsschlüssel für den DBA frei.
| Aufgabe | Artikel | Greifen Sie auf Klartextschlüssel und Schlüsselspeicher zu | Greift auf Datenbank zu |
|---|---|---|---|
| Schritt 1. Rufen Sie von Ihrem DBA den Speicherort des alten Spaltenhauptschlüssels sowie die verschlüsselten Werte der zugeordneten Spaltenverschlüsselungsschlüssel ab, die mit dem alten Spaltenhauptschlüssel geschützt sind. | n/v Beispiele hierzu finden Sie weiter unten. |
Nein | Nein |
| Schritt 2. Erstellen Sie einen neuen Spaltenhauptschlüssel in einem Schlüsselspeicher. Hinweis: Das Modul SqlServer unterstützt diesen Schritt nicht. Sie müssen die Tools Verwenden, die für den Typ Ihres Schlüsselspeichers spezifisch sind, um diese Aufgabe mithilfe einer Befehlszeile durchzuführen. Wenn Sie Azure Key Vault als Schlüsselspeicher verwenden, wird die vom Kunden verwaltete Schlüsselrotation in Multimandantenumgebungen nicht unterstützt. Stellen Sie sicher, dass sich der neue kundenseitig verwaltete Schlüssel im selben Mandanten wie der vorhandene befindet. |
Erstellen und Speichern von Spaltenhauptschlüsseln für Always Encrypted | Ja | Nein |
| Schritt 3. Starten Sie eine PowerShell-Umgebung, und importieren Sie das SqlServer-Modul. | Importieren des SqlServer-Moduls | Nein | Nein |
| Schritt 4. Erstellen Sie ein SqlColumnMasterKeySettings-Objekt, dass Informationen über den Speicherort Ihres alten Spaltenhauptschlüssels enthält. SqlColumnMasterKeySettings ist ein Objekt, das im Arbeitsspeicher (in PowerShell) vorhanden ist. | New-SqlColumnMasterKeySettings | Nein | Nein |
| Schritt 5. Erstellen Sie ein SqlColumnMasterKeySettings-Objekt, dass Informationen über den Speicherort Ihres neuen Spaltenhauptschlüssels enthält. SqlColumnMasterKeySettings ist ein Objekt, das im Arbeitsspeicher (in PowerShell) vorhanden ist. Verwenden Sie das Cmdlet, das für Ihren Schlüsselspeicher spezifisch ist, um es zu erstellen. |
New-SqlAzureKeyVaultColumnMasterKeySettings New-SqlCertificateStoreColumnMasterKeySettings New-SqlCngColumnMasterKeySettings New-SqlCspColumnMasterKeySettings |
Nein | Nein |
| Schritt 6. Authentifizieren Sie sich bei Azure, wenn Ihr bisheriger (aktueller) oder neuer Spaltenhauptschlüssel in einem Schlüsseltresor oder einem verwalteten HSM im Azure Key Vault gespeichert ist. | Connect-AzAccount | Ja | Nein |
| Schritt 7. Rufen Sie ein Zugriffstoken für Azure Key Vaults ab, wenn Ihr Spaltenhauptschlüssel in Azure Key Vault gespeichert ist. | Get-AzAccessToken | Nein | Nein |
| Schritt 8: Verschlüsseln Sie jeden Wert des Spaltenverschlüsselungsschlüssels erneut, der aktuell mit dem alten Spaltenhauptschlüssel geschützt ist, indem Sie den neuen Spaltenhauptschlüssel verwenden. |
New-SqlColumnEncryptionKeyEncryptedValue Hinweis: Übergeben Sie beim Aufrufen dieses Cmdlets die SqlColumnMasterKeySettings-Objekte jeweils für den alten und den neuen Spaltenhauptschlüssel zusammen mit einem Wert des Spaltenverschlüsselungsschlüssels, der erneut verschlüsselt werden soll. |
Ja | Nein |
| Schritt 9 Geben Sie den Speicherort des neuen Spaltenhauptschlüssels (den Anbieternamen und einen Schlüsselpfad des Spaltenhauptschlüssels) sowie den Satz der neu verschlüsselten Werte der Spaltenverschlüsselungsschlüssel für Ihren Datenbankadministrator frei . | Beispiele hierzu finden Sie weiter unten. | Nein | Nein |
Hinweis
Es wird dringend empfohlen, dass Sie den alten Spaltenhauptschlüssel nach der Rotation nicht dauerhaft löschen. Stattdessen sollten Sie den alten Spaltenhauptschlüssel im aktuellen Schlüsselspeicher oder an einem anderen sicheren Ort archivieren. Wenn Sie die Datenbank aus einer Sicherungsdatei auf einen Zeitpunkt vor der Konfiguration des neuen Spaltenhauptschlüssels wiederherstellen, benötigen Sie den alten Schlüssel für den Datenzugriff.
Teil 3: DBA
Der DBA erstellt Metadaten für den neuen Spaltenhauptschlüssel und aktualisiert die Metadaten der betroffenen Spaltenverschlüsselungsschlüssel, um den neuen Satz verschlüsselter Werte hinzuzufügen. In diesem Schritt koordiniert der DBA mit den Administratoren der Anwendungen, die Verschlüsselungsspalten abfragen. Diese stellen sicher, dass die Anwendung über Zugriff auf den neuen Spaltenhauptschlüssel verfügt. Sobald alle Anwendungen so eingerichtet sind, dass sie den neuen Spaltenhauptschlüssel verwenden können, entfernt der DBA den alten Satz der verschlüsselten Werte sowie die alten Spaltenhauptschlüssel-Metadaten.
| Aufgabe | Artikel | Greifen Sie auf Klartextschlüssel und Schlüsselspeicher zu | Greift auf Datenbank zu |
|---|---|---|---|
| Schritt 1. Rufen Sie von Ihrem Sicherheitsadministrator den Speicherort des neuen Spaltenhauptschlüssels sowie den neuen Satz von verschlüsselten Werten der entsprechenden Spaltenverschlüsselungsschlüssel ab, die mit dem alten Spaltenhauptschlüssel geschützt sind. | Beispiele hierzu finden Sie weiter unten. | Nein | Nein |
| Schritt 2. Starten Sie eine PowerShell-Umgebung, und importieren Sie das SqlServer-Modul. | Importieren des SqlServer-Moduls | Nein | Nein |
| Schritt 3. Stellen Sie eine Verbindung mit Ihrem Server und Ihrer Datenbank her. | Herstellen einer Verbindung mit einer Datenbank | Nein | Ja |
| Schritt 4. Erstellen Sie ein SqlColumnMasterKeySettings-Objekt, dass Informationen über den Speicherort Ihres neuen Spaltenhauptschlüssels enthält. SqlColumnMasterKeySettings ist ein Objekt, das im Arbeitsspeicher (in PowerShell) vorhanden ist. | New-SqlColumnMasterKeySettings | Nein | Nein |
| Schritt 5. Erstellen Sie die Metadaten über den neuen Spaltenhauptschlüssel in Ihrer Datenbank. |
New-SqlColumnMasterKey Hinweis: Intern führt dieses Cmdlet die Anweisung CREATE COLUMN MASTER KEY (Transact-SQL) aus, um Schlüsselmetadaten zu erstellen. |
Nein | Ja |
| Schritt 6. Rufen Sie die Metadaten über Spaltenverschlüsselungsschlüssel ab, die vom alten Spaltenhauptschlüssel geschützt werden. | Get-SqlColumnEncryptionKey | Nein | Ja |
| Schritt 7. Fügen Sie einen neuen verschlüsselten Wert (der mit dem neuen Spaltenhauptschlüssel erstellt wurde) zu den Metadaten für jeden betroffenen Spaltenverschlüsselungsschlüssel hinzu. | Add-SqlColumnEncryptionKeyValue | Nein | Ja |
| Schritt 8: Stimmen Sie mit den Administratoren aller Anwendungen ab, die verschlüsselte Spalten in der Datenbank abfragen (die mit dem alten Spaltenhauptschlüssel geschützt sind), sodass sie sicherstellen können, dass die Anwendungen über Zugriff auf den neuen Spaltenhauptschlüssel verfügen. | Erstellen und Speichern von Spaltenhauptschlüsseln (Always Encrypted) | Nein | Nein |
| Schritt 9 Schließen Sie die Rotation ab, indem Sie die verschlüsselten Werte, die mit dem alten Spaltenhauptschlüssel generiert wurden aus der Datenbank entfernen. Hinweis: Stellen Sie vor der Ausführung dieses Schritts sicher, dass alle Anwendungen, die verschlüsselte Spalten abfragen, die mit dem alten Spaltenhauptschlüssel geschützt sind, so konfiguriert sind, dass sie den neuen Spaltenhauptschlüssel verwenden. Wenn Sie diesen Schritt vorzeitig ausführen, können einige der Anwendungen möglicherweise die Daten nicht verschlüsseln. Durch diesen Schritt wird eine Zuordnung zwischen dem alten Spaltenhauptschlüssel und den von ihm geschützten Spaltenverschlüsselungsschlüsseln entfernt. |
Complete-SqlColumnMasterKeyRotation Alternativ können Sie den Wert Remove-SqlColumnEncryptionKeyValueverwenden. |
Nein | Ja |
| Schritt 10. Entfernen Sie die Metadaten des alten Spaltenhauptschlüssel aus der Datenbank. | Remove-SqlColumnMasterKey | Nein | Ja |
Rotieren eines Spaltenhauptschlüssels mit Rollentrennung (Windows-Zertifikat-Beispiel)
Das folgende Skript ist ein End-to-End-Beispiel zum Generieren eines neuen Spaltenhauptschlüssels, der im Windows-Zertifikatspeicher ein Zertifikat darstellt, und zum Rotieren eines vorhandenen (aktuellen) Spaltenhauptschlüssels, um diesen mit dem neuen Spaltenhauptschlüssel zu ersetzen. Das Skript nimmt an, dass die Zieldatenbank den Spaltenhauptschlüssel namens CMK1 (der rotiert werden soll) enthält, der einige Spaltenverschlüsselungsschlüssel verschlüsselt.
Teil 1: DBA
[CmdletBinding()]
param(
[Parameter(Mandatory = $false)]
[ValidateNotNullOrEmpty()]
[string]$ServerName = '<server name>',
[Parameter(Mandatory = $false)]
[ValidateNotNullOrEmpty()]
[string]$DatabaseName = '<database name>',
[Parameter(Mandatory = $false)]
[ValidateNotNullOrEmpty()]
[string]$OldCmkName = 'CMK2',
[Parameter(Mandatory = $false)]
[ValidateNotNullOrEmpty()]
[string]$OutputFolder = 'C:\temp'
)
Set-StrictMode -Version Latest
$ErrorActionPreference = 'Stop'
Import-Module SqlServer -MinimumVersion 22.0.50 -ErrorAction Stop
Write-Host "[CEK Export] Starting CMK and CEK data export"
# Validate output folder
if (-not (Test-Path -Path $OutputFolder -PathType Container)) {
Write-Host "[CEK Export] Creating output folder: $OutputFolder"
New-Item -Path $OutputFolder -ItemType Directory | Out-Null
}
# Connect to database
Write-Host "[CEK Export] Connecting to '$ServerName' / '$DatabaseName'"
$connStr = "Server=$ServerName;Database=$DatabaseName;Integrated Security=True;TrustServerCertificate=True;Connection Timeout=30"
try {
$database = Get-SqlDatabase -ConnectionString $connStr -ErrorAction Stop
}
catch {
Write-Error "Failed to connect to '$ServerName' / '$DatabaseName'."
throw
}
# Retrieve old CMK
Write-Host "[CEK Export] Retrieving CMK '$OldCmkName'"
$oldCmk = Get-SqlColumnMasterKey -InputObject $database | Where-Object { $_.Name -eq $OldCmkName }
if (-not $oldCmk) {
throw "CMK '$OldCmkName' not found in database '$DatabaseName'."
}
# Export CMK metadata using fixed text file name
$cmkFile = Join-Path $OutputFolder "oldcmkdata.txt"
Write-Host "[CEK Export] Exporting CMK metadata to: $cmkFile"
"CMKName|KeyStoreProviderName|KeyPath" | Set-Content -Path $cmkFile -Encoding UTF8
"$OldCmkName|$($oldCmk.KeyStoreProviderName)|$($oldCmk.KeyPath)" | Add-Content -Path $cmkFile -Encoding UTF8
Write-Host "[CEK Export] ✓ CMK metadata exported"
# Discover and export CEKs using fixed text file name
Write-Host "[CEK Export] Discovering CEKs associated with '$OldCmkName'"
$ceks = Get-SqlColumnEncryptionKey -InputObject $database
$cekFile = Join-Path $OutputFolder "oldcekvalues.txt"
"CEKName|CEKEncryptedValue|HasMultipleEncryptedValues" | Set-Content -Path $cekFile -Encoding UTF8
$exportedCount = 0
$multiValueCount = 0
foreach ($cek in $ceks) {
if (-not $cek.ColumnEncryptionKeyValues) {
continue
}
# Check if this CEK has multiple encrypted values
if ($cek.ColumnEncryptionKeyValues.Count -gt 1) {
# CEK has multiple encrypted values - check if any reference the old CMK
$refersToOldCmk = $cek.ColumnEncryptionKeyValues | Where-Object { $_.ColumnMasterKeyName -eq $OldCmkName }
if ($refersToOldCmk) {
Write-Warning "CEK '$($cek.Name)' has $($cek.ColumnEncryptionKeyValues.Count) encrypted values. One references '$OldCmkName'. This CEK cannot be rotated automatically."
"$($cek.Name)|MULTIPLE_ENCRYPTED_VALUES|True" | Add-Content -Path $cekFile -Encoding UTF8
$multiValueCount++
}
}
else {
# CEK has single encrypted value - check if it references the old CMK
if ($cek.ColumnEncryptionKeyValues[0].ColumnMasterKeyName -eq $OldCmkName) {
$encryptedValueHex = "0x" + -join ($cek.ColumnEncryptionKeyValues[0].EncryptedValue | ForEach-Object { $_.ToString("X2") })
"$($cek.Name)|$encryptedValueHex|False" | Add-Content -Path $cekFile -Encoding UTF8
$exportedCount++
}
}
}
Write-Host "[CEK Export] ✓ CEK encrypted values exported"
Write-Host "[CEK Export] - Exported: $exportedCount CEK(s)"
if ($multiValueCount -gt 0) {
Write-Warning " - Multi-valued CEKs (manual review needed): $multiValueCount"
}
Write-Host "[CEK Export] ===== Export Complete ====="
Write-Host "[CEK Export] CMK Metadata: $cmkFile"
Write-Host "[CEK Export] CEK Values: $cekFile"
Teil 2: Sicherheitsadministrator
[CmdletBinding()]
param(
[Parameter(Mandatory = $false)]
[ValidateNotNullOrEmpty()]
[string]$ShareFolder = 'C:\Temp\',
[Parameter(Mandatory = $false)]
[ValidateSet('CurrentUser', 'LocalMachine')]
[string]$StoreLocation = 'CurrentUser',
[Parameter(Mandatory = $false)]
[ValidateNotNullOrEmpty()]
[string]$CertificateSubject = 'AlwaysEncryptedCert'
)
Set-StrictMode -Version Latest
$ErrorActionPreference = 'Stop'
Import-Module SqlServer -MinimumVersion 22.0.50 -ErrorAction Stop
function Import-DelimitedTextFile {
param(
[Parameter(Mandatory = $true)] [string]$Path,
[Parameter(Mandatory = $true)] [string[]]$RequiredColumns
)
if (-not (Test-Path -Path $Path -PathType Leaf)) {
throw "Required file not found: $Path"
}
$raw = Get-Content -Path $Path -Raw
if ([string]::IsNullOrWhiteSpace($raw)) {
throw "File is empty: $Path"
}
$delimiter = if ($raw -match '\|') { '|' } else { ',' }
$rows = @(Import-Csv -Path $Path -Delimiter $delimiter)
if ($rows.Count -eq 0) {
throw "No data rows found in file: $Path"
}
$first = $rows[0]
$RequiredColumns | ForEach-Object {
if (-not $first.PSObject.Properties[$_]) {
throw "Missing required column '$_' in file: $Path"
}
}
return $rows
}
if (-not (Test-Path -Path $ShareFolder -PathType Container)) {
throw "Share folder does not exist: $ShareFolder"
}
$oldCmkDataFile = Join-Path $ShareFolder 'oldcmkdata.txt'
$oldCekValuesFile = Join-Path $ShareFolder 'oldcekvalues.txt'
$newCmkDataFile = Join-Path $ShareFolder 'newcmkdata.txt'
$newCekValuesFile = Join-Path $ShareFolder 'newcekvalues.txt'
Write-Host "[AE] Reading old CMK data from '$oldCmkDataFile'"
$oldCmkDataRows = Import-DelimitedTextFile -Path $oldCmkDataFile -RequiredColumns @('KeyStoreProviderName', 'KeyPath')
$oldCmkData = $oldCmkDataRows[0]
Write-Host "[AE] Reading old CEK values from '$oldCekValuesFile'"
$oldCekValues = Import-DelimitedTextFile -Path $oldCekValuesFile -RequiredColumns @('CEKName', 'CEKEncryptedValue')
Write-Host "[AE] Finding or creating certificate '$CertificateSubject' in $StoreLocation\\My"
$certPath = "Cert:$StoreLocation\My"
$cert = Get-ChildItem -Path $certPath |
Where-Object { $_.Subject -eq "CN=$CertificateSubject" } |
Sort-Object NotAfter -Descending |
Select-Object -First 1
if (-not $cert) {
$cert = New-SelfSignedCertificate `
-Subject $CertificateSubject `
-CertStoreLocation $certPath `
-KeyExportPolicy Exportable `
-Type DocumentEncryptionCert `
-KeyUsage DataEncipherment `
-KeySpec KeyExchange
}
Write-Host '[AE] Building CMK settings'
$oldCmkSettings = New-SqlColumnMasterKeySettings `
-KeyStoreProviderName $oldCmkData.KeyStoreProviderName `
-KeyPath $oldCmkData.KeyPath
$newCmkSettings = New-SqlCertificateStoreColumnMasterKeySettings `
-CertificateStoreLocation $StoreLocation `
-Thumbprint $cert.Thumbprint
Write-Host "[AE] Re-encrypting CEK values and writing '$newCekValuesFile'"
"CEKName|CEKEncryptedValue" | Set-Content -Path $newCekValuesFile -Encoding UTF8
$oldCekValues | ForEach-Object {
$newValue = New-SqlColumnEncryptionKeyEncryptedValue `
-TargetColumnMasterKeySettings $newCmkSettings `
-ColumnMasterKeySettings $oldCmkSettings `
-EncryptedValue $_.CEKEncryptedValue
"$($_.CEKName)|$newValue" | Add-Content -Path $newCekValuesFile -Encoding UTF8
}
Write-Host "[AE] Writing new CMK data to '$newCmkDataFile'"
"KeyStoreProviderName|KeyPath" | Set-Content -Path $newCmkDataFile -Encoding UTF8
"$($newCmkSettings.KeyStoreProviderName)|$($newCmkSettings.KeyPath)" | Add-Content -Path $newCmkDataFile -Encoding UTF8
Write-Host '[AE] Completed successfully'
Write-Host "[AE] Output files: $newCmkDataFile , $newCekValuesFile"
Teil 3: DBA
[CmdletBinding()]
param(
[Parameter(Mandatory = $false)]
[ValidateNotNullOrEmpty()]
[string]$ServerName = '<server name>',
[Parameter(Mandatory = $false)]
[ValidateNotNullOrEmpty()]
[string]$DatabaseName = '<database name>',
[Parameter(Mandatory = $false)]
[ValidateNotNullOrEmpty()]
[string]$OldCmkName = 'CMK1',
[Parameter(Mandatory = $false)]
[ValidateNotNullOrEmpty()]
[string]$NewCmkName = 'CMK2',
[Parameter(Mandatory = $false)]
[ValidateNotNullOrEmpty()]
[string]$InputFolder = 'C:\temp'
)
Set-StrictMode -Version Latest
$ErrorActionPreference = 'Stop'
Import-Module SqlServer -MinimumVersion 22.0.50 -ErrorAction Stop
function Import-DelimitedTextFile {
param(
[Parameter(Mandatory = $true)] [string]$Path,
[Parameter(Mandatory = $true)] [string[]]$RequiredColumns
)
if (-not (Test-Path -Path $Path -PathType Leaf)) {
throw "Required file not found: $Path"
}
$raw = Get-Content -Path $Path -Raw
if ([string]::IsNullOrWhiteSpace($raw)) {
throw "File is empty: $Path"
}
$delimiter = if ($raw -match '\|') { '|' } else { ',' }
$rows = @(Import-Csv -Path $Path -Delimiter $delimiter)
if ($rows.Count -eq 0) {
throw "No data rows found in file: $Path"
}
$first = $rows[0]
$RequiredColumns | ForEach-Object {
if (-not $first.PSObject.Properties[$_]) {
throw "Missing required column '$_' in file: $Path"
}
}
return $rows
}
if (-not (Test-Path -Path $InputFolder -PathType Container)) {
throw "Input folder not found: $InputFolder"
}
$newCmkDataFile = Join-Path $InputFolder 'newcmkdata.txt'
$newCekValuesFile = Join-Path $InputFolder 'newcekvalues.txt'
Write-Host "[AE] Reading new CMK data from '$newCmkDataFile'"
$newCmkRows = Import-DelimitedTextFile -Path $newCmkDataFile -RequiredColumns @('KeyStoreProviderName', 'KeyPath')
$newCmkData = $newCmkRows[0]
Write-Host "[AE] Reading new CEK values from '$newCekValuesFile'"
$newCekValues = Import-DelimitedTextFile -Path $newCekValuesFile -RequiredColumns @('CEKName', 'CEKEncryptedValue')
Write-Host "[AE] Connecting to '$ServerName' / '$DatabaseName'"
$connStr = "Server=$ServerName;Database=$DatabaseName;Integrated Security=True;TrustServerCertificate=True;Connection Timeout=30"
$database = Get-SqlDatabase -ConnectionString $connStr -ErrorAction Stop
Write-Host "[AE] Ensuring target CMK '$NewCmkName' exists"
$newCmkSettings = New-SqlColumnMasterKeySettings -KeyStoreProviderName $newCmkData.KeyStoreProviderName -KeyPath $newCmkData.KeyPath
$existingNewCmk = Get-SqlColumnMasterKey -InputObject $database | Where-Object { $_.Name -eq $NewCmkName }
if (-not $existingNewCmk) {
New-SqlColumnMasterKey -Name $NewCmkName -InputObject $database -ColumnMasterKeySettings $newCmkSettings | Out-Null
}
Write-Host "[AE] Adding new encrypted CEK values under '$NewCmkName'"
$ceks = Get-SqlColumnEncryptionKey -InputObject $database
$ceksToRotate = @(
$ceks | Where-Object {
$_.ColumnEncryptionKeyValues -and
@($_.ColumnEncryptionKeyValues | Where-Object { $_.ColumnMasterKeyName -eq $OldCmkName }).Count -gt 0
}
)
$ceksToRotate | ForEach-Object {
$cek = $_
if (@($cek.ColumnEncryptionKeyValues).Count -gt 1) {
throw "CEK '$($cek.Name)' already has multiple encrypted values and still references '$OldCmkName'."
}
$newValueRow = @($newCekValues | Where-Object { $_.CEKName -eq $cek.Name }) | Select-Object -First 1
if (-not $newValueRow) {
throw "No new encrypted value found for CEK '$($cek.Name)' in file '$newCekValuesFile'."
}
Add-SqlColumnEncryptionKeyValue `
-ColumnMasterKeyName $NewCmkName `
-Name $cek.Name `
-EncryptedValue $newValueRow.CEKEncryptedValue `
-InputObject $database | Out-Null
}
Write-Host "[AE] Completing rotation for source CMK '$OldCmkName'"
Complete-SqlColumnMasterKeyRotation -SourceColumnMasterKeyName $OldCmkName -InputObject $database
Write-Host "[AE] Removing source CMK '$OldCmkName' metadata"
Remove-SqlColumnMasterKey -Name $OldCmkName -InputObject $database
Write-Host '[AE] Completed successfully'
Rotieren eines Spaltenverschlüsselungsschlüssels
Die Rotation eines Spaltenverschlüsselungsschlüssels umfasst das Entschlüsseln der Daten in allen Spalten, die mit dem zu rotierenden Schlüssel verschlüsselt wurden, und die Neuverschlüsselung der Daten mithilfe des neuen Spaltenverschlüsselungsschlüssels. Dieser Workflow für die Rotation benötigt Zugriff auf die Schlüssel und die Datenbank und kann deshalb nicht mit Rollentrennung ausgeführt werden. Die Rotation eines Spaltenverschlüsselungsschlüssels kann viel Zeit in Anspruch nehmen, wenn die Tabellen mit den Spalten, die mit dem zu rotierenden Schlüssel verschlüsselt wurden, groß sind. Daher muss Ihre Organisation eine Rotation der Spaltenverschlüsselungsschlüssel sorgfältig planen.
Sie können einen Spaltenverschlüsselungsschlüssel offline oder online rotieren. Die erste Methode ist wahrscheinlich schneller, aber Ihre Anwendungen können nicht in die betroffenen Tabellen schreiben. Der letztere Ansatz dauert wahrscheinlich länger, aber Sie können den Zeitraum einschränken, in dem die betroffenen Tabellen für Anwendungen nicht verfügbar sind. Weitere Details finden Sie unter Konfigurieren der Spaltenverschlüsselung mithilfe von Always Encrypted mit PowerShell und Set-SqlColumnEncryption.
| Aufgabe | Artikel | Greift auf Klartextschlüssel/Schlüsselspeicher zu | Greift auf Datenbank zu |
|---|---|---|---|
| Schritt 1. Starten Sie eine PowerShell-Umgebung, und importieren Sie das SqlServer-Modul. | Importieren des SqlServer-Moduls | Nein | Nein |
| Schritt 2. Stellen Sie eine Verbindung mit Ihrem Server und Ihrer Datenbank her. | Herstellen einer Verbindung mit einer Datenbank | Nein | Ja |
| Schritt 3. Authentifizieren Sie sich bei Azure, wenn Ihr Spaltenhauptschlüssel (der den zu rotierenden Spaltenverschlüsselungsschlüssel schützt) in einem Schlüsseltresor oder einem verwalteten HSM im Azure Key Vault gespeichert ist. | Connect-AzAccount | Ja | Nein |
| Schritt 4. Rufen Sie ein Zugriffstoken für Azure Key Vaults ab, wenn Ihr Spaltenhauptschlüssel in Azure Key Vault gespeichert ist. | Get-AzAccessToken | Nein | Nein |
| Schritt 5. Generieren Sie einen neuen Spaltenverschlüsselungsschlüssel, verschlüsseln Sie ihn mit dem Spaltenhauptschlüssel, und erstellen Sie Spaltenverschlüsselungsschlüssel-Metadaten in der Datenbank. |
New-SqlColumnEncryptionKey Hinweis: Verwenden Sie eine Variation des Cmdlets, dass intern einen Spaltenverschlüsselungsschlüssel generiert und verschlüsselt. Hinter den Kulissen führt dieses Cmdlet die CREATE COLUMN ENCRYPTION KEY (Transact-SQL)-Anweisung aus, um die Schlüsselmetadaten zu erstellen. |
Ja | Ja |
| Schritt 6. Suchen Sie alle Spalten, die mit dem alten Spaltenverschlüsselungsschlüssel verschlüsselt sind. | Programmierungshandbuch für SQL Server Management Objects (SMO) | Nein | Ja |
| Schritt 7. Erstellen Sie ein SqlColumnEncryptionSettings -Objekt für jede betroffene Spalte. SqlColumnEncryptionSettings ist ein Objekt, das im Arbeitsspeicher (in PowerShell) vorhanden ist. Es gibt das Zielverschlüsselungsschema für eine Spalte an. In diesem Fall sollte das Objekt angeben, dass die betroffene Spalte mit dem neuen Spaltenverschlüsselungsschlüssel verschlüsselt werden soll. | Neue-SqlSpaltenverschlüsselungseinstellungen | Nein | Nein |
| Schritt 8: Verschlüsseln Sie die Spalten, die in Schritt 5 angegeben sind, erneut mit dem neuen Verschlüsselungsschlüssel. |
Set-SqlColumnEncryption Hinweis: Dieser Schritt kann lange dauern. Je nach gewähltem Ansatz (online oder offline) können Ihre Anwendungen während des gesamten Vorgangs oder nur teilweise nicht auf die Tabellen zugreifen. |
Ja | Ja |
| Schritt 9 Entfernen Sie die Metadaten für den alten Spaltenverschlüsselungsschlüssel. | Remove-SqlColumnEncryptionKey | Nein | Ja |
Beispiel – Rotieren eines Spaltenverschlüsselungsschlüssels
Das folgende Skript zeigt, wie ein Spaltenverschlüsselungsschlüssel rotiert wird. Das Skript nimmt an, dass die Zieldatenbank einige Spalten enthält, die mit einem Spaltenverschlüsselungsschlüssel namens CEK1 (der rotiert werden soll) verschlüsselt sind, der mithilfe eines Spaltenhauptschlüssels namens CMK1 geschützt ist (der Spaltenhauptschlüssel ist nicht in Azure Key Vault gespeichert).
[CmdletBinding()]
param(
[Parameter(Mandatory = $false)]
[ValidateNotNullOrEmpty()]
[string]$ServerName = '<server name>',
[Parameter(Mandatory = $false)]
[ValidateNotNullOrEmpty()]
[string]$DatabaseName = '<database name>',
[Parameter(Mandatory = $false)]
[ValidateNotNullOrEmpty()]
[string]$OldCekName = 'CEK1',
[Parameter(Mandatory = $false)]
[ValidateNotNullOrEmpty()]
[string]$NewCekName = 'CEK2',
[Parameter(Mandatory = $false)]
[ValidateNotNullOrEmpty()]
[string]$CmkName = 'CMK2',
[Parameter(Mandatory = $false)]
[ValidateRange(0, 3600)]
[int]$MaxDowntimeInSeconds = 120,
[Parameter(Mandatory = $false)]
[ValidateNotNullOrEmpty()]
[string]$LogFileDirectory = '.'
)
Set-StrictMode -Version Latest
$ErrorActionPreference = 'Stop'
Import-Module SqlServer -MinimumVersion 22.0.50 -ErrorAction Stop
if ($OldCekName -eq $NewCekName) {
throw 'OldCekName and NewCekName must be different.'
}
if (-not (Test-Path -Path $LogFileDirectory -PathType Container)) {
New-Item -Path $LogFileDirectory -ItemType Directory | Out-Null
}
Write-Host "[AE] Connecting to '$ServerName' / '$DatabaseName'"
$connStr = "Server=$ServerName;Database=$DatabaseName;Integrated Security=True;TrustServerCertificate=True;Connection Timeout=30"
$database = Get-SqlDatabase -ConnectionString $connStr -ErrorAction Stop
Write-Host "[AE] Ensuring CMK '$CmkName' exists"
$cmk = Get-SqlColumnMasterKey -InputObject $database | Where-Object { $_.Name -eq $CmkName }
if (-not $cmk) {
throw "Column master key '$CmkName' was not found."
}
Write-Host "[AE] Ensuring target CEK '$NewCekName' exists"
$existingNewCek = Get-SqlColumnEncryptionKey -InputObject $database | Where-Object { $_.Name -eq $NewCekName }
if (-not $existingNewCek) {
New-SqlColumnEncryptionKey -Name $NewCekName -InputObject $database -ColumnMasterKey $CmkName | Out-Null
}
Write-Host "[AE] Discovering encrypted columns using '$OldCekName'"
$settings = @()
$tables = @($database.Tables)
$tables | ForEach-Object {
$table = $_
@($table.Columns) | ForEach-Object {
$column = $_
if ($column.IsEncrypted -and $column.ColumnEncryptionKeyName -eq $OldCekName) {
$columnName = "{0}.{1}.{2}" -f $table.Schema, $table.Name, $column.Name
$settings += New-SqlColumnEncryptionSettings -ColumnName $columnName -EncryptionType $column.EncryptionType -EncryptionKey $NewCekName
}
}
}
if ($settings.Count -eq 0) {
Write-Warning "No encrypted columns found that reference '$OldCekName'. Nothing to rotate."
return
}
Write-Host "[AE] Re-encrypting $($settings.Count) column(s) to '$NewCekName'"
Set-SqlColumnEncryption `
-ColumnEncryptionSettings $settings `
-InputObject $database `
-UseOnlineApproach `
-MaxDowntimeInSeconds $MaxDowntimeInSeconds `
-LogFileDirectory $LogFileDirectory
Write-Host "[AE] Validating no columns still reference '$OldCekName'"
$stillUsingOld = $false
@($database.Tables) | ForEach-Object {
@($_.Columns) | ForEach-Object {
if ($_.IsEncrypted -and $_.ColumnEncryptionKeyName -eq $OldCekName) {
$stillUsingOld = $true
}
}
}
if ($stillUsingOld) {
throw "At least one encrypted column still references '$OldCekName'. Aborting CEK removal."
}
Write-Host "[AE] Removing old CEK '$OldCekName'"
Remove-SqlColumnEncryptionKey -Name $OldCekName -InputObject $database
Write-Host '[AE] Completed successfully'
Nächste Schritte
- Abfragen von Spalten mithilfe von Always Encrypted mit SQL Server Management Studio
- Entwickeln von Anwendungen mit Always Encrypted
Siehe auch
- Immer verschlüsselt
- Übersicht über die Schlüsselverwaltung für Always Encrypted
- Konfigurieren von Always Encrypted mithilfe von PowerShell
- Rotieren von Always Encrypted-Schlüsseln mithilfe von SQL Server Management Studio
- CREATE COLUMN MASTER KEY (Transact-SQL)
- DROP COLUMN MASTER KEY (Transact-SQL)
- CREATE COLUMN ENCRYPTION KEY (Transact-SQL)
- ALTER COLUMN ENCRYPTION KEY (Transact-SQL)
- DROP COLUMN ENCRYPTION KEY (Transact-SQL)
- sys.column_master_keys (Transact-SQL)
- sys.column_encryption_keys (Transact-SQL)