You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
169 lines
7.8 KiB
169 lines
7.8 KiB
# Setup SSH key — Administrator@10.100.1.40 (AD LDAP, Windows Server 2012 R2) |
|
# SSOT: server-audit/docs/guide/ssh-access.md |
|
# Usage: .\server-audit\scripts\setup-ssh-ad-ldap.ps1 |
|
# Sekali jalan: password Administrator 1–2x (scp + ssh), lalu key-only. |
|
# Wajib PowerShell (bukan CMD). |
|
|
|
$ErrorActionPreference = 'Stop' |
|
$hostIp = '10.100.1.40' |
|
$SshUser = 'Administrator' |
|
$key = Join-Path $env:USERPROFILE '.ssh\id_rsa_geonet_laptop' |
|
$pub = "$key.pub" |
|
$aliasName = 'ad-ldap' |
|
|
|
if (-not (Test-Path $pub)) { |
|
Write-Host "Generating key $key ..." |
|
ssh-keygen -t rsa -b 4096 -f $key -C 'geonet-laptop' -N '""' |
|
} |
|
|
|
Write-Host "Fixing private key ACL..." |
|
icacls $key /inheritance:r 2>$null | Out-Null |
|
icacls $key /grant:r "${env:USERNAME}:(R)" 2>$null | Out-Null |
|
|
|
# Pub key LF-only |
|
$tempPub = Join-Path $env:TEMP 'geonet_ad_ldap_key.pub' |
|
$keyLine = (Get-Content $pub -Raw).Trim() -replace "`r", "" |
|
[System.IO.File]::WriteAllText($tempPub, $keyLine + "`n") |
|
|
|
# Remote installer (Windows OpenSSH — Administrator) |
|
# FORCE overwrite UTF-8 no BOM; tulis ke administrators_authorized_keys + profile fallback |
|
$remotePs = @' |
|
$ErrorActionPreference = "Stop" |
|
$authFile = "C:\ProgramData\ssh\administrators_authorized_keys" |
|
$userAuthDir = "C:\Users\Administrator\.ssh" |
|
$userAuthFile = Join-Path $userAuthDir "authorized_keys" |
|
$sshDir = "C:\ProgramData\ssh" |
|
$sshdConfig = "C:\ProgramData\ssh\sshd_config" |
|
$pubPath = Join-Path $env:TEMP "geonet_ad_ldap_key.pub" |
|
if (-not (Test-Path $pubPath)) { throw "Missing $pubPath — scp failed?" } |
|
$keyLine = [System.IO.File]::ReadAllText($pubPath).Trim() -replace "`r","" -replace "`0","" |
|
if ($keyLine -notmatch "^ssh-") { throw "Invalid pubkey content" } |
|
if (-not (Test-Path $sshDir)) { New-Item -ItemType Directory -Path $sshDir | Out-Null } |
|
|
|
$utf8 = New-Object System.Text.UTF8Encoding $false |
|
# FORCE overwrite — jangan merge file korup UTF-16 lama |
|
[System.IO.File]::WriteAllText($authFile, $keyLine + "`n", $utf8) |
|
Write-Host "FORCE wrote administrators_authorized_keys (UTF-8 no BOM)" |
|
|
|
function Fix-AclAdminOnly([string]$path) { |
|
$acl = Get-Acl $path |
|
$acl.SetAccessRuleProtection($true, $false) |
|
@($acl.Access) | ForEach-Object { [void]$acl.RemoveAccessRule($_) } |
|
$acl.AddAccessRule((New-Object System.Security.AccessControl.FileSystemAccessRule("SYSTEM","FullControl","Allow"))) |
|
$acl.AddAccessRule((New-Object System.Security.AccessControl.FileSystemAccessRule("Administrators","FullControl","Allow"))) |
|
Set-Acl -Path $path -AclObject $acl |
|
} |
|
Fix-AclAdminOnly $authFile |
|
Write-Host "ACL ProgramData OK" |
|
|
|
# Fallback: profile authorized_keys (jika Match Group di-comment) |
|
if (-not (Test-Path $userAuthDir)) { New-Item -ItemType Directory -Path $userAuthDir | Out-Null } |
|
[System.IO.File]::WriteAllText($userAuthFile, $keyLine + "`n", $utf8) |
|
$uacl = Get-Acl $userAuthFile |
|
$uacl.SetAccessRuleProtection($true, $false) |
|
@($uacl.Access) | ForEach-Object { [void]$uacl.RemoveAccessRule($_) } |
|
$uacl.AddAccessRule((New-Object System.Security.AccessControl.FileSystemAccessRule("SYSTEM","FullControl","Allow"))) |
|
$uacl.AddAccessRule((New-Object System.Security.AccessControl.FileSystemAccessRule("Administrators","FullControl","Allow"))) |
|
$uacl.AddAccessRule((New-Object System.Security.AccessControl.FileSystemAccessRule("Administrator","FullControl","Allow"))) |
|
Set-Acl -Path $userAuthFile -AclObject $uacl |
|
Write-Host "Wrote profile authorized_keys fallback" |
|
|
|
if (Test-Path $sshdConfig) { |
|
$cfg = Get-Content $sshdConfig -Raw |
|
# Uncomment Match Group administrators if commented |
|
$cfg = $cfg -replace "(?m)^#\s*Match Group administrators","Match Group administrators" |
|
$cfg = $cfg -replace "(?m)^#\s*AuthorizedKeysFile\s+__PROGRAMDATA__/ssh/administrators_authorized_keys"," AuthorizedKeysFile __PROGRAMDATA__/ssh/administrators_authorized_keys" |
|
if ($cfg -match "(?m)^#?\s*PubkeyAuthentication\s+no") { |
|
$cfg = $cfg -replace "(?m)^#?\s*PubkeyAuthentication\s+no","PubkeyAuthentication yes" |
|
Write-Host "Enabled PubkeyAuthentication" |
|
} |
|
if ($cfg -notmatch "(?m)^\s*PubkeyAuthentication\s+yes") { |
|
$cfg = "PubkeyAuthentication yes`r`n" + $cfg |
|
Write-Host "Inserted PubkeyAuthentication yes" |
|
} |
|
# Allow ssh-rsa for older Win32-OpenSSH / mixed client |
|
if ($cfg -notmatch "(?m)^\s*PubkeyAccepted") { |
|
$cfg = $cfg.TrimEnd() + "`r`nPubkeyAcceptedKeyTypes ssh-ed25519,ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,rsa-sha2-512,rsa-sha2-256,ssh-rsa`r`n" |
|
Write-Host "Added PubkeyAcceptedKeyTypes (+ssh-rsa)" |
|
} |
|
if ($cfg -notmatch "(?m)^\s*Match Group administrators") { |
|
$cfg = $cfg.TrimEnd() + "`r`n`r`nMatch Group administrators`r`n AuthorizedKeysFile __PROGRAMDATA__/ssh/administrators_authorized_keys`r`n" |
|
Write-Host "Added Match Group administrators block" |
|
} |
|
[System.IO.File]::WriteAllText($sshdConfig, $cfg, $utf8) |
|
Write-Host "sshd_config updated" |
|
} |
|
|
|
Write-Host "--- diagnostics ---" |
|
Write-Host ("auth bytes: " + (Get-Item $authFile).Length) |
|
$bytes = [System.IO.File]::ReadAllBytes($authFile) |
|
Write-Host ("first3: " + $bytes[0] + "," + $bytes[1] + "," + $bytes[2] + " (expect 115,115,104 = ssh)") |
|
Select-String -Path $sshdConfig -Pattern "Match Group|AuthorizedKeysFile|PubkeyAuth|PubkeyAccepted" | ForEach-Object { $_.Line } |
|
Get-Service sshd | Format-List Status, Name |
|
Restart-Service sshd -Force |
|
Start-Sleep -Seconds 2 |
|
Write-Host "KEY_INSTALLED_OK" |
|
'@ |
|
|
|
$tempRemote = Join-Path $env:TEMP 'setup-ad-ldap-authorized-keys.ps1' |
|
# Remote script must be CRLF-friendly for Windows PowerShell; keep as-is |
|
[System.IO.File]::WriteAllText($tempRemote, $remotePs) |
|
|
|
$commonOpts = @( |
|
'-o', 'PreferredAuthentications=password', |
|
'-o', 'PubkeyAuthentication=no', |
|
'-o', 'StrictHostKeyChecking=accept-new', |
|
'-o', 'MACs=hmac-sha1' |
|
) |
|
# scp: -P (port). ssh: -p (port) + -m hmac-sha1 |
|
$scpOpts = $commonOpts + @('-P', '22') |
|
$sshOpts = $commonOpts + @('-m', 'hmac-sha1', '-p', '22') |
|
|
|
Write-Host "Upload pub + installer ke ${SshUser}@${hostIp} (password)..." |
|
scp @scpOpts $tempPub "${SshUser}@${hostIp}:C:/Users/Administrator/AppData/Local/Temp/geonet_ad_ldap_key.pub" |
|
scp @scpOpts $tempRemote "${SshUser}@${hostIp}:C:/Users/Administrator/AppData/Local/Temp/setup-ad-ldap-authorized-keys.ps1" |
|
|
|
Write-Host "Run installer on server..." |
|
ssh @sshOpts "${SshUser}@${hostIp}" "powershell -NoProfile -ExecutionPolicy Bypass -File C:\Users\Administrator\AppData\Local\Temp\setup-ad-ldap-authorized-keys.ps1" |
|
|
|
Remove-Item $tempPub, $tempRemote -Force -ErrorAction SilentlyContinue |
|
|
|
# Ensure local ssh config alias |
|
$configPath = Join-Path $env:USERPROFILE '.ssh\config' |
|
$block = @" |
|
|
|
Host $aliasName |
|
HostName $hostIp |
|
User $SshUser |
|
Port 22 |
|
IdentityFile ~/.ssh/id_rsa_geonet_laptop |
|
IdentitiesOnly yes |
|
MACs hmac-sha1 |
|
PubkeyAcceptedAlgorithms +ssh-rsa |
|
"@ |
|
|
|
if (-not (Test-Path $configPath)) { |
|
Set-Content -Path $configPath -Value $block.TrimStart() -Encoding UTF8 |
|
Write-Host "Created ~/.ssh/config with Host $aliasName" |
|
} elseif (-not (Select-String -Path $configPath -Pattern "Host\s+$aliasName" -Quiet)) { |
|
Add-Content -Path $configPath -Value $block |
|
Write-Host "Appended Host $aliasName to ~/.ssh/config" |
|
} else { |
|
Write-Host "Host $aliasName already in ~/.ssh/config" |
|
} |
|
|
|
Write-Host "" |
|
Write-Host "Test key-only..." |
|
# Win2012 OpenSSH sering butuh ssh-rsa eksplisit dari client baru |
|
ssh -i $key -o BatchMode=yes -o IdentitiesOnly=yes -o PreferredAuthentications=publickey -o PubkeyAcceptedAlgorithms=+ssh-rsa -m hmac-sha1 "${SshUser}@${hostIp}" -p 22 "echo KEY_AUTH_OK & hostname" |
|
|
|
if ($LASTEXITCODE -ne 0) { |
|
Write-Host "" |
|
Write-Host "Masih gagal. Cek di server (password sekali):" |
|
Write-Host " ssh -m hmac-sha1 ${SshUser}@${hostIp} -p 22 `"powershell -Command Get-Content C:\ProgramData\ssh\administrators_authorized_keys`"" |
|
Write-Host " Pastikan OpenSSH Server terpasang & sshd running." |
|
Write-Host " Win2012 R2: Match Group administrators -> administrators_authorized_keys" |
|
exit 1 |
|
} |
|
|
|
Write-Host "Success. Login: ssh $aliasName"
|
|
|