Co tam Panie w polityce? Zarządzamy uprawnieniami w Amazon Web Services
Artykuł ukazał się pierwotnie na blogu Chmurowiska.
Podczas jednego z ostatnich wdrożeń prowadziliśmy warsztaty dla naszego klienta. Jednym z ważniejszych tematów było oczywiście bezpieczeństwo w chmurze. Jeżeli chodzi o bezpieczeństwo w Amazon Web Services to głównym tematem jest Identity Access Management.
W dużym skrócie, jest to usługa, która pozwala na zarządzanie użytkownikami i ich uprawnieniami. Pozwala między innymi na:
- zcentralizowaną kontrolę nad kontem AWS,
- przydzielanie granularnych uprawnień użytkownikom i usługom,
- Identity Federation, czyli połączenie zewnętrznych użytkowników (np. Active Directory, Facebook) z naszym kontem,
- wielostopniową autentykację (MFA),
- przydzielanie tymczasowego dostępu dla użytkowników lub urządzeń,
- ustawianie własnej polityki haseł.
IAM jest zintegrowane z praktycznie wszystkimi usługami w AWS.
Kluczowe pojęcia konieczne do zrozumienia w pracy z AWS to:
- user – użytkownik, czyli człowiek pracujący z usługami,
- group – grupa ludzi posiadająca takie same uprawnienia,
- role – rola, taki użytkownik, tylko nie dla ludzi. Przypinamy ją do usług i zasobów w AWS,
- policy – dokument definiujący uprawnienia.
IAM Policies
Jak wspomniałem polityka (policy) to dokument. Dokument napisany w JSON-ie, który definiuje uprawnienia. Policies, w przeciwieństwie do większości usług w AWS dostępne są globalnie. Raz utworzona, może być używana w każdym regionie.
Polityki przypinamy później do użytkowników, grup lub roli, którzy otrzymują zdefiniowane w polityce uprawnienia. W skrócie, polityka opisuje co użytkownik lub usługa może zrobić w AWS. Gdy tworzymy nowe konto w AWS zawsze definiowany jest użytkownik root, którego polityka wygląda następująco:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "*",
"Resource": "*"
}
]
}
Deklaracja składa się z trzech kluczy:
- Effect – Allow lub Deny, określa czy uprawnienia są udzielone czy zakazane,
- Action – lista akcji, które polityka pozwala lub nie wykonać,
- Resource – lista zasobów, których dana deklaracja dotyczy.
Jak widać, root może zrobić (”Effect” : „Allow”) wszystko (”Action” : ”*”) z każdą usługą lub zasobem (”Resource” : „*”) w AWS. Uprawnienia możemy jednak udzielać o wiele bardziej dokładnie. Dla przykładu polityka pozwalająca na odczyt z koszyków S3 będzie wyglądała tak:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:Get*",
"s3:List*"
],
"Resource": "*"
}
]
}
W takim dokumencie mogą występować także inne klucze. Możemy na przykład, w kluczu Condition wyspecyfikować adres IP, z którego użytkownik musi się połączyć, aby dana zasada bezpieczeństwa mogła mieć zastosowanie. Pełna lista możliwości to:
- Version – wersja języka, którego używamy w polisie. Najlepiej używać ostatniej dostępnej, „2012-10-17”.
- Statement – Główny element poltyki. Może ich być więcej niż jeden.Kontener dla poniższych elementów:
- Sid – opcjonalny identyfikator
- Effect – Allow lub Deny – dajemy bądź odbieramy uprawnienia
- Principal – Konto, rola, użytkownik… któremu przypisujemy politykę Jeżeli tworzymy politykę przypisaną do np. użytkownika lub roli, nie możemy użyć tego klucza
- Action – lista czynności (lista metod API), na które pozwalamy lub których zabraniamy
- Resource – lista zasobów, których polityka dotyczy
- Condition – opcjonalne warunki, po spełnieniu których polityka udziela, bądź nie uprawnień.
Sejm, sejmik, rada nadzorcza
Tak jak w życiu mamy różne rodzaje prawa, tak i Amazon pozwala nam na ustanawianie uprawnień na różnych poziomach. Dostępne rodzaje polityk to:
- AWS Managed Policies,
- Customer Managed Policies,
- Inline Policies.
AWS Managed Policies to polityki tworzone i zarządzane przez Amazona. Są dostępne dla wszystkich i dla każdego są takie same. Co jest ważne? Te polityki mogą się zmienić!!! Co prawda Amazon na pewno uważa co robi i raczej nie będzie chciał odebrać jakichś ważnych uprawnień i spowodować katastrofy, ale trzeba o tym pamiętać. Te polityki oznaczone są na liście żółtymi sześcianami.

Customer Managed Policies z kolei są zarządzane przez nas. Sami je tworzymy, zmieniamy i kasujemy. Przypisujemy je do różnych obiektów (użytkowników i ról) i w ten sposób przydzielamy im uprawnienia.
Inline policies są szczególnie przydatne, gdy chcemy powiązać daną politykę z konkretnym obiektem. Jeżeli na przykład chcemy aby jakieś uprawnienia należały tylko do jednego użytkownika, to możemy je zdefiniować bezpośrednio i nie będzie niebezpieczeństwa, że ktoś, przez przypadek, przydzieli je komuś innemu.
Przeglądając polityki możemy je wygodnie filtrować w zależności od typu.

Często z tego korzystam.
Administrator baz danych
Praca na jednym koncie, dodatkowo z pełnymi uprawnieniami, nie jest czymś, co powinniśmy robić. Zawsze należy przydzielać każdem użytkownikowi tylko takie uprawnienia, których naprawdę potrzebuje, aby wykonać swoją pracę. Amazon tak radzi i naprawdę powinniśmy się tego trzymać. Warto.
Załóżmy więc, że zatrudniliśmy kogoś, kto ma się zajmować naszymi relacyjnymi bazami danych. Administratora naszych usług RDS, który powinien mieć do nich pełny dostęp. Ale raczej tylko do nich. Nie potrzebuje on przecież tworzyć maszyn wirtualnych czy funkcji Lambda. Powinniśmy mu więc przydzielić pełne (prawdopodobnie) uprawnienia do usługi RDS i… tylko do tego. Jeżeli okaże się, że będzie potrzebował kiedyś dodatkowych uprawnień, zawsze możemy mu je przydzielić. Pamiętajmy jednak, że mamy szansę na rozwój naszej firmy i w przyszłości będziemy potrzebowali na pewno więcej administratorów dla naszych baz danych. Mamy nowego człowieka, działajmy.
Tworzymy grupę
Nie chcemy przecież, w momencie zatrudnienia drugiego admina RDS robić wszystkiego od nowa. Stworzymy więc grupę dla użytkowników administrujących naszymi bazami danych.
Przechodzimy do usługi IAM i wybieramy grupy.

klikamy na Create New Group

wpisujemy nazwę grupy, klikamy Next Step i otwiera się ekran, na którym możemy przypisać do naszej grupy politykę z uprawnieniami.
Nie będziemy w tej chwili tworzyli własnej polityki z uprawnieniami, sprawdzimy co oferuje nam Amazon, jeżeli chodzi o uprawnienia do usługi RDS. Przefiltrujmy sobie dostępne polityki

i jako, że mamy do czynienia z administratorem do którego musimy mieć zaufanie, przydzielamy mu pełne uprawnienia do usługi. Klikamy kilka razy niebieski button i mamy utworzoną grupę dla naszych administratorów baz danych.

Mamy nasz grupę, ale liczba użytkowników wynosi zero. Musimy jakiegoś utworzyć.
Nowy użytkownik
Tym razem przechodzimy w menu do Users klikamy Add user wypełniamy niezbędne dane

i na następnym ekranie mamy możliwość przydzielenia naszemu nowemu użytkownikowi uprawnień.

Jak widać możemy dodać użytkownika do grupy, skopiować uprawnienia z innego użytkownika lub przypisać bezpośrednio istniejącą politykę. My po prostu dodamy naszego nowego administratora do grupy RDSAdministrators. Zaznaczamy checkboxa przy wybranej grupie, klikamy dwa razy „next” i możemy przekazać lub przesłać nowe poświadczenia naszemu nowemu pracownikowi.

Testujemy
Zanim to jednak zrobimy, sprawdźmy co tak naprawdę będzie mógł zrobić. Zalogujemy się na jego konto

i poklikamy trochę po różnych usługach. Spróbujmy na przykład utworzyć nową kolejkę w usłudze SQS.

O to chodziło. Między innymi o to. Dla pewności możemy sprawdzić inne usługi, a na koniec przejdźmy do RDS i zobaczymy czy uda się utworzyć nową instancję MySQL na naszym koncie. Kilka minut później widzimy, że wszystko poszło dobrze.

Jeden do zera dla nas.
Nasz admin potrzebuje dokumentacji
Czas mija. Zatrudniliśmy drugiego administratora baz danych, rozpoczęliśmy realizację projektów dla klientów zewnętrznych. Nasza firma dostała prośbę o wykonanie wyceny nowej usługi, która związana jest z bazami danych. Cała dokumentacja do tego projektu leży w koszyku S3, a nasz administrator musi się z nią zapoznać. Musimy mu więc pozwolić na dostęp do tych dokumentów. Nie możemy jednak dać mu dostępu do całej usługi S3. W niektórych bucketach są przecież tajne dane odnośnie innego projektu, dotyczącego naszego planowanego lotu w kosmos 😉 Nie chcemy także, aby niedawno zatrudniony drugi admin miał do tego dostęp. Jest jeszcze na okresie próbnym.
Przy naszych założeniach nie możemy dodać kolejnej gotowej polityki do grupy administratorów baz danych. Musimy utworzyć nową i dołączyć ją do użytkownika.
Zmieniamy uprawnienia
Przechodzimy więc do naszego użytkownika i klikamy niebiestki button Add permissions.

Teraz możemy zarządzać jego uprawnieniami. Tym razem chcemy podpiąć bezpośrednio politykę, która będzie pozwalała na dostęp do koszyka o nazwie secret-docs. Wybieramy więc Attach existing policies directly i Create policy. Tworzymy politykę dla naszego admina w postaci:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::secret-docs/*",
"arn:aws:s3:::secret-docs"
]
},
{
"Effect": "Allow",
"Action": "s3:ListAllMyBuckets",
"Resource": "*"
}
]
}
Nazywamy ją np.: RDSAdmin1-secret-docs-policy i dodajemy ją do użytkownika. Poza dostępem do naszego tajnego koszyka, dodaliśmy także możliwość wylistowania wszystkich bucketów:
{
"Effect": "Allow",
"Action": "s3:ListAllMyBuckets",
"Resource": "*"
}
Czy jest to konieczne? Nie. Bez tej deklaracji nasz administrator baz danych nie mógłby wejść po prostu do koszyka poprzez listę. Musielibyśmy podać mu bezpośredni adrea url naszego bucketa, np.: https://s3.console.aws.amazon.com/s3/buckets/secret-docs/
W tym momencie nasz administrator, poza dostępem do baz danych, ma także możliwość zapoznania się z dokumentacją do naszego projektu.

Jak widać przynależność do grupy i bezpośrednio dodana polityka w niczym sobie nie przeszkadzają. Przynajmniej w tym przypadku 🙂
Polityki dla zasobów
Dość często zastosowanie IAM Policies jest jednak nieergonomiczne lub nawet niemożliwe.
Załóżmy, że mamy setki użytkowników, dziesiątki grup i ról. Dodajemy bucket S3 i edytujemy uprawnienia dla każdego? Trudne. Ponad to wielkość polityk dla użytkowników, grup i ról także ma ograniczenie. Nie możemy rozbudowywać ich w nieskończoność.
Tu z pomocą przychodzą polityki Resource policies. Pisałem już o nich jakiś czas temu w związku z bezpieczeństwem danych w S3. W skrócie są to polityki, które określają kto i co może wrobić z obiektem lub zasobem, do którego są podpięte.
Jaka jest różnica w stosunku do IAM Policies? Wyobraźmy sobie, że wchodzimy, jako użytkownik, do restauracji. Politykę IAM będziemy trzymali na kartce w swojej kieszeni i na tej kartce będzie napisane co możemy, a czego nie możemy zjeść. A drugi rodzaj polityki, to będą karki przypięte do poszczególnych potraw. Na każdej z takich kartek będzie wyszczególnione kto może, a kto nie może danej potrawy zjeść.
Wróćmy do naszego przykładu z administratorem baz danych i koszykiem S3. Pamiętamy, że ma on mieć dostęp tylko do tego koszyka i do dokumentów w nim zawartych. Możemy więc, zamiast dodawać uprawnienia bezpośrednio do użytkownika, stworzyć odpowiednią politykę dla naszego koszyka, w której określimy, kto i co może zrobić.
Do stworzenia takiej polityki wygodnie jest użyć generatora. Znajdziemy go w zakładce Bucket policies dla naszego koszyka. Wpisujemy ARN naszego użytkownika jako Principal, ANR bucketu jako Resource

wybieramy uprawnienia, które chcemy przydzielić i możemy wygenerować politykę. Musimy ją niestety sami przekleić w docelowe miejsce, generator nie jest podłączony bezpośrednio pod ekran, na którym określamy politykę dla koszyka.
Niestety wygenerowany JSON nie jest do końca poprawny i nie uda nam się zapisać naszych zmian.

Musimy poprawić jedną linię. Zamiast
"Resource": "arn:aws:s3:::secret-docs",
powinno być
"Resource": "arn:aws:s3:::secret-docs/*",
Trzeba o tym pamiętać.
W ten sposób pozwoliliśmy naszemu użytkownikowi na pobieranie plików z koszyka nie zmieniając jego bezpośrednich uprawnień.
Wybory, konfilikty
Mamy więc dwa rodzaje polityk. W S3 dochodzą jeszcze Access Listy na poziomie plików. Co stanie się więc, jeżeli jedna polityka będzie na coś pozwalała, a druga nie? Dobre pytanie.
Spróbujcie w naszej polityce przypiętej do koszyka
{
"Id": "Policy1531734719694",
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Stmt1531734689872",
"Action": [
"s3:GetObject"
],
"Effect": "Allow",
"Resource": "arn:aws:s3:::secret-docs/*",
"Principal": {
"AWS": [
"arn:aws:iam::094104221953:user/RDSAdmin1"
]
}
}
]
}
zmienić linię
"Effect": "Allow",
na
"Effect": "Deny",
Jeżeli robicie wszystko tak jak ja, to w tym momencie polityka dla administratora bad danych będzie pozwalała mu na pobranie pliku, a polityka dla koszyka będzie mu tego zabraniała. I co? I nie pobierze pliku.
Jak to działa? Zrozumienie tego nie jest trudne. A jest za to bardzo ważne. Proces ewaluacji uprawnień wygląda następująco.
- Na początku decyzja to Deny. Użytkownik nie ma uprawnień do zasobu.
- Wszystkie polityki łączone są w całość. Coś jak Union all w języku SQL.
- Jeżeli gdziekolwiek występuje wyraźne Deny, użytkownik nie ma prawa do zasobu.
- Jeżeli gdziekolwiek występuje wyraźne Allow użytkownik ma prawo do zasobu.
- Użytkownik nie ma prawa do zasobu.
Czasem nawet w jednej polityce możemy mieć przeczące sobie wpisy. Zawsze górę weźmie wyraźnie wyspecyfikowane Deny.
Przykłady
Mamy da dokumenty. Dla S3:
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"s3:DeleteObject"
],
"Effect": "Deny",
"Resource": "arn:aws:s3:::secret-docs/*",
"Principal": {
"AWS": [
"arn:aws:iam::094104221953:user/S3User"
]
}
}
]
}
i dla użytkownika S3User
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "s3:*",
"Resource": "*"
}
]
}
Użytkownik ma pełne prawa do bucketów S3 oraz do plików w nich umieszczonych. Jednocześnie polityka dla koszyka secret-docs zakazuje mu kasowania plików w tym koszyku. Będzie on więc mógł zrobić wszystko we wszystkich koszykach, poza kasowaniem plików w tym koszyku. Swoją drogą to nie jest zbyt dobry przykład. Użytkownik ma prawo do zmiany polityk, więc nic nie przeszkodzi mu w kasowaniu, jeżeli będzie naprawdę chciał.
I ponownie. Dla S3 mamy:
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"s3:PutObject"
],
"Effect": "Allow",
"Resource": "arn:aws:s3:::secret-docs",
"Principal": {
"AWS": [
"arn:aws:iam::094104221953:user/S3User"
]
}
},
{
"Sid": "Stmt1531745706400",
"Action": [
"s3:DeleteObject"
],
"Effect": "Deny",
"Resource": "arn:aws:s3:::secret-docs",
"Principal": {
"AWS": [
"arn:aws:iam::094104221953:user/S3User"
]
}
}
]
}
a dla naszego użytkownika
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:DeleteObject",
"s3:GetObject"
],
"Resource": "*"
}
]
}
Przyjrzyjmy się obu politykom. Po przejściu przez zasady zawarte w obu dokumentach widać, że S3User będzie mógł do naszego koszyka zapisywać pliki. Będzie je także mógł odczytywać. Nie będzie jednak mógł ich kasować. Deny z polityki dla koszyka jest ważniejsze niż allow z uprawnień S3User.
Podsumowując
Zagadnienia bezpieczeństwa i dostępu do zasobów w chmurze są jednym z najważniejszych.
W artykule nie poruszyłem na pewno wszystkich kwestii. Warto jednak od czegoś zacząć. Pamiętajmy, że jedna z najważniejszych zasad, którymi powinniśmy się kierować przy zarządzaniu uprawnieniami, to zasada przydzielania jak najmniejszych uprawnić. Dajemy użytkownikowi tylko tyle ile naprawdę potrzebuje, żeby wykonać swoje obowiązki.