Eksport i import Sophos Firewall przez Central API
W przypadku systemu SFOS 22.0 MR2 lub nowszego konfiguracje zapór można eksportować i importować przez REST API Sophos Central w Sophos Fusion (dawniej Sophos Central). Proces składa się z kilku kroków: uwierzytelnienia dostępu do API, ustalenia identyfikatora zapory, uruchomienia eksportu lub wysyłania pliku oraz sprawdzania zwróconej transakcji aż do jej zakończenia.
Dla pojedynczej ręcznej zmiany bezpośrednio w lokalnym WebAdmin należy zamiast tego użyć procedury Selektywny eksport i import konfiguracji. Artykuł objaśnia też Entities.xml, SSMK, zależności obiektów i działanie merge podczas importu.
Import zmienia zaporę docelową i nie jest odtworzeniem kopii zapasowej. Najpierw należy utworzyć aktualną kopię zapasową zapory, przetestować proces na zaporze testowej, a następnie lokalnie zweryfikować jego rezultat.
Przygotowanie wymagań i zmiennych API
Potrzebne są:
- zapora połączona z Sophos Fusion i zarządzana przez tę platformę, z systemem co najmniej SFOS 22.0 MR2;
- aktywna płatna subskrypcja zapory wykraczająca poza Base License lub aktywna umowa wsparcia;
- osobne poświadczenie API z wymaganymi uprawnieniami;
curl,jq, a do importu takżemd5lubmd5sum;- identyfikator tenanta, regionalny host API i identyfikator zapory;
- okno serwisowe i przetestowana droga odzyskania dostępu na potrzeby importu.
Tworzenie Credential, role, kontrakty Tokenu i whoami, region, ochrona Secret, walidacja i wspólna diagnostyka są centralnie opisane w Bezpieczne zarządzanie danymi uwierzytelniającymi API Sophos Central. Najpierw wykonać cały ten proces; artykuł używa potem SOPHOS_ACCESS_TOKEN, SOPHOS_TENANT_ID i SOPHOS_API_HOST.
Poświadczenia API tworzy się w Sophos Fusion w obszarze Global Settings > Access Control > API Credentials. Dla tenanta Sophos zaleca rolę Service Principal Firewall. W Partner Dashboard funkcja znajduje się w Global Settings > APIs & Integrations > API Credentials Management; dostępne są tam inne role i należy wybrać rolę o najmniejszym zakresie uprawnień zapewniającą dostęp do docelowego tenanta. Client Secret, JWT, Secure Storage Master Key oraz wydane później adresy URL pobierania i wysyłania nie powinny trafiać do zgłoszeń, czatów ani zrzutów ekranu.
Przykłady działają w Bash i zakładają użycie poświadczenia tenanta. Poświadczenia partnera i organizacji Enterprise muszą najpierw rozpoznać docelowego tenanta wraz z jego regionalnym hostem API. Dla każdego żądania dotyczącego tenanta należy następnie użyć regionalnego apiHost, który whoami zwraca dla tego tenanta.
Przypisać trzy wartości zweryfikowane w procesie Owner do używanych tu zmiennych:
JWT="$SOPHOS_ACCESS_TOKEN"
TENANT_ID="$SOPHOS_TENANT_ID"
API_HOST="$SOPHOS_API_HOST"
Nie pobierać JWT ponownie: JWT jest przejętym wyżej krótkotrwałym Access Tokenem.
Proste przykłady z curl przekazują krótkotrwały JWT jako argument nagłówka. Dlatego należy je uruchamiać na zaufanej stacji administracyjnej, na której inni lokalni użytkownicy nie mogą odczytywać argumentów procesów.
Tenant ID i host regionalny również pochodzą z procesu Owner:
TENANT_ID i API_HOST są już zweryfikowane. Dla Credential Partner lub Enterprise muszą pochodzić z pełnej, stronicowanej listy procesu Owner.
Ustalenie identyfikatora zapory
Lista zapór pokazuje nazwę, hostname, numer seryjny, firmware i 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"
Należy przejąć UUID właściwej zapory i nie wybierać jej wyłącznie na podstawie podobnej nazwy wyświetlanej:
read -r -p 'UUID firewalla z zatwierdzonego spisu: ' 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
Jeśli brakuje zapory, najpierw należy sprawdzić tenanta, region, połączenie z Sophos Fusion i zezwolenie na zarządzanie. Rejestrację opisuje artykuł Łączenie Sophos Firewall z Sophos Fusion.
Eksport konfiguracji
Uruchomienie pełnego eksportu
Eksport jest wykonywany asynchronicznie. Pierwsze wywołanie zwraca więc tylko identyfikator transakcji:
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"
Po kilku sekundach ponownie pobrać status:
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"
Powtarzać żądanie mniej więcej co dziesięć sekund, aż status osiągnie stan końcowy finished. Wartości pending i started nie oznaczają jeszcze błędu.
Dopiero przy status: "finished" i result: "success" pole response.url zawiera ograniczony czasowo adres pobierania:
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
Plik TAR może zawierać poufne dane sieciowe, użytkowników, VPN i polityk. Należy przechowywać go w bezpiecznym miejscu lub usunąć po analizie. Do przygotowania czytelnego raportu albo porównania stanu przed zmianą i po niej można użyć zawartego pliku Entities.xml w Sophos Firewall Config Studio.
Eksport tylko wybranych konfiguracji
Przy eksporcie selektywnym nazwy encji trzeba podać dokładnie i z zachowaniem wielkości liter. Poniższy przykład eksportuje reguły zapory i NAT wraz z obiektami zależnymi:
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"
Nazwy encji są dokładne i uwzględniają wielkość liter; w przykładzie użyto FirewallRule oraz NATRule. Dla eksportu selektywnego domyślna wartość includeDependency to false; opcję należy ustawić świadomie i mimo to sprawdzić wynikowy pakiet.
Zakres i ograniczenia pakietu
Przed importem przez API trzeba również uwzględnić następujące reguły SFOS dotyczące pliku TAR:
- Import aktualizuje istniejące ustawienia. Ustawienie nieobecne w pakiecie pozostaje bez zmian na zaporze docelowej; jeśli występuje w obu konfiguracjach, pierwszeństwo ma wartość importowana.
- Przy uwierzytelnianiu zewnętrznym eksport obejmuje tylko użytkowników utworzonych ręcznie na zaporze.
OTPTokenszawiera wyłącznie tokeny wydane takim użytkownikom. REDDevicenie dołącza automatycznie wymaganego serwera DHCP, nawet zincludeDependency. Należy również wyeksportowaćDHCPServeralbo odtworzyć serwer DHCP po imporcie.- Importowana lista URL może zawierać najwyżej 128 domen.
- Dla modeli XGS 88w, 108w, 118w i 128w obowiązują dodatkowe warunki dotyczące konfiguracji bezprzewodowej, między innymi pasm częstotliwości, Security mode, Encryption, mostów i liczby unikalnych SSID.
Lista zawartości TAR odczytana bez błędów potwierdza więc tylko możliwość otwarcia archiwum. Nie dowodzi, że zawiera ono wszystkie potrzebne obiekty ani że zadziałają one na sprzęcie docelowym.
Import konfiguracji
Import składa się z zażądania adresu URL wysyłania, przesłania pliku TAR, potwierdzenia danych pliku i sprawdzenia transakcji. Przykład używa wyłącznie zapory testowej i celowo ustawia performPartialImport na false. Domyślna wartość API to true i dopuszcza częściowy import dla każdej zapory.
Najpierw należy sprawdzić zgodność: zapora docelowa wymaga co najmniej tej samej wersji firmware i Pattern. Importy selektywne pomiędzy różnymi modelami Sophos obsługuje tylko z modelu niższego do wyższego; sprzęt docelowy musi mieć co najmniej tyle samo portów Ethernet. Przy innych nazwach portów trzeba odpowiednio dostosować Entities.xml przed wysłaniem.
Przygotowanie pliku importu i sumy kontrolnej
Przygotować plik docelowy, sumę kontrolną i rozmiar pliku:
FILE="sophos-firewall-config-2026-08-03.tar"
FILE_SIZE=$(wc -c <"$FILE" | tr -d ' ')
W systemie macOS:
CHECKSUM_MD5=$(md5 -q "$FILE")
W systemie Linux:
CHECKSUM_MD5=$(md5sum "$FILE" | awk '{print $1}')
Żądanie sesji wysyłania i przesłanie pliku
Zażądać sesji wysyłania i wyświetlić tylko pola, które nie są poufne:
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"
Przed wygaśnięciem Pre-signed URL przesłać plik metodą PUT zwróconą przez API. Do tego adresu URL nie wysyłać nagłówka JWT ani tenanta:
curl --fail-with-body --silent --show-error \
--request PUT \
--upload-file "$FILE" \
"$UPLOAD_URL"
unset UPLOAD_URL
Zakończenie importu i sprawdzenie statusu
Jeśli pakiet zawiera informacje poufne i jest importowany na inną lub ponownie wdrożoną zaporę, potrzebny jest właściwy Secure Storage Master Key. Bez niego SFOS nie zaimportuje informacji poufnych ani zależnych od nich konfiguracji. Poniższy monit nie wyświetla sekretu; naciśnięcie Enter pozostawia pole puste:
read -r -s -p "Secure Storage Master Key lub Enter, aby pominąć: " SSMK
printf '\n'
Zakończyć wysyłanie i przypisać pakiet do zapory docelowej:
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"
Jedno żądanie przyjmuje od 1 do 25 unikalnych identyfikatorów zapór. Dla kolejnych zapór pakiet trzeba przesłać ponownie; nie wolno ponownie używać tego samego Pre-signed URL ani identyfikatora transakcji.
Sprawdzić status importu przez ten sam punkt końcowy transakcji:
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"
Także to żądanie należy powtarzać mniej więcej co dziesięć sekund, aż pojawi się status: "finished". Dopiero wtedy ocenić result, a przy wielu zaporach docelowych także każdy element w response.items.
Wartość success potwierdza przetworzenie przez API, a nie merytoryczny rezultat.
Lokalna weryfikacja importu
Po uzyskaniu finished na każdej zaporze docelowej należy sprawdzić:
- Czy znajdują się na niej dokładnie oczekiwane reguły, obiekty i ustawienia?
- Czy z powodu brakującego lub nieprawidłowego SSMK brakuje użytkowników, haseł, certyfikatów albo obiektów zależnych?
- Czy interfejsy, strefy, bramy, firmware, wersja Pattern i model sprzętowy pasują do pakietu?
- Czy routing, NAT, VPN, uwierzytelnianie i dostęp administracyjny działają zgodnie ze zdefiniowanymi przypadkami testowymi?
- Czy Audit Trail i logi konfiguracji pokazują nieoczekiwane zmiany?
- Czy ponowny eksport lub porównanie w Config Studio pokazuje wyłącznie planowane różnice?
Import/Export aktualizuje istniejącą konfigurację i nie usuwa automatycznie wszystkiego, czego brakuje w pakiecie. Plik TAR nie jest więc ani pełnym stanem docelowym, ani zamiennikiem kopii zapasowej, rollbacku i testu działania.
Wycofanie błędnego importu
Jeśli lokalna weryfikacja się nie powiedzie, należy zatrzymać wdrożenie, zachować odpowiedź transakcji i nie maskować wyniku kolejnymi importami. Aby przywrócić konfigurację w lokalnym WebAdmin, przejść do Backup and firmware > Backup and restore. W sekcji Restore configuration wybrać wcześniejszą kopię przez Choose file, podać jej Encryption password i uruchomić Upload and restore.
Odtworzenie zastępuje bieżącą konfigurację, usuwa backup przechowywany na zaporze i uruchamia ją ponownie. Następnie aktywny staje się adres IP WebAdmin z odtworzonej konfiguracji. Przed importem trzeba więc znać ten adres i hasło szyfrowania. Po restarcie należy powtórzyć te same testy funkcjonalne i sprawdzić wynik nowym eksportem; zmiany wykonane po utworzeniu kopii zostaną utracone.
Rozwiązywanie problemów
Eksport pozostaje bez adresu pobierania
Adres URL pojawia się dopiero przy status: "finished" i result: "success". Przy error lub partialSuccess należy sprawdzić pola w response i nie kontynuować z pustym albo wygasłym adresem URL.
HTTP 401 lub 403
Kod 401 zwykle oznacza, że JWT wygasł lub jest nieprawidłowy. Należy uwierzytelnić się ponownie. Przy 403 sprawdzić rolę Sophos Fusion, kontekst tenanta, X-Tenant-ID i regionalny host API. Lokalne zezwolenie XML API pod /webconsole/APIController nie ma tu zastosowania; opisano je osobno w artykule Zabezpieczanie dostępu do XML API w Sophos Firewall.
Upload-complete zwraca 400 lub 409
Sprawdzić identyfikator transakcji, czas wygaśnięcia adresu wysyłania, rzeczywisty rozmiar pliku, szesnastkową sumę kontrolną MD5 oraz unikalność identyfikatorów zapór. Po wysłaniu pliku nie wolno go zmieniać. Przy kolejnej próbie należy utworzyć nową sesję wysyłania.
Import kończy się statusem error lub partialSuccess
Zapisać response, a przy wielu zaporach docelowych także response.items. Jeśli wywołanie API zwraca oddzielną odpowiedź błędu 4xx lub 5xx, dodatkowo udokumentować error, message, code, correlationId i requestId. Następnie lokalnie sprawdzić wersję docelową, Pattern, model, porty, zależności i SSMK. Jeśli odpowiedź Sophos Fusion jest niewystarczająca, sprawdzić na zaporze plik fwcm-api-executor.log zgodnie z artykułem Usługi i pliki logów Sophos Firewall.
Dla statusu API miarodajny jest punkt końcowy transakcji; nie należy zakładać, że zadanie pojawi się w kolejce zadań Sophos Central Firewall.
Na końcu sesji usunąć zmienne zawierające dane poufne:
unset JWT CLIENT_ID TENANT_ID API_HOST FIREWALL_ID TARGET_FIREWALL_ID
unset EXPORT_TX IMPORT_TX CHECKSUM_MD5 FILE_SIZE