feat: integrate AD domain account impersonation for SQL Windows Authentication in SqlService, SettingsView, and SqlDatabaseView

This commit is contained in:
2026-10-21 08:37:11 +09:00
parent 5978de5924
commit 13daed47df
6 changed files with 332 additions and 98 deletions
+93 -7
View File
@@ -228,6 +228,7 @@ $script:loadSettingsToUI = {
$txtSqlServer = $v.FindName("TxtSqlServer")
$cmbSqlAuth = $v.FindName("CmbSqlAuthType")
$txtSqlBackupDir = $v.FindName("TxtSqlBackupDir")
$txtSqlDomain = $v.FindName("TxtSqlDomain")
$txtSqlUser = $v.FindName("TxtSqlUser")
$txtSqlPassword = $v.FindName("TxtSqlPassword")
@@ -250,7 +251,14 @@ $script:loadSettingsToUI = {
if ($chkSqlLive) { $chkSqlLive.IsChecked = [bool]$c.MsSql.UseLive }
if ($txtSqlServer) { $txtSqlServer.Text = $c.MsSql.Server }
if ($cmbSqlAuth) { $cmbSqlAuth.SelectedIndex = if ($c.MsSql.AuthType -eq "Sql") { 1 } else { 0 } }
if ($txtSqlDomain) { $txtSqlDomain.Text = if ($c.MsSql.Domain) { $c.MsSql.Domain } else { "corp" } }
if ($cmbSqlAuth) {
$cmbSqlAuth.SelectedIndex = switch ($c.MsSql.AuthType) {
"AdImpersonated" { 1 }
"Sql" { 2 }
default { 0 }
}
}
if ($txtSqlBackupDir) { $txtSqlBackupDir.Text = $c.MsSql.BackupDirectory }
if ($txtSqlUser) { $txtSqlUser.Text = $c.MsSql.Username }
if ($txtSqlPassword) { $txtSqlPassword.Password = $c.MsSql.Password }
@@ -1152,12 +1160,22 @@ function Navigate-ToPage {
$btnTestConn = $view.FindName("BtnTestSqlConnection")
$btnBackup = $view.FindName("BtnBackupDb")
$btnExecQuery = $view.FindName("BtnExecuteQuery")
$cmbSqlAuthInDb = $view.FindName("CmbSqlAuth")
if ($cmbSqlAuthInDb) {
$cmbSqlAuthInDb.SelectedIndex = switch ($global:AppConfig.MsSql.AuthType) {
"AdImpersonated" { 1 }
"Sql" { 2 }
default { 0 }
}
}
if ($btnSqlRefresh) { $btnSqlRefresh.add_Click({ & $script:reloadSql }) }
if ($btnTestConn) {
$btnTestConn.add_Click({
$res = Test-SqlConnection -Server $global:AppConfig.MsSql.Server -AuthType $global:AppConfig.MsSql.AuthType -Username $global:AppConfig.MsSql.Username -Password $global:AppConfig.MsSql.Password
$cfg = $global:AppConfig.MsSql
$res = Test-SqlConnection -Server $cfg.Server -AuthType $cfg.AuthType -Domain $cfg.Domain -Username $cfg.Username -Password $cfg.Password
$img = if ($res.Success) { [System.Windows.MessageBoxImage]::Information } else { [System.Windows.MessageBoxImage]::Error }
[System.Windows.MessageBox]::Show($res.Message, "MS SQL 연결 테스트", [System.Windows.MessageBoxButton]::OK, $img)
})
@@ -1209,6 +1227,58 @@ function Navigate-ToPage {
& $script:loadSettingsToUI
$updateSqlAuthUi = {
$v = $ViewCache["Settings"]
if (-not $v) { return }
$cmb = $v.FindName("CmbSqlAuthType")
$txtHint = $v.FindName("TxtSqlAuthHint")
$lblDomain = $v.FindName("LblSqlDomain")
$txtDomain = $v.FindName("TxtSqlDomain")
$lblUser = $v.FindName("LblSqlUser")
$txtUser = $v.FindName("TxtSqlUser")
$lblPass = $v.FindName("LblSqlPassword")
$txtPass = $v.FindName("TxtSqlPassword")
switch ($cmb.SelectedIndex) {
1 {
# AdImpersonated
if ($txtHint) { $txtHint.Text = "입력한 AD 도메인 ID/PW를 Windows 토큰(/netonly)으로 위장하여 SQL Server에 Windows 통합 인증으로 접속합니다." }
if ($lblDomain) { $lblDomain.Text = "AD 도메인 (예: corp 또는 corp.local):" }
if ($lblUser) { $lblUser.Text = "AD 도메인 계정 ID (예: sql_admin):" }
if ($lblPass) { $lblPass.Text = "AD 도메인 계정 암호:" }
if ($txtDomain) { $txtDomain.IsEnabled = $true; $txtDomain.Opacity = 1.0 }
if ($txtUser) { $txtUser.IsEnabled = $true; $txtUser.Opacity = 1.0 }
if ($txtPass) { $txtPass.IsEnabled = $true; $txtPass.Opacity = 1.0 }
}
2 {
# Sql Auth
if ($txtHint) { $txtHint.Text = "SQL Server 자체 계정(sa 또는 DB 전용 계정)과 암호로 접속합니다." }
if ($lblDomain) { $lblDomain.Text = "AD 도메인 (SQL 인증 시 불필요):" }
if ($lblUser) { $lblUser.Text = "SQL Server 계정 ID (예: sa):" }
if ($lblPass) { $lblPass.Text = "SQL Server 계정 암호:" }
if ($txtDomain) { $txtDomain.IsEnabled = $false; $txtDomain.Opacity = 0.5 }
if ($txtUser) { $txtUser.IsEnabled = $true; $txtUser.Opacity = 1.0 }
if ($txtPass) { $txtPass.IsEnabled = $true; $txtPass.Opacity = 1.0 }
}
default {
# Integrated (Current Windows User)
if ($txtHint) { $txtHint.Text = "현재 윈도우에 로그인된 사용자 자격증명(Kerberos/NTLM)으로 SQL Server에 접속합니다." }
if ($lblDomain) { $lblDomain.Text = "AD 도메인 (현재 세션 인증 시 불필요):" }
if ($lblUser) { $lblUser.Text = "로그인 계정 (현재 Windows 로그인 토큰 사용):" }
if ($lblPass) { $lblPass.Text = "비밀번호 (현재 세션 인증 시 불필요):" }
if ($txtDomain) { $txtDomain.IsEnabled = $false; $txtDomain.Opacity = 0.5 }
if ($txtUser) { $txtUser.IsEnabled = $false; $txtUser.Opacity = 0.5 }
if ($txtPass) { $txtPass.IsEnabled = $false; $txtPass.Opacity = 0.5 }
}
}
}
$cmbSqlAuth = $view.FindName("CmbSqlAuthType")
if ($cmbSqlAuth) {
$cmbSqlAuth.add_SelectionChanged({ & $updateSqlAuthUi })
}
& $updateSqlAuthUi
# Test AD
if ($btnTestAd) {
$btnTestAd.add_Click({
@@ -1246,11 +1316,16 @@ function Navigate-ToPage {
$v = $ViewCache["Settings"]
$srv = $v.FindName("TxtSqlServer").Text
$cmb = $v.FindName("CmbSqlAuthType")
$authType = if ($cmb.SelectedIndex -eq 1) { "Sql" } else { "Integrated" }
$authType = switch ($cmb.SelectedIndex) {
1 { "AdImpersonated" }
2 { "Sql" }
default { "Integrated" }
}
$domain = $v.FindName("TxtSqlDomain").Text
$user = $v.FindName("TxtSqlUser").Text
$pass = $v.FindName("TxtSqlPassword").Password
$res = Test-SqlConnection -Server $srv -AuthType $authType -Username $user -Password $pass
$res = Test-SqlConnection -Server $srv -AuthType $authType -Domain $domain -Username $user -Password $pass
$img = if ($res.Success) { [System.Windows.MessageBoxImage]::Information } else { [System.Windows.MessageBoxImage]::Warning }
[System.Windows.MessageBox]::Show($res.Message, "MS SQL 연결 테스트", [System.Windows.MessageBoxButton]::OK, $img)
})
@@ -1273,13 +1348,18 @@ function Navigate-ToPage {
$srv = $v.FindName("TxtSqlServer").Text
$cmb = $v.FindName("CmbSqlAuthType")
$authType = if ($cmb.SelectedIndex -eq 1) { "Sql" } else { "Integrated" }
$authType = switch ($cmb.SelectedIndex) {
1 { "AdImpersonated" }
2 { "Sql" }
default { "Integrated" }
}
$sDomain = $v.FindName("TxtSqlDomain").Text
$sUser = $v.FindName("TxtSqlUser").Text
$sPass = $v.FindName("TxtSqlPassword").Password
$adRes = Test-ADConnection -DomainController $dc -BaseOU $ou -Username $user -Password $pass -UseLdaps $ldaps
$netappRes = Test-NetAppConnection -ClusterEndpoint $ep -Username $nUser -Password $nPass -IgnoreSsl $ignoreSsl
$sqlRes = Test-SqlConnection -Server $srv -AuthType $authType -Username $sUser -Password $sPass
$sqlRes = Test-SqlConnection -Server $srv -AuthType $authType -Domain $sDomain -Username $sUser -Password $sPass
$report = @"
=== 전체 인프라 일괄 진단 결과 ===
@@ -1305,7 +1385,11 @@ function Navigate-ToPage {
$btnSave.add_Click({
$v = $ViewCache["Settings"]
$cmb = $v.FindName("CmbSqlAuthType")
$authType = if ($cmb.SelectedIndex -eq 1) { "Sql" } else { "Integrated" }
$authType = switch ($cmb.SelectedIndex) {
1 { "AdImpersonated" }
2 { "Sql" }
default { "Integrated" }
}
$chkGlobalLive = $v.FindName("ChkGlobalLiveMode")
$chkAdLive = $v.FindName("ChkAdLive")
@@ -1340,6 +1424,7 @@ function Navigate-ToPage {
UseLive = [bool]($chkGlobalLive.IsChecked -or $chkSqlLive.IsChecked)
Server = $v.FindName("TxtSqlServer").Text
AuthType = $authType
Domain = $v.FindName("TxtSqlDomain").Text
Username = $v.FindName("TxtSqlUser").Text
Password = $v.FindName("TxtSqlPassword").Password
DefaultDatabase = "master"
@@ -1365,6 +1450,7 @@ function Navigate-ToPage {
$btnReload.add_Click({
$global:AppConfig = Get-AppConfig
& $script:loadSettingsToUI
& $updateSqlAuthUi
Update-ModeBadgeUI
[System.Windows.MessageBox]::Show("config.json 설정을 다시 불러왔습니다.", "알림", [System.Windows.MessageBoxButton]::OK, [System.Windows.MessageBoxImage]::Information)
})