Files
2026-06-05 15:00:42 +00:00

9.1 KiB
Raw Permalink Blame History

Grants Audit — ROA_WEB on MARIUSM_AUTO

Date: 2026-04-11 Auditor: oracle-agent (team service-auto-sapt3) Oracle target: 10.0.20.121:1521/ROA Queries run as: CONTAFIN_ORACLE


1. Findings

1.1. ROA_WEB user — DOES NOT EXIST

Source query Result
SELECT * FROM DBA_USERS WHERE USERNAME='ROA_WEB' 0 rows
SELECT * FROM DBA_TAB_PRIVS WHERE GRANTEE='ROA_WEB' 0 rows
SELECT * FROM DBA_SYS_PRIVS WHERE GRANTEE='ROA_WEB' 0 rows
SELECT * FROM DBA_ROLE_PRIVS WHERE GRANTEE='ROA_WEB' 0 rows

No Oracle user ROA_WEB exists on the ROA instance. All four privilege dictionaries are empty for this grantee. Clean slate — no cleanup needed before creation.

1.2. Why CONTAFIN_ORACLE "just works" on MARIUSM_AUTO

USER_ROLE_PRIVS for CONTAFIN_ORACLE:
  RESOURCE, CONNECT, IMP_FULL_DATABASE, DBA, EXP_FULL_DATABASE

CONTAFIN_ORACLE holds the DBA role, so it has SELECT/INSERT/UPDATE/DELETE/EXECUTE ANY TABLE/PROCEDURE. No explicit per-table grants are needed — that's why the Săpt 1 POC (poc/hello_oracle.py) and this audit script both queried MARIUSM_AUTO without any explicit grant work.

Implication for prototype (Săpt 3): we can connect as CONTAFIN_ORACLE directly, skip ROA_WEB entirely, and still validate hypotheses #1 (oracledb + OUT params) and #2 (SP creation + call). Only hypothesis #3 (grant-scoped access via SP, read-only SELECT rejected) requires the scoped ROA_WEB user and is therefore the only reason to ask DBA for the create.

1.3. Required target objects — exist

Object Type Status
MARIUSM_AUTO.AUTO_VMASINICLIENTI VIEW present
MARIUSM_AUTO.DEV_TIP_DEVIZ TABLE present
MARIUSM_AUTO.SP_CREEAZA_COMANDA_PROTOTIP not yet created (task #3)

2. Decision — Two-phase approach

Phase A — Săpt 3 (this week): use CONTAFIN_ORACLE

  • No DBA request needed.
  • Prototype backend module service_auto connects via the existing CONTAFIN_ORACLE credentials (already in backend/.env).
  • Proves hypotheses #1 + #2 (sync-facade + PL/SQL OUT params) end-to-end.
  • backend/.env entry for MARIUSM_AUTO (task #5) points to existing CONTAFIN_ORACLE user; only schema owner changes (MARIUSM_AUTO instead of whichever the login uses for current companies).

Phase B — Săpt 4+ (after prototype): create ROA_WEB and migrate

Needed only to prove hypothesis #3 (grant-scoped access through SP while direct DML/SELECT is rejected). This requires DBA action.


3. Motivare securitate — de ce ROA_WEB cu SP-only

Oracle version (confirmat 2026-04-12): Oracle Database 21c Express Edition. Schema-level grants (23ai+) nu sunt disponibile. Proxy auth (12c+) există dar anulează beneficiul de securitate — vezi §4.

3.1. Attack surface comparison

User conectare SQL injection poate face Attack surface
CONTAFIN_ORACLE (DBA) SELECT/INSERT/DELETE pe orice tabelă, orice schemă maxim
ROA_WEB proxied ca schemă SELECT/INSERT/DELETE pe orice tabelă din schemă mediu
ROA_WEB cu EXECUTE-only pe SP doar apel SP cu parametri validați de SP minim

CONTAFIN_ORACLE conectat din web = punct slab critic: SQL injection prin parametrii unui request HTTP poate exfiltra sau modifica date din orice schemă de pe server.

ROA_WEB cu EXECUTE-only: atacatorul poate cel mult apela SP-urile cu parametri injectați. SP-urile Oracle sunt compilate, nu interpretate — parametrii sunt bind variables, nu SQL concatenat. Suprafața de atac e redusă la logica validată din SP.

3.2. De ce nu proxy authentication

Proxy auth (ALTER USER MARIUSM_AUTO GRANT CONNECT THROUGH ROA_WEB) dă ROA_WEB identitatea completă a schemei proxied → SELECT/INSERT direct pe orice tabelă din acea schemă. Pierde exact beneficiul de securitate pentru care creăm ROA_WEB.


4. Arhitectura multi-tenant scalabilă (Oracle 21c)

4.1. Workflow firmă nouă

Firmele noi se creează via impdp dintr-o schemă template menținută la zi:

impdp system/... SCHEMAS=TEMPLATE_AUTO REMAP_SCHEMA=TEMPLATE_AUTO:FIRMA_NOUA ...

Schema nouă conține deja toate obiectele (SP-uri, view-uri, tabele) din template. Onboarding-ul ROA_WEB = 1 script rulat după impdp:

-- onboarding_roa_web.sql — rulat ca CONTAFIN_ORACLE după impdp pentru fiecare firmă nouă
-- Înlocuiește FIRMA_NOUA cu schema reală
GRANT EXECUTE ON FIRMA_NOUA.SP_CREEAZA_COMANDA_PROTOTIP TO ROA_WEB;
GRANT SELECT  ON FIRMA_NOUA.AUTO_VMASINICLIENTI         TO ROA_WEB;
GRANT SELECT  ON FIRMA_NOUA.DEV_TIP_DEVIZ               TO ROA_WEB;
GRANT SELECT  ON FIRMA_NOUA.CALENDAR                    TO ROA_WEB;
-- CALENDAR: period selector AppHeader (shared/routes/calendar.py)
GRANT SELECT  ON FIRMA_NOUA.DEV_ORDL                    TO ROA_WEB;
-- DEV_ORDL: GET /api/service-auto/comenzi (list comenzi)
GRANT SELECT  ON FIRMA_NOUA.NOM_LUCRARI                 TO ROA_WEB;
-- NOM_LUCRARI: JOIN cu DEV_ORDL pentru nrord (get_comenzi)
-- adaugă orice alte SP/view-uri noi apărute de la ultimul onboarding

4.2. Workflow SP/obiect nou

Când un SP nou se adaugă în toate schemele (ca parte dintr-o migrare), scriptul de migrare are două componente:

Componenta 1migration_YYYYMMDD_sp_noua.sql — rulat per schemă (existent deja):

CREATE OR REPLACE PROCEDURE MARIUSM_AUTO.SP_NOUA (...) AS ...;
-- (repetat pentru fiecare schemă/firmă)

Componenta 2migration_YYYYMMDD_sp_noua_grants.sql — rulat O SINGURĂ DATĂ, loopează automat toate schemele din V_NOM_FIRME:

-- Rulat ca CONTAFIN_ORACLE după ce migration_1 a rulat pe toate schemele
BEGIN
  FOR firm IN (
    SELECT DISTINCT schema
    FROM contafin_oracle.v_nom_firme
    WHERE schema IS NOT NULL
  ) LOOP
    BEGIN
      EXECUTE IMMEDIATE
        'GRANT EXECUTE ON ' || firm.schema || '.SP_NOUA TO ROA_WEB';
    EXCEPTION WHEN OTHERS THEN
      NULL; -- skip dacă schema nu a primit încă migrarea SP (deployment order)
    END;
  END LOOP;
END;
/

V_NOM_FIRME e sursa de adevăr pentru toate schemele active — același tabel folosit de backend pentru login JWT. Orice firmă adăugată în V_NOM_FIRME e inclusă automat la următoarea migrare grants.

4.3. ROA_WEB creation script (one-time, DBA action)

-- Rulat O SINGURĂ DATĂ ca SYS sau CONTAFIN_ORACLE
CREATE USER ROA_WEB IDENTIFIED BY "<REPLACE_WITH_STRONG_PASSWORD_FROM_VAULT>";
GRANT CREATE SESSION TO ROA_WEB;
-- Fără alte privilegii sistem. Accesul la date = exclusiv prin granturi per-obiect.

4.4. Negative test — confirmă hypothesis #3 (scoped access)

-- Conectat ca ROA_WEB (NU CONTAFIN_ORACLE):
SELECT * FROM MARIUSM_AUTO.DEV_ORDL WHERE ROWNUM < 2;                   -- ORA-00942 așteptat
INSERT INTO MARIUSM_AUTO.DEV_ORDL (id_ordl, id_lucrare) VALUES (1, 1); -- ORA-00942 așteptat

-- SP call via bind vars — succes așteptat (ROLLBACK după verificare):
BEGIN
  MARIUSM_AUTO.SP_CREEAZA_COMANDA_PROTOTIP(
    p_id_tip          => 1,
    p_id_masiniclient => <existing_id>,
    p_id_firma        => 110,
    p_solicitari      => 'Test H3',
    p_id_ordl         => :o_id_ordl,
    p_nrord           => :o_nrord
  );
END;
/
ROLLBACK;

4.5. Sumar scalabilitate

Eveniment Acțiune ROA_WEB Cost
ROA_WEB creat (o dată) CREATE USER + GRANT CREATE SESSION O dată
Firmă nouă (impdp) onboarding_roa_web.sql cu schema nouă 1 script per firmă
SP nou în toate schemele migration_YYYYMMDD_sp_noua_grants.sql (loop V_NOM_FIRME) 1 script per migrare
View/tabelă nouă expusă același pattern ca SP 1 script per migrare
Expunere CALENDAR pentru period selector GRANT SELECT {SCHEMA}.CALENDAR TO ROA_WEB per schemă 1 linie per schemă (parte din onboarding §4.1)
Expunere DEV_ORDL + NOM_LUCRARI pentru GET /comenzi GRANT SELECT {SCHEMA}.DEV_ORDL/NOM_LUCRARI TO ROA_WEB per schemă 2 linii per schemă (parte din onboarding §4.1)

4.6. Deploy procedure

Procedura completă de onboarding pentru o schemă/server nou (impdp → granturi → .env → migrații → smoke tests → rollback) este documentată separat în:

deploy-schema-noua.md

Acest audit (§4.1§4.5) stabilește de ce onboarding-ul arată așa; fișierul deploy-schema-noua.md stabilește cum îl execuți pas-cu-pas. Scriptul onboarding_roa_web.sql e referința canonică pentru GRANT-urile per-schemă, cu header self-documenting și placeholder <SCHEMA>.


5. Action items

  • Task #1 — Grants audit completat (2026-04-11)
  • Task #3SP_CREEAZA_COMANDA_PROTOTIP creat + testat cu rollback (2026-04-11)
  • Task #5mariusm_test entry în backend/.env cu CONTAFIN_ORACLE (2026-04-11)
  • Săpt 4 (deferred, DBA action):
    1. CREATE USER ROA_WEB + GRANT CREATE SESSION (§4.3)
    2. Rulează onboarding_roa_web.sql pentru MARIUSM_AUTO (§4.1)
    3. Switch backend/secrets/mariusm_test.oracle_pass + user → ROA_WEB în .env
    4. Rulează test_grants_integration.py → 3 skipped trebuie să devină 3 passed
    5. Rulează negative test din §4.4 manual (SQL Developer sau sqlplus)