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>
5.7 KiB
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
- In NIS2 (utente org_admin): Connettori Discovery → Nuovo connettore → copia l'API key (mostrata una sola volta).
- Esegui l'agente dentro la rete da mappare (un host qualunque del cliente):
NIS2_API_KEY=nis2_xxxxxxxx TARGETS=192.168.1.0/24 node discovery-agent.mjs - 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
# 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
- In NIS2: Connettori Discovery → Nuovo connettore (es. AWS prod) → copia l'API key.
- Configura le credenziali AWS read-only sull'host (catena standard:
AWS_PROFILE,AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY, profilo~/.aws/credentials, ecc.). - Esegui:
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
# 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):
{
"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-groupsfallisce, 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.