Wywiad z Łukaszem o pragmatycznym podejściu do tworzenia infrastruktury dla klienta korporacyjnego

Łukasz C.: Cześć! Spotkaliśmy się dzisiaj, aby porozmawiać o korzyściach płynących z pragmatycznego podejścia do tworzenia infrastruktury i wykorzystania możliwości chmury obliczeniowej przez klienta korporacyjnego.

Łukasz T.: Cześć, zgadza się, będę opowiadał o podnoszeniu poziomu bezpieczeństwa informacji, automatyzacji procesów związanych z budowaniem produktów i przyspieszeniu działania aplikacji dla klienta korporacyjnego. Współpracę z klientem zaczęliśmy ok. 4 lata temu od audytu infrastruktury. Okazało się, że jest sporo do poprawy lub wypracowania od podstaw.

Na czym polegało podniesienie poziomu bezpieczeństwa informacji?

Wdrożyliśmy podejście polegające na podzieleniu środowisk na konta na poziomie AWS-a. Taka struktura zapewnia izolację poszczególnych kont między sobą, a tym samym zwiększa bezpieczeństwo. Dodatkowo klient uzyskał większą przejrzystość kosztową, widać było co ile kosztuje w rozbiciu na poszczególne aplikacje i środowiska. W efekcie ułatwiliśmy zarządzanie infrastrukturą.
Usunęliśmy Elastic beanstalk, ponieważ rozwiązanie to nie było optymalne dla aplikacji, które klient uruchamiał oraz powodowało wiele problemów, a co za tym idzie – spowalniało tempo wdrażania nowych funkcjonalności. Wdrożyliśmy na początku infrastrukturę opartą o usługę ECS’a, a do bardziej zaawansownych przypadków, które pojawiły się na późniejszych etapach projektu – klastry oparte o Kubernetes’a.

Co zostało poddane automatyzacji?

Zależało nam na zautomatyzowaniu całej procedury wdrażania aplikacji. Dzięki naszej pracy, kod wytworzony przez programistę od momentu przesłania go do repozytorium do uruchomienia wersji produktu był procedowany automatycznie. Jest to istotne pod kątem bezpieczeństwa systemu oraz bezpieczeństwa biznesowego. Innymi słowy, wiedza na temat wdrażania nowej wersji aplikacji nie jest rozproszona między programistami, tylko zamieniona w kod, który realizuje proces automatycznie.

Jak przyspieszyliście działanie aplikacji

Patrząc na architekturę systemu, przed wszystkimi aplikacjami postawiliśmy Cloudfront. To nam dało dodatkową warstwę zabezpieczenia, ponieważ Cloudfront chroni przed atakami typu distributed denial-of-service. Jednocześnie zapewnia mechanizmy Content Delivery Network umożliwiające tworzenie lokalnych kopii rzadko zmieniających się obiektów blisko klienta końcowego, dzięki czemu aplikacja dla klienta końcowego ładuje się o wiele szybciej, co ma duże znaczenie przy aplikacjach, których klient używa.

Co z problemem zarządzania rosnącym środowiskiem aplikacji

Ponieważ zespoły pracujące u klienta najlepiej znały Jenkinsa i umiały go wydajnie automatyzować przy użyciu DSL, wprowadziliśmy jego dodatkową instancję, którą nazwaliśmy roboczo Management. Ten Jenkins różnił się od typowych Jenkinsów tym, że nie budował oprogramowania, natomiast uruchamiał automatyczne playbooki napisane m.in. w Ansible. Innymi słowy stworzyliśmy centralny punkt, w którym odbywało się zarządzanie wszystkimi środowiskami.
Dodatkowo można było ustawić, aby poszczególne rzeczy uruchamiały się albo cyklicznie (na przykład backupy, weryfikacje bezpieczeństwa środowisk) bądź też na żądanie (np. playbooki związane z aktualizacją poszczególnych systemów operacyjnych).

Ansible’a został wybrany jako wiodące narzędzie do automatyzacji całej infrastruktury na poziomie operacyjnym. Dawało nam to bardzo wiele korzyści. Po pierwsze Ansible jest bardziej przejrzysty niż skrypty tworzone manualnie. Po drugie dostarcza dużo gotowych modułów, których można użyć, żeby przyspieszyć wdrażanie oprogramowania. Ansible umożliwia orkiestrację wykonywanych zadań pomiędzy poszczególnymi maszynami. Obsługiwaliśmy nim poszczególne instancje, rzeczy wdrożeniowe, jak również konfigurację baz danych w chmurze.

Co z aktualizacją maszyn?

Maszyny były aktualizowane Ansible’m, przy czym wyróżnić trzeba dwa rodzaje maszyn. Pierwszy rodzaj wymaga pielęgnacji. Były to na przykład serwery obsługujące Active Directory wraz z Federation Services. O te maszyny trzeba było dbać, ponieważ na nich były przechowywane dane i konfiguracja usług. Z drugiej strony mieliśmy klastry, na których były uruchomione aplikacje, w ramach grup autoskalujących. Innymi słowy, liczba dostępnych zasobów dostosowywała się dynamicznie do rosnącego obciążenia. W celu zapewnienia bezpieczeństwa tych maszyn zastosowaliśmy rozwiązanie Packer, które w połączeniu z Ansible generowało nam tzw. golden images, na bazie których stawialśmy klastry aplikacyjne.

Jakie praktyki wykorzystaliście przy projektowaniu infrastruktury?

Architektura była projektowana na bazie najlepszych praktyk branżowych oraz zaleceń AWS, np. Well Architected Framework a także mojego doświadczenia wyniesionego z poprzednich projektów realizowanych w chmurze AWS – m.in. wdrażania infrastruktury dla dwóch zagranicznych domów maklerskich.

Jak wykorzystaliście podejście ‘Infrastructure as a code’?

Całość infrastruktury była tworzona w podejściu infrastructure as a code. W tym podejściu wszystkie zasoby są tworzone w kodzie, a następnie przy użyciu dedykowanych narzędzi typy Terraform, wdrażamy tak opisaną infrastrukturę do chmury. Dało nam to bardzo wiele korzyści.

Po pierwsze audytowalność. Każda zmiana kodu zostawia ślad w repozytorium. Widać, kto zmienił, co zmienił i jak zmienił. Po drugie możliwość wykrycia rozjazdów w konfiguracji. Jeśli ktoś ręcznie dokona modyfikacji po stronie chmury to powstaje różnica względem kodu, którą możemy łatwo wykryć i zlikwidować.
Po trzecie, powtarzalność. Raz napisany kod można używać wielokrotnie do różnych środowisk. Tworząc kolejne rozwiązania, można bazować na gotowych komponentach co znacząco przyspiesza proces wdrażania infrastruktury dla aplikacji.

Jak zostało zrealizowane zarządzanie logami?

Do przetwarzania logów, wybraliśmy rozwiązanie bezpieczne i wygodne dla programistów. Wdrożyliśmy tak zwany stack EFK, czyli Elasticsearch, Fluent Bit i Kibana dla danych aplikacji, natomiast dla logów z chmury zrealizowaliśmy rozwiązania oparte o Kinesis Firehose celem zapewniania optymalnego parsowania danych z logów. Te rozwiązania zbierały logi z aplikacji przekazywało je do centralnego miejsca umożliwiając szybkie i wygodne diagnozowanie problemów z aplikacjami

W jaki sposób zorganizowaliście zarządzanie kontami użytkowników?

Na bazie z Active Directory wraz z Federation Services wdrożyliśmy rozwiązanie umożliwiające logowanie do wszystkich kont AWS, a także do aplikacji biznesowych dostępnych dla pracowników klienta. Dało nam to bardzo wiele korzyści, bo cały proces zarządzania cyklem życia użytkownika w organizacji mógł być wykonywany w centralnym miejscu. Usunęliśmy potrzebę logowania się do wielu usług i miejsce i zastąpiliśmy je zgrabnym rozwiązaniem Single Sign-on.
Dzięki dobrej konfiguracji i definicji ról, można było przypisywać uprawnienia per aplikacja. Na poziomie grup w Active Directory modelowaliśmy Role Based Access Control, który mapował się na faktyczne role czy to w AWS-ie, czy też w poszczególnych aplikacjach.

Co z wdrożeniem MFA?

Ze względów bezpieczeństwa konieczne było wdrożenie rozwiązania MFA. Po analizie dostępnych rozwiązań okazało się, że jest bardzo dużo dostawców, którzy dostarczają swoje rozwiązanie MFA w cenie 10 USD za użytkownika miesięcznie. Dla stu użytkowników w skali roku robi się pokaźny koszt dla klienta. Chcąc tego uniknąć, postanowiliśmy napisać dodatek do Active Directory Federation Services, który realizował funkcjonalność MFA przy użyciu protokołu TOTP, czyli wspierał popularny Google Authenticator i podobne. Podsumowując, nie tylko skonfigurowaliśmy infrastrukturę, ale celem obnizenia kosztów licencji, wytworzyliśmy brakujące elementy dla tej infrastruktury.

Jak został skonfigurowany monitoring bezpieczeństwa aplikacji?

Nasz klient miał duże wymagania w zakresie bezpieczeństwa. Wprowadzaliśmy cały zestaw produktów związanych z monitoringiem, wykrywaniem zagrożeń oraz im przeciwdziałaniu. Między innymi wdrożyliśmy Guard Duty – rozwiązanie, które automatycznie wykrywa anomalie w sieciach i w konfiguracji usług. Wdrożyliśmy AWS Inspector – narzędzie do wykrywania podatności w konfiguracji instancji, a także narzędzia anti-malware zewnętrznych dostawców. Do weryfikacji poprawności konfiguracji po stronie infrastruktury użyliśmy AWS Config. Narzędzie to pozwala zdefiniować reguły bezpieczeństwa i niezależnie od całej reszty platformy weryfikuje te reguły pod kątem zgodności z wymogami (ang. compliance).

Co z bazami danych?

Relacyjne bazy danych wdrożyliśmy w oparciu o usługę zarządzaną o nazwie RDS. To rozwiązanie umożliwia łatwe szyfrowanie at rest oraz in transit, a także uwierzytelnianie bezhasłowe, jak również automatyczne kopie zapasowe w formie snapshotów.

Jak infrastruktura była przygotowana na odparcie najczęstszych ataków na aplikacje webowe?

Aby spełnić wymagania bezpieczeństwa oraz zabezpieczyć się przeciwko najpopularniejszym atakom na aplikacje webowe wdrożyliśmy rozwiązanie web application firewall, które w połączeniu z pozostałym usługami wdrożonymi w ramach infrastruktury dało solidną warstwę zabezpieczeń.

Jak została zorganizowana integracja pomiędzy biurami z różnych regionów oraz chmurą?

Zdecydowaliśmy się na zaawansowany networking. Była to odpowiedź na potrzebę łączenia biur z różnych regionów oraz zapewnienia dostępu do zasobów w chmurze. Po analizie wymagań, zdecydowaliśmy się wdrożyć rozwiązanie transit gateway – hub, który scala sieci w AWS-ie a także pozwala na podpinanie tuneli VPN typu site-to-site.

Jakbyś podsumował wszystkie korzyści dla klienta wynikające z naszego pragmatycznego podejścia?

Bardzo wysoki poziom bezpieczeństwa systemów. Tam, gdzie znalazło to uzasadnienie biznesowe – redukcja zależności od zewnętrznych dostawców poprzez wytworzenie własnych komponentów, centralizacja zarządzania tożsamością i redukcja kosztów. Wysoki poziom automatyzacji. W pewnym momencie de facto całość infrastruktury obsługiwała jedna osoba. Klient się przekonał o naszych wysokich kompetencjach, zaufał nam i w szerokim zakresie wykorzystał możliwości chmury AWS.