Перейти к содержимому

Как в always on mssql синхронизировать логины и пароль на вторичной реплики и удалять логины когда удалили на первичной c проверкой хэш паролей

Первый скрипт 

Задача сделать синхронизацию логинов с праймери реплики в mssql на секондори реплики с проверкой паролей совпадают или нет . если не совпадают то скопировать логин с правильным паролем. Сделал проверку по хэшу паролей. Лог будет удаляться из папки старше 7 дней

Set-DbatoolsInsecureConnection -SessionOnly
# Параметры
$AGListenerName = "db01" # Имя листенера группы доступности
$LogFolder = "D:\DBA_scripts_AG\log"
$MaxLogAge = 7 # Максимальный возраст логов в днях

# Создаем папку для логов если не существует
if (-not (Test-Path $LogFolder)) {
    New-Item -ItemType Directory -Path $LogFolder -Force | Out-Null
}

# Удаляем старые логи (старше 7 дней)
Get-ChildItem -Path $LogFolder  | #-Filter "LoginSync_*.log"
    Where-Object { $_.LastWriteTime -lt (Get-Date).AddDays(-$MaxLogAge) } | 
    Remove-Item -Force

# Создаем лог-файл с датой в имени
$LogPath = Join-Path $LogFolder ("LoginSync_" + (Get-Date -Format "yyyyMMdd_HHmmss") + ".log")

# Функция для получения хэша пароля
function Get-SqlLoginHash {
    param (
        [string]$SqlInstance,
        [string]$LoginName
    )
    
    try {
        $query = @"
SELECT CAST(LOGINPROPERTY(name, 'PasswordHash') AS varbinary(256)) AS PasswordHash
FROM sys.sql_logins 
WHERE name = '$LoginName'
"@
        $result = Invoke-DbaQuery -SqlInstance $SqlInstance -Query $query -ErrorAction Stop
        return $result.PasswordHash
    }
    catch {
        Write-Output "Ошибка при получении хэша для $LoginName на $SqlInstance : $_" | Out-File $LogPath -Append
        return $null
    }
}

# Начало выполнения
Write-Output "Начало синхронизации: $(Get-Date)" | Out-File $LogPath -Append

# Получаем информацию о группе доступности
try {
    $AG = Get-DbaAvailabilityGroup -SqlInstance $AGListenerName -ErrorAction Stop
    $primaryReplica = $AG.AvailabilityReplicas | Where-Object { $_.Role -eq "Primary" }
    $secondaryReplicas = $AG.AvailabilityReplicas | Where-Object { $_.Role -eq "Secondary" }
    
    Write-Output "Первичная реплика: $($primaryReplica.Name)" | Out-File $LogPath -Append
    Write-Output "Вторичные реплики: $($secondaryReplicas.Name -join ', ')" | Out-File $LogPath -Append
}
catch {
    Write-Output "Ошибка при получении информации о группе доступности: $_" | Out-File $LogPath -Append
    exit
}

# Получаем SQL-логины с первичной реплики
try {
    $primaryLogins = Get-DbaLogin -SqlInstance $primaryReplica.Name -Type SQL -ExcludeSystemLogin -ExcludeFilter '##*','NT *','sa'
    Write-Output "Найдено SQL-логинов на первичной реплике: $($primaryLogins.Count)" | Out-File $LogPath -Append
    $primaryLogins | Select-Object Name | Out-File $LogPath -Append
}
catch {
    Write-Output "Ошибка при получении логинов с первичной реплики: $_" | Out-File $LogPath -Append
    exit
}

# Создаем коллекцию для несовпадающих логинов
$mismatchedLogins = @()

# Обрабатываем каждую вторичную реплику
foreach ($secondaryReplica in $secondaryReplicas) {
    $secondaryServer = $secondaryReplica.Name
    Write-Output "`nОбработка вторичной реплики: $secondaryServer" | Out-File $LogPath -Append
    
    try {
        # Получаем логины с вторичной реплики
        $secondaryLogins = Get-DbaLogin -SqlInstance $secondaryServer -Type SQL -ExcludeSystemLogin -ExcludeFilter '##*','NT *','sa'
        Write-Output "Найдено SQL-логинов на вторичной реплике: $($secondaryLogins.Count)" | Out-File $LogPath -Append
        $secondaryLogins | Select-Object Name | Out-File $LogPath -Append

        # Сравниваем каждый логин
        foreach ($login in $primaryLogins) {
            $secondaryLogin = $secondaryLogins | Where-Object Name -eq $login.Name
            
            if ($secondaryLogin) {
                # Получаем хэши паролей
                $primaryHash = Get-SqlLoginHash -SqlInstance $primaryReplica.Name -LoginName $login.Name
                $secondaryHash = Get-SqlLoginHash -SqlInstance $secondaryServer -LoginName $login.Name
                
                if ($primaryHash -and $secondaryHash) {
                    # Сравниваем хэши
                    if (Compare-Object $primaryHash $secondaryHash) {
                        $mismatchInfo = [PSCustomObject]@{
                            LoginName = $login.Name
                            PrimaryServer = $primaryReplica.Name
                            SecondaryServer = $secondaryServer
                            Status = "PasswordMismatch"
                        }
                        $mismatchedLogins += $mismatchInfo
                        
                        Write-Output "Разные пароли для логина: $($login.Name)" | Out-File $LogPath -Append
                        # Обновляем логин
                        #Copy-DbaLogin -Source $primaryReplica.Name -Destination $secondaryServer -Login $login.Name -Force
                        Write-Output "Обновлен логин: $($login.Name)" | Out-File $LogPath -Append
                    }
                    else {
                        Write-Output "Пароли совпадают для: $($login.Name)" | Out-File $LogPath -Append
                    }
                }
            }
            else {
                $mismatchInfo = [PSCustomObject]@{
                    LoginName = $login.Name
                    PrimaryServer = $primaryReplica.Name
                    SecondaryServer = $secondaryServer
                    Status = "MissingOnSecondary"
                }
                $mismatchedLogins += $mismatchInfo
                
                # Копируем отсутствующий логин
                #Copy-DbaLogin -Source $primaryReplica.Name -Destination $secondaryServer -Login $login.Name -Force
                Write-Output "Добавлен новый логин: $($login.Name)" | Out-File $LogPath -Append
            }
        }

        # Удаляем лишние логины
        foreach ($login in $secondaryLogins) {
            if ($login.Name -notin $primaryLogins.Name) {
                $mismatchInfo = [PSCustomObject]@{
                    LoginName = $login.Name
                    PrimaryServer = $primaryReplica.Name
                    SecondaryServer = $secondaryServer
                    Status = "ExtraOnSecondary"
                }
                $mismatchedLogins += $mismatchInfo
                
                #Remove-DbaLogin -SqlInstance $secondaryServer -Login $login.Name -Force
                Write-Output "Удален лишний логин: $($login.Name)" | Out-File $LogPath -Append
            }
        }
    }
    catch {
        Write-Output "Ошибка при обработке вторичной реплики $secondaryServer : $_" | Out-File $LogPath -Append
    }
}

# Выводим сводку по несовпадающим логинам
if ($mismatchedLogins.Count -gt 0) {
    Write-Output "`nСводка по несовпадающим логинам:" | Out-File $LogPath -Append
    Write-Output "=================================" | Out-File $LogPath -Append
    $mismatchedLogins | Format-Table -AutoSize | Out-File $LogPath -Append
    
    # Экспортируем несовпадающие логины в CSV
    $csvPath = Join-Path $LogFolder ("LoginSyncMismatches_" + (Get-Date -Format "yyyyMMdd_HHmmss") + ".csv")
    $mismatchedLogins | Export-Csv -Path $csvPath -NoTypeInformation -Encoding UTF8
    Write-Output "Список несовпадающих логинов сохранен в: $csvPath" | Out-File $LogPath -Append
}
else {
    Write-Output "`nВсе логины синхронизированы, несовпадений не обнаружено." | Out-File $LogPath -Append
}

Write-Output "`nСинхронизация завершена: $(Get-Date)" | Out-File $LogPath -Append

Как в always on mssql синхронизировать логины и пароль на вторичной реплики и удалять логины когда удалили на первичной c проверкой хэш паролей

Similar Posts:

Метки:

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Яндекс.Метрика