SDK Pythona i CLI
Autor: Zespół Aether365 Odbiorcy: Programiści i inżynierowie DevOps Zakres: Instalacja i korzystanie z oficjalnego SDK Pythona aether365 oraz interfejsu wiersza poleceń
Pakiet aether365 to oficjalny SDK Pythona i interfejs wiersza poleceń dla API Aether365. Opakowuje https://api.aether365.io, obsługuje uwierzytelnianie, rozpakowuje kopertę odpowiedzi i automatycznie ponawia żądania przy przejściowych błędach. Wszystko, co da się zrobić przez curl, da się też zrobić przez SDK lub CLI.
SDK i CLI używają klucza API (ak_live_...) i kierują żądania na ujednolicony endpoint - zapytania trafiają automatycznie do regionu macierzystego Twojego tenanta. Jak działają klucze, opisuje strona Uwierzytelnianie.
Instalacja
Pakiet jest dystrybuowany wewnętrznie (nie przez PyPI). Zainstaluj go bezpośrednio z repozytorium lub z lokalnej kopii.
bash
# From a local checkout of the monorepo
pip install ./packages/cli
# Or with Poetry, from a path
poetry add ./packages/cliWymagany jest Python 3.12 lub nowszy. Instalacja pakietu dodaje też polecenie aether365 do PATH.
Konfiguracja
Zarówno SDK, jak i CLI czytają te same zmienne środowiskowe:
| Zmienna | Przeznaczenie | Domyślnie |
|---|---|---|
AETHER365_API_KEY | Twój klucz API (ak_live_...). Wymagany. | - |
AETHER365_API_URL | Nadpisanie bazowego URL (np. endpointu dev). | https://api.aether365.io |
AETHER365_OUTPUT | Format wyjścia CLI: table lub json. | table |
bash
export AETHER365_API_KEY="ak_live_..."Region jest automatyczny: API rozpoznaje tenanta po kluczu i przekazuje żądanie do właściwego regionu, więc regionu nigdy nie konfigurujesz ani nie przekazujesz.
Szybki start: 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")Szybki start: 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-findingsCo klucz API może, a czego nie
Klucz API ma bezpieczny zakres: odczyt plus operacje bieżące. Może czytać Twoje dane, uruchamiać skany i nimi zarządzać, generować raporty oraz zarządzać celami attack surface. Nie może wykonywać działań kontrolujących konto ani grożących zablokowaniem katalogu - zarządzania kluczami API, rozliczeń, członkostwa w zespole, podłączania/odłączania połączeń, SSO, zastosowania planu remediacji ani zapisów AI Pilot dotyczących conditional access / break-glass. Te operacje pozostają dostępne wyłącznie w zalogowanej sesji w dashboardzie. Żądanie do niedozwolonej trasy zwraca 403 AUTH_INSUFFICIENT_SCOPE.
Przegląd poleceń i metod
Każdy wiersz pokazuje tę samą operację na trzy sposoby: surowy curl, metoda SDK i polecenie CLI.
Tenant i konto
| Operacja | curl | SDK | CLI |
|---|---|---|---|
| Pobranie profilu tenanta | GET /tenants/me | client.tenants.me() | aether365 tenant me |
| Lista połączeń | GET /tenants/me/connections | client.connections.list() | aether365 tenant connections |
| Preferencje powiadomień | GET /tenants/me/notifications | client.notifications.get() | aether365 tenant notifications |
| Zaplanowane skany | GET /tenants/me/scheduled-scans | client.scheduled_scans.list() | aether365 tenant scheduled-scans |
Skany
| Operacja | curl | SDK | CLI |
|---|---|---|---|
| Lista skanów | GET /tenants/me/scans | client.scans.list() | aether365 scan list |
| Uruchomienie skanu | POST /tenants/me/scans | client.scans.create("compliance") | aether365 scan run --type compliance |
| Pobranie skanu | GET /scans/{id} | client.scans.get(id) | aether365 scan get <id> |
| Odczyt wyników | GET /scans/{id}/results | client.scans.results(id) | aether365 scan results <id> |
| Anulowanie skanu | POST /scans/{id}/cancel | client.scans.cancel(id) | aether365 scan cancel <id> |
| Ukrycie skanu | PATCH /scans/{id}/hide | client.scans.hide(id) | aether365 scan hide <id> |
| Przywrócenie skanu | PATCH /scans/{id}/unhide | client.scans.unhide(id) | aether365 scan unhide <id> |
| Usunięcie skanu | DELETE /scans/{id} | client.scans.delete(id) | aether365 scan delete <id> |
Wywołanie curl uruchamiające skan:
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"}'Raporty
| Operacja | curl | SDK | CLI |
|---|---|---|---|
| Status raportu | GET /scans/{id}/report | client.reports.status(id) | aether365 report status <id> |
| Wygenerowanie raportu | POST /scans/{id}/report/generate | client.reports.generate(id) | aether365 report generate <id> |
| Lista raportów | GET /tenants/me/reports | client.reports.list() | aether365 report list |
| Pobranie pliku raportu | GET /scans/{id}/report (presigned) | client.reports.download(id, path) | aether365 report download <id> -o out.pdf |
Status raportu to jedna z wartości: ready, rendering, orgNameRequired lub locked. Wygenerowanie raportu może zużyć kredyt raportowy (jednorazowa opłata, gdy plan nie zawiera przydziału) - właściciel klucza wyraża na to zgodę, wywołując generate.
Lista raportów jest stronicowana offsetowo: przekaż meta["nextCursor"] (całkowitoliczbowy offset wiersza albo None na ostatniej stronie) z powrotem jako cursor. client.reports.iter_all() podąża za kursorem za Ciebie.
Attack surface
| Operacja | curl | SDK | CLI |
|---|---|---|---|
| Podsumowanie | GET /tenants/me/attack-surface | client.attack_surface.summary() | aether365 eas summary |
| Historia | GET /tenants/me/attack-surface/history | client.attack_surface.history() | aether365 eas history |
| Lista celów | GET /tenants/me/attack-surface/targets | client.attack_surface.targets() | aether365 eas targets list |
| Dodanie celu | POST /tenants/me/attack-surface/targets | client.attack_surface.add_target(host) | aether365 eas targets add <host> |
| Aktualizacja celu | PATCH /tenants/me/attack-surface/targets/{id} | client.attack_surface.update_target(id, ...) | aether365 eas targets update <id> --label ... |
| Usunięcie celu | DELETE /tenants/me/attack-surface/targets/{id} | client.attack_surface.remove_target(id) | aether365 eas targets remove <id> |
| Weryfikacja celu | POST /tenants/me/attack-surface/targets/{id}/verify | client.attack_surface.verify_target(id) | aether365 eas targets verify <id> |
| Uruchomienie skanu EAS | POST /tenants/me/attack-surface/scan | client.attack_surface.scan() | aether365 eas scan |
Postawa bezpieczeństwa, remediacja i AI Pilot
| Operacja | curl | SDK | CLI |
|---|---|---|---|
| Widok zagrożeń i ryzyka | GET /tenants/me/threats | client.threats.list() | aether365 threats |
| Postawa polityk | GET /tenants/me/policies | client.policies.list() | aether365 policies |
| Możliwości remediacji | GET /tenants/me/remediation/capabilities | client.remediation.capabilities() | aether365 remediation capabilities |
| Lista planów remediacji | GET /tenants/me/remediation-plans | client.remediation.plans() | aether365 remediation plans |
| Pobranie planu remediacji | GET /tenants/me/remediation-plans/{id} | client.remediation.plan(id) | aether365 remediation plan <id> |
| AI Pilot: elementy do naprawy | GET /tenants/me/ai-pilot/remediable | client.ai_pilot.remediable() | aether365 ai-pilot remediable |
| AI Pilot: konta break-glass | GET /tenants/me/ai-pilot/break-glass | client.ai_pilot.break_glass() | aether365 ai-pilot break-glass |
| AI Pilot: polityki CA | GET /tenants/me/ai-pilot/conditional-access | client.ai_pilot.conditional_access() | aether365 ai-pilot conditional-access |
Remediacja jest dla kluczy API tylko do odczytu. Zastosowanie planu nie jest udostępnione: pozycje planu z rejestru akcji mogą zawierać poprawki Conditional Access / authorization policy, które odcięłyby tenanta od jego własnego katalogu (AADSTS50097), więc apply pozostaje w dashboardzie, z operatorem w pętli decyzyjnej. Z tego samego powodu conditional-access i break-glass w AI Pilot są również dostępne wyłącznie do odczytu.
Obsługa błędów i ponawianie
Każdy błąd API mapuje się na typowany wyjątek dziedziczący po 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.")Klient automatycznie ponawia 429 RATE_LIMITED i 503 SERVICE_STARTING (rozgrzewanie zimnej bazy w środowisku dev) z wykładniczym backoffem, respektując nagłówek Retry-After. Błędy limitów, takie jak SCAN_PLAN_LIMIT_REACHED, są zgłaszane natychmiast - nie są ponawiane.
Użycie CLI w CI
aether365 scan results <id> --fail-on-findings kończy się kodem 2, gdy istnieje jakiekolwiek nieudane znalezisko, więc pipeline może uzależnić przejście od wyników skanu:
bash
aether365 scan run --type compliance --watch
aether365 scan results "$SCAN_ID" --fail-on-findingsCLI zapisuje błędy na stderr i kończy się kodem 1 przy dowolnym błędzie API, a kodem 2 na bramce znalezisk.