Exporter et importer Sophos Firewall via l’API Central
Avec SFOS 22.0 MR2 ou une version ultérieure, les configurations des firewalls peuvent être exportées et importées via l’API REST Sophos Central dans Sophos Fusion (anciennement Sophos Central). Le processus comprend quelques étapes : authentifier l’accès à l’API, déterminer l’ID du firewall, démarrer l’exportation ou le chargement, puis vérifier la transaction renvoyée jusqu’à son terme.
Pour un changement manuel unique directement dans le WebAdmin local, utiliser plutôt Exporter et importer sélectivement la configuration. L’article explique également Entities.xml, le SSMK, les dépendances d’objets et l’effet de fusion de l’import.
Une importation modifie le firewall cible et ne constitue pas une restauration de sauvegarde. Il faut d’abord créer une sauvegarde du firewall à jour, exécuter le processus sur un firewall de test, puis valider localement le résultat.
Préparer les prérequis et les variables de l’API
Les éléments suivants sont nécessaires :
- un firewall exécutant SFOS 22.0 MR2 ou une version ultérieure, connecté à Sophos Fusion et géré depuis cette plateforme ;
- un abonnement payant actif pour le firewall, autre que la Base License, ou un contrat de support actif ;
- un identifiant d’API dédié disposant des autorisations nécessaires ;
curl,jqet, pour une importation,md5oumd5sum;- l’ID du tenant, l’hôte régional de l’API et l’ID du firewall ;
- une fenêtre de maintenance et un chemin de retour testé pour les importations.
La création des Credentials, les rôles, les contrats Token et whoami, la région, les secrets, la validation et le diagnostic commun sont centralisés dans Gérer les API Credentials Sophos Central en sécurité. Exécuter d’abord ce processus ; cet article reprend ensuite SOPHOS_ACCESS_TOKEN, SOPHOS_TENANT_ID et SOPHOS_API_HOST.
Les identifiants d’API sont créés dans Sophos Fusion sous Global Settings > Access Control > API Credentials. Pour un tenant, Sophos recommande le rôle Service Principal Firewall. Dans le Partner Dashboard, la fonction se trouve sous Global Settings > APIs & Integrations > API Credentials Management ; d’autres rôles y sont proposés et il convient d’utiliser celui qui dispose des privilèges minimaux nécessaires pour accéder au tenant cible. Le Client Secret, le JWT, le Secure Storage Master Key ainsi que les URL de téléchargement ou de chargement générées ultérieurement ne doivent pas figurer dans des tickets, chats ou captures d’écran.
Les exemples s’exécutent dans Bash et supposent l’utilisation d’un identifiant de tenant. Les identifiants Partner et Enterprise doivent d’abord résoudre le tenant cible et son hôte régional de l’API. Pour chaque requête propre au tenant, utiliser ensuite l’apiHost régional que whoami renvoie pour ce tenant.
Associer les trois valeurs validées par le processus Owner aux variables utilisées ici :
JWT="$SOPHOS_ACCESS_TOKEN"
TENANT_ID="$SOPHOS_TENANT_ID"
API_HOST="$SOPHOS_API_HOST"
Ne pas redemander le JWT : JWT est l’Access Token temporaire repris ci-dessus.
Les exemples curl simples transmettent le JWT de courte durée comme argument d’en-tête. Ils doivent donc être exécutés sur un poste d’administration de confiance où aucun utilisateur non autorisé ne peut lire les arguments des processus locaux.
Le Tenant ID et l’hôte régional proviennent eux aussi du processus Owner :
TENANT_ID et API_HOST sont déjà validés. Avec une Credential Partner ou Enterprise, ils doivent provenir de la liste paginée complète du processus Owner.
Déterminer l’ID du firewall
La liste des firewalls affiche le nom, le hostname, le numéro de série, le firmware et l’UUID :
FIREWALLS_FILE=$(mktemp); printf '[]\n' >"$FIREWALLS_FILE"; page=1; max_pages=1000; expected_pages=
while (( page <= max_pages )); do
PAGE_RESPONSE=$(curl --fail-with-body --silent --show-error --get --header "Authorization: Bearer $JWT" --header "X-Tenant-ID: $TENANT_ID" --data-urlencode "page=${page}" --data-urlencode 'pageSize=100' --data-urlencode 'pageTotal=true' "$API_HOST/firewall/v1/firewalls")
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' "$FIREWALLS_FILE" >"${FIREWALLS_FILE}.new"; mv "${FIREWALLS_FILE}.new" "$FIREWALLS_FILE"
(( page >= expected_pages )) && break; ((page++))
done
(( page == expected_pages )) || exit 1
jq -r '.[]|[.name,.hostname,.serialNumber,.firmwareVersion,.id]|@tsv' "$FIREWALLS_FILE"
Utiliser l’UUID du firewall approprié et ne pas le sélectionner uniquement en fonction d’un nom d’affichage similaire :
read -r -p 'UUID du pare-feu dans l’inventaire approuvé : ' REQUESTED_FIREWALL_ID
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}$'
FIREWALL_ID=$(jq -er --arg id "$REQUESTED_FIREWALL_ID" --arg re "$UUID_RE" '[.[]|select((.id|type)=="string" and (.id|test($re)) and (.id|ascii_downcase)==($id|ascii_downcase))]|select(length==1)|.[0].id' "$FIREWALLS_FILE")
rm -f "$FIREWALLS_FILE"; unset PAGE_RESPONSE REQUESTED_FIREWALL_ID page page_total expected_pages max_pages
Si le firewall n’apparaît pas, vérifier d’abord le tenant, la région, la connexion à Sophos Fusion et l’approbation de la gestion. L’enregistrement est expliqué dans Connecter Sophos Firewall à Sophos Fusion.
Exporter la configuration
Démarrer une exportation complète
L’exportation s’exécute de manière asynchrone. Le premier appel ne renvoie donc qu’un ID de transaction :
EXPORT_RESPONSE=$(
curl --fail-with-body --silent --show-error \
--request POST \
--header "Authorization: Bearer $JWT" \
--header "X-Tenant-ID: $TENANT_ID" \
--header 'Content-Type: application/json' \
--data '{"fullExport":true}' \
"$API_HOST/firewall/v1/firewall-config/firewalls/$FIREWALL_ID/export"
)
EXPORT_TX=$(jq -er '.transactionId' <<<"$EXPORT_RESPONSE")
printf 'Export transaction: %s\n' "$EXPORT_TX"
Récupérer à nouveau l’état après quelques secondes :
EXPORT_STATUS=$(
curl --fail-with-body --silent --show-error \
--header "Authorization: Bearer $JWT" \
--header "X-Tenant-ID: $TENANT_ID" \
"$API_HOST/firewall/v1/firewall-config/firewalls/transactions/$EXPORT_TX"
)
jq '{status, result, createdAt, finishedAt, expiryAt, response}' \
<<<"$EXPORT_STATUS"
Répéter la requête environ toutes les dix secondes jusqu’à ce que status atteigne l’état final finished. pending et started ne constituent pas encore des erreurs.
Ce n’est que lorsque status: "finished" et result: "success" sont renvoyés que response.url contient l’URL de téléchargement à durée limitée :
DOWNLOAD_URL=$(
jq -er '
select(.status == "finished" and .result == "success") |
.response.url
' <<<"$EXPORT_STATUS"
)
OUTPUT="sophos-firewall-config-$(date +%F).tar"
curl --fail-with-body --location --output "$OUTPUT" "$DOWNLOAD_URL"
tar -tf "$OUTPUT"
unset DOWNLOAD_URL
Le fichier TAR peut contenir des données sensibles relatives au réseau, aux utilisateurs, aux VPN et aux stratégies. Il faut le stocker de manière sécurisée ou le supprimer après l’analyse. Pour obtenir un rapport lisible ou effectuer une comparaison avant-après, le fichier Entities.xml inclus peut être utilisé dans Sophos Firewall Config Studio.
Exporter uniquement certaines configurations
Pour une exportation sélective, les noms des entités doivent être saisis exactement et en respectant la casse. Cet exemple exporte les règles de firewall et de NAT avec les objets dépendants :
curl --fail-with-body --silent --show-error \
--request POST \
--header "Authorization: Bearer $JWT" \
--header "X-Tenant-ID: $TENANT_ID" \
--header 'Content-Type: application/json' \
--data '{
"fullExport": false,
"includeDependency": true,
"exportEntities": ["FirewallRule", "NATRule"]
}' \
"$API_HOST/firewall/v1/firewall-config/firewalls/$FIREWALL_ID/export"
Les noms d’entité sont exacts et sensibles à la casse ; l’exemple utilise FirewallRule et NATRule. Pour une exportation sélective, la valeur par défaut de includeDependency est false ; définir cette option délibérément et contrôler malgré tout le paquet obtenu.
Périmètre et limites du paquet
Avant une importation par API, il faut également tenir compte des règles SFOS suivantes applicables au fichier TAR :
- L’importation met à jour les paramètres existants. Un paramètre absent du paquet reste inchangé sur la cible ; s’il existe dans les deux configurations, la valeur importée prévaut.
- Avec une authentification externe, l’exportation contient uniquement les utilisateurs créés manuellement sur le firewall.
OTPTokensinclut seulement les tokens émis pour ces utilisateurs. REDDevicen’inclut pas automatiquement le serveur DHCP requis, même avecincludeDependency. Il faut aussi exporterDHCPServerou recréer le serveur DHCP après l’importation.- Une liste d’URL importée ne peut pas contenir plus de 128 domaines.
- Les modèles XGS 88w, 108w, 118w et 128w imposent des conditions supplémentaires aux configurations sans fil, notamment pour les bandes de fréquences, Security mode, Encryption, les bridges et le nombre de SSID uniques.
Une liste TAR lisible sans erreur prouve donc uniquement que l’archive peut être ouverte. Elle ne garantit ni la présence de tous les objets nécessaires ni leur application sur le matériel cible.
Importer la configuration
L’importation consiste à demander une URL de chargement, charger le fichier TAR, confirmer les métadonnées du fichier et vérifier la transaction. L’exemple n’utilise qu’un firewall de test et définit volontairement performPartialImport sur false. La valeur par défaut de l’API est true et autorise une importation partielle pour chaque firewall.
Vérifier d’abord la compatibilité : le firewall cible doit disposer au minimum de la même version du firmware et des patterns. Sophos ne prend en charge les importations sélectives entre différents modèles que d’un modèle inférieur vers un modèle supérieur ; le matériel cible doit posséder au moins autant de ports Ethernet. Si les noms des ports diffèrent, il faut adapter Entities.xml avant le chargement.
Préparer le fichier d’importation et la somme de contrôle
Préparer le fichier cible, la somme de contrôle et la taille du fichier :
FILE="sophos-firewall-config-2026-08-03.tar"
FILE_SIZE=$(wc -c <"$FILE" | tr -d ' ')
Sous macOS :
CHECKSUM_MD5=$(md5 -q "$FILE")
Sous Linux :
CHECKSUM_MD5=$(md5sum "$FILE" | awk '{print $1}')
Demander une session de chargement et charger le fichier
Demander une session de chargement et afficher uniquement les champs non secrets :
IMPORT_SESSION=$(
curl --fail-with-body --silent --show-error \
--request POST \
--header "Authorization: Bearer $JWT" \
--header "X-Tenant-ID: $TENANT_ID" \
"$API_HOST/firewall/v1/firewall-config/firewalls/import"
)
IMPORT_TX=$(jq -er '.transactionId' <<<"$IMPORT_SESSION")
UPLOAD_URL=$(jq -er '.url' <<<"$IMPORT_SESSION")
jq '{transactionId, method, expiresAt}' <<<"$IMPORT_SESSION"
Charger le fichier avec la méthode PUT renvoyée avant l’expiration de l’URL présignée. Ne pas envoyer d’en-tête JWT ou de tenant à cette URL :
curl --fail-with-body --silent --show-error \
--request PUT \
--upload-file "$FILE" \
"$UPLOAD_URL"
unset UPLOAD_URL
Terminer l’importation et vérifier l’état
Si le paquet contient des informations sensibles et qu’il est importé sur un firewall différent ou nouvellement déployé, le Secure Storage Master Key correspondant est nécessaire. Sans cette clé, SFOS n’importe pas les informations sensibles ni les configurations qui en dépendent. L’invite suivante n’affiche pas le secret ; appuyer sur Entrée permet de l’omettre :
read -r -s -p "Secure Storage Master Key, ou appuyez sur Entrée : " SSMK
printf '\n'
Terminer le chargement et attribuer le paquet au firewall cible :
TARGET_FIREWALL_ID="$FIREWALL_ID"
COMPLETE_RESPONSE=$(
printf '%s' "$SSMK" |
jq -Rsc \
--arg firewall "$TARGET_FIREWALL_ID" \
--arg checksum "$CHECKSUM_MD5" \
--argjson size "$FILE_SIZE" '
. as $ssmk |
{
firewallIds: [$firewall],
checksumMd5: $checksum,
fileSizeBytes: $size,
performPartialImport: false
}
+ if ($ssmk | length) > 0
then {secureMasterKey: $ssmk}
else {}
end
' |
curl --fail-with-body --silent --show-error \
--request POST \
--header "Authorization: Bearer $JWT" \
--header "X-Tenant-ID: $TENANT_ID" \
--header 'Content-Type: application/json' \
--data-binary @- \
"$API_HOST/firewall/v1/firewall-config/firewalls/import/$IMPORT_TX/upload-complete"
)
unset SSMK
jq '{id, status, result}' <<<"$COMPLETE_RESPONSE"
Une requête accepte entre 1 et 25 ID de firewall uniques. Pour d’autres firewalls, le paquet doit être chargé à nouveau ; il ne faut pas réutiliser la même URL présignée ni le même ID de transaction.
Vérifier l’état de l’importation via le même endpoint de transaction :
IMPORT_STATUS=$(
curl --fail-with-body --silent --show-error \
--header "Authorization: Bearer $JWT" \
--header "X-Tenant-ID: $TENANT_ID" \
"$API_HOST/firewall/v1/firewall-config/firewalls/transactions/$IMPORT_TX"
)
jq '{status, result, createdAt, finishedAt, response}' <<<"$IMPORT_STATUS"
Répéter également cette requête environ toutes les dix secondes jusqu’à ce que status: "finished" apparaisse. Ce n’est qu’ensuite qu’il faut évaluer result et, pour plusieurs cibles, chaque élément de response.items.
success confirme le traitement par l’API, et non le résultat fonctionnel.
Valider localement l’importation
Après finished, vérifier les points suivants sur chaque firewall cible :
- Les règles, objets et paramètres attendus sont-ils exactement présents ?
- Des utilisateurs, mots de passe, certificats ou objets dépendants sont-ils absents en raison d’un SSMK manquant ou incorrect ?
- Les interfaces, zones, passerelles, le firmware, la version des patterns et le modèle matériel correspondent-ils au paquet ?
- Le routage, le NAT, les VPN, l’authentification et l’accès d’administration fonctionnent-ils avec des cas de test définis ?
- L’Audit Trail et les journaux de configuration indiquent-ils des modifications inattendues ?
- Une nouvelle exportation ou comparaison avec Config Studio ne montre-t-elle que les différences prévues ?
L’importation et l’exportation mettent à jour la configuration existante et ne suppriment pas automatiquement tout ce qui est absent du paquet. Le fichier TAR ne représente donc ni un état cible complet ni un substitut à une sauvegarde, un rollback et un test fonctionnel.
Revenir en arrière après une importation défectueuse
Si la validation locale échoue, arrêter le déploiement, conserver la réponse de la transaction et ne pas masquer le résultat par d’autres importations. Pour revenir en arrière dans le WebAdmin local, aller dans Backup and firmware > Backup and restore. Sous Restore configuration, utiliser Choose file pour sélectionner la sauvegarde créée auparavant, saisir son Encryption password, puis lancer Upload and restore.
La restauration remplace la configuration actuelle, supprime la sauvegarde stockée sur le firewall et redémarre celui-ci. L’adresse IP WebAdmin de la configuration restaurée devient alors active. Cette adresse et le mot de passe de chiffrement doivent être disponibles avant l’importation. Après le redémarrage, répéter les mêmes tests fonctionnels et contrôler le résultat avec une nouvelle exportation ; les modifications postérieures à la sauvegarde sont perdues lors de la restauration.
Dépannage
L’exportation ne fournit pas d’URL de téléchargement
L’URL apparaît uniquement après status: "finished" et result: "success". En cas de error ou de partialSuccess, vérifier les champs de response et ne pas poursuivre avec une URL vide ou expirée.
HTTP 401 ou 403
Avec 401, le JWT est généralement expiré ou non valide. Il faut s’authentifier à nouveau. Avec 403, vérifier le rôle Sophos Fusion, le contexte du tenant, X-Tenant-ID et l’hôte régional de l’API. L’autorisation de l’API XML locale sous /webconsole/APIController ne s’applique pas ici ; elle est traitée séparément dans Sécuriser l’accès à l’API XML de Sophos Firewall.
Upload-complete renvoie 400 ou 409
Vérifier l’ID de transaction, l’heure d’expiration de l’URL de chargement, la taille réelle du fichier, la somme de contrôle MD5 hexadécimale et les ID de firewall uniques. Ne pas modifier le fichier après son chargement. Utiliser une nouvelle session de chargement pour une nouvelle tentative.
L’importation se termine par error ou partialSuccess
Enregistrer response et, pour plusieurs firewalls cibles, response.items. Si un appel d’API renvoie une réponse d’erreur 4xx ou 5xx distincte, consigner également error, message, code, correlationId et requestId. Vérifier ensuite localement la version cible, la version des patterns, le modèle, les ports, les dépendances et le SSMK. Si la réponse de Sophos Fusion ne suffit pas, contrôler fwcm-api-executor.log sur le firewall comme décrit dans Services et fichiers journaux de Sophos Firewall.
L’endpoint de transaction fait foi pour l’état de l’API ; ne pas supposer que la tâche apparaît dans la Central Firewall Task Queue.
À la fin de la session, supprimer les variables sensibles :
unset JWT CLIENT_ID TENANT_ID API_HOST FIREWALL_ID TARGET_FIREWALL_ID
unset EXPORT_TX IMPORT_TX CHECKSUM_MD5 FILE_SIZE