# netbird-claude-install.ps1
# Установка Netbird на Windows + регистрация в tenant netbird.io (группа Claude-Diag)
# + создание пользователя claude/Kl@udeD1ag!2026
# + OpenSSH Server, RDP, WinRM для удалённой диагностики через Netbird.
#
# Запуск: PowerShell от администратора
#   iwr -useb https://git.dttb.ru/oleg/knowledge-base/raw/branch/main/snippets/netbird-claude-install.ps1 | iex
# Или скачать и выполнить локально:
#   powershell -ExecutionPolicy Bypass -File .\netbird-claude-install.ps1
#
# Идемпотентно: можно запускать повторно.

$ErrorActionPreference = "Continue"  # не падаем на одной ошибке — нужен максимум сделанного

# ===== TLS 1.2+ (PowerShell 5.1 на 2012R2/2016 по умолчанию TLS 1.0) =====
try {
    [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]'Tls12,Tls13'
} catch {
    [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
}

# ===== Параметры =====
$SETUP_KEY    = "9E31C0F0-CB3A-4D5A-87FD-4804E913FD29"   # Claude-Diag, истекает 2026-07-25
$NETBIRD_CIDR = "100.70.0.0/16"                          # адресное пространство tenant'а
$NETBIRD_EXE  = "C:\Program Files\Netbird\netbird.exe"
$CLAUDE_USER  = "claude"
$CLAUDE_PASS  = "Kl@udeD1ag!2026"

# ===== 1. Проверка прав =====
$isAdmin = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
if (-not $isAdmin) {
    Write-Error "Нужен PowerShell от администратора."
    exit 1
}

Write-Host "=== Netbird Claude-Diag setup ===" -ForegroundColor Cyan

# ===== 2. Установка Netbird =====
if (-not (Test-Path $NETBIRD_EXE)) {
    Write-Host "[1/7] Скачиваю Netbird MSI..."
    $msi = "$env:TEMP\netbird.msi"
    Invoke-WebRequest -UseBasicParsing -Uri "https://pkgs.netbird.io/windows/x64" -OutFile $msi
    Write-Host "[2/7] Устанавливаю (silent)..."
    Start-Process msiexec.exe -ArgumentList "/i `"$msi`" /qn" -Wait
    Start-Sleep 5
} else {
    Write-Host "[1-2/7] Netbird уже установлен: $NETBIRD_EXE"
}

# ===== 3. Регистрация =====
# Если уже подключён к tenant (например, через свой setup-key в другой группе) — не перерегистрировать
$nbStatus = & $NETBIRD_EXE status 2>$null | Out-String
if ($nbStatus -match "Management:\s*Connected" -or $nbStatus -match "Signal:\s*Connected") {
    Write-Host "[3/7] Netbird уже подключён, перерегистрацию пропускаем"
} else {
    Write-Host "[3/7] Регистрация в tenant с Claude-Diag ключом..."
    & $NETBIRD_EXE up --setup-key $SETUP_KEY 2>&1 | Out-Host
    Start-Sleep 3
}

# ===== 4. Пользователь claude =====
Write-Host "[4/7] Создаю/обновляю пользователя $CLAUDE_USER..."
$securePass = ConvertTo-SecureString $CLAUDE_PASS -AsPlainText -Force
$existing = Get-LocalUser -Name $CLAUDE_USER -ErrorAction SilentlyContinue
if (-not $existing) {
    New-LocalUser -Name $CLAUDE_USER -Password $securePass -PasswordNeverExpires:$true `
        -AccountNeverExpires:$true -UserMayNotChangePassword:$true `
        -FullName "Claude Diagnostics" -Description "Remote diagnostics via Netbird" | Out-Null
} else {
    Set-LocalUser -Name $CLAUDE_USER -Password $securePass -PasswordNeverExpires:$true
}
# Группа Administrators — пробуем оба варианта (en-US и ru-RU имена)
foreach ($grp in @("Administrators","Администраторы")) {
    try {
        Add-LocalGroupMember -Group $grp -Member $CLAUDE_USER -ErrorAction Stop 2>$null
    } catch {
        # member already in group или группа не та локаль — ок
    }
}
# Через SID — самый надёжный способ для русской Windows
try {
    $adminGroup = (Get-LocalGroup | Where-Object { $_.SID -eq "S-1-5-32-544" }).Name
    Add-LocalGroupMember -Group $adminGroup -Member $CLAUDE_USER -ErrorAction SilentlyContinue
} catch {}

# ===== 5. RDP =====
Write-Host "[5/7] Включаю RDP..."
Set-ItemProperty -Path "HKLM:\System\CurrentControlSet\Control\Terminal Server" -Name "fDenyTSConnections" -Value 0 -ErrorAction SilentlyContinue
Enable-NetFirewallRule -DisplayGroup "Remote Desktop" -ErrorAction SilentlyContinue

# ===== 6. WinRM + OpenSSH Server =====
Write-Host "[6/7] WinRM + OpenSSH Server..."
# Сначала перевести Public-сети в Private (иначе Set-Item WSMan ругается)
try {
    Get-NetConnectionProfile -ErrorAction SilentlyContinue | `
        Where-Object { $_.NetworkCategory -eq 'Public' } | `
        Set-NetConnectionProfile -NetworkCategory Private -ErrorAction SilentlyContinue
} catch {}
try {
    Enable-PSRemoting -Force -SkipNetworkProfileCheck | Out-Null
} catch {
    try { winrm quickconfig -force -q | Out-Null } catch {}
}
try { Set-Item WSMan:\localhost\Service\Auth\Basic -Value $true -Force -ErrorAction SilentlyContinue } catch {}
try { Set-Item WSMan:\localhost\Service\AllowUnencrypted -Value $true -Force -ErrorAction SilentlyContinue } catch {}
# LocalAccountTokenFilterPolicy — чтобы локальный admin claude мог в WinRM
New-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" `
    -Name "LocalAccountTokenFilterPolicy" -Value 1 -PropertyType DWord -Force | Out-Null

# OpenSSH Server (Win10 1809+ / Win11 — встроен как Capability)
try {
    $sshCap = Get-WindowsCapability -Online -Name "OpenSSH.Server*" -ErrorAction SilentlyContinue | Select-Object -First 1
    if ($sshCap -and $sshCap.State -ne "Installed") {
        Add-WindowsCapability -Online -Name $sshCap.Name | Out-Null
    }
    Set-Service -Name sshd -StartupType Automatic -ErrorAction SilentlyContinue
    Start-Service -Name sshd -ErrorAction SilentlyContinue
} catch {
    Write-Host "  OpenSSH установка не удалась (возможно домашняя редакция Windows)" -ForegroundColor Yellow
}

# Установить дефолтный shell на PowerShell для удобства
try {
    New-ItemProperty -Path "HKLM:\SOFTWARE\OpenSSH" -Name DefaultShell `
        -Value "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" -PropertyType String -Force | Out-Null
} catch {}

# Mac-ключ Олега в administrators_authorized_keys (для админов sshd читает только этот файл)
$macKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPonNRAAJRK5wISltjR65MmeP7fQjf5HmYdQD9mlZ07F ai@mac-20260112"
$authKeys = "C:\ProgramData\ssh\administrators_authorized_keys"
try {
    if (-not (Test-Path "C:\ProgramData\ssh")) {
        New-Item -ItemType Directory -Path "C:\ProgramData\ssh" -Force | Out-Null
    }
    $current = if (Test-Path $authKeys) { Get-Content $authKeys -Raw -ErrorAction SilentlyContinue } else { "" }
    if ($current -notmatch [regex]::Escape($macKey)) {
        Add-Content -Path $authKeys -Value $macKey -Encoding ASCII
    }
    # Жёсткие права: только SYSTEM и Administrators (требование sshd для admin-ключей)
    icacls $authKeys /inheritance:r /grant "SYSTEM:F" /grant "BUILTIN\Administrators:F" 2>&1 | Out-Null
} catch {
    Write-Host "  Не удалось установить Mac-ключ в administrators_authorized_keys" -ForegroundColor Yellow
}

# ===== 7. Firewall rules — только для NetBird CIDR =====
Write-Host "[7/7] Firewall rules для $NETBIRD_CIDR..."
$rules = @(
    @{Name = "Claude-Diag-RDP";        Port = 3389},
    @{Name = "Claude-Diag-WinRM-HTTP"; Port = 5985},
    @{Name = "Claude-Diag-WinRM-HTTPS";Port = 5986},
    @{Name = "Claude-Diag-SSH";        Port = 22}
)
foreach ($r in $rules) {
    Get-NetFirewallRule -DisplayName $r.Name -ErrorAction SilentlyContinue | Remove-NetFirewallRule
    New-NetFirewallRule -DisplayName $r.Name `
        -Direction Inbound -Protocol TCP -LocalPort $r.Port `
        -RemoteAddress $NETBIRD_CIDR -Action Allow `
        -Profile Any | Out-Null
}

# ===== Итог =====
Write-Host ""
Write-Host "=== Статус ===" -ForegroundColor Green
& $NETBIRD_EXE status

$nbIp = (Get-NetIPAddress -AddressFamily IPv4 -ErrorAction SilentlyContinue |
         Where-Object {$_.IPAddress -like "100.70.*"} | Select-Object -First 1).IPAddress

Write-Host ""
Write-Host "=== Данные для Claude ===" -ForegroundColor Yellow
Write-Host "Netbird IP : $nbIp"
Write-Host "Hostname   : $env:COMPUTERNAME"
Write-Host "User local : $env:USERNAME"
Write-Host "User claude: $CLAUDE_USER / $CLAUDE_PASS (Administrator)"
Write-Host "RDP        : mstsc /v:$nbIp"
Write-Host "WinRM      : 5985/tcp HTTP, 5986/tcp HTTPS"
Write-Host "SSH        : ssh ${CLAUDE_USER}@$nbIp"
Write-Host ""
Write-Host "Пришли Claude: IP $nbIp + кто это"
