Sposób na dane wrażliwe z Secret Manager i EC2 User data
Ostatnio pracowałem nad automatyzacją ustawienia środowiska na EC2. AWS pozwala na zdefiniowanie powtarzalnych kroków i wykonywanie ich przy tworzeniu nowej EC2 poprzez parametr User Data. Skrypt jest uruchamiany z uprawnieniami systemowymi root. Jednak co w przypadku konieczności użycia danych wrażliwych takich jak hasło czy klucz?
Umieszczenie danych wrażliwych w skrypcie pod postacią zwykłego tekstu jest niezgodne z bezpieczeństwem oraz stwarza problem w przyszłości, gdy ktoś postanowi zmienić ich wartość. AWS posiada serwis do bezpiecznego przechowywania danych - Secret Manager. Tylko jak go użyć w połączeniu z User Data?
Agenda
- Przechowywanie danych w Secret Manger
- Odczyt danych z Secret Manager
- EC2 i odczyt danych z Secret Manager przy starcie
- Wykorzystanie danych z Secret Manager w praktyce
- Podsumowanie
Przechowywanie danych w Secret Manger
Zacznijmy od stworzenia nowego sekretu w Secret Manager. Użyjemy go podczas startu EC2. Przejdź do Secret Manager -> Store a new secret. Następnie wybierz Other type of secret i zdefiniuj klucz/wartość.
Kliknij Next, zdefiniuj nazwę i ponownie naciśnij Next. W następnym kroku możesz zdefiniować automatyczną rotację sekretu. Możemy zostawić domyślne wartości i ponownie nacisnąć Next. Przejrzyj podsumowanie i naciśnij Store, aby zakończyć tworzenie nowego sekretu w Secret Manager.
Zostaniesz przeniesiony na widok wszystkich dostępnych sekretów. W moim przypadku jest to tylko jeden sekret stworzony przed momentem.
Odczyt danych z Secret Manager
Mamy już bezpiecznie przechowywany sekret w Secret Manager. Nie można go jednak odczytać bez odpowiednich uprawnień. EC2 nie będzie w stanie pobrać wartości sekretu bez dodania uprawnień odczytu dla roli EC2. Stwórzmy nową rolę dla EC2.
Przejdź do IAM -> Roles -> Create Role. Wybierz EC2 i kliknij Next: Permissions. Następnie kliknij Create Policy. Zostaniesz przeniesiony do nowej zakładki w przeglądarce, gdzie możesz zdefiniować nową politykę. Przejdź do zakładki JSON i wklej poniższy kod:
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"secretsmanager:GetSecretValue"
],
"Resource": "arn:aws:secretsmanager:us-east-1:215538436894:secret:MySecret-u7eM2x",
"Effect": "Allow"
}
]
}
Pamiętaj o zastąpieniu ARN przez ARN dla Twojego sekretu.
Następnie kliknij Next: Tagi -> Next: Review, nadaj nazwę SecretReadAccess i utwórz Create Policy.
Wróć do zakładki w przeglądarce, gdzie rozpoczęliśmy tworzenie nowe roli. Odśwież widok. W pasku wyszukiwania wpisz SecretReadAccess, zaznacz wiersz i kliknij Next: Tagi -> Next: Review. Nazwij nową rolę EC2InstanceRole i stwórz ją Create role.
EC2 i odczyt danych z Secret Manager przy starcie
Mamy wszystko gotowe do stworzenie nowej EC2 i bezpiecznego odczytania sekretu w skrypcie user data.
Przejdź do EC2 -> Instances -> Launch instances. Wybierz Amazon Linux 2 AMI, typ instancji t2.micro, a następnie przejdź do Configuration Instance Details.
Upewnij się czy opcja Auto-assign Pubilc IP jest aktywna oraz wybierz rolę EC2InstanceRole, którą stworzyliśmy w poprzednim punkcie.
Przewiń stronę aż znajdziesz sekcję Advanced Details, rozwiń ją i powinieneś zobaczyć parametr User data. User data jest skryptem uruchamianym podczas uruchamiania EC2. Stanowi doskonałe narzędzie do automatyzacji instalacji wymaganego oprogramowania czy konfiguracji serwera.
Może się zdarzyć, że Twój skrypt będzie wymagał danych wrażliwych jak hasła, klucze. Nie jest dobrym pomysłem umieszczanie tego typu danych otwartym tekstem w skryptach ze względu na widoczność w logach i w samym skrypcie. Sposobem na użycie wrażliwych danych jest wykorzystanie Secret Managera do przechowywania danych wrażliwych i ich odczyt w skrypcie User data.
Skopiuj poniższy kod do parametru User data. Ta jedna linijka pobierze klucz/wartość z sekretu.
!/bin/bash
aws secretsmanager get-secret-value --region us-east-1 --secret-id MySecret
Pamiętaj o zastąpieniu regionu i secret-id swoimi wartościami.
Kliknij Review and Launch -> Launch (Utwórz nowy klucz SSH, jeżeli nie posiadasz istniejącego). Przejdź do EC2 -> Instances i poczekaj, aż nowa instancja będzie w statusie Running.
Gdy już będzie w poprawnym statusie możemy się do niej zalogować. Zaznacz instancję, a następnie przejdź do Connect -> EC2 Instant Connect -> Connect. Skrypt user data generuje logi, które są składowane w pliku znajdującym się w /var/log/cloud-init-output.log. Powinieneś znaleźć w logu fragment podobny do przedstawionego poniżej.
Jak widzisz, pobraliśmy dane z sekretu bez ich jawnego ujawniania w skrypcie. Nie przejmuj się, że dane są nadal widoczne w logu. W tym kroku jedynie sprawdziliśmy, czy możemy pobrać sekret. W rzeczywistym użyciu raczej chcesz wykorzystać pobraną wartość bez ujawniania w logu.
Wykorzystanie danych z Secret Manager w praktyce
Udało się nam poprawnie pobrać sekret, jednak nie jest on użyteczny w swojej domyślnej wersji. Ze wszystkich informacji, jakie uzyskaliśmy najbardziej pożądana dla nas jest wartość w SecretString. Pokaże Ci teraz jak zwiększyć użyteczność danych pobranych z Secret Managera.
Pobierz tylko SecretString
!/bin/bash
aws secretsmanager get-secret-value --region us-east-1 --secret-id MySecret --query SecretString --output text
Opcja —query pozwala na pobranie wybranej pary klucz/wartość. W naszym przypadku interesuje nas klucz SecretString i jego wartość. Opcja —output definiuje w jakiej postaci chcemy otrzymać dane.
Pobierz wartość dla klucza SecretString
!/bin/bash
yum update -y
yum install -y jq
aws secretsmanager get-secret-value --region us-east-1 --secret-id MySecret --query SecretString --output text | jq -r .mySecretKey
Niestety nie istnieje łatwy sposób na pobranie wartości z pary klucz/wartość z wykorzystaniem jedynie bash. Jeżeli masz czas i chęci możesz napisać skrypt bash, który będzie w stanie w tym pomóc.
Osobiście wolę zaoszczędzić czas i wykorzystać gotowe rozwiązanie, jakim jest jq. Przed pobraniem sekretu dodałem dwie linie, które zaktualizują yum i zainstalują jq. Następnie jq może być wykorzystany do pobrania wartości przez definiowanie klucza.
Pobierz wartość sekretu i przechowaj w zmiennej środowiskowej
!/bin/bash
yum update -y
yum install -y jq
myValue=$(aws secretsmanager get-secret-value --region us-east-1 --secret-id MySecret --query SecretString --output text | jq -r .mySecretKey)
echo $myValue > /var/log/echoSecret.txt
Do tej pory pobieraliśmy sekret, przetwarzaliśmy i drukowaliśmy w logach.
Tym razem przechowamy wartość sekretu w zmiennej środowiskowej myValue bez umieszczania jej w widoczny sposób w logach.
Aby sprawdzić poprawność skryptu, dodałem do niego linię z komendą echo, która zapisze wartość zmiennej środowiskowej do pliku w lokalizacji /var/log/echoSecret.txt.
Podsumowanie
Stworzyliśmy nowy sekret w AWS Secret Manager. Utworzyliśmy rolę nadającą uprawnienie odczytu sekretu dla EC2. Na koniec odczytaliśmy w bezpieczny sposób sekret podczas uruchamiania EC2 z wykorzystaniem skryptu user data.
Tym sposobem możemy bezpiecznie używać danych takich jak hasła czy klucze podczas uruchamiania EC2, co może być szczególnie przydatne przy wykorzystaniu AWS EC2 Auto Scaling do automatyzacji nowych serwerów.