Provisioning idempotente di un'azienda cliente cloud-only (Aruba/Hetzner/AI, no server in sede, PC portatili): - Fase 1: org + classificazione NIS2 (important, sub_threshold_candidate/preliminary) + 3 membri esistenti collegati + organigramma 8 ruoli - Fase 2: 12 asset (NIS2-rilevanti) + 4 fornitori + 10 rischi + gap analysis (80 risposte, 45%) - Fase 3: ISMS model + SoA 111 controlli (27001/27017/27018) + 31 documenti (Manuale/10 politiche/13 procedure/7 istruzioni) - Fase 4: 15 piani di controllo periodici + 5 corsi formazione Documenti AI-redatti con regole fonti-certe (D.Lgs.138/2024 art.23/24/25; 24h/72h/1 mese). Sorgenti in _docs_na/. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
104 lines
6.9 KiB
PHP
104 lines
6.9 KiB
PHP
<?php
|
|
/**
|
|
* build_nuova_agile_p1.php — FASE 1: fondazione "Nuova Agile Technology srl"
|
|
* Org + classificazione NIS2 (important) + membership utenti esistenti + organigramma (org_roles).
|
|
* IDEMPOTENTE (rilanciabile). READ creds da config app (TLS).
|
|
* Uso: docker exec nis2-app php /var/www/nis2-agile/application/cli/build_nuova_agile_p1.php
|
|
*/
|
|
if (PHP_SAPI !== 'cli') { http_response_code(403); exit("CLI only\n"); }
|
|
require_once __DIR__ . '/../config/env.php';
|
|
require_once __DIR__ . '/../config/database.php';
|
|
$pdo = Database::getInstance();
|
|
function ex(PDO $p, string $sql, array $a = []): void { $s=$p->prepare($sql); $s->execute($a); }
|
|
function one(PDO $p, string $sql, array $a = []) { $s=$p->prepare($sql); $s->execute($a); return $s->fetch(PDO::FETCH_ASSOC); }
|
|
$NOW = '2026-06-20 10:30:00';
|
|
|
|
/* ---- 1) Organization (idempotente per name) -------------------------------- */
|
|
$ORG_NAME = 'Nuova Agile Technology srl';
|
|
$org = one($pdo, "SELECT id FROM organizations WHERE name = ?", [$ORG_NAME]);
|
|
$mission = "Software house italiana che sviluppa e fornisce soluzioni applicative ai propri clienti con due modelli: "
|
|
. "(a) prodotti in licenza d'uso installati sui server dei clienti (on-premise presso il cliente); "
|
|
. "(b) servizi SaaS erogati in cloud. Infrastruttura interamente cloud (Aruba, Hetzner) e piattaforme AI; "
|
|
. "nessun server gestito in sede; postazioni di lavoro su PC portatili. "
|
|
. "Organico: 9 dipendenti, 2 collaboratori esterni con P.IVA, Presidente Silvia Garretto.";
|
|
if (!$org) {
|
|
ex($pdo, "INSERT INTO organizations
|
|
(name, sector, entity_type, voluntary_compliance, employee_count, annual_turnover_eur,
|
|
country, city, website, contact_email, subscription_plan, is_active,
|
|
is_autonomous, size_independent_category, has_code_of_ethics, designation_basis,
|
|
self_assessment_status, mission, created_at, updated_at)
|
|
VALUES (?, 'digital_infra', 'important', 0, 9, NULL,
|
|
'IT', NULL, NULL, 'presidenza@agile.software', 'enterprise', 1,
|
|
1, 'none', 0, 'sub_threshold_candidate',
|
|
'preliminary', ?, ?, ?)",
|
|
[$ORG_NAME, $mission, $NOW, $NOW]);
|
|
$orgId = (int)$pdo->lastInsertId();
|
|
echo "ORG creata id=$orgId\n";
|
|
} else {
|
|
$orgId = (int)$org['id'];
|
|
ex($pdo, "UPDATE organizations SET sector='digital_infra', entity_type='important', voluntary_compliance=0,
|
|
employee_count=9, country='IT', subscription_plan='enterprise', is_active=1, is_autonomous=1,
|
|
size_independent_category='none', has_code_of_ethics=0, designation_basis='sub_threshold_candidate',
|
|
self_assessment_status='preliminary', mission=?, updated_at=? WHERE id=?",
|
|
[$mission, $NOW, $orgId]);
|
|
echo "ORG esistente id=$orgId (aggiornata)\n";
|
|
}
|
|
|
|
/* ---- 2) Membership utenti ESISTENTI (no duplicati) -------------------------- */
|
|
// Silvia Garretto=103 (Presidente), Massimo Tagliavini=326 (Resp. SGSI), Simon Fattori=330 (org_admin/IT)
|
|
$members = [
|
|
[103, 'board_member', 1], // Presidente / Alta Direzione (primary)
|
|
[326, 'compliance_manager', 0], // Responsabile SGSI
|
|
[330, 'org_admin', 0], // Amministratore piattaforma / IT security
|
|
];
|
|
foreach ($members as [$uid, $role, $primary]) {
|
|
$u = one($pdo, "SELECT id, full_name FROM users WHERE id=?", [$uid]);
|
|
if (!$u) { echo " ! utente $uid inesistente, salto\n"; continue; }
|
|
$ex = one($pdo, "SELECT id FROM user_organizations WHERE user_id=? AND organization_id=?", [$uid, $orgId]);
|
|
if (!$ex) {
|
|
ex($pdo, "INSERT INTO user_organizations (user_id, organization_id, role, is_primary, joined_at) VALUES (?,?,?,?,?)",
|
|
[$uid, $orgId, $role, $primary, $NOW]);
|
|
echo " membership +{$u['full_name']} ($role)\n";
|
|
} else {
|
|
ex($pdo, "UPDATE user_organizations SET role=?, is_primary=? WHERE id=?", [$role, $primary, $ex['id']]);
|
|
echo " membership ~{$u['full_name']} ($role)\n";
|
|
}
|
|
}
|
|
|
|
/* ---- 3) Organigramma (org_roles) ------------------------------------------- */
|
|
// key, role_name, parent_key, holder_user_id, is_governance_body, description, sort
|
|
$roles = [
|
|
['cda', 'Consiglio di Amministrazione / Presidenza', null, 103, 1, 'Alta Direzione: definisce indirizzo strategico, approva la Politica SGSI e gli obiettivi, assegna risorse, riesame della direzione (ISO 27001 cl.5/9.3). Presidente: Silvia Garretto.', 1],
|
|
['dg', 'Direzione Generale', 'cda', 103, 1, 'Conduzione operativa dell\'azienda; sponsor del Sistema di Gestione; garantisce la leadership e l\'impegno (ISO 27001 cl.5.1).', 2],
|
|
['rsgsi','Responsabile del Sistema di Gestione (RSGSI)','dg', 326, 0, 'Responsabile SGSI/ISMS: mantiene il sistema, coordina valutazione rischi, audit interni, SoA, formazione, gestione NC/azioni correttive. Riferisce alla Direzione.', 3],
|
|
['itsec','Responsabile IT e Sicurezza Tecnica', 'dg', 330, 0, 'Gestione infrastruttura cloud (Aruba, Hetzner), piattaforme AI, sicurezza tecnica, gestione accessi/MFA, backup, patch, monitoraggio, gestione incidenti tecnici.', 4],
|
|
['dpo', 'Referente Protezione Dati (DPO/Privacy)', 'dg', null, 0, 'Presidio GDPR e ISO 27018 (dati personali nel cloud), DPIA, gestione richieste interessati. Ruolo coperto da consulente esterno (da nominare).', 5],
|
|
['dev', 'Team Sviluppo Software / SaaS', 'itsec', null, 0, 'Sviluppo prodotti in licenza e piattaforma SaaS; secure SDLC, gestione vulnerabilità applicative, code review. Composto da dipendenti.', 6],
|
|
['ops', 'Erogazione SaaS & Supporto Clienti', 'itsec', null, 0, 'Esercizio dei servizi SaaS, supporto ai clienti, gestione delle installazioni on-premise presso i clienti.', 7],
|
|
['ext', 'Collaboratori esterni (P.IVA)', 'dg', null, 0, '2 collaboratori esterni/interni con partita IVA: prestazioni specialistiche sotto accordo contrattuale con clausole di riservatezza e sicurezza (ISO 27001 A.5.19/A.6.6).', 8],
|
|
];
|
|
$idByKey = [];
|
|
foreach ($roles as [$key,$name,$pkey,$holder,$gov,$desc,$sort]) {
|
|
$exr = one($pdo, "SELECT id FROM org_roles WHERE organization_id=? AND role_name=?", [$orgId, $name]);
|
|
if (!$exr) {
|
|
ex($pdo, "INSERT INTO org_roles (organization_id, role_name, parent_role_id, holder_user_id, is_governance_body, description, sort_order, created_by, created_at, updated_at)
|
|
VALUES (?,?,?,?,?,?,?,?,?,?)",
|
|
[$orgId, $name, null, $holder, $gov, $desc, $sort, 103, $NOW, $NOW]);
|
|
$rid = (int)$pdo->lastInsertId();
|
|
echo " role + $name\n";
|
|
} else {
|
|
$rid = (int)$exr['id'];
|
|
ex($pdo, "UPDATE org_roles SET holder_user_id=?, is_governance_body=?, description=?, sort_order=?, updated_at=? WHERE id=?",
|
|
[$holder, $gov, $desc, $sort, $NOW, $rid]);
|
|
echo " role ~ $name\n";
|
|
}
|
|
$idByKey[$key] = $rid;
|
|
}
|
|
// seconda passata: parent linking
|
|
foreach ($roles as [$key,$name,$pkey]) {
|
|
if ($pkey && isset($idByKey[$pkey])) ex($pdo, "UPDATE org_roles SET parent_role_id=? WHERE id=?", [$idByKey[$pkey], $idByKey[$key]]);
|
|
}
|
|
echo "ORGANIGRAMMA: ".count($idByKey)." ruoli\n";
|
|
|
|
echo "\nFASE 1 OK — org_id=$orgId\n";
|