Automatyzacja S/MIME Sophos Email przez API
Sophos Email Management API umożliwia zarządzanie całym cyklem życia certyfikatów S/MIME. Bezpieczna kolejność to: odczyt inwentarza, utworzenie lub przesłanie dokładnie jednego wewnętrznego CA tenanta, początkowe utworzenie wyłączonej konfiguracji, dodanie zaufanych CA i certyfikatów zewnętrznych, włączenie S/MIME, dodanie certyfikatów wewnętrznych, a następnie test przepływu poczty. Artykuł celowo rozróżnia wewnętrzny CA tenanta, zaufane zewnętrzne CA, certyfikaty użytkowników wewnętrznych oraz certyfikaty odbiorców zewnętrznych. Mają różne ścieżki i nie są zamienne.
Architekturę, policy i testy w interfejsie opisuje instrukcja S/MIME w GUI. Wprowadzenie do Sophos Email Management API wyjaśnia ogólny kontrakt; OAuth2, wybór tenanta i host regionalny znajdą się w planowanym runbooku uwierzytelniania API i tenant routing.
Ostrzeżenie krytyczne:
DELETE /smime/config/{deleteToken}usuwa wszystkie certyfikaty S/MIME i klucze prywatne tenanta oraz ustawiasmimeEnablednafalse. Nie jest to rotacja ani zwykłe rozwiązywanie problemu. API nie dokumentuje eksportu kluczy prywatnych. Bez osobno zachowanych, autoryzowanych źródeł PKCS#12 klucze i możliwość odszyfrowania historycznej treści mogą zostać utracone bezpowrotnie.
Wymagania i bezpieczna baza requestów
Użyj tylko zweryfikowanych SOPHOS_ACCESS_TOKEN (krótkotrwały bearer token), SOPHOS_TENANT_ID (UUID tenanta) i SOPHOS_API_HOST (pełny host regionalny). Sprawdzona specyfikacja to Email Management API v1.4.0; przed wdrożeniem sprawdź aktualną wersję. Wszystkie ścieżki są względne wobec /email/v1 i wymagają Authorization: Bearer ***, X-Tenant-ID, a dla JSON także Content-Type: application/json:
EMAIL_API_HOST="${SOPHOS_API_HOST%/}/email/v1"
Tokenów, deleteToken, haseł i treści PKCS#12 ani kluczy prywatnych nie umieszczaj w argumentach, kodzie, zwykłych logach lub zgłoszeniach. Używaj zatwierdzonego secret store, plików w trybie 600 i usuwaj pliki tymczasowe. Zastąp ops@example.net i alice@example.net zatwierdzonymi adresami.
Przed pierwszym zapisem wykonaj odczyty i zapisuj tylko status HTTP, requestId/correlationId błędów oraz wynik walidacji schematu:
GET /smime/config
GET /smime/ca/internal
GET /smime/users/internal?pageSize=1
404 w dwóch pierwszych oznacza brak obiektu. Listy zwracają items i pages; przekazuj pages.nextKey zakodowane dla URL jako pageFromKey, aż zabraknie nextKey.
Przygotowanie wewnętrznego CA tenanta
Wewnętrzny CA podpisuje certyfikaty tworzone przez Sophos dla użytkowników wewnętrznych. Tenant ma dokładnie jeden taki CA. Utworzenie lub upload w razie potrzeby automatycznie tworzy wyłączoną konfigurację S/MIME, ale nie włącza S/MIME. Druga próba zwraca 409; sprawdzone API nie ma osobnej ścieżki usuwania lub wymiany tylko tego CA.
Opcja A: CA tworzony przez Sophos
POST /smime/ca/internal wymaga organizationName, locality, country i email. country to dokładnie dwie wielkie litery ISO 3166-1. Opcjonalne są organizationUnit oraz certExpiryDate (YYYY-MM-DD) albo certValidityPeriod (1–20 lat). Domyślnie jest 20 lat; gdy podano oba, API wybiera krótszy okres.
{
"organizationName": "Example Operations GmbH",
"organizationUnit": "Messaging",
"locality": "Zurich",
"country": "CH",
"email": "ops@example.net",
"certValidityPeriod": 10
}
Sukces to 201. Zachowaj 64-znakowy SHA-256 fingerprint, issuer, validFrom, expiresAt i origin, nie logując niepotrzebnie całej odpowiedzi.
Opcja B: upload CA z kluczem
POST /smime/ca/internal/certificate oczekuje zakodowanego Base64 pakietu certyfikatu i klucza PKCS#12, a nie PEM:
{
"pkcs12": "<BASE64_PKCS12>",
"password": "<PKCS12_PASSWORD>"
}
Po kodowaniu pkcs12 musi mieć 1200–24000 znaków, a password 3–50. Właściciel PKI sprawdza certyfikat, klucz prywatny, łańcuch, przeznaczenie i hasło. Base64 nie chroni klucza. Usuń końce linii i nigdy nie wkładaj PEM do pkcs12.
W obu opcjach potwierdź: GET /smime/ca/internal zwraca ten sam fingerprint; GET /smime/ca/internal/certificate pobiera publiczny PEM jako application/octet-stream; fingerprint odpowiada inwentarzowi. PEM nie zawiera odzyskiwalnego klucza prywatnego CA.
Włączenie konfiguracji dopiero później
GET /smime/config zwraca smimeEnabled, extractCertificate, maksymalnie pięć certExpiryNotificationEmailAddresses i ośmioznakowy deleteToken, który jest destrukcyjnym sekretem.
Brakującą konfigurację utwórz przez POST /smime/config; smimeEnabled jest wymagane, a extractCertificate domyślnie ma false:
{
"smimeEnabled": false,
"extractCertificate": false,
"certExpiryNotificationEmailAddresses": ["ops@example.net"]
}
Dla istniejącej użyj PATCH /smime/config: co najmniej jedno pole, pominięte pola bez zmian, null lub [] usuwa wszystkie adresy, duplikaty są usuwane. Najpierw zapisz smimeEnabled: false, dodaj i zinwentaryzuj zaufane CA oraz zewnętrzne certyfikaty pilota, a dopiero potem wyślij {"smimeEnabled":true}. Bez wewnętrznego CA API zwraca 409. Potwierdź GET, dodaj wewnętrzne certyfikaty pilota i przetestuj podpis oraz szyfrowanie. extractCertificate: true umożliwia tylko ekstrakcję z poczty przychodzącej; nadal obowiązują warunki weryfikacji podpisu w policy Secure Message z instrukcji GUI.
Zarządzanie zaufanymi zewnętrznymi CA
Te CA służą do weryfikacji podpisanych wiadomości; nie są wewnętrznym CA ani certyfikatami użytkowników. Przed uploadem sprawdź w Sophos Fusion (dawniej Sophos Central), czy issuer nie jest już globalnie zaufany, i potwierdź SHA-256 niezależnym kanałem.
GET /smime/cas/external: filtrycommonName,certValidBefore,certValidAfter,certExpiryBefore,certExpiryAfter,certFingerprint,issuerCN,pageFromKey,pageSize(domyślnie50).POST /smime/cas/external/certificate: PEM wcertificate, 300–32000 znaków wraz z nagłówkiem i stopką.GET /smime/cas/external/certificate/{fingerprint}: pobiera dokładny PEM.DELETE /smime/cas/external?certFingerprint=...: usuwa dokładnie ten wpis zaufania.
{
"certificate": "-----BEGIN CERTIFICATE-----\n<BASE64_CERTIFICATE>\n-----END CERTIFICATE-----"
}
Duplikat zwraca 409. Przed DELETE dokładny list read ma zwrócić jeden oczekiwany wpis; po 200 i deleted: true filtr ma być pusty. Następnie sprawdź podpis przez pozostały łańcuch.
Zarządzanie certyfikatami odbiorców zewnętrznych
To publiczne certyfikaty partnerów bez prywatnych kluczy tenanta. POST /smime/users/external/certificate przyjmuje PEM w certificate (300–32000 znaków), ustala tożsamość z certyfikatu i włącza S/MIME dla użytkownika:
{
"certificate": "-----BEGIN CERTIFICATE-----\n<BASE64_CERTIFICATE>\n-----END CERTIFICATE-----",
"confirmVerificationOnlyCert": false
}
Dla DSA/EC confirmVerificationOnlyCert: true świadomie potwierdza ograniczenie do podpisu/weryfikacji, bez szyfrowania/deszyfrowania. Maksymalnie dwa certyfikaty na tożsamość (422 przy następnym); duplikat daje 409.
GET /smime/users/external?email=partner@example.net filtruje dokładny adres i obsługuje emailStartsWith, daty, fingerprint, issuer oraz paginację. GET /smime/users/external/certificate/{fingerprint} pobiera PEM. DELETE /smime/users/external?email=...&certFingerprint=... usuwa tylko dokładną parę z parametrami URL-encoded; ostatni certyfikat usuwa użytkownika z listy. Po uploadzie sprawdź email, fingerprint, issuer i ważność, po czym partner pilota powinien odszyfrować wiadomość testową.
Tworzenie lub upload certyfikatów wewnętrznych
Użytkownik musi istnieć jako pasująca tożsamość tenanta. Create lub upload włącza dla niego S/MIME. Nie normalizuj adresów: użyj dokładnego email z GET.
Do tworzenia użyj POST /smime/users/internal:
{
"email": "alice@example.net",
"certValidityPeriod": 3
}
Tylko email jest wymagany. certExpiryDate/certValidityPeriod podlega tym samym regułom 1–20 lat co CA. Wymagany jest wewnętrzny CA oraz skonfigurowane/włączone S/MIME.
Do uploadu klucza użyj POST /smime/users/internal/certificate:
{
"email": "alice@example.net",
"pkcs12": "<BASE64_PKCS12>",
"password": "<PKCS12_PASSWORD>",
"confirmSigningOnlyCert": false
}
Wymagane są email, pkcs12, password; limity to 1200–24000 znaków Base64 i 3–50 znaków hasła. DSA/EC wymaga confirmSigningOnlyCert: true i pozwala tylko podpisywać/weryfikować. CA zawarte w pakiecie są zapisywane jako zaufane: zweryfikuj łańcuch i sprawdź /smime/cas/external. Maksymalnie dwa certyfikaty na użytkownika; duplikat 409, trzeci 422.
GET /smime/users/internal?email=alice@example.net zwraca dokładnego użytkownika i certyfikaty, a także obsługuje userName, emailStartsWith, filtry daty/fingerprint/issuer i paginację. GET /smime/users/internal/certificate/{fingerprint} pobiera PEM wraz z CA przesłanymi w pakiecie, ale bez klucza prywatnego. DELETE /smime/users/internal?email=...&certFingerprint=... usuwa tylko parę; ostatni usuwa użytkownika z listy S/MIME. Po 201 sprawdź adres, fingerprint, issuer i wygaśnięcie oraz testuj podpis wychodzący i odszyfrowanie przychodzące.
Destrukcyjny reset tylko jako zatwierdzona odbudowa
Wymagana zgoda: usunięte zostaną wewnętrzny CA, zaufane CA, certyfikaty wewnętrzne i zewnętrzne oraz wszystkie zapisane klucze prywatne;
smimeEnabledstanie sięfalse. Nie naprawia to jednego obiektu.
Przed działaniem: (1) zinwentaryzuj wszystkie strony GET /smime/config, /smime/ca/internal, /smime/cas/external, /smime/users/internal, /smime/users/external; (2) dla każdego odzyskiwalnego klucza potwierdź autoryzowane źródło PKCS#12 i przetestowane hasło—PEM nie jest backupem klucza; (3) udokumentuj policy, okno, ownera, partnerów, przerwę i pełną kolejność; (4) pobierz aktualny deleteToken bezpośrednio z GET; (5) druga uprawniona osoba ma sprawdzić tenant, inwentarz, skutek i powiązanie tokena.
Dopiero wtedy wywołaj dokładnie DELETE /smime/config/{deleteToken}. Błędny token daje 409, brak konfiguracji 404. Po timeout, 5xx lub nieznanym wyniku nie ponawiaj w ciemno: najpierw odczytaj konfigurację i inwentarze. Sukces wymaga 200 i deleted: true; potem konfiguracji ma nie być albo ma zostać odbudowana z smimeEnabled: false. Kolejność: wewnętrzny CA, wyłączona konfiguracja, zaufanie, użytkownicy, finalne włączenie.
Walidacja i troubleshooting
Sprawdź dwa poziomy: stan API, przez dokładny GET z email, 64 znakami hex SHA-256, issuer, validFrom, expiresAt, origin, końcem paginacji i konfiguracją; oraz działanie wiadomości, podpisując wychodzącą, weryfikując przychodzącą, szyfrując do pilota zewnętrznego i deszyfrując dla wewnętrznego w małej policy Secure Message. Zapisz Message-ID, UTC i wynik, nigdy klucze lub pełne payloady.
400: pola JSON, nagłówek/stopka PEM, Base64 bez końców linii, hasło PKCS#12, długości, data i email; przetwórz każdeerrors.401/403: token, minimalne uprawnienie i przypisanie tenanta; nie zgaduj regionu.404: host regionalny, dokładna ścieżka, para email/fingerprint i inwentarz.409: CA/certyfikat już istnieje, brak CA przy włączaniu albo złydeleteToken; czytaj stan przed kolejnym zapisem.422: są już dwa certyfikaty; nie usuwaj nieznanego fingerprintu.- Niespodziewana lista: przejdź
pages.nextKey, zakodujpageFromKeyi stosuj dokładny filtr. - Wiadomość nie działa mimo poprawnego GET: sprawdź włączenie, scope/kolejność policy, ważność, tożsamość, łańcuch i key usage; dokończ test według instrukcji GUI.
Do eskalacji wystarczą metoda, ścieżka bez wrażliwych queries, HTTP, UTC, requestId/correlationId, tenant ID, typ obiektu i zanonimizowane metadane. Wyklucz bearer token, deleteToken, hasła, PKCS#12, klucze prywatne i pełne listy osób.