Skip to content

SDK Python & CLI

Maintenu par : Aether365 Team Public : Développeurs et ingénieurs DevOps Périmètre : Installation et utilisation du SDK Python officiel aether365 et de son interface en ligne de commande

Le package aether365 est le SDK Python officiel et l'interface en ligne de commande de l'API Aether365. Il encapsule https://api.aether365.io, gère l'authentification, extrait l'enveloppe de réponse et relance automatiquement les requêtes en cas d'échec transitoire. Tout ce que vous pouvez faire avec curl, vous pouvez le faire avec le SDK ou la CLI.

Le SDK et la CLI utilisent une clé API (ak_live_...) et ciblent l'endpoint unifié : les requêtes sont routées automatiquement vers la région d'origine de votre tenant. Consultez Authentification pour comprendre le fonctionnement des clés.

Installation

Le package est distribué en interne (il n'est pas sur PyPI). Installez-le directement depuis le dépôt ou un checkout local.

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 ou plus récent est requis. L'installation du package ajoute aussi la commande aether365 à votre PATH.

Configuration

Le SDK et la CLI lisent les mêmes variables d'environnement :

VariableRôlePar défaut
AETHER365_API_KEYVotre clé API (ak_live_...). Obligatoire.-
AETHER365_API_URLRemplace l'URL de base (par exemple l'endpoint de dev).https://api.aether365.io
AETHER365_OUTPUTFormat de sortie de la CLI : table ou json.table
bash
export AETHER365_API_KEY="ak_live_..."

La région est automatique : l'API identifie votre tenant à partir de la clé et transfère la requête vers la bonne région, vous n'avez donc jamais à configurer ni à passer une région.

Démarrage rapide : 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")

Démarrage rapide : 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

Ce qu'une clé API peut et ne peut pas faire

Une clé API est limitée à une surface sûre, en lecture plus opérationnelle. Elle peut lire vos données, déclencher et gérer des scans, générer des rapports et gérer les cibles de surface d'attaque. Elle ne peut pas effectuer d'actions de contrôle du compte ni de verrouillage d'annuaire : gestion des clés API, facturation, membres de l'équipe, ajout/retrait de connexions, SSO, application d'un plan de remédiation, ou les écritures AI Pilot conditional-access/break-glass. Ces actions restent réservées à une session connectée dans le dashboard. Une requête vers une route non autorisée renvoie 403 AUTH_INSUFFICIENT_SCOPE.

Référence des commandes et méthodes

Chaque ligne montre la même opération de trois façons : curl brut, la méthode SDK et la commande CLI.

Tenant et compte

OpérationcurlSDKCLI
Profil du tenantGET /tenants/meclient.tenants.me()aether365 tenant me
Lister les connexionsGET /tenants/me/connectionsclient.connections.list()aether365 tenant connections
Préférences de notificationGET /tenants/me/notificationsclient.notifications.get()aether365 tenant notifications
Scans planifiésGET /tenants/me/scheduled-scansclient.scheduled_scans.list()aether365 tenant scheduled-scans

Scans

OpérationcurlSDKCLI
Lister les scansGET /tenants/me/scansclient.scans.list()aether365 scan list
Déclencher un scanPOST /tenants/me/scansclient.scans.create("compliance")aether365 scan run --type compliance
Récupérer un scanGET /scans/{id}client.scans.get(id)aether365 scan get <id>
Lire les résultatsGET /scans/{id}/resultsclient.scans.results(id)aether365 scan results <id>
Annuler un scanPOST /scans/{id}/cancelclient.scans.cancel(id)aether365 scan cancel <id>
Masquer un scanPATCH /scans/{id}/hideclient.scans.hide(id)aether365 scan hide <id>
Réafficher un scanPATCH /scans/{id}/unhideclient.scans.unhide(id)aether365 scan unhide <id>
Supprimer un scanDELETE /scans/{id}client.scans.delete(id)aether365 scan delete <id>

Le curl pour déclencher un 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"}'

Rapports

OpérationcurlSDKCLI
Statut du rapportGET /scans/{id}/reportclient.reports.status(id)aether365 report status <id>
Générer un rapportPOST /scans/{id}/report/generateclient.reports.generate(id)aether365 report generate <id>
Lister les rapportsGET /tenants/me/reportsclient.reports.list()aether365 report list
Télécharger un rapportGET /scans/{id}/report (presigned)client.reports.download(id, path)aether365 report download <id> -o out.pdf

Le statut d'un rapport est l'une des valeurs ready, rendering, orgNameRequired ou locked. Générer un rapport peut consommer un crédit de rapport (un paiement ponctuel lorsqu'aucune allocation n'est incluse) : c'est le propriétaire de la clé qui y consent en appelant generate.

La liste des rapports est paginée par offset : renvoyez meta["nextCursor"] (un offset de ligne entier, ou None sur la dernière page) comme paramètre cursor. client.reports.iter_all() suit le curseur pour vous.

Surface d'attaque

OpérationcurlSDKCLI
Vue d'ensembleGET /tenants/me/attack-surfaceclient.attack_surface.summary()aether365 eas summary
HistoriqueGET /tenants/me/attack-surface/historyclient.attack_surface.history()aether365 eas history
Lister les ciblesGET /tenants/me/attack-surface/targetsclient.attack_surface.targets()aether365 eas targets list
Ajouter une ciblePOST /tenants/me/attack-surface/targetsclient.attack_surface.add_target(host)aether365 eas targets add <host>
Mettre à jour une ciblePATCH /tenants/me/attack-surface/targets/{id}client.attack_surface.update_target(id, ...)aether365 eas targets update <id> --label ...
Supprimer une cibleDELETE /tenants/me/attack-surface/targets/{id}client.attack_surface.remove_target(id)aether365 eas targets remove <id>
Vérifier une ciblePOST /tenants/me/attack-surface/targets/{id}/verifyclient.attack_surface.verify_target(id)aether365 eas targets verify <id>
Lancer un scan EASPOST /tenants/me/attack-surface/scanclient.attack_surface.scan()aether365 eas scan

Posture, remédiation et AI Pilot

OpérationcurlSDKCLI
Vue menaces / risquesGET /tenants/me/threatsclient.threats.list()aether365 threats
Posture des politiquesGET /tenants/me/policiesclient.policies.list()aether365 policies
Capacités de remédiationGET /tenants/me/remediation/capabilitiesclient.remediation.capabilities()aether365 remediation capabilities
Lister les plans de remédiationGET /tenants/me/remediation-plansclient.remediation.plans()aether365 remediation plans
Récupérer un plan de remédiationGET /tenants/me/remediation-plans/{id}client.remediation.plan(id)aether365 remediation plan <id>
Éléments remédiables 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
Politiques CA AI PilotGET /tenants/me/ai-pilot/conditional-accessclient.ai_pilot.conditional_access()aether365 ai-pilot conditional-access

La remédiation est en lecture seule pour les clés API. L'application d'un plan n'est pas exposée : les éléments de l'action-registry d'un plan peuvent inclure des patchs Conditional-Access / authorization-policy susceptibles de verrouiller un tenant hors de son propre annuaire (AADSTS50097), donc l'application reste dans le dashboard avec un opérateur dans la boucle. Les vues AI Pilot conditional-access et break-glass sont, pour la même raison, exposées elles aussi en lecture seule.

Gestion des erreurs et retries

Chaque erreur d'API correspond à une exception typée, sous-classe de 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.")

Le client relance automatiquement 429 RATE_LIMITED et 503 SERVICE_STARTING (le démarrage à froid de la base de données en dev) avec un backoff exponentiel, en respectant l'en-tête Retry-After. Les erreurs de quota comme SCAN_PLAN_LIMIT_REACHED sont levées immédiatement : elles ne sont pas retentées.

Utiliser la CLI en CI

aether365 scan results <id> --fail-on-findings se termine avec le code 2 dès qu'un finding en échec est présent, ce qui permet à un pipeline de conditionner son résultat aux résultats du scan :

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

La CLI écrit les erreurs sur stderr et se termine avec 1 sur toute erreur d'API, 2 sur le gate des findings.

Cette page vous a-t-elle été utile ?