Ir al contenido
Avanet

Exportar e importar Sophos Firewall mediante la API de Central

Con SFOS 22.0 MR2 o posterior, las configuraciones de firewall se pueden exportar e importar mediante la API REST de Sophos Central en Sophos Fusion (antes Sophos Central). El proceso consta de unos pocos pasos: autenticar el acceso a la API, determinar el ID del firewall, iniciar la exportación o la carga y comprobar la transacción devuelta hasta que finalice.

Para acceder directamente al firewall, API REST local y claves API en SFOS 23.0 describe otro camino. Las claves administrativas locales no sustituyen el principal de servicio cloud, token, tenant ni host API regional de este artículo.

Para un único cambio manual directamente en WebAdmin local, conviene usar exportar e importar selectivamente la configuración. El artículo también explica Entities.xml, SSMK, dependencias de objetos y efecto merge del import.

Una importación modifica el firewall de destino y no es una restauración de una copia de seguridad. Primero debe crearse una copia de seguridad del firewall actual, ejecutar el proceso inicialmente con un firewall de prueba y validar después el resultado de forma local.

Preparar los requisitos y las variables de la API

Se necesita lo siguiente:

  • un firewall con SFOS 22.0 MR2 o posterior conectado y administrado mediante Sophos Fusion;
  • una suscripción de pago activa para el firewall distinta de la Base License o un contrato de soporte activo;
  • una credencial de API propia con los permisos necesarios;
  • curl, jq y, para una importación, md5 o md5sum;
  • el ID del tenant, el host regional de la API y el ID del firewall;
  • una ventana de mantenimiento y un procedimiento de recuperación probado para las importaciones.

La creación de credenciales, roles, contratos de Token y whoami, región, protección de secretos, validación y diagnóstico común se centralizan en Gestionar de forma segura las credenciales de la API de Sophos Central. Complete primero ese proceso; este artículo reutiliza después SOPHOS_ACCESS_TOKEN, SOPHOS_TENANT_ID y SOPHOS_API_HOST.

Las credenciales de API se crean en Sophos Fusion en Global Settings > Access Control > API Credentials. Para un tenant, Sophos recomienda el rol Service Principal Firewall. En el Partner Dashboard, la función se encuentra en Global Settings > APIs & Integrations > API Credentials Management; allí hay otros roles disponibles y debe utilizarse el rol con menos privilegios que permita acceder al tenant de destino. El Client Secret, el JWT, el Secure Storage Master Key y las URL de descarga o carga emitidas posteriormente no deben incluirse en tickets, chats ni capturas de pantalla.

Los ejemplos se ejecutan en Bash y presuponen una credencial de tenant. Las credenciales de Partner y Enterprise primero deben resolver el tenant de destino y su host regional de la API. Para cada solicitud del tenant se debe usar después el apiHost regional que whoami devuelve para ese tenant.

Asignar los tres valores validados por el proceso Owner a las variables utilizadas aquí:

JWT="$SOPHOS_ACCESS_TOKEN"
TENANT_ID="$SOPHOS_TENANT_ID"
API_HOST="$SOPHOS_API_HOST"

No solicite de nuevo el JWT: JWT es el Access Token temporal reutilizado arriba.

Los ejemplos sencillos de curl pasan el JWT de corta duración como argumento de cabecera. Por tanto, deben ejecutarse en una estación de administración de confianza en la que ningún usuario no autorizado pueda leer los argumentos de los procesos locales.

El Tenant ID y el host regional también proceden del proceso Owner:

TENANT_ID y API_HOST ya están validados. Para credenciales Partner o Enterprise deben proceder de la lista de tenants completamente paginada del proceso Owner.

Determinar el ID del firewall

La lista de firewalls muestra el nombre, el hostname, el número de serie, el firmware y el 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"

Debe utilizarse el UUID del firewall correcto y no seleccionarlo únicamente por un nombre para mostrar similar:

read -r -p 'UUID del firewall del inventario aprobado: ' 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 el firewall no aparece, primero deben comprobarse el tenant, la región, la conexión con Sophos Fusion y la aprobación de la administración. El registro se explica en Conectar Sophos Firewall con Sophos Fusion.

Exportar la configuración

Iniciar una exportación completa

La exportación se ejecuta de forma asíncrona. Por ello, la primera solicitud solo devuelve un ID de transacción:

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"

Volver a consultar el estado después de unos segundos:

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"

Repetir la solicitud aproximadamente cada diez segundos hasta que status alcance el estado final finished. pending y started todavía no son errores.

Solo cuando aparecen status: "finished" y result: "success", response.url contiene la URL de descarga de duración limitada:

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

El archivo TAR puede contener datos confidenciales de red, usuarios, VPN y políticas. Debe almacenarse de forma segura o eliminarse después del análisis. Para obtener un informe legible o comparar el antes y el después, el archivo Entities.xml incluido puede utilizarse en Sophos Firewall Config Studio.

Exportar solo configuraciones seleccionadas

Para una exportación selectiva, los nombres de las entidades deben indicarse de forma exacta y respetando las mayúsculas y minúsculas. Este ejemplo exporta reglas de firewall y NAT con los objetos dependientes:

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"

Los nombres de entidad son exactos y distinguen mayúsculas de minúsculas; el ejemplo utiliza FirewallRule y NATRule. En una exportación selectiva, el valor predeterminado de includeDependency es false; establezca la opción de forma deliberada y compruebe igualmente el paquete resultante.

Alcance y límites del paquete

Antes de una importación mediante la API también deben tenerse en cuenta estas reglas de SFOS aplicables al archivo TAR:

  • La importación actualiza los ajustes existentes. Un ajuste ausente del paquete no cambia en el destino; si aparece en ambas configuraciones, prevalece el valor importado.
  • Con autenticación externa, la exportación solo contiene los usuarios creados manualmente en el firewall. OTPTokens incluye únicamente los tokens emitidos para esos usuarios.
  • REDDevice no incluye automáticamente el servidor DHCP necesario, ni siquiera con includeDependency. Debe exportarse también DHCPServer o recrear el servidor DHCP después de la importación.
  • Una lista de URL importada puede contener un máximo de 128 dominios.
  • Los modelos XGS 88w, 108w, 118w y 128w tienen condiciones adicionales para configuraciones inalámbricas, entre ellas bandas de frecuencia, Security mode, Encryption, bridges y número de SSID únicos.

Por tanto, poder listar el TAR sin errores solo demuestra que el archivo se puede abrir. No confirma que estén presentes todos los objetos necesarios ni que se apliquen en el hardware de destino.

Importar la configuración

La importación consiste en solicitar una URL de carga, cargar el archivo TAR, confirmar los metadatos del archivo y comprobar la transacción. El ejemplo utiliza un único firewall de prueba y establece deliberadamente performPartialImport en false. El valor predeterminado de la API es true y permite una importación parcial por firewall.

Antes debe comprobarse la compatibilidad: el firewall de destino necesita como mínimo la misma versión de firmware y patrones. Sophos solo admite importaciones selectivas entre modelos distintos desde un modelo inferior a otro superior; el hardware de destino debe tener al menos el mismo número de puertos Ethernet. Si los nombres de los puertos son distintos, debe adaptarse Entities.xml antes de la carga.

Preparar el archivo de importación y la suma de comprobación

Preparar el archivo de destino, la suma de comprobación y el tamaño del archivo:

FILE="sophos-firewall-config-2026-08-03.tar"
FILE_SIZE=$(wc -c <"$FILE" | tr -d ' ')

En macOS:

CHECKSUM_MD5=$(md5 -q "$FILE")

En Linux:

CHECKSUM_MD5=$(md5sum "$FILE" | awk '{print $1}')

Solicitar una sesión de carga y cargar el archivo

Solicitar una sesión de carga y mostrar únicamente los campos que no son secretos:

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"

Cargar el archivo con el método PUT devuelto antes de que caduque la URL prefirmada. No debe enviarse a esta URL ninguna cabecera JWT ni de tenant:

curl --fail-with-body --silent --show-error \
  --request PUT \
  --upload-file "$FILE" \
  "$UPLOAD_URL"
unset UPLOAD_URL

Completar la importación y comprobar el estado

Si el paquete contiene información confidencial y se importa en un firewall diferente o recién desplegado, se necesita el Secure Storage Master Key correspondiente. Sin él, SFOS no importa la información confidencial ni las configuraciones que dependen de ella. La siguiente solicitud no muestra el secreto; puede pulsarse Enter para omitirlo:

read -r -s -p "Secure Storage Master Key, o pulse Enter: " SSMK
printf '\n'

Completar la carga y asignar el paquete al firewall de destino:

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"

Una solicitud acepta entre 1 y 25 ID de firewall únicos. Para otros firewalls, el paquete debe cargarse de nuevo; no debe reutilizarse la misma URL prefirmada ni el mismo ID de transacción.

Comprobar el estado de la importación mediante el mismo endpoint de transacción:

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"

Repetir también esta consulta aproximadamente cada diez segundos hasta que aparezca status: "finished". Solo entonces deben evaluarse result y, si hay varios destinos, cada elemento de response.items.

success confirma el procesamiento por la API, no el resultado funcional.

Validar la importación de forma local

Después de finished, comprobar en cada firewall de destino:

  1. ¿Están presentes exactamente las reglas, los objetos y los ajustes esperados?
  2. ¿Faltan usuarios, contraseñas, certificados u objetos dependientes debido a un SSMK ausente o incorrecto?
  3. ¿Coinciden las interfaces, las zonas, los gateways, el firmware, la versión de patrones y el modelo de hardware con el paquete?
  4. ¿Funcionan el enrutamiento, NAT, VPN, la autenticación y el acceso de administración con casos de prueba definidos?
  5. ¿Muestran el Audit Trail y los registros de configuración cambios inesperados?
  6. ¿Muestra una nueva exportación o comparación con Config Studio únicamente las diferencias previstas?

La importación y exportación actualizan la configuración existente y no eliminan automáticamente todo lo que falta en el paquete. Por tanto, el archivo TAR no representa un estado objetivo completo ni sustituye a una copia de seguridad, un rollback y una prueba funcional.

Revertir una importación defectuosa

Si falla la validación local, debe detenerse el despliegue, conservarse la respuesta de la transacción y no ocultar el resultado con nuevas importaciones. Para volver atrás en WebAdmin local, ir a Backup and firmware > Backup and restore. En Restore configuration, usar Choose file para seleccionar la copia creada anteriormente, introducir su Encryption password y ejecutar Upload and restore.

La restauración sustituye la configuración actual, elimina la copia almacenada en el firewall y reinicia el dispositivo. A continuación se activa la IP de WebAdmin de la configuración restaurada. Esa IP y la contraseña de cifrado deben estar disponibles antes de importar. Tras el reinicio, repetir las mismas pruebas funcionales y comprobar el resultado con otra exportación; los cambios posteriores a la copia se pierden al restaurar.

Solución de problemas

La exportación no muestra una URL de descarga

La URL solo aparece después de status: "finished" y result: "success". Si se obtiene error o partialSuccess, deben comprobarse los campos de response y no continuar con una URL vacía o caducada.

HTTP 401 o 403

Con 401, el JWT suele haber caducado o no ser válido. Debe repetirse la autenticación. Con 403, deben comprobarse el rol de Sophos Fusion, el contexto del tenant, X-Tenant-ID y el host regional de la API. El permiso de la API XML local en /webconsole/APIController no se aplica aquí; se trata por separado en Proteger el acceso a la API XML de Sophos Firewall.

Upload-complete devuelve 400 o 409

Comprobar el ID de transacción, la caducidad de la URL de carga, el tamaño real del archivo, la suma de comprobación MD5 hexadecimal y los ID de firewall únicos. El archivo cargado no debe modificarse posteriormente. Para realizar otro intento debe utilizarse una nueva sesión de carga.

La importación termina con error o partialSuccess

Guardar response y, si hay varios firewalls de destino, response.items. Si una llamada a la API devuelve una respuesta de error 4xx o 5xx independiente, documentar también error, message, code, correlationId y requestId. A continuación, comprobar localmente la versión de destino, la versión de patrones, el modelo, los puertos, las dependencias y el SSMK. Si la respuesta de Sophos Fusion no es suficiente, comprobar fwcm-api-executor.log en el firewall tal como se describe en Servicios y archivos de registro de Sophos Firewall.

El endpoint de transacción es determinante para el estado de la API; no debe presuponerse que la tarea aparece en la Central Firewall Task Queue.

Al final de la sesión deben eliminarse las variables confidenciales:

unset JWT CLIENT_ID TENANT_ID API_HOST FIREWALL_ID TARGET_FIREWALL_ID
unset EXPORT_TX IMPORT_TX CHECKSUM_MD5 FILE_SIZE