Skip to content

Set-ColumnEncryption

DBSystems: Configures column encryption for a SQL Server database

#Requires -Version 5.0
#Requires -Modules SQLServer

[CmdLetBinding()]
Param(
    [Parameter(Mandatory = $true)]   
    [string]$ServerInstance,     
    [Parameter(Mandatory = $true)]   
    [string]$DatabaseName,    
    [Parameter(Mandatory = $true)]   
    [string]$SettingsCsvFile,
    [pscredential]$ServerCredential,
    [switch]$KeepCheckForeignKeyConstraints,
    [string]$LogFileDirectory,
    [int]$MaxDivergingIterations,
    [int]$MaxDowntimeInSeconds,
    [int]$MaxIterationDurationInDays,
    [int]$MaxIterations,
    [switch]$UseOnlineApproach,
    [string]$CsvDelimiter = ';',
    [ValidateSet('Unicode','UTF7','UTF8','ASCII','UTF32','BigEndianUnicode','Default','OEM')]
    [string]$FileEncoding = 'UTF8',
    [int]$ConnectionTimeout = 30
)

function Get-SqlServerInstanceInternal {
    [CmdLetBinding()]
    Param(
        [Parameter(Mandatory = $true)]   
        [string]$ServerInstance,    
        [pscredential]$ServerCredential,
        [int]$ConnectionTimeout = 30
    )
    try {
        [hashtable]$cmdArgs = @{
            'ErrorAction' = 'Stop'
            'Confirm' = $false
            'ServerInstance' = $ServerInstance
            'ConnectionTimeout' = $ConnectionTimeout
        }
        if ($null -ne $ServerCredential) {
            $cmdArgs.Add('Credential', $ServerCredential)
        }
        return Get-SqlInstance @cmdArgs
    } catch {
        throw
    }
}

function Get-SqlDatabaseInternal {
    [CmdLetBinding()]
    Param(
        [Parameter(Mandatory = $true)]   
        [object]$ServerInstance,    
        [Parameter(Mandatory = $true)]   
        [string]$DatabaseName
    )
    try {
        [hashtable]$cmdArgs = @{
            'ErrorAction' = 'Stop'
            'InputObject' = $ServerInstance
            'Name' = $DatabaseName
            'Confirm' = $false
        }
        return Get-SqlDatabase @cmdArgs
    } catch {
        throw
    }
}

Import-Module SQLServer

try {
    $instance = Get-SqlServerInstanceInternal -ServerInstance $ServerInstance -ServerCredential $ServerCredential -ConnectionTimeout $ConnectionTimeout
    $db = Get-SqlDatabaseInternal -DatabaseName $DatabaseName -ServerInstance $instance

    if (-not (Test-Path -Path $SettingsCsvFile)) {
        throw "CSV file not found: $SettingsCsvFile"
    }
    
    $settings = Import-Csv -Path $SettingsCsvFile -Delimiter $CsvDelimiter -Encoding $FileEncoding -Header @('ColumnName', 'EncryptionType', 'EncryptionKey') -ErrorAction Stop
    
    $colEncry = @()
    foreach ($item in $settings) {
        if ($item.EncryptionType -eq 'EncryptionType' -or [string]::IsNullOrWhiteSpace($item.ColumnName)) {
            continue
        }
        
        $setParams = @{
            'ColumnName'     = $item.ColumnName
            'EncryptionType' = $item.EncryptionType
        }
        if ($item.EncryptionType -ne 'Plaintext' -and -not [string]::IsNullOrWhiteSpace($item.EncryptionKey)) {
            $setParams.Add('EncryptionKey', $item.EncryptionKey)
        }
        
        $colEncry += New-SqlColumnEncryptionSettings @setParams
    }
    
    if ($colEncry.Count -eq 0) {
        throw "No valid encryption settings found in CSV file."
    }

    [hashtable]$cmdArgs = @{
        'ErrorAction' = 'Stop'
        'ColumnEncryptionSettings' = $colEncry
        'InputObject' = $db                            
    }    
    
    if (-not [string]::IsNullOrWhiteSpace($LogFileDirectory)) {
        $cmdArgs.Add('LogFileDirectory', $LogFileDirectory)
    }
    
    if ($UseOnlineApproach) {
        $cmdArgs.Add('UseOnlineApproach', $true)
        $cmdArgs.Add('KeepCheckForeignKeyConstraints', $KeepCheckForeignKeyConstraints.ToBool())
        if ($MaxIterations -gt 0) { $cmdArgs.Add('MaxIterations', $MaxIterations) }
        if ($MaxDowntimeInSeconds -gt 0) { $cmdArgs.Add('MaxDowntimeInSeconds', $MaxDowntimeInSeconds) }
        if ($MaxIterationDurationInDays -gt 0) { $cmdArgs.Add('MaxIterationDurationInDays', $MaxIterationDurationInDays) }
        if ($MaxDivergingIterations -gt 0) { $cmdArgs.Add('MaxDivergingIterations', $MaxDivergingIterations) }
    }

    $result = Set-SqlColumnEncryption @cmdArgs | Select-Object *    
    Write-Output $result
} catch {
    throw
}

Specifies the name of the target computer including the instance name, e.g. MyServer\Instance

Specifies the name of the SQL database to modify

Specifies the path to a CSV file containing the encryption settings. Required columns: ColumnName (e.g. Table.Col), EncryptionType (Deterministic, Randomized, or Plaintext), EncryptionKey (Name of CEK)

Specifies a PSCredential object for the connection to the SQL Server. ServerCredential is ONLY used for SQL Logins. When you are using Windows Authentication you don't specify -Credential. It is picked up from your current login.

Off

If set, check semantics of foreign key constraints are preserved

If set, a log file will be created in the specified directory

Specifies the maximum number of consecutive catch-up iterations allowed before failing

Specifies the maximum downtime (in seconds) allowed for the source table

Specifies the maximum time (in days) for a single iteration

Specifies the maximum number of iterations in the catch-up phase

Off

If set, the cmdlet will use the online approach to minimize downtime

Specifies the delimiter used in the CSV file (defaults to ';')

Specifies the character encoding of the CSV file (defaults to 'UTF8')

Specifies the time period to retry the command on the target server

An interactive directory of PowerShell scripts.