Bezpieczny DevOps w chmurze publicznej: praktyczne wzorce dla AWS, Azure i GCP

0
41
4/5 - (1 vote)

Nawigacja:

DevOps w chmurze publicznej bez luk w bezpieczeństwie – po co to wszystko

DevOps vs DevSecOps – praktyczna różnica w codziennej pracy

DevOps skupia się na szybkim, powtarzalnym dostarczaniu zmian: od commita do produkcji. DevSecOps dodaje do tego jeden kluczowy element – bezpieczeństwo traktowane jako wymaganie niefunkcjonalne, które jest sprawdzane i egzekwowane na każdym etapie pipeline’u CI/CD, a nie dopiero na końcu przez osobny zespół bezpieczeństwa.

W praktyce różnica wygląda tak:

  • w zwykłym podejściu DevOps aplikacja, kontenery i infrastruktura trafiają na produkcję, jeśli „pipeline jest na zielono” i testy funkcjonalne przejdą bez błędów,
  • w DevSecOps pipeline nigdy nie staje się „zielony”, jeśli skanery wykryją krytyczne podatności w obrazie kontenera, błędne reguły IAM w Terraformze czy publiczny dostęp do storage’u.

Security przestaje być jednorazowym audytem i staje się automatycznym strażnikiem wbudowanym w proces wytwórczy. Zespół DevOps nie musi znać każdego CVE na pamięć, ale musi mieć pipeline, który nie przepuści znanych dziur na produkcję.

Specyfika chmur publicznych: shared responsibility i „klikologia”

Chmury publiczne (AWS, Azure, GCP) działają w modelu shared responsibility: dostawca odpowiada za bezpieczeństwo infrastruktury chmurowej, a klient za to, co i jak na niej uruchamia. Dla zespołów DevOps oznacza to trzy rzeczy:

  • dostawca gwarantuje fizyczne DC, hypervisory, podstawowe patche i izolację między tenantami,
  • DevOps odpowiada za konfigurację sieci, IAM, szyfrowanie, exposure usług, rotację sekretów i zgodność z wymaganiami biznesowymi,
  • źle ustawione S3, Blob Storage czy Cloud Storage to wina konfiguracji, nie „chmury jako takiej”.

Drugą cechą chmury jest łatwość i szybkość zmian. Kilka kliknięć w konsoli potrafi w sekundę otworzyć port 22 z całego Internetu, podłączyć publiczny IP i wystawić bazę danych bez hasła. Ta „klikologia” jest największym wrogiem bezpiecznego DevOps: brak powtarzalności, brak historii zmian i brak recenzji sprawiają, że nawet dobra architektura po kilku tygodniach robi się pełna luk.

Zaufanie do chmury a bezpieczeństwo aplikacji i procesu wdrożeń

Mit wygląda tak: „Skoro przenosimy się do AWS/Azure/GCP, to oni zajmą się bezpieczeństwem, bo mają lepszych ekspertów”. Rzeczywistość jest bardziej brutalna: dostawca chmury zapewnia narzędzia, ale to zespół DevOps konfiguruje każdy element – od poziomu szyfrowania po zasady dostępu do danych.

Samo użycie usługi typu AWS RDS, Azure SQL czy Cloud SQL nie oznacza jeszcze, że dane są bezpieczne. Jeśli:

  • stawiasz instancję w publicznej podsieci,
  • ignorujesz Security Groups / NSG / Firewall Rules,
  • dajesz uprawnienia „*:*” w IAM/Entra ID/Cloud IAM do tej bazy,

to odpowiedzialność za wyciek będzie w całości po stronie Twojej organizacji. Chmura dostarczy logi, mechanizmy audytu i szyfrowanie, ale nikt nie zabroni stworzenia fatalnej konfiguracji. Bezpieczny DevOps w chmurze publicznej to umiejętność właściwego używania narzędzi, a nie wiara, że dostawca „naprawi” błędy zespołu.

Trzy realne cele bezpieczeństwa w DevOps w chmurze

Bezpieczny DevOps nie sprowadza się do „zaliczenia compliance”. Dobrze zaprojektowany proces ma trzy konkretne cele:

  1. Zmniejszenie powierzchni ataku – czyli mniej publicznie dostępnych zasobów, mniej nadmiernych uprawnień, mniej tajnych danych w repozytoriach i pipeline’ach.
  2. Skrócenie czasu wykrycia incydentu – centralne logowanie, alerty z CloudTrail/CloudWatch, Azure Monitor/Defender, Cloud Logging/SCC, sensowne dashboardy i integracja z systemem SIEM.
  3. Automatyzacja reakcji i naprawy – mechanizmy takie jak AWS Config Rules, Azure Policy, GCP Organization Policy mogą automatycznie blokować, korygować lub oznaczać niezgodne zasoby, a pipeline’y CI/CD powinny potrafić szybko wdrożyć poprawkę na wielu środowiskach.

DevSecOps daje największą wartość tam, gdzie nie trzeba czekać tydzień na ręczną analizę incydentu, bo system sam wykrywa niezgodność, blokuje wdrożenie i daje zespołowi jasny komunikat: „ta zmiana łamie zasady bezpieczeństwa, popraw konfigurację”.

Mit: „chmura z definicji jest bezpieczniejsza niż własna serwerownia”

Często pada zdanie: „Przenosimy się do chmury, bo tam będzie bezpieczniej niż w naszej starej serwerowni”. Prawda i fałsz jednocześnie. Faktycznie, AWS, Azure i GCP mają lepszą fizyczną infrastrukturę, procesy, mechanizmy DDoS i całe działy bezpieczeństwa, których większość firm nie zbuduje samodzielnie. Ale jednocześnie każda zła decyzja konfiguracyjna skaluje się dużo szybciej: jedna błędna polityka IAM może otworzyć setki zasobów naraz.

Rzeczywistość jest więc taka: chmura daje potencjalnie wyższy poziom bezpieczeństwa, ale tylko wtedy, gdy zespół DevOps ma dojrzałe praktyki DevSecOps, IaC, kontrolę dostępu i monitorowanie. Bez tego chmura staje się tylko szybszym sposobem na popełnianie starych błędów – tyle że na większą skalę.

Model odpowiedzialności i podstawy bezpieczeństwa w AWS, Azure i GCP

Shared Responsibility Model – co robi dostawca, a co DevOps

Wspólny mianownik dla AWS, Azure i GCP to prosty schemat:

  • Dostawca chmury – odpowiada za security of the cloud: fizyczna infrastruktura, zasilanie, chłodzenie, sieć szkieletowa, hypervisory, bezpieczeństwo centrów danych, patchowanie warstwy hosta dla usług zarządzanych.
  • Klient (Twoja organizacja) – odpowiada za security in the cloud: konfigurację usług, sieci, IAM, szyfrowanie, kontrolę dostępu, polityki backupu, logowanie, monitorowanie oraz bezpieczeństwo aplikacji i pipeline’ów CI/CD.

W praktyce granica bywa ruchoma: dla IaaS (np. EC2, Azure VM, Compute Engine) klient odpowiada dodatkowo za system operacyjny, patche i agentów. Dla PaaS (RDS, Azure App Service, Cloud Run) dostawca przejmuje więcej obowiązków, ale konfiguracja dostępu i danych nadal jest po stronie klienta.

Wspólne fundamenty: IAM, sieć, szyfrowanie, logowanie

Bezpieczny DevOps w chmurze publicznej zawsze opiera się na kilku filarach, które w każdej chmurze nazywają się trochę inaczej, ale działają podobnie:

  • IAM / Identity and Access Management – zasady kto, co i gdzie może zrobić; obejmuje użytkowników, role, tożsamości aplikacyjne i uprawnienia do konkretnych usług.
  • Sieć – VPC/VNet, subnety, routing, Security Groups/NSG/Firewall Rules, peering, VPN, prywatny dostęp do usług zarządzanych (Private Link/Private Endpoint/Private Service Connect).
  • Szyfrowanie – klucze KMS/Key Vault/Cloud KMS, szyfrowanie danych w spoczynku i w tranzycie (TLS), zarządzanie kluczami i rotacją.
  • Logowanie i audyt – AWS CloudTrail i CloudWatch, Azure Monitor i Activity Log, GCP Cloud Logging i Audit Logs, plus integracja z SIEM.
  • Tożsamość użytkownika – integracja z IdP (np. Azure AD / Entra ID, Okta), SSO, MFA, federacja, role przypisywane grupom, a nie pojedynczym osobom.

Jeśli te fundamenty są chaotyczne – konta bez MFA, logi niecentralizowane, brak KMS i przypadkowe polityki IAM – żaden skaner w pipeline CI/CD nie nadrobi tych braków.

IAM, Entra ID i Cloud IAM – mentalne „tłumaczenie” między chmurami

Pracując wielochmurowo lub migrując między dostawcami, przydaje się prosty słownik pojęć. W dużym uproszczeniu:

ZakresAWSAzureGCP
Tożsamość użytkownikaAWS IAM User / SSOEntra ID (dawniej Azure AD)Google Workspace / Cloud Identity
Role / uprawnieniaIAM Roles, PoliciesRBAC Roles, Role AssignmentsCloud IAM Roles, Bindings
Tożsamości aplikacyjneIAM Role, IAM Role for Service AccountsManaged Identities, App RegistrationsService Accounts
Organizacja / tenantAWS OrganizationsTenant + Management GroupOrganization
Konto / subskrypcja / projektAccountSubscriptionProject

Mechanizm jest ten sam: role przypisywane są tożsamościom (użytkownikom, grupom, aplikacjom) na jakimś zakresie (organizacja, konto/subskrypcja/projekt, zasób). Bezpieczny DevOps używa tych mechanizmów, aby:

  • nie przyznawać nadmiernych uprawnień (least privilege),
  • przypisywać role do workloadów (aplikacji), a nie ludzi,
  • centralnie zarządzać tożsamością przez IdP i SSO.

Współpraca z SecOps: granice odpowiedzialności i RACI

DevOps i centralny zespół bezpieczeństwa (SecOps) często wchodzą sobie w paradę: jedni chcą szybko wdrażać, drudzy blokować ryzyko. Dobrze zdefiniowane role i RACI (Responsible, Accountable, Consulted, Informed) pomagają uniknąć chaosu:

  • SecOps – odpowiedzialny za polityki, standardy, narzędzia centralne (SIEM, skanery, KMS, IdP) oraz za akceptację wyjątków.
  • DevOps / zespoły produktowe – odpowiedzialne za implementację tych polityk w pipeline’ach CI/CD, IaC, konfiguracji usług.
  • Platform Team – często pośrednik, budujący „złote szablony” (golden templates), moduły Terraform, wspólne wzorce CI/CD z wbudowanymi kontrolkami bezpieczeństwa.

Dobrym wzorcem jest ustalenie kontraktów SLO dla bezpieczeństwa: np. maksymalny czas reakcji na krytyczną podatność w obrazie bazowym, standardowe poziomy logowania dla aplikacji, minimalne wymagania co do segmentacji środowisk. Zespoły DevOps wiedzą wtedy, co jest niepodlegającym negocjacji minimum, a gdzie mają swobodę.

Przykład odpowiedzialności: publiczny bucket S3/Blob/Cloud Storage

Wyobraźmy sobie prostą sytuację: zespół tworzy bucket S3 (lub Blob/Cloud Storage) na logi aplikacyjne. Ktoś, żeby „ułatwić testy”, ustawia publiczny dostęp do całego kubełka. Po kilku dniach narzędzia skanujące Internet odkrywają otwarty storage z logami zawierającymi tokeny i dane klientów.

Kto jest odpowiedzialny?

  • Dostawca chmury – zapewnił mechanizmy: blokady publicznego dostępu, logi audytu, narzędzia typu Security Hub/Defender/SCC, a także dokumentację ostrzegającą przed publicznym storage’em.
  • Twoja organizacja – skonfigurowała bucket, zignorowała ostrzeżenia, nie uruchomiła polityk wymuszających prywatność i wpuściła na produkcję IaC z błędnymi ustawieniami.

W modelu shared responsibility takim wyciekiem zarządza się na własny koszt i z własnymi konsekwencjami. Bezpieczny DevOps oznacza, że pipeline CI/CD i polityki organizacyjne nie pozwolą w ogóle utworzyć publicznego bucketu bez uzasadnionego wyjątku zaakceptowanego przez SecOps.

Programista pisze kod na laptopie, obok leży telefon, motyw cyberbezpieczeństwa
Źródło: Pexels | Autor: Antoni Shkraba Studio

Tożsamość i dostęp: least privilege jako fundament bezpiecznego DevOps

Dlaczego incydenty w chmurze wynikają z uprawnień i kluczy

Ogromna część realnych incydentów w chmurze wiąże się z dwoma zjawiskami:

  • nadmierne uprawnienia – użytkownicy lub role z dostępem „admin” do wszystkiego,
  • kradzione lub wyciekłe klucze – klucze API, access keys, tokeny zapisane w repozytoriach, plikach .env, logach pipeline’u.

Jeśli atakujący przejmie konto użytkownika lub klucz z uprawnieniami „AdministratorAccess” (AWS), „Owner” (Azure) lub „Project Owner” (GCP), to zyskuje pełną kontrolę nad zasobami. Z perspektywy DevOps to często efekt lenistwa lub presji czasu: „dajmy admina, będzie działać, a potem to posprzątamy”. To „potem” zwykle nigdy nie nadchodzi.

Least privilege dla ludzi: role tymczasowe, nie wieczny admin

Najprostsze miejsce na uporządkowanie uprawnień to wcale nie kontenery czy Lambdy, tylko zwykli użytkownicy i zespoły DevOps. To oni często dostają „na wszelki wypadek” pełne uprawnienia, bo „i tak są odpowiedzialni za całą platformę”.

Mit jest taki, że senior DevOps „musi mieć pełnego admina, inaczej nic nie zrobi”. W praktyce 95% codziennej pracy to odczyt logów, modyfikacja konfiguracji i deployment – do tego nie potrzeba roli właściciela subskrypcji ani konta.

Bezpieczny wzorzec dla ludzi to:

  • dostęp domyślny – rola z uprawnieniami do odczytu (read-only) i podstawowej operacji w swoim obszarze odpowiedzialności,
  • dostęp podwyższony – rola administracyjna przyznawana tymczasowo, na określony czas i cel, z pełnym audytem.

W praktyce można to zrealizować różnie:

  • AWS – AWS SSO / IAM Identity Center z rolami przypisanymi do grup, a do podwyższonego dostępu użycie mechanizmów privileged access (np. integracja z narzędziem PAM) i krótkotrwałych sesji STS; dla zadań ad-hoc – role assumowane zamiast stałych użytkowników IAM.
  • Azure – Entra ID Privileged Identity Management (PIM): dostęp eligible, aktywowany na godzinę czy dwie z uzasadnieniem i MFA, role „Owner” ograniczone do minimum; większość zespołu działa na roli Contributor lub jeszcze węższej.
  • GCP – Cloud IAM z rozbiciem na custom roles zamiast szerokich Owner/Editor; podwyższony dostęp wymuszany przez workflow (np. ticket + zatwierdzenie + krótkotrwały binding roli do grupy).

Rzeczywistość nie jest skomplikowana: jeśli ktoś potrzebuje „admina” na stałe, to zwykle znaczy, że brakuje drobniejszych ról i automatyzacji, a nie że model least privilege się nie sprawdza.

Tożsamości aplikacyjne: klucze API do lamusa

Najgroźniejsze incydenty w chmurze często zaczynają się od przypadkowego commita z kluczem dostępowym do repo publicznego. Potem jest już prosto: bot indeksuje GitHuba, wyciąga klucz, uruchamia koparki kryptowalut albo listuje dyski ze snapshotami baz danych.

Mit numer dwa: „Aplikacja musi mieć klucz, żeby gadać z chmurą”. Nie musi – każda z głównych chmur ma natywne mechanizmy tożsamości zarządzanych, które zastępują klucze statyczne:

  • AWSIAM Role for Service (EC2, ECS Task Role, IRSA dla EKS), gdzie aplikacja dostaje metadane z tymczasowymi credencialami i nie trzyma kluczy na dysku.
  • AzureManaged Identities (system-assigned, user-assigned) dla App Service, Functions, VM, AKS; aplikacja pobiera token z endpointu MSI i używa go do dostępu do Key Vault, Storage, itp.
  • GCPService Accounts przypisane do VM, GKE, Cloud Run; aplikacja korzysta z metadanych instancji, a biblioteki klienckie same obsługują tokeny.

W tych modelach jedyny przypadek, kiedy potrzebny jest „klucz serwisowy”, to:

  • integracja z systemem poza chmurą, który nie umie używać OIDC/MST albo tożsamości zarządzanych,
  • zadania lokalne (on-prem, laptop), zanim pipeline lub agent CI będzie potrafił użyć federacji tożsamości.

Wtedy i tak lepiej sięgnąć po krótkotrwałe tokeny (OIDC, SAML, workload identity), a nie wieloletni plik JSON albo para access key/secret key.

Sekrety i klucze w pipeline’ach CI/CD

Pipeline’y to kolejna studnia wycieków: logi z buildów, artefakty, konfiguracje agentów – wszystko to potrafi przechować tokeny na dłużej, niż ktokolwiek się spodziewa. Jedna nieopatrzna instrukcja echo $SECRET i poufne dane lądują w logu, który czyta pół zespołu.

Bezpieczne podejście to kombinacja kilku prostych zasad:

  • centralny magazyn sekretów – AWS Secrets Manager / Parameter Store, Azure Key Vault, Google Secret Manager, a nie zmienne środowiskowe zakodowane w repo lub pipeline’ach YAML,
  • odczyt „just in time” – pipeline pobiera sekret na czas kroku, przekazuje go do aplikacji przez tymczasową zmienną środowiskową, po czym nie zapisuje go w artefaktach ani logach,
  • rotacja – klucze i hasła mają określony czas życia; rotacja jest zautomatyzowana i testowana w środowisku testowym, zanim trafi na produkcję,
  • maskowanie w logach – funkcje „secret masking” w narzędziach CI (GitHub Actions, GitLab CI, Azure DevOps) oraz ograniczone uprawnienia read do logów z produkcyjnych buildów.

Dobrym krokiem jest też audyt samych pipeline’ów: kto może je modyfikować, czy w merge requestach są obowiązkowe code review i czy zmiany w pipeline’ach przechodzą przez ten sam proces co kod aplikacji.

Polityki organizacyjne: guardraile zamiast ręcznego pilnowania

Trzymanie least privilege „na słowo honoru” zawsze kończy się tym samym: ktoś w stresie awaryjnym doda sobie uprawnienia, a potem zapomni je zdjąć. Lepiej zainwestować w twarde ograniczenia na poziomie organizacji.

Przykładowe guardraile, które realnie pomagają DevOpsom, zamiast tylko przeszkadzać:

  • bloki organizacyjne – AWS Organizations SCP blokujące tworzenie użytkowników IAM z access key, gdy używane jest SSO; Azure Management Groups z politykami, które zabraniają tworzenia zasobów poza określonymi regionami i wymuszają użycie Managed Identities; w GCP – organization policy wymuszający Cloud KMS / CMEK,
  • polityki „deny by default” – np. brak możliwości tworzenia publicznych bucketów, publicznych IP w środowiskach produkcyjnych lub baz danych niezabezpieczonych siecią prywatną,
  • standaryzowane role – gotowe zestawy ról dla typowych ról zespołowych (Dev, QA, SRE, SecOps), przypinane do grup w IdP zamiast ręcznego „klejenia” uprawnień każdemu z osobna.

Na poziomie mentalnym to zmiana: zamiast „każdy zespół robi, jak chce, dopóki coś nie wybuchnie”, ustala się minimalne standardy, które platforma technicznie egzekwuje. DevOpsi przestają być policjantami, a stają się użytkownikami sensownie zaprojektowanej szyny bezpieczeństwa.

Detekcja nadużyć: logi, które ktoś naprawdę czyta

Bez logów dostępu IAM, eventów administracyjnych i monitoringu anomalii żaden model uprawnień nie będzie skuteczny. Zawsze znajdzie się konto serwisowe z za szeroką rolą lub token, który wyciekł. Kluczowe jest, aby narzędzia chmurowe nie kończyły na „wysłaliśmy event do SIEM, reszta to nie nasz problem”.

Prosty, ale skuteczny zestaw praktyk:

  • pełne logowanie audytu – AWS CloudTrail, Azure Activity Log, GCP Audit Logs włączone dla wszystkich kont/projektów, agregowane centralnie i zabezpieczone przed modyfikacją,
  • reguły detekcji – alerty na dodanie roli admina do użytkownika, stworzenie access key dla konta ludzkiego, masowe nieudane loginy, użycie starych kluczy, zmiana polityk IAM/RBAC,
  • integracja z IdP – korelacja logów logowania SSO z akcjami w chmurze; zespół wie, czy „podejrzany” dostęp pochodził z nietypowego kraju, urządzenia, czasu,
  • prosta ścieżka reakcji – playbook: kto wyłącza dostęp, kto analizuje logi, kto komunikuje się z właścicielem aplikacji; procedura przetestowana jak każdy inny runbook SRE.

Mit, że „i tak nikt nie nadąży czytać tych logów” bierze się zwykle stąd, że logów jest dużo, ale brakuje sensownych reguł. Kilka dobrze zaprojektowanych alertów z niskim poziomem szumu działa lepiej niż setka ogólnikowych.

Infrastruktura jako kod (IaC) – bezpieczeństwo od pierwszego commita

Dlaczego „klikana” infrastruktura zabija powtarzalność i bezpieczeństwo

Ręczne klikanie zasobów w konsoli to kusząca droga na skróty: szybko, wygodnie, bez potrzeby znajomości Terraform czy Bicep. Problem pojawia się po tygodniu, gdy druga osoba próbuje odtworzyć środowisko i nie ma pojęcia, jakie dokładnie opcje były ustawione w GUI.

Mit: „Na początek szybciej jest wszystko wyklikać, a potem się to przepisze do IaC”. Potem prawie nigdy nie nadchodzi, a różnice między stanem rzeczywistym a kodem stają się na tyle duże, że nikt nie chce ich ruszać.

Bezpieczniejszy wzorzec to zasada: nie ma zasobu produkcyjnego bez definicji w IaC. Nawet jeśli pierwszy prototyp powstanie w konsoli, to zanim zasób trafi na stałe do środowiska, jego konfiguracja musi wylądować w repozytorium jako kod.

Wybór narzędzia IaC: Terraform, natywne szablony i miks podejść

Na poziomie bezpieczeństwa mniej ważne jest, czy używany jest Terraform, Bicep, CloudFormation czy Deployment Manager, a bardziej – jak są używane:

  • AWS – popularne są Terraform i CloudFormation; do bardziej zaawansowanych zastosowań pojawia się CDK (TypeScript/Python). Bezpieczny wzorzec to moduły Terraform z wbudowanymi politykami (np. prywatne subnety, domyślnie włączone KMS, zakaz publicznych bucketów).
  • Azure – Bicep jako lżejsza warstwa nad ARM, często w połączeniu z Terraformem zarządzającym wyższym poziomem (subskrypcje, management groups), a Bicep – szczegółami wewnątrz subskrypcji.
  • GCP – Terraform z Google Providerem dominuje, choć Deployment Manager bywa używany w starszych projektach; dodatkowo Blueprints i Config Controller dla bardziej złożonych środowisk.

Istotne jest, aby centralne moduły IaC były własnością platform teamu / SecOps i zawierały bezpieczeństwo „w standardzie”: szyfrowanie, logowanie, standardy tagowania, parametryzację sieci.

Repozytoria i podział kodu: granice bezpieczeństwa w IaC

Struktura repozytoriów IaC mocno wpływa na kontrolę dostępu. Połączenie wszystkiego w jednym monolicie kończy się tym, że junior devops może przypadkowo zmodyfikować produkcyjną sieć. Z drugiej strony zbyt silne rozdrobnienie uniemożliwia spójne polityki.

Praktyczny kompromis to:

  • osobne repozytorium (lub katalog) dla warstwy organizacyjnej – konta/subskrypcje/projekty, organizacja, polityki,
  • osobne dla warstwy sieci – VPC/VNet, peering, bramy, DNS,
  • repozytoria per produkt/aplikację, które używają zdefiniowanych wcześniej modułów do tworzenia baz danych, kolejek, storage’u.

Do każdego z tych obszarów przypisane są inne role: konfiguracja organizacji i sieci jest zwykle w rękach platform teamu, a repo aplikacyjne – w rękach zespołu produktowego.

Pipeline’y dla IaC: walidacja, plany i approvals

Bezpieczny DevOps traktuje kod infrastruktury jak kod aplikacji, ale z kilkoma dodatkowymi wymogami:

  • linting i validateterraform validate, bicep build, cfn-lint w pipeline’ach, aby wyłapywać błędy zanim dotkną zasobów,
  • plan jako artefakt – generowanie terraform plan i przechowywanie go jako artefaktu do review; zmiany w zasobach muszą być widoczne, zanim zostaną zastosowane,
  • approval gates – dla środowisk produkcyjnych zmianę IaC zatwierdza ktoś inny niż autor (code review + formalny approval w narzędziu CI/CD),
  • rozróżnienie środowisk – osobne workspace’y / katalogi / projekty dla dev, test, prod, bez „przeklikiwania” tych samych zasobów między środowiskami.

Dobrą praktyką jest też automatyczne porównywanie stanu rzeczywistego z IaC: jeśli ktoś zmienił konfigurację ręcznie w konsoli, pipeline pokaże drift i zmusi zespół do przywrócenia zgodności albo świadomego wprowadzenia zmiany do kodu.

Policy as Code: reguły bezpieczeństwa wbudowane w IaC

Zamiast recenzować każdy pull request pod kątem „czy ten bucket jest prywatny?”, wygodniej jest użyć narzędzi typu Policy as Code, które automatycznie ocenią konfigurację:

  • AWS – AWS Config z regułami, Service Control Policies, a także narzędzia open source jak Open Policy Agent (OPA) / Conftest lub Checkov skanujące Terraform/CloudFormation,
  • Azure, GCP i wspólne narzędzia do Policy as Code

    Choć każdy vendor ma swoje „wynalazki”, da się zbudować spójny zestaw reguł, który obejmie wszystkie trzy chmury i jednocześnie pozostanie zrozumiały dla zespołów.

  • AzureAzure Policy i Azure Blueprints pozwalają wymusić np. szyfrowanie dysków, określone SKU, blokadę publicznych IP dla PaaS. Polityki można przypinać na poziomie Management Group, co upraszcza utrzymanie. Dodatkowo Terraform + OPA/Conftest lub Checkov pozwalają wykryć naruszenia jeszcze przed deploymentem.
  • GCPOrganization Policy (np. blokada 0.0.0.0/0 w firewallu, wymuszenie użycia CMEK), a na warstwie IaC – Terraform Validator (Policy Library) oparty o reguły w Rego lub YAML. Do tego narzędzia typu tfsec, Checkov scalają kontrolę z AWS/Azure.
  • Wspólna warstwa – OPA/Conftest, Checkov, tfsec czy Regula działają na samym kodzie IaC. Dzięki temu można mieć wspólne reguły typu „żaden storage nie jest publiczny”, a szczegóły vendorowe zostawić platform teamowi.

Mit: „Policy as Code to rakietowa inżynieria dla wielkich korporacji”. W rzeczywistości kilka prostych reguł typu „brak publicznego S3/Storage/Bucket” i „wymagane tagi owner/cost-center” daje szybki zwrot – zwłaszcza gdy DevOps nie musi tego ręcznie recenzować w każdym PR.

Przeglądy bezpieczeństwa IaC: code review z checklistą, nie z intuicją

Automatyczne skanery nie wychwycą wszystkiego. W szczególności nie ocenią, czy architektura w ogóle ma sens, albo czy otwarcie portu 22 do świata jest uzasadnione. Dlatego przegląd zmian w IaC powinien mieć formę prostej, ale powtarzalnej checklisty.

Kilka pytań, które pomagają w codziennej praktyce:

  • czy nowy zasób ma włączone logowanie (S3 access logs, Azure Diagnostics, GCP Logs) i jest ono wysyłane do centralnego miejsca,
  • czy ruch przychodzący jest ograniczony do znanych segmentów (VPC/VNet peering, VPN, Private Link / Private Service Connect),
  • czy włączono szyfrowanie z odpowiednim KMS/CMEK i czy klucze nie są przypadkiem zarządzane na poziomie projektu/konta, które może za chwilę zniknąć,
  • czy zmiana nie obniża poziomu uprawnień (np. przyznanie roli Owner na subskrypcji „na chwilę”),
  • czy istnieje plan migracji/rollbacku, jeśli zmiana dotyczy krytycznych komponentów (gateway, routing, DNS).

Bez takiej listy review szybko zamienia się w „wygląda ok” – i wtedy nawet najlepszy scanner nie uchroni przed wprowadzeniem fałszywie „tymczasowych” wyjątków.

Okulary odbijające kod na monitorze podczas pracy nad DevOps w chmurze
Źródło: Pexels | Autor: Kevin Ku

Sieć i segmentacja: wzorce izolacji środowisk w trzech chmurach

Po co tyle segmentacji: co faktycznie chroni izolacja sieciowa

Segmentacja sieciowa to nie ozdoba do diagramu, tylko sposób na ograniczenie skutków błędów aplikacyjnych i ludzkich. Jeśli kompromitowane jest pojedyncze konto serwisowe lub jeden workload, dobrze zaprojektowana sieć potrafi zatrzymać atak w jednym segmencie.

Mit: „w chmurze wszystko jest tak czy inaczej za NAT-em, więc jest bezpieczne”. Rzeczywistość jest bardziej brutalna – publiczne IP, źle ustawiony load balancer, zbyt szeroki firewall czy otwarte porty w Security Group/VNet NSG potrafią wystawić wrażliwe usługi prosto do internetu, nawet jeśli nikt nie planował takiego scenariusza.

Dlatego sensowny DevOps zaczyna od pytania: co może rozmawiać z czym, zamiast: „gdzie tu kliknąć, żeby zadziałało”.

Wzorzec: osobne konta/subskrypcje/projekty dla środowisk

Najpierw izolacja na poziomie „kontenerów” chmurowych, potem dopiero zabawa w mikrosegmentację. Mieszanie dev, test i prod w jednym koncie to zaproszenie do kłopotów – zarówno operacyjnych, jak i bezpieczeństwa.

  • AWS – konta w AWS Organizations podzielone przynajmniej na: sandbox/dev, test/stage, prod i shared services. SCP ograniczające możliwości w sandbox (np. brak możliwości tworzenia publicznych baz danych) i twardsze reguły dla prod.
  • Azure – oddzielne subskrypcje na środowiska, spięte w Management Groups. Dla subskrypcji produkcyjnej zwykle osobne polityki, billing i jeszcze ostrzejsze wymagania (np. wymuszony Private Link dla PaaS).
  • GCP – podział na projekty per środowisko (a często per aplikacja + środowisko), umieszczone w strukturze folders w ramach jednej organizacji. Organization Policies różnicują możliwe konfiguracje między dev a prod.

Taki podział naturalnie ogranicza skutki błędu w IaC – jeśli ktoś w dev wytnie routing lub otworzy wszystko na świat, prod będzie dalej działał, a polityki organizacyjne zablokują najbardziej ryzykowne ruchy.

Topologie VPC/VNet/VPC: hub-and-spoke i warianty

Niezależnie od chmury powtarza się kilka sprawdzonych wzorców. Najczęściej w dużych organizacjach ląduje układ hub-and-spoke z niewielkimi wariacjami.

  • AWScentralny VPC (hub) z VPN/Direct Connect do on-prem, współdzielonymi usługami (np. centralny Bastion, systemy monitoringu, proxy), a do tego spoke VPC per aplikacja/produkt połączone przez VPC Peering lub Transit Gateway. Ruch między spoke zwykle blokowany lub mocno filtrowany.
  • AzureHub VNet z Azure Firewall / NVA i bramami VPN/ExpressRoute, oraz Spoke VNet na aplikacje. Komunikacja zwykle poprzez peering VNet, kontrolowana przez UDR i NSG. Często osobny hub dla prod i non-prod.
  • GCPShared VPC z host project pełniącym rolę huba i service projects jako spoke. Do tego Cloud VPN/Interconnect w hubie. Firewall rules zarządzane centralnie, aplikacje korzystają z odseparowanych subnetów.

Ten wzorzec ma jedną dużą zaletę: centralizuje punkty styku ze światem. Łatwiej jest obserwować i filtrować ruch, jeśli internet i on-prem wchodzą do chmury przez dwie–trzy kontrolowane bramy, a nie przez kilkadziesiąt losowych publicznych IP w każdym projekcie.

Prywatny dostęp do usług zarządzanych: uszczelnianie PaaS

Najbardziej niedoszacowany wektor ryzyka to PaaS-y wystawione „na chwilę” publicznie, żeby ułatwić sobie życie. Publiczny endpoint bazy danych, storage dostępny z dowolnego IP czy funkcje serverless z otwartym HTTP szybko stają się domyślnym rozwiązaniem, jeśli nikt nie narzuci lepszego standardu.

W każdej z chmur da się zbudować wzorzec „PaaS tylko prywatnie”:

  • AWSVPC Endpoints (Gateway/Interface) dla S3, DynamoDB i innych usług; RDS i ElastiCache tylko w prywatnych subnetach; PrivateLink do własnych usług eksponowanych między kontami. Dla S3 – bucket policy blokująca dostęp spoza określonych VPC Endpointów.
  • AzurePrivate Endpoint dla Storage, SQL, Web Apps itd., powiązany z prywatnym IP w VNet. W połączeniu z Azure Policy można zablokować tworzenie publicznych endpointów dla określonych typów zasobów.
  • GCPPrivate Service Connect i Private Google Access, które umożliwiają dostęp do usług Google i własnych backendów tylko z sieci prywatnej. Dodatkowo rezygnacja z publicznych IP dla VM (dostęp przez IAP/Bastion, nie bezpośredni SSH).

Mit: „bez publicznego IP debugging jest niemożliwy”. W praktyce dostęp przez bastion, Session Manager (AWS), Azure Bastion, IAP (GCP) i dobre logi daje większą kontrolę, a po stronie bezpieczeństwa zamyka sporą grupę ataków skanujących.

Warstwy sieci w ramach jednego środowiska: podział na strefy

Gdy środowisko urośnie, pojedynczy „płaski” VPC/VNet to za mało. Dobry, pragmatyczny podział to klasyczne strefy:

  • edge/public – load balancery, WAF, CDN; wystawione do internetu, ale z minimalnym zakresem otwartych portów; tu kończy się TLS z przeglądarki/klienta,
  • application – serwisy backendowe, API, worker’y; zwykle bez publicznych IP, komunikujące się tylko z edge i niższymi warstwami,
  • data – bazy danych, kolejki, magazyny plików; dostęp tylko z aplikacji, bez bezpośredniej komunikacji z edge.

W AWS rolę podstawowej zapory pełnią Security Groups i NACL, w Azure – NSG i opcjonalnie Azure Firewall, w GCP – VPC firewall rules. Zasada jest jedna: reguły są oparte na tożsamości segmentu (tagi, security groups, service accounts), a nie na „losowych” IP.

Przykładowo:

  • Security Group „app” może mówić „przyjmuję ruch tylko z SG edge na port 443”,
  • NSG dla subnetu „data” w Azure zezwala wyłącznie na ruch z podów Kubernetes o określonych labelach (przy użyciu Azure CNI/Calico z Network Policies),
  • GCP firewall rule dopuszcza ruch tylko od instancji z konkretnym tagiem app-backend do instancji z tagiem db na port 5432.

Kontrola ruchu w klastrach Kubernetes: CNI i Network Policies

Kubernetes w chmurze potrafi zniweczyć część wysiłku włożonego w segmentację, jeśli zostanie pozostawiony w domyślnej konfiguracji „wszystko ze wszystkim”. Przy większej liczbie mikroserwisów sieć w klastrze staje się miniaturowym „internetem wewnątrz” – bez filtracji ruchu szybko robi się z tego chaos.

Na rynku chmurowym pojawiają się dwa główne kierunki:

  • Korzystanie z sieci natywnej chmury – EKS + VPC CNI (AWS), AKS + Azure CNI, GKE + VPC-native. Zaleta: integracja z istniejącymi VPC/VNet i firewallami. Wadą bywa skomplikowane zarządzanie IP przy dużej skali.
  • Sieci z własnym modelem polityk – np. Calico, Cilium, Azure Network Policies. Tutaj kontrola ruchu odbywa się na poziomie podów, z wykorzystaniem NetworkPolicy i labeli.

Bez względu na wybór CNI, trzyma się prostego zestawu reguł:

  • domyślnie brak ruchu między przestrzeniami nazw (namespace),
  • otwieranie tylko tych ścieżek, które są faktycznie używane (np. frontendbackend, backenddb-proxy),
  • brak bezpośredniego ruchu z podów do internetu – wszystko idzie przez egress gateway / proxy / NAT w hubie.

Mit: „NetworkPolicy to zbędna komplikacja, wystarczą Security Groups”. Security Groups/NSG/VPC firewalle działają na poziomie VM/node; w Kubernetes ruch wewnętrzny między podami na jednym hoście bywa niewidoczny dla tych mechanizmów. Bez polityk sieciowych w klastrze otrzymujemy zaufaną sieć „płaską”, w której każdy kompromitowany pod może próbować skanować całą resztę.

Inspekcja i obserwowalność ruchu: nie tylko firewall, ale też oczy

Segmentacja ma sens wtedy, gdy ktoś widzi, jak ruch przepływa przez sieć. Same reguły firewalli bez logów i metryk są ślepą uliczką – coś zablokują, ale nie powiedzą, czy nie powstał nowy, nieoczekiwany kanał komunikacji.

W chmurze da się połączyć zapory z telemetrią:

  • AWSVPC Flow Logs dla kluczowych subnetów, logowanie z AWS Network Firewall, statystyki z load balancerów (ALB/NLB) wysyłane do CloudWatch/ELK. Na tej podstawie wykrywa się nietypowe kierunki ruchu, skany portów czy nagłe wzrosty połączeń między segmentami.
  • AzureNSG Flow Logs, logi z Azure Firewall i Application Gateway, wszystko agregowane w Log Analytics/ Sentinel. Dzięki Kusto Query Language da się szybko sprawdzić, czy np. aplikacja w dev nagle rozmawia z bazą produkcyjną.
  • GCPVPC Flow Logs, logi z Cloud Armor, Internal/External HTTP(S) Load Balancerów i firewall rules w Cloud Logging; łatwo z nich zbudować podstawowe dashboardy w Cloud Monitoring lub przerzucić dane do zewnętrznego SIEM.

W praktyce kilka prostych raportów wystarcza, by wcześnie wykrywać problemy:

  • lista top 10 par źródło–cel według ilości ruchu,
  • nowe kierunki ruchu między środowiskami (np. dev → prod),
  • nietypowe porty i protokoły, które pojawiły się w ostatnich dniach.

Kluczowe Wnioski

  • DevSecOps to nie „nowa naklejka na DevOps”, tylko realna zmiana: bezpieczeństwo staje się wymaganiem niefunkcjonalnym egzekwowanym automatycznie w pipeline’ie CI/CD, a nie ręcznym audytem na końcu.
  • Mit: „Jak jesteśmy w chmurze, to dostawca zadba o bezpieczeństwo”. Rzeczywistość: AWS, Azure i GCP zabezpieczają infrastrukturę, ale konfiguracja sieci, IAM, szyfrowania, ekspozycji usług i pipeline’ów w 100% leży po stronie zespołu DevOps.
  • Największym wrogiem bezpieczeństwa w chmurze jest „klikologia”: ręczne zmiany w konsoli bez IaC prowadzą do braku powtarzalności, braku historii i recenzji – nawet dobrze zaprojektowana architektura szybko zamienia się w zlepek niekontrolowanych wyjątków.
  • Skorzystanie z usług zarządzanych (RDS, Azure SQL, Cloud SQL) nie gwarantuje bezpieczeństwa, jeśli baza stoi w publicznej podsieci, ma otwarte reguły sieciowe i nadmiarowe uprawnienia IAM – wyciek danych będzie skutkiem złej konfiguracji, nie „błędu chmury”.
  • Bezpieczny DevOps w chmurze ma trzy główne cele: ograniczenie powierzchni ataku (mniej publicznych zasobów i nadmiernych ról), skrócenie czasu wykrycia incydentu (sensowne logowanie i alerty) oraz automatyzację reakcji (polityki typu AWS Config Rules, Azure Policy, GCP Organization Policy + szybkie rollouty poprawek).