Skip to content

SDK Python e CLI

Maintainer: Aether365 Team Destinatari: Sviluppatori e ingegneri DevOps Ambito: Installazione e utilizzo dell'SDK Python ufficiale aether365 e della relativa interfaccia a riga di comando

Il pacchetto aether365 è l'SDK Python ufficiale e l'interfaccia a riga di comando per l'API di Aether365. Incapsula https://api.aether365.io, gestisce l'autenticazione, estrae l'envelope di risposta e riprova automaticamente in caso di errori transitori. Tutto ciò che puoi fare con curl lo puoi fare anche con l'SDK o la CLI.

L'SDK e la CLI usano una chiave API (ak_live_...) e puntano all'endpoint unificato: le richieste vengono instradate automaticamente verso la region di origine del tuo tenant. Consulta Autenticazione per capire come funzionano le chiavi.

Installazione

Il pacchetto è distribuito internamente (non su PyPI). Installalo direttamente dal repository o da un checkout locale.

bash
# From a local checkout of the monorepo
pip install ./packages/cli

# Or with Poetry, from a path
poetry add ./packages/cli

È richiesto Python 3.12 o superiore. L'installazione del pacchetto rende inoltre disponibile il comando aether365 nel tuo PATH.

Configurazione

Sia l'SDK sia la CLI leggono le stesse variabili d'ambiente:

VariabileScopoPredefinito
AETHER365_API_KEYLa tua chiave API (ak_live_...). Obbligatoria.-
AETHER365_API_URLSovrascrive l'URL di base (ad esempio l'endpoint di dev).https://api.aether365.io
AETHER365_OUTPUTFormato di output della CLI: table o json.table
bash
export AETHER365_API_KEY="ak_live_..."

La region è automatica: l'API risolve il tuo tenant dalla chiave e inoltra la richiesta alla region corretta, quindi non devi mai configurare o passare una region.

Avvio rapido: SDK

python
from aether365 import Aether365Client

with Aether365Client() as client:          # reads AETHER365_API_KEY
    tenant = client.tenants.me()
    print(tenant["name"])

    # Trigger a scan and wait for it to finish
    scan = client.scans.create("compliance")
    for snapshot in client.scans.wait(scan["id"]):
        print(snapshot["status"])

    # Read the findings
    findings = client.scans.results(scan["id"], result="Failed")
    print(f"{len(findings)} failed checks")

Avvio rapido: CLI

bash
# Show the authenticated tenant
aether365 tenant me

# Trigger a scan and follow progress until it finishes
aether365 scan run --type compliance --watch

# List scans as JSON
aether365 --output json scan list

# Fail a CI job when a scan has failed findings (exit code 2)
aether365 scan results <SCAN_ID> --fail-on-findings

Cosa può e cosa non può fare una chiave API

Una chiave API è limitata a una superficie sicura, di lettura più operatività. Può leggere i tuoi dati, avviare e gestire scan, generare report e gestire i target della superficie di attacco. Non può eseguire azioni di controllo dell'account o di blocco della directory: gestione delle chiavi API, fatturazione, membri del team, onboarding/offboarding delle connessioni, SSO, applicazione di un piano di remediation o le scritture conditional-access/break-glass di AI Pilot. Queste azioni restano disponibili solo per una sessione autenticata nella dashboard. Una richiesta verso una route non consentita restituisce 403 AUTH_INSUFFICIENT_SCOPE.

Riferimento a comandi e metodi

Ogni riga mostra la stessa operazione in tre modi: curl puro, il metodo dell'SDK e il comando della CLI.

Tenant e account

OperazionecurlSDKCLI
Profilo del tenantGET /tenants/meclient.tenants.me()aether365 tenant me
Elencare le connessioniGET /tenants/me/connectionsclient.connections.list()aether365 tenant connections
Preferenze di notificaGET /tenants/me/notificationsclient.notifications.get()aether365 tenant notifications
Scan pianificatiGET /tenants/me/scheduled-scansclient.scheduled_scans.list()aether365 tenant scheduled-scans

Scan

OperazionecurlSDKCLI
Elencare gli scanGET /tenants/me/scansclient.scans.list()aether365 scan list
Avviare uno scanPOST /tenants/me/scansclient.scans.create("compliance")aether365 scan run --type compliance
Ottenere uno scanGET /scans/{id}client.scans.get(id)aether365 scan get <id>
Leggere i risultatiGET /scans/{id}/resultsclient.scans.results(id)aether365 scan results <id>
Annullare uno scanPOST /scans/{id}/cancelclient.scans.cancel(id)aether365 scan cancel <id>
Nascondere uno scanPATCH /scans/{id}/hideclient.scans.hide(id)aether365 scan hide <id>
Mostrare di nuovo uno scanPATCH /scans/{id}/unhideclient.scans.unhide(id)aether365 scan unhide <id>
Eliminare uno scanDELETE /scans/{id}client.scans.delete(id)aether365 scan delete <id>

Il curl per avviare uno scan:

bash
curl -X POST https://api.aether365.io/tenants/me/scans \
  -H "Authorization: Bearer $AETHER365_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"scanType": "compliance"}'

Report

OperazionecurlSDKCLI
Stato del reportGET /scans/{id}/reportclient.reports.status(id)aether365 report status <id>
Generare un reportPOST /scans/{id}/report/generateclient.reports.generate(id)aether365 report generate <id>
Elencare i reportGET /tenants/me/reportsclient.reports.list()aether365 report list
Scaricare un reportGET /scans/{id}/report (presigned)client.reports.download(id, path)aether365 report download <id> -o out.pdf

Lo stato di un report è uno tra ready, rendering, orgNameRequired o locked. Generare un report può consumare un credito report (un addebito una tantum quando nessuna quota è inclusa): il titolare della chiave lo accetta chiamando generate.

L'elenco dei report è paginato per offset: ripassa meta["nextCursor"] (un offset di riga intero, oppure None sull'ultima pagina) come cursor. client.reports.iter_all() segue il cursore per te.

Superficie di attacco

OperazionecurlSDKCLI
PanoramicaGET /tenants/me/attack-surfaceclient.attack_surface.summary()aether365 eas summary
CronologiaGET /tenants/me/attack-surface/historyclient.attack_surface.history()aether365 eas history
Elencare i targetGET /tenants/me/attack-surface/targetsclient.attack_surface.targets()aether365 eas targets list
Aggiungere un targetPOST /tenants/me/attack-surface/targetsclient.attack_surface.add_target(host)aether365 eas targets add <host>
Aggiornare un targetPATCH /tenants/me/attack-surface/targets/{id}client.attack_surface.update_target(id, ...)aether365 eas targets update <id> --label ...
Eliminare un targetDELETE /tenants/me/attack-surface/targets/{id}client.attack_surface.remove_target(id)aether365 eas targets remove <id>
Verificare un targetPOST /tenants/me/attack-surface/targets/{id}/verifyclient.attack_surface.verify_target(id)aether365 eas targets verify <id>
Eseguire uno scan EASPOST /tenants/me/attack-surface/scanclient.attack_surface.scan()aether365 eas scan

Postura, remediation e AI Pilot

OperazionecurlSDKCLI
Vista minacce / rischiGET /tenants/me/threatsclient.threats.list()aether365 threats
Postura delle policyGET /tenants/me/policiesclient.policies.list()aether365 policies
Capacità di remediationGET /tenants/me/remediation/capabilitiesclient.remediation.capabilities()aether365 remediation capabilities
Elencare i piani di remediationGET /tenants/me/remediation-plansclient.remediation.plans()aether365 remediation plans
Ottenere un piano di remediationGET /tenants/me/remediation-plans/{id}client.remediation.plan(id)aether365 remediation plan <id>
Elementi remediabili AI PilotGET /tenants/me/ai-pilot/remediableclient.ai_pilot.remediable()aether365 ai-pilot remediable
Break-glass AI PilotGET /tenants/me/ai-pilot/break-glassclient.ai_pilot.break_glass()aether365 ai-pilot break-glass
Policy CA AI PilotGET /tenants/me/ai-pilot/conditional-accessclient.ai_pilot.conditional_access()aether365 ai-pilot conditional-access

La remediation è in sola lettura per le chiavi API. L'applicazione di un piano non è esposta: gli elementi dell'action-registry di un piano possono includere patch Conditional-Access / authorization-policy in grado di escludere un tenant dalla propria directory (AADSTS50097), quindi l'applicazione resta nella dashboard con un operatore coinvolto nel processo. Anche le viste conditional-access e break-glass di AI Pilot sono esposte in sola lettura per lo stesso motivo.

Gestione degli errori e retry

Ogni errore dell'API corrisponde a un'eccezione tipizzata, sottoclasse di Aether365Error:

python
from aether365 import Aether365Client
from aether365.exceptions import PermissionError_, PlanLimitError, NotFoundError

with Aether365Client() as client:
    try:
        client.scans.create("compliance")
    except PlanLimitError:
        print("Scan quota reached for this plan.")
    except PermissionError_:
        print("Route not allowed for this key, or plan lacks API access.")
    except NotFoundError:
        print("Resource not found.")

Il client riprova automaticamente 429 RATE_LIMITED e 503 SERVICE_STARTING (il warm-up a freddo del database in dev) con backoff esponenziale, rispettando l'header Retry-After. Gli errori di quota come SCAN_PLAN_LIMIT_REACHED vengono sollevati subito: non vengono ritentati.

Usare la CLI nella CI

aether365 scan results <id> --fail-on-findings termina con codice 2 quando è presente almeno un finding fallito, così una pipeline può vincolare il proprio esito ai risultati dello scan:

bash
aether365 scan run --type compliance --watch
aether365 scan results "$SCAN_ID" --fail-on-findings

La CLI scrive gli errori su stderr e termina con 1 per qualsiasi errore dell'API, con 2 sul gate dei finding.

Questa pagina ti è stata utile?