feat(oracle): kit de instalare la client + corectarea lipsurilor din instalare

Blocul de instalare/migrare Oracle 21c XE, terminat si validat pe VM 302.

Kit de instalare (nou)

  scripts/build-client-kit.ps1 exporta CONTAFIN_ORACLE si FIRMANOUA de pe
  LXC 108 (PDB ROA2, nu ROA - ROA e productia ROA_CENTRAL), le aduce local
  prin cele trei hopuri container -> LXC -> host -> statie, le redenumeste la
  numele pe care le asteapta scripturile si le impacheteaza cu o copie a
  directorului roa-windows-setup. Citeste logul expdp si raporteaza cate
  firme are NOM_FIRME, ca sa nu plece din greseala datele unui client.

  roa-windows-setup/INSTALEAZA.cmd ruleaza pasii 01..08 fara "set /p", deci
  merge si prin SSH - RunAll.cmd nu poate fi rulat neinteractiv. Trateaza
  corect codul 5 de la pasul 03 si se opreste la prima eroare reala.

Corectii

  01-setup-database.ps1 nu mai scrie SQLNET.RECV_TIMEOUT / SEND_TIMEOUT in
  sqlnet.ora. Le hardcoda la 30 s, iar fisierul e citit si de impdp: in timpul
  unui import serverul poate lucra minute fara sa trimita un pachet, clientul
  murea cu ORA-12609 iar scriptul raporta esec pentru un import care se
  terminase cu bine pe server. Reprodus si reparat pe VM 302.

  01-setup-database.ps1: Step 4c optional (-ResetSystemPassword) care curata
  EXPIRED(GRACE) pe SYSTEM in CDB root; ALTER PROFILE opreste expirarile
  viitoare dar nu reseteaza un cont deja intrat in gratie.

  uninstall-roa.sql: retry la DROP USER dupa KILL SESSION, plus un bloc final
  de verdict care numara ce a ramas si iese cu ORA-20900 daca baza nu e
  curata. Pana acum toate sectiunile prindeau exceptiile in WHEN OTHERS si
  scriptul tiparea "UNINSTALL COMPLETE" chiar si cand un user supravietuise,
  iar instalarea urmatoare dadea ORA-31684 in lant. 99-uninstall-roa.ps1
  propaga codul de iesire.

  08-post-install-config.ps1: Step 7b seteaza SMTP_OUT_SERVER si ACL-ul de
  retea pentru CONTAFIN_ORACLE. UTL_MAIL se instala si primea EXECUTE, adica
  destul cat sa compileze, dar nu si cat sa trimita. Privilegiul resolve nu
  accepta interval de porturi (ORA-24244), deci se acorda separat de connect.

  07-verify-installation.ps1: sectiune noua care verifica prezenta lui
  FIRMANOUA.dmp in DMPDIR si o raporteaza ca eroare daca lipseste. Fara el,
  adaugarea unei firme noi pica in DBMS_DATAPUMP.ADD_FILE peste luni de la
  instalare, cand nimeni nu mai leaga eroarea de instalare.

  configure-profile.sql: antetul spune ca e unealta de remediere manuala, nu
  parte din flux; pas nou la final pentru CDB root.

Documentatie

  README-ul roa-windows-setup descrie acum explicit cele doua scenarii -
  instalare pe curat si migrare - de unde se iau DMP-urile sablon, si capcana
  ORA-12609. Handoff-urile de sesiune au fost sterse; ce era durabil in ele a
  intrat in README-uri si in docs/diagnostic-spatiu-clienti.md.

Validare pe VM 302: ciclu complet din kit, instalare pe curat, verificarea
finala "[OK] All checks passed!".

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SzF1hf4aFS1tmJWpPMiwGp
This commit is contained in:
Marius
2026-08-25 18:05:56 +03:00
parent 3a7e751fc1
commit 7fce925349
17 changed files with 3329 additions and 1753 deletions

View File

@@ -0,0 +1,199 @@
# Acces administrativ la un server de client prin Tailscale + SSH
De ce: pentru instalări/migrări Oracle la client avem nevoie de **shell text** pe serverul lui.
RustDesk nu ajută — e sesiune grafică, nu se poate automatiza. Iar la mulți clienți **nu se pot
face forward-uri de porturi pe router**. Tailscale rezolvă exact asta: nodul face doar conexiuni
de ieșire (UDP 41641 pentru NAT traversal, cu cădere pe releu DERP peste 443), deci merge și în
spatele CGNAT, fără nicio regulă pe router.
RustDesk rămâne util pentru **bootstrap-ul de o singură dată** — pașii de mai jos se execută
manual, o dată, prin el.
Primul caz aplicat: **VADECO** — `vadeco-server`, Windows Server 2019 Standard, Tailscale
`100.93.100.75` (2026-08-25).
Context conex: `acces-ssh-chei-angajati.md` (Bitvise pe chei, capcana LSA protection).
---
## 1. Tailscale pe serverul clientului
1. Instalezi Tailscale, te loghezi cu contul ROMFAST.
2. **Run unattended** — din tray → Preferences, sau `tailscale up --unattended`. Fără el,
tailscaled pornește abia după ce cineva face login în Windows; pe un server la care nu se
loghează nimeni, accesul e mort după fiecare reboot.
3. Cere acordul clientului înainte — e VPN pe serverul lui.
## 2. Izolarea nodului: tag + ACL
Fără asta, serverul clientului intră în tailnet ca device obișnuit și **vede toată
infrastructura ROMFAST**. Dacă e vreodată compromis, atacatorul sare mai departe.
Modelul Tailscale, pe scurt:
- ACL-ul e **default-deny**: ce nu e permis explicit, e blocat. Nu scrii interdicții.
- Regulile au **direcție**: `src` = cine deschide conexiunea, `dst` = cine o primește.
- Fiecare device are o **identitate**: fie contul care l-a logat (*user-owned*), fie **tag-ul**.
Aplicarea unui tag **înlocuiește** proprietatea contului, nu se adaugă la ea.
- `autogroup:member` = conturile umane din tailnet. Un device tagged **nu** e member.
### Politica
Admin console → Access controls. UI-ul nou are editor vizual (Definitions / Grants); fișierul
HuJSON brut e la `https://login.tailscale.com/admin/acls/file`.
```hujson
{
"tagOwners": {
"tag:client": ["autogroup:admin"],
},
"acls": [
// device-urile noastre (ne-tagged) ajung oriunde
{ "action": "accept", "src": ["autogroup:member"], "dst": ["*:*"] },
// NU exista nicio regula cu "src": ["tag:client"]
// => serverul clientului nu poate initia nimic in tailnet
],
}
```
> **Obligatoriu:** șterge regula implicită `src: ["*"]` → `dst: ["*:*"]`. Cât timp există,
> `*` include și `tag:client` și toată izolarea e degeaba.
> **Înainte de a șterge**, verifică în Machines că niciun nod ROMFAST nu e deja tagged — ar
> rămâne fără acces.
### Aplicarea tag-ului
Machines → nodul → `...` → **Edit ACL tags** → `tag:client`.
Efecte: proprietatea trece la tag (dispare din „owned by you" — normal), iar **expirarea cheii
se dezactivează automat** la device-urile tagged, deci nu mai trebuie dezactivată manual.
Verificare rapidă în `tailscale status` — nodul apare cu owner `tagged-devices`:
```
100.93.100.75 vadeco-server tagged-devices windows -
```
### Testul de izolare
Rulează **aceeași** comandă înainte și după aplicarea tag-ului, de pe serverul clientului:
```powershell
Test-NetConnection 100.95.55.51 -Port 22 # 100.95.55.51 = LXC 171, are sshd pornit
```
- înainte de tag: `TcpTestSucceeded : True` (nodul e încă member) — confirmă că testul e valid
- după tag: `TcpTestSucceeded : False` (~20s până expiră) — confirmă izolarea
> **Nu folosi `tailscale ping` ca test de ACL.** Lucrează sub filtrul de pachete și poate
> reuși chiar când ACL-ul blochează traficul real. Doar un test TCP pe un port concret spune
> adevărul.
Sensul invers (noi → client) se testează la punctul 4, cu serverul SSH pornit.
> „Dacă nodul nu poate ajunge la noi, cum îmi răspunde SSH-ul?" — ACL-ul reglementează **cine
> deschide** o conexiune, nu direcția octeților. Sesiunea deschisă dinspre noi funcționează
> normal în ambele sensuri; clientul doar nu poate iniția el ceva spre tailnet.
## 3. Serverul SSH pe mașina clientului
Două variante; ambele merg, alege după context.
### Bitvise SSH Server (consecvent cu restul clienților)
Control Panel → **Easy settings**:
- **Windows accounts** → `Administrator` (sau alt cont din grupul Administrators) →
**Public keys** → Import cheia publică. Shell access: terminal + exec.
- Conturile **virtuale** rămân pentru tuneluri (la VADECO: `romfast`, `vadeco`, s2c pe 1521/80).
> **Capcana conturilor virtuale:** implicit sunt mapate pe contul Windows `bvssh_virtualusers`,
> cu privilegii minime. Prin ele obții shell, dar `Get-Service`, `Get-CimInstance` și
> `Get-PSDrive` întorc **gol** — nu erori, ci nimic — și nu se poate instala Oracle. Simptom:
> `whoami` întoarce `<host>\bvssh_virtualusers` și verificarea de admin dă `False`.
>
> Fie folosești un cont Windows real (mai simplu), fie mapezi contul virtual pe un cont admin
> din Advanced settings → Access control → grup → **Windows account** + parolă, plus setarea
> **Elevation** (fără ea, token filtrat de UAC și instalarea Oracle pică pe permisiuni obscure).
> Dezavantaj: parola de admin ajunge stocată în configul Bitvise.
> **Capcana LSA protection:** pe Windows recent (~2025+) cu Bitvise < 9.51, autentificarea cu
> cheie pe **conturi Windows** eșuează (parola merge, cheia nu) — vezi
> `acces-ssh-chei-angajati.md`. Pe Server 2019 nu se aplică. Conturile virtuale nu sunt afectate
> niciodată.
### OpenSSH nativ Windows (alternativă, fără licențiere)
```powershell
Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0
Set-Service -Name sshd -StartupType Automatic
Start-Service sshd
New-ItemProperty -Path "HKLM:\SOFTWARE\OpenSSH" -Name DefaultShell `
-Value "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" `
-PropertyType String -Force
$f = "$env:ProgramData\ssh\administrators_authorized_keys"
Set-Content -Path $f -Encoding ascii -Value 'ssh-ed25519 AAAA... comentariu'
icacls $f /inheritance:r /grant "*S-1-5-32-544:F" /grant "*S-1-5-18:F"
Restart-Service sshd
```
- `administrators_authorized_keys` e fișierul corect pentru conturi **admin** (nu `~/.ssh`).
- ACL-ul de la `icacls` e obligatoriu: cu moștenire de permisiuni, sshd ignoră fișierul **în
tăcere** și vezi doar „Permission denied". SID-urile evită problema pe Windows localizat.
- `-Encoding ascii` intenționat — `utf8` în PowerShell 5.1 scrie BOM, iar sshd nu digeră cheia.
### Firewall
```powershell
Set-NetFirewallRule -Name 'OpenSSH-Server-In-TCP' -RemoteAddress 100.64.0.0/10
# Bitvise:
Get-NetFirewallRule -DisplayName '*Bitvise*' | Set-NetFirewallRule -RemoteAddress 100.64.0.0/10
```
Restricția se face **pe firewall**, nu prin bind pe adresa 100.x în configul serverului SSH: la
boot, interfața Tailscale urcă adesea *după* serviciu, bind-ul eșuează și serverul rămâne mort.
## 4. Testul de acceptanță
De pe orice device ROMFAST din tailnet:
```bash
ssh Administrator@100.93.100.75 "powershell -c (Get-Item 'C:\').FullName"
```
Pentru comenzi mai complexe, ghilimelele se pierd prin lanțul ssh → Bitvise → PowerShell.
Folosește `-EncodedCommand`:
```bash
ENC=$(iconv -f UTF-8 -t UTF-16LE script.ps1 | base64 -w0)
ssh Administrator@100.93.100.75 "powershell -NoProfile -EncodedCommand $ENC"
```
Output-ul PowerShell prin exec vine cu antet `#< CLIXML` și un bloc `<Objs Version=...>` —
se filtrează cu `grep -v`.
## 5. Verificare de mediu înainte de instalarea Oracle
```powershell
"ADMIN = $(([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator))"
"OS = $((Get-CimInstance Win32_OperatingSystem).Caption)"
"RAM_GB = $([math]::Round((Get-CimInstance Win32_ComputerSystem).TotalPhysicalMemory/1GB,1))"
Get-Service | Where-Object {$_.Name -like 'Oracle*'} | Select-Object Name,Status,StartType
Get-PSDrive -PSProvider FileSystem | Select-Object Name,@{n='FreeGB';e={[math]::Round($_.Free/1GB,1)}}
```
`ADMIN = True` e condiția minimă — dacă e `False`, restul câmpurilor vin goale din lipsă de
drepturi, nu pentru că lipsesc, și orice concluzie despre mașină e falsă.
## Revocarea accesului
1. Machines → nodul → **Remove** (îl scoate din tailnet complet); și/sau
2. ștergerea cheii publice din contul de pe serverul SSH.
Pasul 1 e suficient și instantaneu — fără el, ștergerea cheii lasă nodul în rețea.