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-ключ обмежений безпечною поверхнею читання та операційних дій. Він може читати ваші дані, запускати сканування й керувати ними, генерувати звіти та керувати цілями поверхні атаки. Він не може виконувати дії з керування обліковим записом чи блокування каталогу - керування API-ключами, білінг, склад команди, підключення та відключення з'єднань, SSO, застосування плану виправлення або записи AI Pilot для умовного доступу чи 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() проходить курсор за вас.
Поверхня атаки
| Операція | 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 |
| Політики CA в AI Pilot | GET /tenants/me/ai-pilot/conditional-access | client.ai_pilot.conditional_access() | aether365 ai-pilot conditional-access |
Виправлення для API-ключів доступне лише для читання. Застосування плану не відкрито: елементи реєстру дій плану можуть містити патчі Conditional-Access / політики авторизації, які здатні заблокувати tenant'у доступ до власного каталогу (AADSTS50097), тому застосування залишається в панелі керування, де в процесі бере участь оператор. З тієї ж причини AI Pilot conditional-access та break-glass також доступні лише для читання.
Обробка помилок і повторні спроби
Кожна помилка 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) з експоненційною затримкою, враховуючи заголовок Retry-After. Помилки квот, як-от SCAN_PLAN_LIMIT_REACHED, викидаються одразу - вони не повторюються.
Використання CLI в CI
aether365 scan results <id> --fail-on-findings завершується з кодом 2, коли присутня хоча б одна невдала знахідка, тож pipeline може використовувати результати сканування як шлюз:
bash
aether365 scan run --type compliance --watch
aether365 scan results "$SCAN_ID" --fail-on-findingsCLI пише помилки в stderr і завершується з кодом 1 за будь-якої помилки API та з кодом 2, коли спрацьовує шлюз знахідок.