SDK Python și CLI
Pachetul aether365 este SDK-ul Python oficial și interfața de linie de comandă pentru API-ul Aether365. Încapsulează https://api.aether365.io, gestionează autentificarea, despachetează envelope-ul de răspuns și reia automat cererile în caz de erori tranzitorii. Tot ce poți face cu curl poți face și cu SDK-ul sau CLI-ul.
SDK-ul și CLI-ul folosesc o cheie API (ak_live_...) și țintesc endpoint-ul unificat: cererile sunt direcționate automat către regiunea de origine a tenant-ului tău. Vezi Autentificare pentru modul în care funcționează cheile.
Instalare
Pachetul este distribuit intern (nu se află pe PyPI). Instalează-l direct din repository sau dintr-un checkout local.
bash
# From a local checkout of the monorepo
pip install ./packages/cli
# Or with Poetry, from a path
poetry add ./packages/cliEste necesar Python 3.12 sau mai nou. Instalarea pachetului adaugă totodată comanda aether365 în PATH.
Configurare
Atât SDK-ul, cât și CLI-ul citesc aceleași variabile de mediu:
| Variabilă | Rol | Implicit |
|---|---|---|
AETHER365_API_KEY | Cheia ta API (ak_live_...). Obligatorie. | - |
AETHER365_API_URL | Suprascrie URL-ul de bază (de exemplu endpoint-ul de dev). | https://api.aether365.io |
AETHER365_OUTPUT | Formatul de ieșire al CLI-ului: table sau json. | table |
bash
export AETHER365_API_KEY="ak_live_..."Regiunea este automată: API-ul identifică tenant-ul din cheie și redirecționează cererea către regiunea corectă, așa că nu configurezi și nu transmiți niciodată o regiune.
Pornire rapidă: 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")Pornire rapidă: 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-findingsCe poate și ce nu poate face o cheie API
O cheie API este limitată la o suprafață sigură, de citire plus operațiuni. Poate citi datele tale, poate porni și gestiona scan-uri, poate genera rapoarte și poate administra țintele de suprafață de atac. Nu poate efectua acțiuni de control al contului sau de blocare a directorului: gestionarea cheilor API, facturarea, membrii echipei, adăugarea/eliminarea conexiunilor, SSO, aplicarea unui plan de remediere sau scrierile conditional-access/break-glass din AI Pilot. Aceste acțiuni rămân disponibile doar pentru o sesiune autentificată în dashboard. O cerere către o rută nepermisă returnează 403 AUTH_INSUFFICIENT_SCOPE.
Referință de comenzi și metode
Fiecare rând arată aceeași operațiune în trei moduri: curl direct, metoda din SDK și comanda CLI.
Tenant și cont
| Operațiune | curl | SDK | CLI |
|---|---|---|---|
| Profilul tenant-ului | GET /tenants/me | client.tenants.me() | aether365 tenant me |
| Listarea conexiunilor | GET /tenants/me/connections | client.connections.list() | aether365 tenant connections |
| Preferințe de notificare | GET /tenants/me/notifications | client.notifications.get() | aether365 tenant notifications |
| Scan-uri programate | GET /tenants/me/scheduled-scans | client.scheduled_scans.list() | aether365 tenant scheduled-scans |
Scan-uri
| Operațiune | curl | SDK | CLI |
|---|---|---|---|
| Listarea scan-urilor | GET /tenants/me/scans | client.scans.list() | aether365 scan list |
| Pornirea unui scan | POST /tenants/me/scans | client.scans.create("compliance") | aether365 scan run --type compliance |
| Obținerea unui scan | GET /scans/{id} | client.scans.get(id) | aether365 scan get <id> |
| Citirea rezultatelor | GET /scans/{id}/results | client.scans.results(id) | aether365 scan results <id> |
| Anularea unui scan | POST /scans/{id}/cancel | client.scans.cancel(id) | aether365 scan cancel <id> |
| Ascunderea unui scan | PATCH /scans/{id}/hide | client.scans.hide(id) | aether365 scan hide <id> |
| Reafișarea unui scan | PATCH /scans/{id}/unhide | client.scans.unhide(id) | aether365 scan unhide <id> |
| Ștergerea unui scan | DELETE /scans/{id} | client.scans.delete(id) | aether365 scan delete <id> |
Comanda curl pentru pornirea unui 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"}'Rapoarte
| Operațiune | curl | SDK | CLI |
|---|---|---|---|
| Starea raportului | GET /scans/{id}/report | client.reports.status(id) | aether365 report status <id> |
| Generarea unui raport | POST /scans/{id}/report/generate | client.reports.generate(id) | aether365 report generate <id> |
| Listarea rapoartelor | GET /tenants/me/reports | client.reports.list() | aether365 report list |
| Descărcarea unui raport | GET /scans/{id}/report (presigned) | client.reports.download(id, path) | aether365 report download <id> -o out.pdf |
Starea unui raport este una dintre valorile ready, rendering, orgNameRequired sau locked. Generarea unui raport poate consuma un credit de raport (o taxă unică atunci când nu este inclusă nicio alocație): proprietarul cheii acceptă acest lucru apelând generate.
Listarea rapoartelor este paginată prin offset: trimite înapoi meta["nextCursor"] (un offset de rând întreg, sau None pe ultima pagină) ca cursor. client.reports.iter_all() urmărește cursorul pentru tine.
Suprafață de atac
| Operațiune | curl | SDK | CLI |
|---|---|---|---|
| Prezentare generală | GET /tenants/me/attack-surface | client.attack_surface.summary() | aether365 eas summary |
| Istoric | GET /tenants/me/attack-surface/history | client.attack_surface.history() | aether365 eas history |
| Listarea țintelor | GET /tenants/me/attack-surface/targets | client.attack_surface.targets() | aether365 eas targets list |
| Adăugarea unei ținte | POST /tenants/me/attack-surface/targets | client.attack_surface.add_target(host) | aether365 eas targets add <host> |
| Actualizarea unei ținte | PATCH /tenants/me/attack-surface/targets/{id} | client.attack_surface.update_target(id, ...) | aether365 eas targets update <id> --label ... |
| Ștergerea unei ținte | DELETE /tenants/me/attack-surface/targets/{id} | client.attack_surface.remove_target(id) | aether365 eas targets remove <id> |
| Verificarea unei ținte | POST /tenants/me/attack-surface/targets/{id}/verify | client.attack_surface.verify_target(id) | aether365 eas targets verify <id> |
| Rularea unui scan EAS | POST /tenants/me/attack-surface/scan | client.attack_surface.scan() | aether365 eas scan |
Postură, remediere și AI Pilot
| Operațiune | curl | SDK | CLI |
|---|---|---|---|
| Vedere amenințări / riscuri | GET /tenants/me/threats | client.threats.list() | aether365 threats |
| Postura politicilor | GET /tenants/me/policies | client.policies.list() | aether365 policies |
| Capacități de remediere | GET /tenants/me/remediation/capabilities | client.remediation.capabilities() | aether365 remediation capabilities |
| Listarea planurilor de remediere | GET /tenants/me/remediation-plans | client.remediation.plans() | aether365 remediation plans |
| Obținerea unui plan de remediere | GET /tenants/me/remediation-plans/{id} | client.remediation.plan(id) | aether365 remediation plan <id> |
| Elemente remediabile AI Pilot | GET /tenants/me/ai-pilot/remediable | client.ai_pilot.remediable() | aether365 ai-pilot remediable |
| Break-glass AI Pilot | GET /tenants/me/ai-pilot/break-glass | client.ai_pilot.break_glass() | aether365 ai-pilot break-glass |
| Politici CA AI Pilot | GET /tenants/me/ai-pilot/conditional-access | client.ai_pilot.conditional_access() | aether365 ai-pilot conditional-access |
Remedierea este doar în citire pentru cheile API. Aplicarea unui plan nu este expusă: elementele din action-registry ale unui plan pot include patch-uri Conditional-Access / authorization-policy care ar putea bloca un tenant în afara propriului director (AADSTS50097), așa că aplicarea rămâne în dashboard, cu un operator implicat. Vederile conditional-access și break-glass din AI Pilot sunt expuse, din același motiv, tot doar în citire.
Tratarea erorilor și reîncercări
Fiecare eroare de API corespunde unei excepții tipizate, subclasă a 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.")Clientul reîncearcă automat 429 RATE_LIMITED și 503 SERVICE_STARTING (pornirea la rece a bazei de date din dev) cu backoff exponențial, respectând header-ul Retry-After. Erorile de cotă precum SCAN_PLAN_LIMIT_REACHED sunt ridicate imediat: nu sunt reîncercate.
Utilizarea CLI-ului în CI
aether365 scan results <id> --fail-on-findings iese cu codul 2 când există cel puțin un finding eșuat, astfel încât un pipeline își poate condiționa rezultatul de rezultatele scan-ului:
bash
aether365 scan run --type compliance --watch
aether365 scan results "$SCAN_ID" --fail-on-findingsCLI-ul scrie erorile pe stderr și iese cu 1 la orice eroare de API și cu 2 la gate-ul de findings.