Python SDK и CLI
Пакетът aether365 е официалният Python SDK и интерфейс за команден ред за Aether365 API. Той обвива https://api.aether365.io, поема удостоверяването, разопакова обвивката на отговора и автоматично повтаря заявките при преходни грешки. Всичко, което можете да направите с curl, можете да направите и със SDK или CLI.
SDK и CLI използват API ключ (ak_live_...) и се насочват към унифицирания endpoint - заявките автоматично се маршрутизират към домашния регион на вашия tenant. Как работят ключовете е описано в Удостоверяване.
Инсталация
Пакетът се разпространява вътрешно (не е в PyPI). Инсталирайте го директно от репозитория или от локално копие.
bash
# From a local checkout of the monorepo
pip install ./packages/cli
# Or with Poetry, from a path
poetry add ./packages/cliИзисква се Python 3.12 или по-нов. Инсталирането на пакета добавя и командата aether365 към PATH.
Конфигурация
SDK и CLI четат едни и същи променливи на средата:
| Променлива | Предназначение | По подразбиране |
|---|---|---|
AETHER365_API_KEY | Вашият API ключ (ak_live_...). Задължително. | - |
AETHER365_API_URL | Замяна на базовия URL (например dev endpoint-а). | https://api.aether365.io |
AETHER365_OUTPUT | Изходен формат на CLI: table или json. | table |
bash
export AETHER365_API_KEY="ak_live_..."Регионът е автоматичен: API определя вашия tenant по ключа и препраща заявката към правилния регион, така че никога не конфигурирате и не подавате регион.
Бърз старт: 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")Бърз старт: 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Какво може и какво не може един API ключ
API ключът е ограничен до безопасна повърхност: четене плюс оперативни действия. Той може да чете вашите данни, да стартира и управлява сканирания, да генерира отчети и да управлява цели за attack surface. Той не може да извършва действия за контрол на акаунта или действия, които биха заключили директорията - управление на API ключове, фактуриране, членство в екипа, включване и изключване на връзки, SSO, прилагане на план за отстраняване или записите на AI Pilot за conditional access / break-glass. Те остават достъпни само за влязла сесия в таблото. Заявка към непозволен маршрут връща 403 AUTH_INSUFFICIENT_SCOPE.
Справочник на командите и методите
Всеки ред показва една и съща операция по три начина: чист curl, метод от SDK и команда на CLI.
Tenant и акаунт
| Операция | curl | SDK | CLI |
|---|---|---|---|
| Профил на tenant-а | GET /tenants/me | client.tenants.me() | aether365 tenant me |
| Списък на връзките | GET /tenants/me/connections | client.connections.list() | aether365 tenant connections |
| Настройки за известия | GET /tenants/me/notifications | client.notifications.get() | aether365 tenant notifications |
| Планирани сканирания | GET /tenants/me/scheduled-scans | client.scheduled_scans.list() | aether365 tenant scheduled-scans |
Сканирания
| Операция | curl | SDK | CLI |
|---|---|---|---|
| Списък на сканиранията | GET /tenants/me/scans | client.scans.list() | aether365 scan list |
| Стартиране на сканиране | POST /tenants/me/scans | client.scans.create("compliance") | aether365 scan run --type compliance |
| Извличане на сканиране | GET /scans/{id} | client.scans.get(id) | aether365 scan get <id> |
| Четене на резултати | GET /scans/{id}/results | client.scans.results(id) | aether365 scan results <id> |
| Отказ на сканиране | POST /scans/{id}/cancel | client.scans.cancel(id) | aether365 scan cancel <id> |
| Скриване на сканиране | PATCH /scans/{id}/hide | client.scans.hide(id) | aether365 scan hide <id> |
| Показване на сканиране | PATCH /scans/{id}/unhide | client.scans.unhide(id) | aether365 scan unhide <id> |
| Изтриване на сканиране | DELETE /scans/{id} | client.scans.delete(id) | aether365 scan delete <id> |
curl за стартиране на сканиране:
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"}'Отчети
| Операция | curl | SDK | CLI |
|---|---|---|---|
| Статус на отчет | GET /scans/{id}/report | client.reports.status(id) | aether365 report status <id> |
| Генериране на отчет | POST /scans/{id}/report/generate | client.reports.generate(id) | aether365 report generate <id> |
| Списък на отчетите | GET /tenants/me/reports | client.reports.list() | aether365 report list |
| Изтегляне на отчет | GET /scans/{id}/report (presigned) | client.reports.download(id, path) | aether365 report download <id> -o out.pdf |
Статусът на отчета е една от стойностите ready, rendering, orgNameRequired или locked. Генерирането на отчет може да изразходва отчетен кредит (еднократна такса, когато планът не включва квота) - собственикът на ключа се съгласява с това, като извика generate.
Списъкът с отчети е странициран с отместване: подайте обратно meta["nextCursor"] (целочислено отместване на ред или None на последната страница) като cursor. client.reports.iter_all() следва курсора вместо вас.
Attack surface
| Операция | curl | SDK | CLI |
|---|---|---|---|
| Обзор | GET /tenants/me/attack-surface | client.attack_surface.summary() | aether365 eas summary |
| История | GET /tenants/me/attack-surface/history | client.attack_surface.history() | aether365 eas history |
| Списък на целите | GET /tenants/me/attack-surface/targets | client.attack_surface.targets() | aether365 eas targets list |
| Добавяне на цел | POST /tenants/me/attack-surface/targets | client.attack_surface.add_target(host) | aether365 eas targets add <host> |
| Актуализиране на цел | PATCH /tenants/me/attack-surface/targets/{id} | client.attack_surface.update_target(id, ...) | aether365 eas targets update <id> --label ... |
| Изтриване на цел | DELETE /tenants/me/attack-surface/targets/{id} | client.attack_surface.remove_target(id) | aether365 eas targets remove <id> |
| Потвърждаване на цел | POST /tenants/me/attack-surface/targets/{id}/verify | client.attack_surface.verify_target(id) | aether365 eas targets verify <id> |
| Стартиране на EAS сканиране | POST /tenants/me/attack-surface/scan | client.attack_surface.scan() | aether365 eas scan |
Състояние на сигурността, отстраняване и AI Pilot
| Операция | curl | SDK | CLI |
|---|---|---|---|
| Изглед на заплахи и рискове | GET /tenants/me/threats | client.threats.list() | aether365 threats |
| Състояние на политиките | GET /tenants/me/policies | client.policies.list() | aether365 policies |
| Възможности за отстраняване | GET /tenants/me/remediation/capabilities | client.remediation.capabilities() | aether365 remediation capabilities |
| Списък на плановете за отстраняване | GET /tenants/me/remediation-plans | client.remediation.plans() | aether365 remediation plans |
| Извличане на план за отстраняване | GET /tenants/me/remediation-plans/{id} | client.remediation.plan(id) | aether365 remediation plan <id> |
| AI Pilot: подлежащи на отстраняване | GET /tenants/me/ai-pilot/remediable | client.ai_pilot.remediable() | aether365 ai-pilot remediable |
| AI Pilot: break-glass акаунти | GET /tenants/me/ai-pilot/break-glass | client.ai_pilot.break_glass() | aether365 ai-pilot break-glass |
| AI Pilot: CA политики | GET /tenants/me/ai-pilot/conditional-access | client.ai_pilot.conditional_access() | aether365 ai-pilot conditional-access |
Отстраняването е само за четене за API ключове. Прилагането на план не е достъпно през API: елементите на плана от регистъра с действия могат да включват промени по Conditional Access / authorization policy, които биха заключили tenant-а извън собствената му директория (AADSTS50097), затова apply остава в таблото с оператор в процеса. По същата причина conditional-access и break-glass на AI Pilot също са достъпни само за четене.
Обработка на грешки и повторни опити
Всяка грешка на API се съпоставя с типизирано изключение, наследяващо 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.")Клиентът автоматично повтаря 429 RATE_LIMITED и 503 SERVICE_STARTING (загряването на студената база данни в dev) с експоненциален backoff, като спазва хедъра Retry-After. Грешки за квоти като SCAN_PLAN_LIMIT_REACHED се хвърлят веднага - те не се повтарят.
Използване на CLI в CI
aether365 scan results <id> --fail-on-findings завършва с код 2, когато има поне една неуспешна находка, така че pipeline може да използва резултатите от сканирането като gate:
bash
aether365 scan run --type compliance --watch
aether365 scan results "$SCAN_ID" --fail-on-findingsCLI записва грешките в stderr и завършва с код 1 при всяка грешка на API и с код 2 при gate-а за находки.