# ============================================================================
# Synology Permission Discovery - cascadesDS (192.168.0.120)
# ----------------------------------------------------------------------------
# Runs on CS-SERVER via GuruRMM. Uses plink.exe (PuTTY) to SSH into the
# Synology and dump users, groups, share ACLs, and SMB share configs.
#
# Strictly read-only. No writes, no creates, no config changes.
# Output is captured and printed to stdout for the RMM command to return.
#
# Prepared: 2026-04-22 (Cascades Phase 4 Synology retirement prep)
# ============================================================================

$ErrorActionPreference = 'Continue'
$SynoHost = '192.168.0.120'
$SynoUser = 'admin'
# Password injected via command substitution at execution time.
# Do NOT hardcode here - see the submission wrapper.
$SynoPass = '__SYNO_PASSWORD__'

function Section($n) {
    Write-Output ''
    Write-Output ('=' * 72)
    Write-Output "== $n"
    Write-Output ('=' * 72)
}

# ----------------------------------------------------------------------------
Section 'Step 1: Connectivity'
# ----------------------------------------------------------------------------
$reach = Test-NetConnection -ComputerName $SynoHost -Port 22 -InformationLevel Detailed -WarningAction SilentlyContinue
Write-Output "SSH 192.168.0.120:22 reachable: $($reach.TcpTestSucceeded)"
if (-not $reach.TcpTestSucceeded) {
    Write-Output 'ABORT: Cannot reach Synology over SSH. Check pfSense rules + Synology service state.'
    exit 1
}

# ----------------------------------------------------------------------------
Section 'Step 2: Locate plink.exe'
# ----------------------------------------------------------------------------
$plink = $null
$candidates = @(
    'C:\Program Files\PuTTY\plink.exe',
    'C:\Program Files (x86)\PuTTY\plink.exe',
    'C:\Tools\plink.exe'
)
foreach ($c in $candidates) { if (Test-Path $c) { $plink = $c; break } }
if (-not $plink) {
    $plink = (Get-Command plink.exe -ErrorAction SilentlyContinue | Select-Object -First 1).Source
}
if (-not $plink) {
    Write-Output 'ABORT: plink.exe not found. Install PuTTY or point at a plink.exe path.'
    exit 1
}
Write-Output "plink.exe: $plink"
$plinkVer = & $plink -V 2>&1 | Select-Object -First 1
Write-Output "plink version: $plinkVer"

# ----------------------------------------------------------------------------
Section 'Step 3: Pre-accept SSH host key (first run)'
# ----------------------------------------------------------------------------
# plink with -batch refuses unknown host keys. Pre-accept by piping 'y' into a
# non-batch run that does a harmless probe. Subsequent calls use -batch.
$preaccept = 'y' | & $plink -ssh -pw $SynoPass "$SynoUser@$SynoHost" 'echo preaccept-ok' 2>&1
Write-Output ($preaccept -join "`n")

# ----------------------------------------------------------------------------
Section 'Step 4: Synology probe - identity + shares + ACLs'
# ----------------------------------------------------------------------------
# Single heredoc-style payload: one SSH session, captures everything.
# synogroup/synouser/synoacltool/synoshare often need sudo on DSM 7; admin is
# in administrators group but sudo may still prompt. Use 'sudo -S' with the
# password piped via echo to handle the prompt gracefully.
$probe = @'
PASS="__SUDO_PASSWORD__"
sudo_run() { echo "$PASS" | sudo -S -p '' "$@" 2>&1; }

echo "### date ###"
date
echo
echo "### dsm version ###"
cat /etc.defaults/VERSION 2>&1 || cat /etc/VERSION 2>&1
echo
echo "### synogroup --list ###"
sudo_run synogroup --list
echo
echo "### synogroup --enum global ###"
sudo_run synogroup --enum global
echo
echo "### synouser --enum all ###"
sudo_run synouser --enum all
echo
echo "### /volume1/ directory listing ###"
ls -la /volume1/ 2>&1
echo
echo "### /etc/samba/smb.share.conf ###"
sudo_run cat /etc/samba/smb.share.conf 2>&1 | head -200
echo
echo "### synoshare --enum all ###"
sudo_run synoshare --enum all
echo
for S in homes Management SalesDept Server chat Public Culinary IT Receptionist directoryshare Marketing; do
  if [ -d /volume1/$S ]; then
    echo "### synoshare --get $S ###"
    sudo_run synoshare --get "$S"
    echo
    echo "### synoacltool -get /volume1/$S ###"
    sudo_run synoacltool -get "/volume1/$S"
    echo
    echo "### ls -la /volume1/$S (first 15 entries) ###"
    ls -la "/volume1/$S" 2>&1 | head -15
    echo
  fi
done
echo "### NET SESSIONS / SMB share access (smbstatus) ###"
sudo_run smbstatus -p 2>&1 | head -20
echo
echo "### EOF ###"
'@

# Splice in the sudo password (same as SSH password for admin account)
$probe = $probe -replace '__SUDO_PASSWORD__', [regex]::Escape($SynoPass) -replace '\\/','/'
# Proper way: use literal replacement without regex escape tricks
$probe = $probe.Replace('__SUDO_PASSWORD__', $SynoPass)

# Execute via plink; batch mode since host key is now cached
$result = $probe | & $plink -ssh -batch -pw $SynoPass "$SynoUser@$SynoHost" 'bash -s' 2>&1
$result | ForEach-Object { Write-Output $_ }

# ----------------------------------------------------------------------------
Section 'Done'
# ----------------------------------------------------------------------------
Write-Output "Completed at $(Get-Date)"
