W części 1 zaprezentowaliśmy szybki przegląd S/MIME, przyglądając się podpisywaniu i szyfrowaniu naszych strumieni wiadomości w różnych klientach pocztowych. Część 2 wprowadziła nas do prostego narzędzia wiersza poleceń do podpisywania i szyfrowania e-maili, a następnie przesyłania ich przez SparkPost. Część 3 pokazała, jak wstrzykiwać zabezpieczone strumienie e-mailowe do lokalnych platform takich jak Port25 PowerMTA i Momentum.
W tej serii widzieliśmy, jak łatwo można dodać podpis S/MIME. Wysyłanie szyfrowanych wiadomości S/MIME jest bardziej skomplikowane, ponieważ musisz uzyskać publiczne klucze odbiorców. To jedna rzecz, gdy używasz klienta poczty dla ludzi, takiego jak Thunderbird – ale jak to działa z generowanymi przez aplikacje strumieniami e-mailowymi?
Ale poczekaj – jest inny sposób na dostęp do Mordoru, aby uzyskać te klucze. Twoja usługa może zaprosić klientów (za pośrednictwem e-maila, oczywiście) do odesłania podpisanego e-maila na znany adres obsługi klienta. Używając magicznych mocy webhooks SparkPost Inbound Relay, wyciągniemy i zapisujemy ten klucz publiczny, abyś mógł go używać.
Możemy to podsumować w prostym przypadku użycia:
Jako odbiorca wiadomości, przekazuję Twojej usłudze mój osobisty podpis e-mailowy za pośrednictwem e-maila, aby w przyszłości e-maile mogły być wysyłane do mnie w szyfrowanej formie S/MIME.
Z tego możemy wyprowadzić bardziej szczegółowe wymagania:
Potrzebujemy usługi e-mailowej z zawsze włączonym i niezawodnym odbiorem do odbierania tych podpisanych e-maili.
Nie powinno być żadnych specjalnych wymagań dotyczących formatu maila, poza tym, że powinien zawierać podpis S/MIME.
Ponieważ każdy może próbować wysłać e-mail do tej usługi, powinna być zaprojektowana defensywnie, na przykład, aby odrzucać „fałszywe” wiadomości od złych podmiotów. Będzie potrzebnych kilka warstw sprawdzania.
Jeśli wszystko wygląda dobrze, usługa zapisze certyfikat w pliku, używając znanego formatu Privacy-Enhanced Mail (PEM).
Są pewne wymagania niefunkcjonalne:
Usługi webhook machine-to-machine mogą być trudne do zauważenia tylko na podstawie odpowiedzi na to, co dzieje się w środku. Usługa powinna zapewniać obfite logi aplikacyjne czytelne dla ludzi. W szczególności powinno być rejestrowane analizowanie i sprawdzanie certyfikatu.
Dodajemy przypadki testowe dla wewnętrznych procesów aplikacji, korzystając z ładnego frameworka Pytest, i uruchamiamy te testy automatycznie podczas dodawania za pomocą integracji Travis CI z GitHubem.
Dobrze – zaczynajmy!
1. Przegląd rozwiązania
Oto, jak będzie wyglądać ogólne rozwiązanie.
2. Instalacja, konfiguracja i uruchamianie aplikacji webowej
Zaczniemy od tej części, aby mieć ją w pełni przetestowaną przed zrealizowaniem webhooków relayowego odbioru.
Aplikacja webowa jest zawarta w tym samym projekcie GitHub co części 1 – 3, więc jeśli śledziłeś te części, już ją masz. Oto nowe elementy:
Program readSMIMEsig.py – odczytuje e-mail i wyodrębnia certyfikaty pośrednie i użytkownika.
Program webapp.py – prosta aplikacja webowa zgodna z Flask, do użycia z webhookami SparkPost Inbound Relay.
webapp.ini – plik konfiguracyjny dla powyższego. Plik konfiguracyjny umożliwia łatwe przekazywanie tych samych wartości zarówno do aplikacji wiersza poleceń, jak i aplikacji webowych.
Musisz upewnić się, że Twój host ma otwarty odpowiedni numer portu TCP do przychodzących żądań z zewnątrz, aby SparkPost mógł przesyłać wiadomości do Twojej aplikacji. Jeśli jesteś hostowany na AWS EC2, na przykład, będziesz musiał skonfigurować grupę zabezpieczeń swojego instancji.
Instrukcje dotyczące konfigurowania i uruchamiania aplikacji webowej znajdują się tutaj – to dość łatwe. Aby sprawdzić, czy Twoja aplikacja działa i jest dostępna z zewnątrz, możesz wysłać (puste) żądania z innego hosta, używając curl, na przykład:
curl -X POST https://app.trymsys.net:8855/
Powinieneś zobaczyć odpowiedź taką jak:
{"message":"Nieznany typ treści w nagłówkach żądania"}
To dobra rzecz – Twoja aplikacja działa!
W webapp.log na swoim hoście zobaczysz dane wyjściowe podobne do tego:
2019-01-15 00:11:07,575,root,INFO,Żądanie od 38.96.5.10,schemat=https,ścieżka=/ 2019-01-15 00:11:07,575,root,INFO,| len(nagłówki)=3,len(ciało)=Brak 2019-01-15 00:11:07,575,root,INFO,| Nieznany typ treści: None
Aby pomóc Ci od razu bawić się rzeczywistymi danymi w Twojej aplikacji, możesz zaimportować to konkretne żądanie Postman z repozytorium projektu. To symuluje, co będzie robić Twoje konto SparkPost, tzn. wysyła https POST zawierające e-mail z określonym, ważnym certyfikatem (należącym do mojego konta testowego) do Twojej aplikacji.
Musisz tylko zmienić adres docelowy w żądaniu (w szarej ramce powyżej), aby dopasować go do swojej instalacji. Jeśli zmieniłeś wartość tokena w webapp.ini, dostosuj wartość nagłówka w Postmanie, aby była zgodna.
Jeśli Twoja aplikacja działa, zobaczysz odpowiedź „200 OK” w Postmanie. Twój plik logów webapp.log na hoście będzie zawierał dane wyjściowe podobne do tego:
2019-01-15 00:11:48,554,root,INFO,Żądanie od 38.96.5.10,schemat=https,ścieżka=/ 2019-01-15 00:11:48,554,root,INFO,| len(nagłówki)=10,len(ciało)=14778 2019-01-15 00:11:48,555,root,INFO,| msg_from=bob.lumreeker@gmail.com,rcpt_to=secureme@inbound.thetucks.com,len(email_rfc822)=9223 2019-01-15 00:11:48,599,root,INFO,| from=bob.lumreeker@gmail.com,DKIM przeszło 2019-01-15 00:11:48,600,root,INFO,| typ-treści=multipart/signed; protokół="application/pkcs7-signature"; micalg=sha-256; granica="------------ms010908020707040304020406",opis-treści=Brak 2019-01-15 00:11:48,600,root,INFO,| typ-treści=text/plain; charset=utf-8; format=flowed,opis-treści=Brak 2019-01-15 00:11:48,600,root,INFO,| typ-treści=application/pkcs7-signature; nazwa="smime.p7s",opis-treści=Podpis kryptograficzny S/MIME 2019-01-15 00:11:48,600,root,INFO,| nazwa pliku=smime.p7s,bytes=3998 2019-01-15 00:11:48,601,root,INFO,| Certyfikat: podmiot email_address=['bob.lumreeker@gmail.com'],not_valid_before=2018-10-03 00:00:00,not_valid_after=2019-10-03 23:59:59,hash_algorithm=sha256,key_size=2048 bajtów, issuer={'countryName': 'GB', 'stateOrProvinceName': 'Greater Manchester', 'localityName': 'Salford', 'organizationName': 'COMODO CA Limited', 'commonName': 'COMODO RSA Client Authentication and Secure Email CA'} 2019-01-15 00:11:48,602,root,INFO,| Certyfikat: podmiot email_address=[],not_valid_before=2013-01-10 00:00:00,not_valid_after=2028-01-09 23:59:59,hash_algorithm=sha384,key_size=2048 bajtów, issuer={'countryName': 'GB', 'stateOrProvinceName': 'Greater Manchester', 'localityName': 'Salford', 'organizationName': 'COMODO CA Limited', 'commonName': 'COMODO RSA Certification Authority'} 2019-01-15 00:11:48,616,root,INFO,| zapisany plik ./bob.lumreeker@gmail.com.crt,bajty=1870,ok=True
Aby szybko sprawdzić poprawność, poszukaj ostatniej linii – jeśli mówi „zapisany plik”, to jesteś w porządku. Reszta tego pokazuje proces sprawdzania DKIM i walidacji certyfikatu.
3. Ustawienia webhooków relayowego odbioru SparkPost
Najpierw wybieramy domenę do wykorzystania jako nasz adres wiadomości przychodzącej – tutaj będzie to inbound.thetucks.com. Skonfiguruj swoją domenę zgodnie z tym przewodnikiem. Oto kroki, które użyłem szczegółowo:
3.1 Dodaj rekordy MX
Będziesz potrzebował dostępu do swojego konta u konkretnego dostawcy usług internetowych. Po zakończeniu możesz je sprawdzić za pomocą dig – oto polecenie dla mojej domeny.
dig +short MX inbound.thetucks.com
Powinieneś zobaczyć:
10 rx3.sparkpostmail.com. 10 rx1.sparkpostmail.com. 10 rx2.sparkpostmail.com.
3.2 Utwórz domenę przychodzącą
Skorzystaj z kolekcji API Postman SparkPost, wybierając wywołanie Inbound Domains / Create... Ciało żądania POST zawiera Twoją domenę, na przykład:
{ "domain": "inbound.thetucks.com" }
3.3 Utwórz webhook relayowy
Utwórz webhook relayowy przychodzący, używając odpowiedniego wywołania Postman. Ciało wiadomości w moim przypadku zawiera:
{ "name": "Webhook zbierania certyfikatów", "target": "https://app.trymsys.net:8855/", "auth_token": "t0p s3cr3t t0k3n", "match": { "protocol": "SMTP", "domain": "inbound.thetucks.com" } }
Jak już wspomniałem, polecam ustawić auth_token na swoją własną tajną wartość, jak ustawiono w pliku webapp.ini na Twoim hoście.
Wartość „target” musi pasować do adresu Twojego hosta oraz portu TCP, na którym będziesz hostować aplikację webową.
Wartość „domain” musi pasować do rekordów MX ustawionych w kroku 1.
To wszystko! Instalacja jest zakończona. Powinieneś teraz być w stanie wysyłać certyfikaty na swój adres przychodzący, będą przetwarzane i pojawią się na hoście Twojej aplikacji webowej – w tym przypadku plik o nazwie bob.lumreeker@gmail.com.crt.
Teraz możesz wysyłać szyfrowane e-maile do Boba, korzystając z narzędzi opisanych w częściach 2 i 3 tej serii.
Możesz zbadać zawartość certyfikatu, używając:
openssl x509 -inform PEM -in bob.lumreeker\@gmail.com.crt -text -noout
4. Wnętrze: sprawdzanie DKIM, walidacja certyfikatu
Aplikacja sprawdza, czy otrzymane e-maile mają ważny DKIM i sprawdza, czy certyfikaty same w sobie są ważne, jak opisano tutaj. Są tam również notatki dotyczące implementacji i pomysły na dalsze prace.
Podsumowując…
Widzieliśmy, jak łatwo można zebrać publiczne klucze odbiorców, korzystając z e-maila wysłanego na adres webhooka przychodzącego. Kiedy to się uda, ci odbiorcy mogą otrzymywać swoje wiadomości w szyfrowanej formie S/MIME.
Na razie to wszystko! Szczęśliwego wysyłania.