Niniejszym artykułem o AWS rozpoczynamy kolejny mini-cykl artykułów, tym razem poświęcony organizacji zarządzania uprawnieniami w poszczególnych chmurach publicznych - a także temu, jakie dane związane z logowaniem mogą być przechowywane po stronie użytkownika i w jaki sposób.
Amazon jest pionierem rynku chmurowego, a AWS wręcz synonimem chmury. Jest tak nie tylko ze względu na najdłuższy staż usług Amazonu, ale też (a może przede wszystkim) na zdecydowaną dojrzałość i przewagę jakościową nad konkurencją.
Struktura uprawnień
AWS ma także najbardziej przejrzysty model uprawnień wśród "pełnych" chmur (a więc pomijając takie, które oferują tylko usługi "Infrastructure as a Service":
- podstawowym podmiotem zabezpieczeń jest użytkownik (główny lub IAM)
- użytkownik posiada uprawnienia (tzw. polisy) przypisywane na jeden z kilku opisanych niżej sposobów - uprawnienia te pozwalają na dostęp do poszczególnych usług i funkcji
- użytkownik może (ale nie musi) posiadać hasła pozwalającego na dostęp do konsoli AWS z poziomu przeglądarki
- użytkownik może posiadać 1 lub więcej kluczy API, pozwalających na dostęp do interfejsów API - z poziomu zewnętrznych narzędzi, lub samodzielnie napisanych aplikacji
- podmiotem nadrzędnym nad użytkownikiem jest konto AWS - konto składa się z użytkownika głównego (mającego kilka dodatkowych uprawnień, np. dostęp do billingu i danych finansowych konta), oraz potencjalnie z użytkowników IAM (gdy zostaną manualnie założeni)
Jak działają uprawnienia
Uprawnienia (tzw. policies) to lista ponad 700 pozycji o samoopisujących się nazwach np. AmazonEC2FullAccess, które można przypisywać użytkownikom na kilka sposobów:
- bezpośrednio przypisując konkretne uprawnienie konkretnemu użytkownikowi (można w ten sposób przypisać maksymalnie 10 pozycji)
- przypisując uprawnienie do grupy (np. programiści), oraz dołączając użytkownika do tej grupy
- przypisując uprawnienie do roli (np. dostęp do danych finansowych firmy), oraz:
- dodając użytkownikowi tą rolę na stałe
- przekazując użytkownikowi tą rolę tymczasowo (na od 15 minut do 12 godzin, na zasadzie podobnej do sudo)
Z tego ostatniego sposobu korzysta się najczęściej do umożliwiania tymczasowego dostępu do konta dla różnych konsultantów zewnętrznych i innych osób, które nie mają mieć uprawnień na stałe, oraz wobec których chcemy prowadzić dodatkowy audyt korzystania z tych uprawnień.
Nazwy ważnych polis
Nie ma sensu przytaczać wszystkich nazw polis, zwłaszcza iż w miarę rozwoju usług AWS, co jakiś czas dochodzą nowe. Poniżej natomiast znajdziesz listę najistotniejszych polis, tj. tych dających pełny dostęp do konta AWS, możliwość tworzenia nowych instancji EC2, albo przynajmniej dostęp do instancji już uruchomionych:
AdministratorAccess AmazonEC2FullAccess EC2InstanceConnect AWSKeyManagementServicePowerUser IAMFullAccessDefiniowanie własnych polis
Wspomniane wyżej ponad 700 zestawów uprawnień, zwanych też polisami, może być poszerzane o własne polisy. Możliwe jest przy tym konstruowanie polis zawierających różne warunki, np. przynależność do konkretnej grupy, konkretny ciąg znaków w nazwie użytkownika, albo np. test, czy do bieżącego zalogowania był użyty token MFA - aby w razie potrzeby selektywnie blokować nadmierne uprawnienia.
Polisy te definiuje się w specjalnym metajęzyku, w formacie JSON - w tym samym formacie są też przygotowane standardowe polisy, których zawartość również można podejrzeć. Poniżej przykładowa definicja polisy AmazonRoute53FullAccess, dającej dostęp do usługi DNS Route53 (a tak naprawdę również do całego szeregu metod API innych usług):
{ "PolicyVersion": { "CreateDate": "2018-12-20T21:42:00Z", "VersionId": "v4", "Document": { "Version": "2012-10-17", "Statement": [ { "Action": [ "route53:*", "route53domains:*", "cloudfront:ListDistributions", "elasticloadbalancing:DescribeLoadBalancers", "elasticbeanstalk:DescribeEnvironments", "s3:ListBucket", "s3:GetBucketLocation", "s3:GetBucketWebsite", "ec2:DescribeVpcs", "ec2:DescribeVpcEndpoints", "ec2:DescribeRegions", "sns:ListTopics", "sns:ListSubscriptionsByTopic", "cloudwatch:DescribeAlarms", "cloudwatch:GetMetricStatistics" ], "Resource": "*", "Effect": "Allow" }, { "Action": "apigateway:GET", "Resource": "arn:aws:apigateway:*::/domainnames", "Effect": "Allow" } ] }, "IsDefaultVersion": true } }Użytkownik główny vs IAM
Różnice pomiędzy użytkownikiem głównym, a użytkownikiem IAM:
- użytkownik główny ma login będący zarazem adresem mailowym (który jest zarazem adresem kontaktowym), natomiast użytkownik IAM dowolnie nadany login (mogący być adresem mailowym lub nie), oraz ID konta (np. konto 123456783456, użytkownik tklim)
- użytkownik główny ma kilka dodatkowych uprawnień - część z nich da się przekazać innym użytkownikom (dodając im uprawnienie o nazwie "Billing" oraz włączając w panelu konfiguracyjnym dostęp do billingu dla użytkowników IAM), a część nie (np. nie da się zmienić hasła użytkownika głównego z poziomu użytkownika IAM)
Sposoby dostępu
W AWS są 3 główne sposoby dostępu do usług:
- przez konsolę webową - dostęp taki wymaga, aby użytkownik miał nadane hasło do konsoli (ale uwaga: da się je sobie samemu nadać, mając dostęp API z odpowiednio szerokimi uprawnieniami)
- przez API poszczególnych usług - posiadając aktywny klucz API
- dedykowany dostęp do wybranych usług w specjalny sposób, np.:
- logowanie ssh do instancji EC2 dzięki klucza ssh (definiowanego z poziomu konsoli lub API)
- dostęp do baz danych w usłudze RDS dzięki ich natywnych mechanizmów kontroli dostępu (aczkolwiek możliwa jest też integracja z IAM)
- osobny system uprawnień w usłudze EKS (Kubernetes)
- publiczne adresy (tzw. presigned urls) dla niepublicznych plików w bucketach S3, które mają być wyświetlone w przeglądarce bez logowania na konto AWS
Struktura kluczy API
Przede wszystkim, w AWS istnieją 2 typy kluczy: 2-członowe (stałe) i 3-członowe (tymczasowe, z dodatkowym tokenem):
- access key ID (część jawna) - np. AKIAI44QH8DHBEXAMPLE
- secret access key (część niejawna) - np. wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
- session token (niejawna część opcjonalna, występuje tylko w przypadkach opisanych poniżej) - np. AQ...1BQ==
Część jawna klucza (ID) jest unikalna w skali całego AWS, nie tylko w skali pojedynczego konta. Najczęściej ma formę AKIAxxxxxxxxyyyyyyyy, gdzie pierwsze 8 znaków po AKIA jest najczęściej (choć nie zawsze) takie same dla wszystkich kluczy w ramach konta AWS - np. AKIA43GLFLF2ZT4PHKKM i AKIA43GLFLF223B3SJWX.
Istnieją też klucze o prefiksach innych niż AKIA - np. te zwracane przez opisaną niżej metodę AssumeRole. Jednak przeszukując jakiekolwiek dane (np. repozytorium, konfigurację serwera) pod kątem kluczy AWS, najczęściej nie ma sensu zwracać na nie uwagi z uwagi na ich krótki okres ważności (od 15 minut do 12 godzin).
Tokeny mogą być pozyskiwane na 2 sposoby, dwoma metodami API usługi STS:
- GetSessionToken - po prostu pobiera token dla podanego klucza
- AssumeRole - tworzy nowy komplet danych dostępowych (ma to sens przy dawaniu tymczasowego dostępu dla użytkownika IAM z innego konta AWS)
Obie wymienione metody umożliwiają też logowanie do API w trybie MFA, tj. z użyciem dodatkowego tokenu przepisanego z urządzenia zewnętrznego.
MFA
Zamiast urządzenia zewnętrznego, albo np. Google Authenticatora, w roli generatora tokenów MFA można też użyć programu oathtool:
oathtool --totp -b WGW1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890ABCDEFGHIJKLMNOGdzie ostatni z parametrów to klucz prywatny, który można pobrać z IAM podczas rejestracji MFA.
Sposoby zapisu kluczy i innych danych dostępowych
Istnieją 2 typowe sposoby zapisu danych dostępowych: jako zmienne środowiskowe lub w pliku konfiguracyjnym.
W przypadku zmiennych środowiskowych, można szukać konkretnie poniższych nazw, takie właśnie bowiem nazwy są rozpoznawane przez narzędzie awscli.
export AWS_ACCESS_KEY_ID=AKIAI44QH8DHBEXAMPLE export AWS_SECRET_ACCESS_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY export AWS_SESSION_TOKEN=AQoDYXdzEJrubJnDILxqIFzdebBx65noy347e5HdubJnDILxqIFzdeb...Często spotyka się również zmienną środowiskową AWS_CREDENTIAL_EXPIRATION, ale tak naprawdę nie jest ona do niczego potrzebna (jej jedyne zastosowanie to zablokowanie działania danych dostępowych po upływie podanej daty).
Drugi sposób zapisu tych danych, to zapis w plikach o nazwie najczęściej ~/.aws/credentials:
[default] aws_access_key_id=AKIAIOSFODNN7EXAMPLE aws_secret_access_key=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEYTen sposób również obsługuje tokeny sesyjne, zwykle jednak stosuje się go do konfigurowania dostępów stałych, które tych tokenów nie wymagają.
Pliki ~/.aws/credentials obsługują wiele kont AWS - są one podzielone na konta (składnia plików INI) - w powyższym przypadku "default" jest nazwą konta, do której można odwoływać się z poziomu narzędzia awscli.
Ostatnią metodą szukania danych dostępowych jest szukanie 20-znakowych wyrazów rozpoczynających się od "AKIA".
Narzędzia do enumeracji zawartości kont AWS
Istnieje wiele lepszych lub gorszych narzędzi do skanowania kont AWS i zautomatyzowanego wyciągania listy użytkowników, usług itp. Jednym z ciekawszych projektów zorientowanych stricte na testy bezpieczeństwa jest enumerate-iam.
Jeśli nie zależy nam na szybkości i możemy poświęcić kilka godzin, znacznie lepszym rozwiązaniem będzie projekt Polynimbus - jest to narzędzie typu inventory, zorientowane na codzienne, bardzo dogłębne skanowanie konta AWS pod kątem wielu usług, oraz udostępnienie panelu webowego, w którym można nawigować po liście użytkowników, podglądać ich uprawnienia, klucze wraz z datami ich ostatniego użycia, oraz konfigurację usług.