Первый скрипт
Задача сделать синхронизацию логинов с праймери реплики в 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
Similar Posts:
- Как бэкапить логины (login) и задания (JOB) mssql через dbatools
- Как в always on mssql синхронизировать логины и пароль на вторичной реплики и удалять логины когда удалили на первичной.
- Как синхронизировать обьекты в always on c первичной реплики на вторичную
- Как в always on mssql синхронизировать JOB на вторичной реплики и удалять JOB со вторичной когда удалили на первичной.
- Как провести адудит паролей в windows ad