# ============================================================ # RDP Certificate Manager - Menu Script (PS 5.1 Compatible) # Zapusk: irm https://git.help-d.ru/installSSL.ps1 | iex # ============================================================ # ========== НАСТРОЙКИ ========== $GiteaUrl = "https://git.help-d.ru" $RepoPath = "helmut/ssl.git//raw/branch/main" $CertFileName = "Help-D_RDP.pfx" $CertPassword = "sj032ssa" $CertStorePath = "C:\tmp\cert" $ThumbprintFile = "$CertStorePath\thumbprint.txt" $RdpSign = "$env:SystemRoot\System32\rdpsign.exe" # =============================== # Фикс TLS для Windows Server [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 -bor [Net.SecurityProtocolType]::Tls13 # Проверка прав администратора $IsAdmin = ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator") # Цвета $HeaderColor = "Cyan" $SuccessColor = "Green" $ErrorColor = "Red" $WarningColor = "Yellow" $GrayColor = "Gray" function Show-Header { param([string]$Title) Clear-Host Write-Host "`n================================================" -ForegroundColor $HeaderColor Write-Host " $Title" -ForegroundColor $HeaderColor Write-Host "================================================`n" -ForegroundColor $HeaderColor } function Get-Thumbprint { if (Test-Path $ThumbprintFile) { return (Get-Content $ThumbprintFile -Raw).Trim() } $Cert = Get-ChildItem Cert:\LocalMachine\My | Where-Object { $_.Subject -like "*Help-D*" } | Select-Object -First 1 if ($Cert) { return $Cert.Thumbprint } return $null } function Install-Certificate { Show-Header " [1] УСТАНОВКА СЕРТИФИКАТА " if (-not $IsAdmin) { Write-Host "❌ Требуется запуск от имени Администратора" -ForegroundColor $ErrorColor Pause return } if (-not (Test-Path $CertStorePath)) { New-Item -ItemType Directory -Path $CertStorePath -Force | Out-Null } $CertUrl = "$GiteaUrl/$RepoPath/$CertFileName" $CertPath = "$CertStorePath\$CertFileName" Write-Host "📥 Скачивание сертификата..." -ForegroundColor $GrayColor try { Invoke-WebRequest -Uri $CertUrl -OutFile $CertPath -ErrorAction Stop -UseBasicParsing Write-Host " ✅ Загружено: $CertFileName" -ForegroundColor $SuccessColor } catch { Write-Host " ❌ Ошибка загрузки: $_" -ForegroundColor $ErrorColor Pause return } Write-Host "`n🔐 Установка в хранилища..." -ForegroundColor $GrayColor $SecurePass = ConvertTo-SecureString -String $CertPassword -AsPlainText -Force try { $Cert = Import-PfxCertificate -FilePath $CertPath -CertStoreLocation Cert:\LocalMachine\My -Password $SecurePass -Exportable Import-PfxCertificate -FilePath $CertPath -CertStoreLocation Cert:\LocalMachine\Root -Password $SecurePass | Out-Null Import-PfxCertificate -FilePath $CertPath -CertStoreLocation Cert:\LocalMachine\TrustedPublisher -Password $SecurePass | Out-Null $Thumb = $Cert.Thumbprint $Thumb | Out-File -FilePath $ThumbprintFile -Encoding ASCII -Force Write-Host " ✅ LocalMachine\My" -ForegroundColor $SuccessColor Write-Host " ✅ LocalMachine\Root" -ForegroundColor $SuccessColor Write-Host " ✅ LocalMachine\TrustedPublisher" -ForegroundColor $SuccessColor Write-Host "`n📋 Отпечаток сохранён: $Thumb" -ForegroundColor $HeaderColor } catch { if ($_.Exception.Message -match "already exists") { $Cert = Get-ChildItem Cert:\LocalMachine\My | Where-Object { $_.Subject -like "*Help-D*" } | Select-Object -First 1 $Thumb = $Cert.Thumbprint if (-not (Test-Path $ThumbprintFile)) { $Thumb | Out-File -FilePath $ThumbprintFile -Encoding ASCII -Force } Write-Host " ℹ️ Сертификат уже установлен" -ForegroundColor $WarningColor Write-Host "📋 Отпечаток: $Thumb" -ForegroundColor $HeaderColor } else { Write-Host " ❌ Ошибка: $_" -ForegroundColor $ErrorColor Pause return } } Remove-Item $CertPath -Force -ErrorAction SilentlyContinue Write-Host "`n🗑️ PFX-файл удалён (безопасность)" -ForegroundColor $GrayColor Write-Host "`n✅ Установка завершена!" -ForegroundColor $SuccessColor Pause } function Sign-RdpFiles { param( [string[]]$Files, [string]$Description ) $Thumb = Get-Thumbprint if (-not $Thumb) { Write-Host "❌ Сертификат не найден. Сначала выполните пункт 1." -ForegroundColor $ErrorColor Pause return } if (-not (Test-Path $RdpSign)) { Write-Host "❌ rdpsign.exe не найден" -ForegroundColor $ErrorColor Pause return } Write-Host "`n$Description" -ForegroundColor $GrayColor Write-Host "🔑 Отпечаток: $Thumb`n" -ForegroundColor $GrayColor $Success = 0 $Failed = 0 foreach ($File in $Files) { $FileName = Split-Path $File -Leaf Write-Host " 📝 $FileName ... " -NoNewline -ForegroundColor $GrayColor $Args = "/sha256", $Thumb, $File & $RdpSign @Args 2>&1 | Out-Null if ($LASTEXITCODE -ne 0) { $Args = "/sha1", $Thumb, $File & $RdpSign @Args 2>&1 | Out-Null } if ($LASTEXITCODE -eq 0) { Write-Host "✅" -ForegroundColor $SuccessColor $Success++ } else { Write-Host "❌" -ForegroundColor $ErrorColor $Failed++ } } Write-Host "`n📊 Результат: ✅ $Success | ❌ $Failed" -ForegroundColor $HeaderColor Pause } function Sign-AllDesktopRdp { Show-Header " [2] ПОДПИСАТЬ ВСЕ RDP НА РАБОЧИХ СТОЛАХ " $Files = @() $CurrentUserDesktop = [Environment]::GetFolderPath("Desktop") if (Test-Path $CurrentUserDesktop) { $Files += Get-ChildItem -Path $CurrentUserDesktop -Filter "*.rdp" -File | Select-Object -ExpandProperty FullName } $PublicDesktop = "C:\Users\Public\Desktop" if (Test-Path $PublicDesktop) { $Files += Get-ChildItem -Path $PublicDesktop -Filter "*.rdp" -File | Select-Object -ExpandProperty FullName } $UserFolders = Get-ChildItem "C:\Users" -Directory -ErrorAction SilentlyContinue | Where-Object { $_.Name -notmatch "Public|Default|All Users" } foreach ($User in $UserFolders) { $UserDesktop = "$($User.FullName)\Desktop" if (Test-Path $UserDesktop) { $Files += Get-ChildItem -Path $UserDesktop -Filter "*.rdp" -File -ErrorAction SilentlyContinue | Select-Object -ExpandProperty FullName } } $RemoteAppPath = "C:\Program Files\Packaged Programs" if (Test-Path $RemoteAppPath) { $Files += Get-ChildItem -Path $RemoteAppPath -Filter "*.rdp" -File -Recurse -ErrorAction SilentlyContinue | Select-Object -ExpandProperty FullName $Files += Get-ChildItem -Path $RemoteAppPath -Filter "*.msc" -File -Recurse -ErrorAction SilentlyContinue | Select-Object -ExpandProperty FullName } $Files = $Files | Select-Object -Unique if ($Files.Count -eq 0) { Write-Host "⚠️ RDP-файлы не найдены" -ForegroundColor $WarningColor Pause return } Write-Host "📁 Найдено файлов: $($Files.Count)" -ForegroundColor $GrayColor $Confirm = Read-Host "Подписать все? (y/n)" if ($Confirm -ne "y") { return } Sign-RdpFiles -Files $Files -Description "🚀 Начало пакетного подписания..." } function Sign-SelectedRdp { Show-Header " [3] ПОДПИСАТЬ ВЫБРАННЫЙ RDP " Add-Type -AssemblyName System.Windows.Forms $ofd = New-Object System.Windows.Forms.OpenFileDialog $ofd.Title = "Выберите RDP файл для подписания" $ofd.Filter = "RDP Files|*.rdp|All Files|*.*" $ofd.InitialDirectory = [Environment]::GetFolderPath("Desktop") if ($ofd.ShowDialog() -ne 'OK') { return } Sign-RdpFiles -Files @($ofd.FileName) -Description "📝 Подписание файла:" } function Remove-Certificate { Show-Header " [4] УДАЛИТЬ СЕРТИФИКАТ ИЗ СИСТЕМЫ " if (-not $IsAdmin) { Write-Host "❌ Требуется запуск от имени Администратора" -ForegroundColor $ErrorColor Pause return } $Thumb = Get-Thumbprint if (-not $Thumb) { Write-Host "⚠️ Сертификат не найден в системе" -ForegroundColor $WarningColor Pause return } Write-Host "🔍 Найден сертификат:" -ForegroundColor $GrayColor $Cert = Get-ChildItem Cert:\LocalMachine\My | Where-Object { $_.Thumbprint -eq $Thumb } if ($Cert) { Write-Host " Subject: $($Cert.Subject)" -ForegroundColor $GrayColor Write-Host " Thumbprint: $($Cert.Thumbprint)" -ForegroundColor $GrayColor } $Confirm = Read-Host "`nУдалить из Root, TrustedPublisher и My? (y/n)" if ($Confirm -ne "y") { return } $Stores = "Cert:\LocalMachine\Root", "Cert:\LocalMachine\TrustedPublisher", "Cert:\LocalMachine\My" foreach ($Store in $Stores) { $Cert = Get-ChildItem $Store -ErrorAction SilentlyContinue | Where-Object { $_.Thumbprint -eq $Thumb } if ($Cert) { Remove-Item $Cert.PSPath -Force -ErrorAction SilentlyContinue Write-Host " ✅ Удалено из $Store" -ForegroundColor $SuccessColor } } if (Test-Path $ThumbprintFile) { Remove-Item $ThumbprintFile -Force Write-Host " ✅ Удалён файл отпечатка" -ForegroundColor $SuccessColor } Write-Host "`n✅ Удаление завершено" -ForegroundColor $SuccessColor Pause } function Check-Certificate { Show-Header " [5] ПРОВЕРКА СТАТУСА СЕРТИФИКАТА " Write-Host "📋 Диагностика:" -ForegroundColor $HeaderColor # 1. Проверяем, есть ли подписанные RDP на рабочем столе $Desktop = [Environment]::GetFolderPath("Desktop") $RdpFiles = Get-ChildItem -Path $Desktop -Filter "*.rdp" -File -ErrorAction SilentlyContinue $RdpThumb = $null if ($RdpFiles.Count -gt 0) { # Берём первый RDP и читаем его подпись $FirstRdp = $RdpFiles[0].FullName $Content = Get-Content $FirstRdp -Encoding UTF8 -ErrorAction SilentlyContinue $SigLine = $Content | Where-Object { $_ -match "^signature:s:" } if ($SigLine) { # Извлекаем отпечаток из подписи (упрощённо: берём первые 40 символов после префикса) $RawSig = $SigLine -replace "signature:s:","" # В реальной подписи это баз64-блок, но для проверки нам хватит поиска по субъекту $RdpThumb = "из файла $(Split-Path $FirstRdp -Leaf)" Write-Host " 📄 Найден подписанный RDP: $(Split-Path $FirstRdp -Leaf)" -ForegroundColor $GrayColor } } if (-not $RdpThumb) { Write-Host " ⚠️ Подписанные RDP не найдены на рабочем столе" -ForegroundColor $WarningColor } # 2. Ищем сертификаты по имени издателя (как в твоём рабочем скрипте) $SearchPattern = "*Help-D*" # <-- Поменяй на своё имя, если нужно Write-Host "`n🔍 Поиск в хранилищах (по субъекту: $SearchPattern):" -ForegroundColor $GrayColor $Stores = @{ "Cert:\LocalMachine\My" = "My (приватный ключ)" "Cert:\LocalMachine\Root" = "Root (доверенные центры)" "Cert:\LocalMachine\TrustedPublisher" = "TrustedPublisher (издатели RDP)" } $FoundCerts = @{} foreach ($StorePath in $Stores.Keys) { $Certs = Get-ChildItem $StorePath -ErrorAction SilentlyContinue | Where-Object { $_.Subject -like $SearchPattern } $FoundCerts[$StorePath] = $Certs $Count = $Certs.Count $Status = if ($Count -gt 0) { "✅ Найден ($Count шт.)" } else { "❌ Не найден" } $Color = if ($Count -gt 0) { $SuccessColor } else { $ErrorColor } Write-Host " $($Stores[$StorePath]): " -NoNewline Write-Host "$Status" -ForegroundColor $Color # Показываем отпечатки найденных foreach ($Cert in $Certs) { Write-Host " • $($Cert.Thumbprint)" -ForegroundColor $GrayColor } } # 3. Сверка: есть ли отпечаток из RDP в доверенных хранилищах Write-Host "`n🔗 Сверка доверия:" -ForegroundColor $HeaderColor if ($RdpThumb -and $FoundCerts["Cert:\LocalMachine\Root"] -and $FoundCerts["Cert:\LocalMachine\TrustedPublisher"]) { # Если в обоих хранилищах есть сертификаты с нужным именем — скорее всего, всё ок $RootThumb = $FoundCerts["Cert:\LocalMachine\Root"][0].Thumbprint $TrustedThumb = $FoundCerts["Cert:\LocalMachine\TrustedPublisher"][0].Thumbprint if ($RootThumb -eq $TrustedThumb) { Write-Host " ✅ Сертификат в Root и TrustedPublisher совпадает" -ForegroundColor $SuccessColor Write-Host " ✅ RDP-клиент покажет «Проверенный издатель»" -ForegroundColor $SuccessColor } else { Write-Host " ⚠️ В Root и TrustedPublisher разные сертификаты" -ForegroundColor $WarningColor Write-Host " Root: $RootThumb" -ForegroundColor $GrayColor Write-Host " TrustedPublisher: $TrustedThumb" -ForegroundColor $GrayColor } } elseif (-not $FoundCerts["Cert:\LocalMachine\Root"] -or -not $FoundCerts["Cert:\LocalMachine\TrustedPublisher"]) { Write-Host " ❌ Сертификат должен быть в Root И в TrustedPublisher" -ForegroundColor $ErrorColor Write-Host " Запусти пункт [1] для установки" -ForegroundColor $GrayColor } # 4. Проверка rdpsign.exe Write-Host "`n🔧 Инструменты:" -ForegroundColor $HeaderColor if (Test-Path $RdpSign) { Write-Host " rdpsign.exe: ✅ Найден ($RdpSign)" -ForegroundColor $SuccessColor } else { Write-Host " rdpsign.exe: ❌ Не найден" -ForegroundColor $ErrorColor } Write-Host "`n💡 Подсказка:" -ForegroundColor $GrayColor Write-Host " Если RDP показывает «Неизвестный издатель»:" -ForegroundColor $GrayColor Write-Host " 1. Убедись, что сертификат установлен в Root и TrustedPublisher" -ForegroundColor $GrayColor Write-Host " 2. Перезапусти Remote Desktop клиент" -ForegroundColor $GrayColor Write-Host " 3. Если не помогло — перезагрузи компьютер" -ForegroundColor $GrayColor Pause } # ========== ГЛАВНОЕ МЕНЮ ========== do { Show-Header " RDP CERTIFICATE MANAGER " Write-Host " [1] Установить сертификат" -ForegroundColor $HeaderColor Write-Host " [2] Подписать все RDP (рабочие столы + RemoteApp)" -ForegroundColor $HeaderColor Write-Host " [3] Подписать выбранный RDP" -ForegroundColor $HeaderColor Write-Host " [4] Удалить сертификат из системы" -ForegroundColor $HeaderColor Write-Host " [5] Проверка статуса сертификата" -ForegroundColor $HeaderColor Write-Host " [0] Выход" -ForegroundColor $WarningColor Write-Host "`n------------------------------------------------" -ForegroundColor $GrayColor $Choice = Read-Host "Выберите действие (0-5)" switch ($Choice) { "1" { Install-Certificate } "2" { Sign-AllDesktopRdp } "3" { Sign-SelectedRdp } "4" { Remove-Certificate } "5" { Check-Certificate } "0" { Write-Host "`n👋 Выход. Удачи!" -ForegroundColor $SuccessColor; Start-Sleep -Seconds 1 } default { Write-Host "`n⚠️ Неверный выбор" -ForegroundColor $WarningColor; Start-Sleep -Seconds 1 } } } while ($Choice -ne "0")