Aller au contenu
Avanet
Connexion

Gérer en toute sécurité les identifiants API Sophos Central

Sophos Fusion (anciennement Sophos Central) peut être automatisé par API et intégré à des plateformes SIEM, RMM, de reporting ou d’assurance. On n’utilise pas de compte administrateur personnel à cette fin, mais des API Credentials constitués d’un Client ID et d’un Client Secret.

Ces identifiants sont des identités de machine. Toute personne qui possède le secret peut exécuter les actions API autorisées par le rôle de service principal attribué. Un secret doit donc être traité comme un mot de passe privilégié et ne doit jamais se trouver dans un script, un ticket, un e-mail ou un dépôt Git.

Distinguer API Credentials et Integration Credential Manager

Sous Global Settings > Access Control, deux sections portent des noms proches :

SectionFonction
API CredentialsIdentité technique avec laquelle une application appelle les API Sophos Central
Integration Credential ManagerIdentifiants de produits tiers utilisés par Sophos pour des intégrations telles que Data Ingestion ou Response Actions

Pour un script interne, une requête SIEM ou un client API, on crée des API Credentials. Les identifiants d’un produit tiers que Sophos Fusion doit lui-même utiliser appartiennent en revanche à l’Integration Credential Manager.

Toutes les automatisations ne nécessitent pas des API Credentials générales : les utilisateurs et groupes se synchronisent via un service d’annuaire, et les logiciels peuvent être déployés par un script d’installation exécuté localement sur chaque appareil. On ne crée une identité API pour AD Sync que si le processus prévu l’exige, avec le seul rôle Service Principal Directory Sync.

Conditions préalables et responsabilité

Seul un Super Admin peut créer et gérer des API Credentials. L’application s’authentifie avec ses propres Client ID et Client Secret, et non avec le compte personnel de l’administrateur.

Avant la création, on documente la finalité, le propriétaire, le système cible, le rôle requis, la date d’expiration et le contact d’urgence. Chaque application et chaque environnement disposent de leur propre identifiant. Un secret partagé entre un script de sauvegarde, un SIEM et un prestataire externe empêche une révocation ciblée et complique l’analyse des causes.

Choisir le rôle de service principal approprié

Sophos propose plusieurs rôles :

  • Service Principal Read-Only lit les données du tenant, mais ne peut ni les modifier ni exécuter de requêtes Live Discover.
  • Service Principal Management peut consulter, créer, modifier et supprimer des utilisateurs et groupes d’utilisateurs, consulter et traiter des alertes, interroger les endpoints et déclencher des actions telles qu’une analyse, ainsi qu’afficher et modifier les paramètres globaux d’Endpoint Protection. Ce rôle gère aussi les administrateurs, les rôles et les Security Policies, mais n’a pas accès aux requêtes Live Discover.
  • Service Principal Forensics crée, affiche, exécute et supprime des requêtes Live Discover.
  • Service Principal Directory Sync est exclusivement destiné à la synchronisation Active Directory et ne peut effectuer aucune autre tâche API.
  • Service Principal Firewall limite l’identité à l’administration des firewalls et n’autorise aucune autre tâche de l’API Central.
  • Service Principal Audit Log permet aux applications externes, outils SIEM et scripts d’intégration de récupérer les événements d’Audit Log avec un accès en lecture seule.
  • Service Principal Super Admin possède des droits étendus de lecture, d’écriture et de suppression ainsi que l’accès aux requêtes.

On commence toujours par le rôle le plus limité. Une intégration de reporting ou de cyberassurance reçoit Read-Only. AD Sync reçoit le rôle prévu à cet effet. Super Admin ne s’utilise que lorsque les endpoints API documentés exigent réellement des droits d’écriture étendus et qu’aucun rôle plus restreint ne convient.

Créer un identifiant

Connectez-vous à fusion.sophos.com, puis ouvrez Global Settings > Access Control > API Credentials. Lors du premier accès, il faut accepter les conditions d’utilisation.

  1. Ouvrir Add Credential.
  2. Saisir un nom explicite et une description indiquant l’application, l’environnement et le propriétaire.
  3. Sélectionner le rôle de service principal minimal nécessaire.
  4. Créer l’identifiant et récupérer immédiatement le Client ID et le Client Secret.
  5. Déposer le secret dans le coffre-fort de secrets de l’entreprise et effacer les copies temporaires.

Le Client Secret n’est affiché qu’une seule fois. Il est impossible de le révéler à nouveau par la suite. S’il est perdu, on ne restaure pas le secret existant : on crée un nouvel identifiant, puis on supprime l’ancien après une migration réussie.

Contrat API, authentification et région

Le processus suivant décrit les API produit REST régionales Sophos Central : l’hôte Identity global émet le jeton OAuth ; l’hôte global whoami identifie l’identifiant. Pour les contrats REST à routage régional, les appels produit du tenant utilisent ensuite l’hôte renvoyé pour ce tenant. Les destinations HTTPS suivantes doivent être accessibles depuis le poste d’administration ou le système d’intégration à cet effet :

  • POST https://id.sophos.com/api/v2/oauth2/token pour OAuth2;
  • GET https://api.central.sophos.com/whoami/v1 pour identifier et découvrir l’hôte;
  • GET https://api.central.sophos.com/partner/v1/tenants pour les identifiants partenaire;
  • GET https://api.central.sophos.com/organization/v1/tenants pour les identifiants Enterprise;
  • l’hôte HTTPS renvoyé dans apiHosts.dataRegion ou le champ tenant apiHost pour l’API produit.

Ne pas deviner une URL régionale ni la copier d’un tableau statique. Pour ce processus REST, accepter uniquement l’hôte HTTPS complet renvoyé, puis ajouter les chemins produit. Le contrôle d’hôte du script ci-dessous s’applique à ce contrat, pas universellement à toutes les API Sophos.

La Search GraphQL API possède son propre contrat de destination : POST JSON vers https://api.taegis.sophos.com/graphql avec jeton Bearer, X-Tenant-ID et X-GraphQL-Schema: default. Ni l’hôte REST régional ni un remplacement global de apiHosts.dataRegion ne conviennent. L’obtention du jeton et l’association au tenant restent nécessaires ; clarifier séparément les permissions et droits d’accès requis pour l’opération concernée. Les descriptions générales de rôles ci-dessus ne prouvent pas un rôle Search GraphQL minimal. Le runbook des recherches QL historiques détaille le processus complet. Le seul nom d’hôte ne garantit pas la résidence des données.

Demander un jeton d’accès en toute sécurité

Lire le secret sans l’afficher et envoyer les données de formulaire sur l’entrée standard. Il ne se retrouve ainsi ni dans l’historique du shell ni comme argument développé dans la liste des processus :

read -r -p "Client ID: " SOPHOS_CLIENT_ID
read -r -s -p "Client Secret: " SOPHOS_CLIENT_SECRET; printf '\n'
TOKEN_RESPONSE=$(printf 'grant_type=client_credentials&client_id=%s&client_secret=%s&scope=token' \
  "$(printf '%s' "$SOPHOS_CLIENT_ID" | jq -sRr '@uri')" \
  "$(printf '%s' "$SOPHOS_CLIENT_SECRET" | jq -sRr '@uri')" |
  curl --fail-with-body --silent --show-error --request POST \
    --header 'Content-Type: application/x-www-form-urlencoded' --data-binary @- \
    https://id.sophos.com/api/v2/oauth2/token)
unset SOPHOS_CLIENT_SECRET
SOPHOS_ACCESS_TOKEN=$(jq -er '
  select(.token_type == "bearer") |
  select((.expires_in | type) == "number" and .expires_in > 0) |
  .access_token | select(type == "string" and length > 0)
' <<<"$TOKEN_RESPONSE")
unset TOKEN_RESPONSE
WHOAMI=$(printf 'header = "Authorization: Bearer %s"\n' "$SOPHOS_ACCESS_TOKEN" |
  curl --fail-with-body --silent --show-error --config - \
    https://api.central.sophos.com/whoami/v1
)

Une réponse réussie contient au moins access_token, token_type: "bearer" et expires_in ; refresh_token, errorCode, message et trackingId peuvent aussi apparaître. expires_in est la durée de validité en secondes. Pour le flux Client Credentials, demander un nouveau jeton à l’expiration plutôt que compter sur le refresh_token facultatif. Ne jamais journaliser la réponse : les deux champs de jeton sont des secrets.

Évaluer whoami

Transmettre l’en-tête Bearer à curl par l’entrée standard et ne conserver que les champs de découverte non secrets. Les valeurs de l’exemple de réponse tenant sont des espaces réservés, pas des valeurs de production.

{
  "id": "<tenant-uuid>",
  "idType": "tenant",
  "apiHosts": {
    "global": "https://api.central.sophos.com",
    "dataRegion": "https://api-us03.central.sophos.com"
  }
}

Avec idType: "tenant", vérifier strictement l’UUID et l’hôte avant de les reprendre. Avec idType: "partner" ou "organization", whoami ne contient normalement que apiHosts.global ; SOPHOS_ID n’est alors pas un ID de tenant. La boucle bornée utilise l’en-tête de contexte requis et suit pages.total. Chaque objet tenant fournit son id et son apiHost. Choisir la cible par un UUID issu d’une correspondance interne fiable, jamais par le seul nom d’affichage ressemblant.

SOPHOS_ID=$(jq -er '.id | select(type == "string" and length > 0)' <<<"$WHOAMI")
SOPHOS_ID_TYPE=$(jq -er '.idType | select(. == "tenant" or . == "partner" or . == "organization")' <<<"$WHOAMI")
UUID_RE='^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$'
if [[ "$SOPHOS_ID_TYPE" == tenant ]]; then
  SOPHOS_TENANT_ID=$(jq -er --arg re "$UUID_RE" '.id | select(type=="string" and test($re))' <<<"$WHOAMI")
  SOPHOS_API_HOST=$(jq -er '.apiHosts.dataRegion | select(type=="string" and test("^https://api-[a-z0-9-]+\\.central\\.sophos\\.com$"))' <<<"$WHOAMI")
else
  case "$SOPHOS_ID_TYPE" in
    partner) TENANTS_URL='https://api.central.sophos.com/partner/v1/tenants'; CONTEXT_HEADER="X-Partner-ID: ${SOPHOS_ID}" ;;
    organization) TENANTS_URL='https://api.central.sophos.com/organization/v1/tenants'; CONTEXT_HEADER="X-Organization-ID: ${SOPHOS_ID}" ;;
    *) exit 1 ;;
  esac
  TENANTS_FILE=$(mktemp); printf '[]\n' >"$TENANTS_FILE"
  page=1; max_pages=1000; expected_pages=
  while (( page <= max_pages )); do
    PAGE_RESPONSE=$(printf 'header = "Authorization: Bearer %s"\n' "$SOPHOS_ACCESS_TOKEN" | curl --fail-with-body --silent --show-error --get --config - --header "$CONTEXT_HEADER" --data-urlencode "page=${page}" --data-urlencode 'pageSize=100' --data-urlencode 'pageTotal=true' "$TENANTS_URL")
    page_total=$(jq -er 'select((.items|type)=="array") | .pages.total | select(type=="number" and floor==. and .>=1 and .<=1000)' <<<"$PAGE_RESPONSE")
    if [[ -z "$expected_pages" ]]; then expected_pages=$page_total; fi
    [[ "$page_total" == "$expected_pages" ]] || exit 1
    jq -e --argjson page "$PAGE_RESPONSE" '. + $page.items' "$TENANTS_FILE" >"${TENANTS_FILE}.new"; mv "${TENANTS_FILE}.new" "$TENANTS_FILE"
    (( page >= expected_pages )) && break; ((page++))
  done
  (( page == expected_pages )) || exit 1
  read -r -p 'UUID du tenant cible selon la correspondance approuvée : ' TARGET_TENANT_ID
  TARGET_TENANT=$(jq -cer --arg id "$TARGET_TENANT_ID" --arg re "$UUID_RE" '[.[] | select((.id|type)=="string" and (.id|test($re)) and (.id|ascii_downcase)==($id|ascii_downcase)) | select((.apiHost|type)=="string" and (.apiHost|test("^https://api-[a-z0-9-]+\\.central\\.sophos\\.com$")))] | select(length==1) | .[0]' "$TENANTS_FILE")
  SOPHOS_TENANT_ID=$(jq -r '.id' <<<"$TARGET_TENANT"); SOPHOS_API_HOST=$(jq -r '.apiHost' <<<"$TARGET_TENANT"); rm -f "$TENANTS_FILE"
fi
export SOPHOS_TENANT_ID SOPHOS_API_HOST

Chaque requête produit du tenant dans ce processus REST régional associe alors trois valeurs : le jeton Bearer, X-Tenant-ID: <Tenant-UUID> et l’apiHost régional de ce tenant. Ne pas remplacer une API produit REST régionale par l’hôte global. Un hôte cible GraphQL propre à l’API est distinct. scope=token n’autorise aucune opération métier ; rôle, accès au tenant, licence et endpoint précis interviennent aussi.

Validation et récupération contrôlée

Avant une écriture, appeler un endpoint de lecture sans risque de l’API cible et vérifier idType attendu, UUID du tenant, format d’hôte autorisé, JSON valide, pagination complète et objets attendus. Confirmer ensuite un cas de test explicitement interdit avec 403, sans provoquer de modification en production. En fin de session, supprimer jeton d’accès, ID du tenant et hôte :

unset SOPHOS_ACCESS_TOKEN SOPHOS_CLIENT_ID SOPHOS_ID SOPHOS_ID_TYPE
unset SOPHOS_TENANT_ID SOPHOS_API_HOST WHOAMI

En cas de tenant ou d’hôte incorrect, arrêter immédiatement l’exécution, n’envoyer aucune écriture et isoler les résultats enregistrés comme données potentiellement étrangères au tenant, ou les supprimer selon les règles applicables. Annuler une modification métier déjà effectuée avec le rollback produit documenté auparavant ; supprimer l’identifiant révoque uniquement les appels futurs et n’annule aucune modification.

Dépanner l’accès API commun

  • 400 : vérifier encodage du formulaire, champs obligatoires et exactement grant_type=client_credentials et scope=token.
  • 401 : vérifier existence et expiration de l’identifiant, dernier jeu de secrets, jeton et syntaxe Bearer ; puis s’authentifier une fois à nouveau.
  • 403 : l’identité est authentifiée, mais il manque rôle, accès tenant ou permission propre à l’opération. Ne pas attribuer systématiquement Super Admin.
  • 404 : vérifier hôte global ou régional, version API et chemin ; ne pas chercher une région par essais.
  • 429 : respecter Retry-After et réessayer dans une limite avec backoff et jitter.
  • 5xx : conserver ID de requête ou trackingId, heure, méthode et chemin expurgé, puis réessayer dans une limite ; ne jamais copier secret ou jeton dans un ticket de support.
  • idType inattendu ou apiHost absent : ne construire aucun en-tête tenant. Vérifier le type d’identifiant et la liste partenaire/Enterprise intégralement paginée.

Tester l’authentification de manière contrôlée

Le premier test n’est pas une écriture en production. Pour le test REST régional présenté ici, obtenir d’abord un jeton d’accès OAuth auprès de l’endpoint Sophos Identity. L’endpoint whoami fournit ensuite identité, type de compte et, pour les identifiants tenant, hôte API régional ; les identifiants partenaire et organisation nécessitent la liste des tenants. Effectuer seulement ensuite une lecture sans risque vers l’hôte API REST renvoyé pour ce tenant.

Ne pas copier un hôte API REST régional depuis un exemple. Pour ce contrat, utiliser l’URL fournie par whoami ou la liste des tenants ; Search GraphQL utilise l’hôte distinct décrit plus haut. ID de tenant et ID d’organisation ne sont pas interchangeables non plus.

Le test doit documenter au minimum les points suivants :

  • l’authentification avec la nouvelle identité fonctionne ;
  • le tenant attendu est retourné ;
  • les opérations de lecture autorisées fonctionnent ;
  • une opération interdite est rejetée avec 403 Forbidden ;
  • le système cible consigne le test de manière traçable sans enregistrer le Client Secret.

Gérer l’expiration et la rotation

Sophos n’envoie aucun avertissement lorsqu’un API Credential expire. Après expiration, il ne peut plus servir à l’authentification et est automatiquement supprimé de Sophos Fusion. La surveillance doit donc être assurée en dehors de Sophos Fusion.

Une rotation propre utilise une courte période de chevauchement :

  1. Créer un nouvel identifiant avec un rôle identique ou plus limité.
  2. Configurer l’application avec le Client ID et le secret du nouvel identifiant.
  3. Tester l’authentification et le fonctionnement métier.
  4. Supprimer l’ancien identifiant.
  5. Vérifier la modification dans le registre des secrets et la documentation d’exploitation.

L’ancien identifiant ne reste pas actif pendant des mois « par précaution ». Si une application ne prend en charge qu’un seul jeu de secrets, on planifie une fenêtre de maintenance.

Remplacer les anciens jetons de l’API SIEM

API Token Management est l’ancien mécanisme d’authentification de la SIEM Integration API. Sophos n’y délivre plus de nouveaux jetons et ne prolonge plus leur durée de validité. Les jetons existants ne fonctionnent que jusqu’à leur expiration.

Une intégration qui les utilise encore ne doit donc pas attendre le dernier jour. On inventorie le jeton, le système cible, la date d’expiration et les endpoints utilisés, puis on crée un API Credential approprié, on migre l’application et on vérifie l’ensemble du flux de données. L’ancien jeton n’est supprimé qu’après un contrôle parallèle concluant.

Le passage d’un jeton historique à des API Credentials ne constitue pas un simple changement de nom. L’intégration doit prendre en charge l’authentification OAuth, whoami, l’hôte régional et le modèle de rôles. Un connecteur SIEM se configure donc selon la documentation actuelle de son éditeur et non à l’aide d’un ancien exemple de jeton.

Prestataires externes et accès tiers

Pour un tiers, on crée une identité Service Principal Read-Only distincte lorsque des droits de lecture suffisent. Client ID et secret sont transmis par des canaux chiffrés séparés. Une date de fin est définie et l’accès est supprimé à la fin du projet.

Par API, un tel tiers peut notamment lire les alertes et événements, les résultats de l’Account Health Check, les détails des appareils et les configurations de stratégies. Read-Only empêche l’ajout, la modification et la suppression dans Sophos Fusion, mais ne limite pas automatiquement les données que la plateforme tierce consulte ou conserve. Avant l’autorisation, il faut donc régler contractuellement le périmètre des données, leur finalité, leur lieu de stockage, leur conservation et leur suppression.

La création suit le chemin habituel Global Settings > Access Control > API Credentials > Add Credential. Lors du premier accès, les conditions d’utilisation et de confidentialité sont acceptées. On choisit Service Principal Read-Only, puis on récupère immédiatement le Client ID et le Client Secret qui ne s’affiche qu’une seule fois. Le transfert passe par un canal chiffré approuvé, par exemple le portail HTTPS du fournisseur, jamais par e-mail ou dans le texte d’un ticket.

L’hôte API n’est pas copié d’un tableau régional statique. L’application utilise whoami pour déterminer l’hôte API valable pour ce tenant précis. L’intégration reste ainsi correctement documentée même si Sophos modifie ses régions ou endpoints. Dès que le prestataire n’a plus besoin de l’accès, l’identifiant est supprimé et l’autorisation API immédiatement révoquée.

Il est inacceptable d’exporter le compte Super Admin personnel, d’utiliser une identité API commune pour plusieurs clients ou de placer un secret dans un ticket de support. Le prestataire doit aussi indiquer où le secret est stocké, comment il est protégé et quand il sera supprimé.

Cibler la recherche d’erreurs

401 Unauthorized

Le Client ID, le secret, l’endpoint de jeton ou la requête OAuth sont généralement incorrects. Un identifiant expiré et déjà supprimé provoque aussi cette erreur. On vérifie d’abord si l’identifiant existe encore dans Sophos Fusion et si l’application utilise réellement le dernier jeu de secrets.

403 Forbidden

L’authentification a réussi, mais le rôle n’autorise pas l’action. Au lieu d’accorder immédiatement Super Admin, on associe l’endpoint API requis au rôle de service principal approprié.

Jeton correct, mauvaise région de données

Le jeton d’accès ne détermine pas à lui seul l’hôte API métier. Pour une API produit REST à routage régional, l’application doit utiliser l’hôte régional fourni par whoami ou la liste des tenants ; Search GraphQL possède son propre contrat de destination. Un hôte fixe d’une autre région provoque des erreurs ou des requêtes vers une mauvaise frontière de plateforme.

L’intégration tombe en panne sans avertissement

Si Sophos Fusion ne présente aucune alerte ouverte, on contrôle la date d’expiration, le dernier appel API réussi et la version du secret dans le système cible. La surveillance de l’expiration appartient au monitoring externe.

Contrôle régulier

Au moins chaque trimestre, on contrôle le nom, le propriétaire, le rôle, la dernière utilisation, l’expiration et le système cible de chaque identifiant. Les identités inutilisées ou sans propriétaire sont supprimées. En cas de suspicion de fuite, l’identifiant concerné est immédiatement supprimé et remplacé. Les journaux du système cible et de l’intégration sont ensuite examinés à la recherche d’appels API inhabituels.

Les droits des administrateurs personnels sont contrôlés séparément selon Attribuer correctement les rôles d’administration Sophos Fusion. Les API Credentials ne remplacent ni la MFA ni un accès administrateur personnel et traçable.

Questions fréquentes

Peut-on afficher à nouveau un Client Secret existant ?

Non. Le secret n’est visible qu’immédiatement après sa création. En cas de perte, on crée et teste un nouvel identifiant, puis on supprime l’ancien.

Quel rôle convient à un SIEM qui ne fait que lire des données ?

En règle générale, Service Principal Read-Only. Si l’intégration nécessite des actions d’investigation ou d’écriture spécifiques, celles-ci doivent être examinées séparément et mises en oeuvre avec une identité distincte appropriée.

Sophos Fusion avertit-il avant l'expiration ?

Non. L’expiration doit être surveillée dans le registre des secrets ou le système de monitoring. Une fois expiré, l’identifiant ne peut plus s’authentifier et est automatiquement supprimé.