Connettore di discovery cloud AWS parallelo all'agente di rete: elenca EC2/RDS/S3 via AWS CLI (zero dipendenze npm) + flussi SG ingress aperti verso 0.0.0.0/0, mappa in asset NIS2 e POSTa a /api/services/assets-ingest (source=aws). Config via env (RESOURCES/AWS_REGION/MAX_ITEMS/DRY_RUN), gestione errori robusta (aws assente o comando fallito → messaggio chiaro). README aggiornato con sezione AWS + permessi IAM read-only minimi. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
129 lines
5.7 KiB
Markdown
129 lines
5.7 KiB
Markdown
# Agente di Discovery NIS2 (`discovery-agent.mjs`)
|
|
|
|
Mappa automaticamente la rete del cliente e **auto-popola** l'Inventario NIS2
|
|
(asset + scoring rilevanza NIS2 + Mappa Dipendenze + flussi di rete ID.AM-03).
|
|
Node 18+, **nessuna dipendenza** (usa `fetch`/`net`/`dns` nativi).
|
|
|
|
## Come funziona
|
|
1. In NIS2 (utente org_admin): **Connettori Discovery → Nuovo connettore** → copia l'**API key** (mostrata una sola volta).
|
|
2. Esegui l'agente **dentro la rete da mappare** (un host qualunque del cliente):
|
|
```bash
|
|
NIS2_API_KEY=nis2_xxxxxxxx TARGETS=192.168.1.0/24 node discovery-agent.mjs
|
|
```
|
|
3. L'agente scansiona i target (TCP-connect, no root), deduce host/porte/tipo asset e li
|
|
invia a `POST /api/services/assets-ingest`. NIS2 fa dedup (per IP), scoring e tracciamento
|
|
del run (visibile nel dettaglio del connettore).
|
|
|
|
## Variabili
|
|
| Var | Default | Note |
|
|
|---|---|---|
|
|
| `NIS2_API_KEY` | — (obbligatoria) | chiave del connettore |
|
|
| `NIS2_API_URL` | `https://nis2.agile.software` | |
|
|
| `TARGETS` | — (obbligatoria) | CIDR/IP separati da virgola: `192.168.1.0/24,10.0.0.5` |
|
|
| `PORTS` | `22,80,443,445,3306,3389,5432,8080,8443` | porte TCP da sondare |
|
|
| `SOURCE` | `network` | etichetta provenienza (`network`/`aws`/…) |
|
|
| `TIMEOUT_MS` | `400` | timeout per porta |
|
|
| `MAX_HOSTS` | `1024` | tetto host per esecuzione |
|
|
| `CONCURRENCY` | `64` | socket paralleli |
|
|
| `DRY_RUN` | — | `1` = non invia, stampa solo l'anteprima JSON |
|
|
|
|
## Esempi
|
|
```bash
|
|
# Anteprima senza inviare
|
|
DRY_RUN=1 TARGETS=10.0.0.0/28 node discovery-agent.mjs
|
|
|
|
# Scansione + invio, porte e timeout custom
|
|
NIS2_API_KEY=nis2_xxx TARGETS=192.168.10.0/24 PORTS=22,80,443 TIMEOUT_MS=600 node discovery-agent.mjs
|
|
|
|
# Pianificato (cron, ogni notte)
|
|
0 2 * * * NIS2_API_KEY=nis2_xxx TARGETS=192.168.0.0/23 node /opt/nis2/discovery-agent.mjs >> /var/log/nis2-discovery.log 2>&1
|
|
```
|
|
|
|
## Più connettori per azienda
|
|
Crea un connettore per ciascuna sorgente (es. *Rete sede Roma*, *Rete sede Modena*, *AWS prod*):
|
|
ognuno ha la sua API key e il suo storico run. L'agente di rete copre i CIDR; per il cloud
|
|
(`aws`/`azure`/`gcp`) si estende lo stesso schema elencando le istanze via SDK del provider e
|
|
inviandole con lo stesso formato `assets-ingest` (`source: "aws"`, `external_ref: "aws:i-..."`).
|
|
|
|
## Sicurezza
|
|
- L'API key ha **solo** scope `ingest:assets` (può solo aggiungere asset/flussi alla **sua** org).
|
|
- Esegui l'agente da un host fidato; ruota la chiave dal connettore se compromessa (**Rigenera chiave**).
|
|
- Scansiona **solo reti di tua proprietà / autorizzate**.
|
|
|
|
---
|
|
|
|
# Connettore AWS (`discovery-agent-aws.mjs`)
|
|
|
|
Variante **cloud** dell'agente: invece di scansionare CIDR via TCP, elenca le risorse
|
|
di un account **AWS** (EC2 / RDS / S3 + Security Group) tramite la **AWS CLI** e le
|
|
mappa in asset NIS2, inviandole allo stesso `POST /api/services/assets-ingest`
|
|
(`source: "aws"`). Node 18+, **nessuna dipendenza** npm.
|
|
|
|
## Mappatura risorse → asset
|
|
| Risorsa AWS | `asset_type` | `external_ref` |
|
|
|---|---|---|
|
|
| EC2 instance | `server` | `aws:ec2:<instance-id>` |
|
|
| RDS db instance | `database` | `aws:rds:<db-id>` |
|
|
| S3 bucket | `storage` | `aws:s3:<bucket>` |
|
|
| Security Group ingress aperta verso `0.0.0.0/0` / `::/0` | *flusso* `inbound` | `aws:sg:<sg-id>:<port>` |
|
|
|
|
`name` EC2 = tag `Name` (fallback all'instance-id); `ip_address` = IP privato (o pubblico
|
|
se manca); `internet_facing=1` se l'istanza/RDS ha un endpoint pubblico. La criticità è
|
|
un'euristica (tipo/stato istanza, RDS pubblico). Lo **scoring rilevanza NIS2** lo calcola
|
|
comunque il backend.
|
|
|
|
## Come funziona
|
|
1. In NIS2: **Connettori Discovery → Nuovo connettore** (es. *AWS prod*) → copia l'**API key**.
|
|
2. Configura le **credenziali AWS read-only** sull'host (catena standard: `AWS_PROFILE`,
|
|
`AWS_ACCESS_KEY_ID`/`AWS_SECRET_ACCESS_KEY`, profilo `~/.aws/credentials`, ecc.).
|
|
3. Esegui:
|
|
```bash
|
|
NIS2_API_KEY=nis2_xxxxxxxx AWS_REGION=eu-south-1 node discovery-agent-aws.mjs
|
|
```
|
|
|
|
## Variabili
|
|
| Var | Default | Note |
|
|
|---|---|---|
|
|
| `NIS2_API_KEY` | — (obbligatoria, tranne in `DRY_RUN`) | chiave del connettore |
|
|
| `NIS2_API_URL` | `https://nis2.agile.software` | |
|
|
| `SOURCE` | `aws` | etichetta provenienza |
|
|
| `RESOURCES` | `ec2,rds,s3` | csv: quali risorse raccogliere (i flussi SG richiedono `ec2`) |
|
|
| `AWS_REGION` | — (config CLI) | regione AWS (passata a `--region`) |
|
|
| `MAX_ITEMS` | `2000` | tetto asset per esecuzione |
|
|
| `DRY_RUN` | — | `1` = non invia, stampa solo l'anteprima JSON |
|
|
|
|
Le credenziali AWS **non** sono variabili di questo script: usa la catena standard della
|
|
AWS CLI (`aws sts get-caller-identity` per verificarle).
|
|
|
|
## Esempi
|
|
```bash
|
|
# Anteprima (non invia) solo EC2
|
|
DRY_RUN=1 RESOURCES=ec2 node discovery-agent-aws.mjs
|
|
|
|
# Inventario completo EC2+RDS+S3 di una regione
|
|
NIS2_API_KEY=nis2_xxx AWS_REGION=eu-south-1 node discovery-agent-aws.mjs
|
|
|
|
# Solo storage
|
|
NIS2_API_KEY=nis2_xxx RESOURCES=s3 node discovery-agent-aws.mjs
|
|
```
|
|
|
|
## Permessi IAM minimi (read-only)
|
|
Policy con sole letture (nessuna `Get`/lettura di oggetti, solo metadati/inventario):
|
|
```json
|
|
{
|
|
"Version": "2012-10-17",
|
|
"Statement": [
|
|
{ "Effect": "Allow", "Action": ["ec2:Describe*", "rds:Describe*", "s3:ListAllMyBuckets"], "Resource": "*" }
|
|
]
|
|
}
|
|
```
|
|
- `ec2:Describe*` → EC2 instances + Security Group (flussi ingress).
|
|
- `rds:Describe*` → RDS db instances.
|
|
- `s3:ListAllMyBuckets` → elenco bucket S3 (solo nomi, nessun contenuto).
|
|
|
|
## Note operative
|
|
- Se la AWS CLI non è installata, o un comando fallisce (credenziali/permessi), l'agente
|
|
termina con un **messaggio chiaro** (no stacktrace). I flussi Security Group sono opzionali:
|
|
se la `describe-security-groups` fallisce, l'agente continua con i soli asset.
|
|
- Crea un connettore distinto per account/regione: ognuno ha la sua API key e il suo storico run.
|