Vanilla Kubernetes

Drugi deo: Workload platforma, mreža, podaci i bezbednost
Autentikacija i identiteti – korisnici, sertifikati, OIDC i granice Kubernetes API-ja
VIII. Identitet, autorizacija i zaštita workload-a
34. Autentikacija i identiteti – korisnici, sertifikati, OIDC i granice Kubernetes API-ja

Posle mreže, skladišta i oporavka podataka, sledeće administratorsko pitanje glasi: ko sme da pošalje zahtev Kubernetes API-ju i kako klaster utvrđuje identitet pošiljaoca? Svaki poziv koji šalju kubectl, kontroler, kubelet, operator ili aplikacija prolazi kroz TLS vezu i lanac obrade u API serveru. Autentikacija pokušava da zahtev poveže sa korisničkim imenom, UID-om, grupama i dodatnim atributima. Tek zatim autorizacija odlučuje da li taj identitet sme da izvrši traženu radnju, a admission kontrola proverava ili menja objekat pre čuvanja.

Najvažnija granica ove lekcije jeste da autentikovan ne znači ovlašćen. Važeći sertifikat ili OIDC token dokazuje identitet prema pravilima API servera, ali sam po sebi ne daje pravo na čitanje Secret objekata, kreiranje podova ili administraciju klastera. Ta prava obrađuje naredna lekcija o RBAC-u. Ovde gradimo pouzdanu osnovu: razlikujemo ljudske i workload identitete, biramo odgovarajući autentikacioni mehanizam, proveravamo šta server zaista vidi i dijagnostikujemo neuspeh bez izlaganja poverljivih podataka.

Putanja API zahteva: TLS, autentikacija, autorizacija i admission

Klijent najpre proverava serving sertifikat API servera pomoću CA podatka iz kubeconfig-a. Ako TLS identitet servera nije pouzdan, zahtev se ne šalje bezbedno i autentikacija korisnika još nije ni počela. Opcija --insecure-skip-tls-verify uklanja ovu proveru i zato nije rešenje za produkciju: omogućava presretanje veze i krađu tokena ili podataka. Ispravka je pouzdan CA lanac i serving sertifikat čiji SAN obuhvata DNS ime ili IP adresu endpoint-a.

Posle uspostavljanja TLS veze, jedan ili više konfigurisanih autentikatora obrađuju kredencijal. Uspešan rezultat sadrži najmanje korisničko ime, a može sadržati UID, grupe i extra atribute. API server uspešno autentikovane identitete dodaje u grupu system:authenticated. Ako nijedan mehanizam ne prihvati zahtev, rezultat zavisi od toga da li je omogućen anonimni pristup: zahtev može dobiti identitet system:anonymous u grupi system:unauthenticated ili biti odbijen.

  1. TLS autentikacija servera: klijent potvrđuje da razgovara sa očekivanim API serverom.
  2. Autentikacija klijenta: sertifikat, bearer token, OIDC JWT, webhook ili autentikacioni proxy mapira zahtev na identitet.
  3. Autorizacija: RBAC, Node ili drugi authorizer donosi odluku dozvoli ili zabrani.
  4. Admission: mutating i validating kontroleri primenjuju politike na zahtev koji je prošao autorizaciju.
  5. Izvršenje i audit: zahtev se izvršava, a audit politika može zabeležiti identitet, glumljeni identitet, objekat i ishod.
Simptom Najverovatniji sloj Administratorsko tumačenje
x509: certificate signed by unknown authority TLS poverenje prema serveru Klijent ne veruje CA lancu API endpoint-a; RBAC još nije relevantan.
401 Unauthorized Autentikacija Kredencijal nedostaje, istekao je, ima pogrešan issuer/audience ili nije prihvaćen.
403 Forbidden Autorizacija Identitet je uglavnom prepoznat, ali nema traženo pravo ili pokušava nedozvoljenu impersonaciju.
Admission webhook odbija objekat Admission Identitet je prošao ranije faze, ali zahtev krši politiku ili webhook nije dostupan.

Korisnici u Kubernetes-u i granice API-ja

Kubernetes razlikuje normalne korisnike, koje održava spoljašnji sistem, i ServiceAccount identitete, kojima upravlja Kubernetes API. Ne postoji ugrađeni API objekat User za zaposlenog, niti komanda kojom se u vanilla Kubernetes-u kreira lokalni ljudski nalog. Ime poput natasa@example.com nastaje tek kada autentikator prihvati sertifikat ili token i iz njega izvede atribute identiteta.

Zato brisanje RoleBinding-a nije isto što i gašenje korisničkog naloga, a brisanje nepostojećeg User objekta ne može opozvati sertifikat. Životni ciklus zaposlenih, MFA, reset lozinke, zaključavanje naloga, članstvo u organizacionim grupama i dokaz identiteta pripadaju identity provider-u, korporativnom PKI-ju ili drugom spoljašnjem sistemu. Kubernetes troši rezultat tog sistema i primenjuje svoja pravila autorizacije.

Identitet Izvor i tipičan oblik Životni ciklus Najvažniji rizik
Ljudski korisnik OIDC provider ili X.509 klijentski sertifikat Van klastera; prava se povezuju unutar klastera Deljeni kubeconfig, dugačak vek kredencijala, slabo ukidanje pristupa
ServiceAccount system:serviceaccount:<namespace>:<name> Kubernetes API objekat u namespace-u Preširoka prava ili nepotrebno automatsko montiranje tokena
Node/kubelet system:node:<node-name>, grupa system:nodes Bootstrap i rotacija klijentskog sertifikata Pogrešno odobren CSR može dati identitet drugog noda
Kontrolna komponenta Komponentni kubeconfig ili ServiceAccount Instalacioni alat/distribucija Krađa privilegovanog kubeconfig-a ili privatnog ključa
Anonimni zahtev system:anonymous, system:unauthenticated Konfiguracija API servera Nenamerno javno pravo kroz pogrešan binding

Korisnička imena i grupe su za autentikacioni sloj neprozirni stringovi, ali prefiks system: rezervisan je za Kubernetes sistemske identitete. Organizacione identitete ne treba imenovati tim prefiksom. Posebno je rizična grupa system:masters: u tipičnoj konfiguraciji zaobilazi uobičajenu RBAC politiku preko privilegovanog authorizer puta i ne treba je koristiti kao svakodnevnu administratorsku grupu. Redovni pristup se vezuje za eksplicitne, revizibilne organizacione grupe.

Kubeconfig: endpoint, poverenje, identitet i kontekst

Kubeconfig nije korisnički nalog, već konfiguracioni dokument koji povezuje clusters, users i contexts. Stavka klastera određuje API endpoint i CA poverenje; stavka korisnika sadrži ili pribavlja kredencijal; context bira njihov par i podrazumevani namespace. Imena ovih stavki su lokalne oznake. Naziv natasa u kubeconfig-u ne garantuje da API server vidi isto korisničko ime.

apiVersion: v1
kind: Config
clusters:
- name: lab-cluster
  cluster:
    server: https://api.lab.example:6443
    certificate-authority: /etc/kubernetes/pki/ca.crt
users:
- name: lab-reader
  user:
    client-certificate: /secure/kube/lab-reader.crt
    client-key: /secure/kube/lab-reader.key
contexts:
- name: lab-reader@lab-cluster
  context:
    cluster: lab-cluster
    user: lab-reader
    namespace: identity-lab
current-context: lab-reader@lab-cluster

Polja sa sufiksom -data sadrže base64-kodirane bajtove, ne šifrovane tajne. Fajl sa ugrađenim client-key-data ili bearer tokenom mora imati ograničene dozvole, ne sme se slati e-poštom, stavljati u Git niti uključivati u nezaštićeni support bundle. Spajanje više fajlova preko promenljive KUBECONFIG takođe nosi rizik: kubeconfig može sadržati exec plugin koji pokreće lokalni program. Nepouzdan kubeconfig tretira se kao izvršni sadržaj.

kubectl config current-context
kubectl config get-contexts
kubectl config view --minify --raw
kubectl auth whoami
kubectl auth can-i get pods --namespace identity-lab

Prve dve komande su read-only i bezbedne. kubectl config view --raw može prikazati privatne ključeve ili tokene i zato se njegov izlaz ne kopira u ticket; za rutinsku proveru izostavlja se --raw. Komanda kubectl auth whoami koristi SelfSubjectReview API i prikazuje identitet koji je server zaista izveo. Ako server ili prava ne omogućavaju tu proveru, audit zapis ili kontrolisani SelfSubjectReview zahtev služi kao alternativa. kubectl auth can-i proverava autorizaciju, ne validnost identiteta uopšte.

X.509 klijentski sertifikati

Kada API server veruje CA autoritetu navedenom kroz --client-ca-file, validan X.509 klijentski sertifikat potpisan tim CA-om može postati Kubernetes identitet. U uobičajenom mapiranju Common Name (CN) postaje korisničko ime, a Organization (O) postaje grupa. Sertifikat mora imati namenu client auth; serving sertifikat nije automatski klijentski kredencijal.

Subject: CN=lab-reader, O=platform-readers
Kubernetes username: lab-reader
Kubernetes groups:   platform-readers, system:authenticated

Privatni ključ nikada se ne šalje API serveru niti ugrađuje u CSR. Vlasnik ga generiše i štiti lokalno, a CSR sadrži javni ključ i traženi subject. Kubernetes CertificateSigningRequest API razdvaja podnošenje, odobravanje i potpisivanje. Ugrađeni signer kubernetes.io/kube-apiserver-client namenjen je API klijentskim sertifikatima i kube-controller-manager ga nikada ne odobrava automatski. Administrator koji odobrava zahtev mora izvan samog CSR-a potvrditi identitet podnosioca, subject, grupe, signer, usages i traženi rok.

Polje spec.expirationSeconds postoji od Kubernetes 1.22. Ugrađeni signer izdaje sertifikat sa kraćim od traženog roka i svog maksimalnog --cluster-signing-duration. To nije garancija da će svaki spoljašnji signer poštovati isto pravilo. Kratkotrajni sertifikati smanjuju prozor zloupotrebe, ali zahtevaju pouzdanu obnovu. Kubernetes nema opšti, automatski CRL/OCSP mehanizam za trenutno opozivanje proizvoljnog klijentskog sertifikata; kod kompromitacije se odmah uklanjaju autorizaciona povezivanja, rotira kredencijal, a po potrebi menja ili sužava CA poverenje prema incident proceduri.

Provera pre odobravanja CSR-a Zašto je obavezna
spec.username i spec.groups podnosioca Pokazuju ko je kreirao CSR, ali ne dokazuju da sme da traži navedeni subject.
Dekodirani PKCS#10 subject i javni ključ Otkriva traženi CN, O, SAN i algoritam, umesto oslanjanja na ime objekta.
signerName i usages Sprečava izdavanje sertifikata za pogrešnu trust domenu ili svrhu.
expirationSeconds Ograničava vek kredencijala u skladu sa politikom.
Odobrenje naspram izdavanja Approved CSR može ostati bez sertifikata ako signer nije funkcionalan; proverava se status.certificate.

OIDC za ljudske identitete

OpenID Connect omogućava da korporativni identity provider autentikuje čoveka, primeni MFA i izda potpisani ID token, dok API server proverava potpis, issuer, audience, vreme važenja i claim pravila. API server nije OIDC web aplikacija za interaktivno prijavljivanje: on ne prikazuje login stranicu, ne čuva korisničke lozinke i uglavnom ne osvežava token. kubectl zato koristi credential ili exec plugin koji obavlja authorization-code/device tok prema provider-u i API-ju prosleđuje važeći token.

Za produkciju je OIDC obično pogodniji od ručnog deljenja dugotrajnih klijentskih sertifikata: centralizuje gašenje naloga, MFA i grupno članstvo. Ipak, gašenje sesije kod provider-a ne mora trenutno poništiti već izdat JWT; prozor zavisi od veka tokena i pravila validacije. Kratak vek, bezbedan refresh tok i razumno keširanje predstavljaju deo dizajna.

OIDC element Administratorska odluka Tipična greška
Issuer Mora se tačno poklapati sa iss claim-om i koristiti pouzdani HTTPS endpoint. Razlika u putanji ili završnoj kosi crti daje 401.
Audience Poseban client ID/audience za Kubernetes API. Prihvatanje tokena izdatog drugoj aplikaciji.
Username claim Stabilan, jedinstven claim; često email ili kombinacija issuer+subject. Promenljiv ili ponovo upotrebljen identifikator prekida ili preusmerava RBAC veze.
Groups claim Kontrolisana lista organizacionih grupa i bezbedan prefiks. Kolizija sa lokalnim ili system: grupama.
Signing keys/JWKS API server mora dohvatiti i osvežavati pouzdane javne ključeve. Rotacija ključa, DNS, proxy ili CA problem prekida nove prijave.
Vreme NTP sinhronizacija na klijentima, provider-u i control-plane nodovima. exp/nbf odbijanje usled clock skew-a.

Savremeni API server podržava strukturisanu AuthenticationConfiguration datoteku sa više JWT autentikatora i CEL pravilima za validaciju i mapiranje claim-ova. Konfiguracija se učitava opcijom --authentication-config; ne kombinuje se za isti JWT/OIDC slučaj sa odgovarajućim --oidc-* zastavicama. Pre primene proverava se dokumentacija tačne verzije klastera i podrška distribucije. Primer je obrazac za pregled, a ne univerzalna copy-paste konfiguracija:

apiVersion: apiserver.config.k8s.io/v1
kind: AuthenticationConfiguration
jwt:
- issuer:
    url: https://id.example.com
    audiences:
    - kubernetes-prod
    audienceMatchPolicy: MatchAny
  claimValidationRules:
  - claim: hd
    requiredValue: example.com
  claimMappings:
    username:
      expression: "claims.email"
    groups:
      expression: "claims.groups"
    uid:
      expression: "claims.sub"
  userValidationRules:
  - expression: "!user.username.startsWith('system:')"
    message: "username ne sme koristiti rezervisani prefiks system:"

U Kubernetes 1.34 konfiguracija anonimnog autentikatora kroz isti API stabilna je i može ograničiti anoniman pristup na tačno definisane endpoint-e, na primer health provere. Ako se polje anonymous postavi u konfiguracionoj datoteci, ne koristi se istovremeno zastavica --anonymous-auth. Promena autentikacije API servera ima veliki blast radius: na HA control plane-u uvodi se postepeno, uz rezervni administratorski pristup, validaciju svakog endpoint-a i unapred pripremljen rollback statičkog Pod manifesta ili upravljane konfiguracije.

ServiceAccount i workload identitet

ServiceAccount je namespaced Kubernetes objekat namenjen procesima, a ne zamena za ljudski nalog. Njegovo kanonsko korisničko ime je system:serviceaccount:<namespace>:<name>, uz grupe system:serviceaccounts i system:serviceaccounts:<namespace>. Podrazumevani default ServiceAccount postoji u svakom namespace-u, ali aplikacije sa različitim potrebama treba da koriste zasebne, namenski imenovane naloge.

Bound ServiceAccount token volume stabilan je od Kubernetes 1.22. Kubelet preko TokenRequest API-ja dobija kratkotrajni, audience-bound token, montira ga kao projected volume i osvežava pre isteka. Ovaj mehanizam zamenjuje automatski generisane, dugotrajne Secret tokene iz starijih verzija. Ručno pravljenje ServiceAccount token Secret-a i dalje je moguće za retke legacy integracije, ali stvara kredencijal bez automatskog kratkog roka i nije preporučeni obrazac.

apiVersion: v1
kind: ServiceAccount
metadata:
  name: inventory-reader
  namespace: identity-lab
automountServiceAccountToken: false
---
apiVersion: v1
kind: Pod
metadata:
  name: api-client
  namespace: identity-lab
spec:
  serviceAccountName: inventory-reader
  automountServiceAccountToken: false
  containers:
  - name: client
    image: registry.k8s.io/e2e-test-images/agnhost:2.53
    args: ["pause"]

Vrednost automountServiceAccountToken: false smanjuje izloženost kada workload ne poziva API. Ako mu je potreban token za drugi servis, projected volume treba da koristi posebnu audience vrednost i kratak rok; servis primalac token proverava preko TokenReview API-ja ili odgovarajuće JWT validacije. Token namenjen Kubernetes API-ju ne koristi se kao generički identitet za svaku internu aplikaciju.

volumes:
- name: workload-identity
  projected:
    sources:
    - serviceAccountToken:
        path: token
        audience: https://vault.example.com
        expirationSeconds: 3600

Komanda kubectl create token inventory-reader -n identity-lab --duration=10m poziva TokenRequest i pogodna je za kratku, kontrolisanu proveru. Token se ne ispisuje u zajednički terminal log niti smešta u shell history. Brisanje ServiceAccount-a nije univerzalna trenutna revokacija svih mogućih tokena, dok se token vezan za konkretan Pod poništava brisanjem tog Pod-a; incident procedura mora znati koji tip tokena je izdat.

Ostali autentikacioni mehanizmi i izbor rešenja

API server može koristiti autentikacioni webhook, authenticating proxy i client-go exec credential plugin. Webhook prosleđuje bearer token spoljašnjem servisu kroz TokenReview zahtev i uvodi mrežnu zavisnost, keširanje odluka, TLS poverenje i zahtev za visokom dostupnošću. Authenticating proxy sme postavljati korisničke headere samo ako API server pouzdano autentikuje proxy klijentskim sertifikatom i uklanja mogućnost da neposredni klijent falsifikuje te headere.

Statička datoteka tokena zahteva restart API servera za promenu, tokeni nemaju ugrađen rok i teško se opozivaju; bootstrap tokeni su namenjeni kontrolisanom pridruživanju nodova, ne svakodnevnom ljudskom pristupu. Statička basic-auth datoteka više nije podržani savremeni mehanizam. Za nove implementacije prednost imaju centralni OIDC za ljude, kratkotrajni TokenRequest tokeni za workload-e i automatizovani, strogo provereni sertifikati za komponente kojima su potrebni.

Mehanizam Pogodna namena Produkcioni uslov
OIDC Ljudski pristup i organizacione grupe MFA, kratki tokeni, stabilni claim-ovi, HA provider i testirana rotacija ključeva
X.509 client cert Komponente, bootstrap i ograničeni administratorski slučajevi PKI zaštita ključa, kratak rok, kontrolisan CSR approval i plan opoziva
ServiceAccount TokenRequest Podovi i automatizacija Namenski nalog, audience binding, minimalna prava i bez logovanja tokena
Webhook Integracija sa nestandardnim token sistemom HA, TLS, timeout, keš politika, monitoring i fail-safe odluka
Authenticating proxy Kontrolisana enterprise pristupna kapija Ekskluzivno poverenje u proxy sertifikat i zaštita request header-a

Projektovanje identiteta za produkciju

Dobar dizajn počinje inventarom aktera i trust domena, a ne izborom zastavice API servera. Za svaki identitet beleže se vlasnik, izvor istine, način izdavanja, rok, audience, grupe, klasteri kojima pristupa, način opoziva i audit korelacija. Ljudski nalog se ne deli sa CI sistemom; workload ne koristi lični kubeconfig; break-glass identitet ne koristi se za redovan rad.

Performanse autentikacije posebno zavise od udaljenog webhook-a i dostupnosti OIDC metapodataka/JWKS-a. Lokalna JWT provera je obično jeftina, ali rotacija ključeva i nedostupan issuer mogu pogoditi nove zahteve. Monitoring obuhvata apiserver request metrike po kodu odgovora, latenciju autentikacionog webhook-a, greške učitavanja konfiguracije, vreme važenja sertifikata i korelaciju sa promenama IdP-a, DNS-a, proxy-ja i NTP-a.

Dijagnostika autentikacije i bezbedan incident response

Dijagnostika se vodi od najmanje invazivne provere ka promeni control plane-a. Najpre se beleže vreme, pogođeni korisnici, klaster, endpoint, context i tačna greška bez kredencijala. Zatim se odvaja TLS problem od 401, 403 i admission problema. Tek kada je hipoteza potvrđena menja se konfiguracija.

  1. Obim: da li je pogođen jedan korisnik, jedna grupa, svi OIDC korisnici, ServiceAccount ili svi klijenti jednog API endpoint-a?
  2. Klijentska činjenica: proveriti current-context, endpoint, CA referencu, lokalno vreme i rok sertifikata/tokena.
  3. Serverov pogled: ako autentikacija radi, izvršiti kubectl auth whoami; zatim odvojeno proveriti can-i.
  4. Control-plane dokaz: pregledati kube-apiserver logove i audit događaje u relevantnom vremenskom prozoru na svim HA instancama.
  5. Spoljne zavisnosti: proveriti issuer discovery, JWKS, DNS, CA, proxy, NTP ili webhook latenciju bez kopiranja tokena.
  6. Korekcija: obnoviti kredencijal, ispraviti claim mapping ili vratiti poslednju dobru konfiguraciju; ne gasiti TLS proveru.
  7. Oporavak: potvrditi identitet, dozvoljenu i zabranjenu radnju, sve API endpoint-e i audit trag.
# Read-only lokalne provere
kubectl config current-context
kubectl cluster-info
kubectl auth whoami -o yaml

# Pregled roka klijentskog sertifikata; ne ispisuje privatni ključ
openssl x509 -in /secure/kube/lab-reader.crt -noout \
  -subject -issuer -dates -ext extendedKeyUsage

# Control-plane host; zahtevaju odobren sudo pristup
sudo crictl ps --name kube-apiserver
sudo crictl logs --since 15m APISERVER_CONTAINER_ID

U systemd ili upravljanim distribucijama putanja do loga zavisi od implementacije; može se koristiti journalctl, platformni log servis ili cloud control-plane zapis. Traže se vreme zahteva, HTTP status, autentikator, issuer/audience ili x509 greška, korisničko ime i audit ID. Token, refresh token, privatni ključ i cela Authorization vrednost moraju biti redigovani.

Simptom Neposredni uzrok Bezbedna korekcija Trajna mera
Samo jedan x509 korisnik dobija 401 Istekao sertifikat, pogrešan key pair ili clientAuth usage Izdati novi kratkotrajni sertifikat posle provere identiteta Monitoring isteka i automatizovana obnova
Svi OIDC korisnici povremeno dobijaju 401 JWKS/issuer dostupnost, rotacija ključa ili razlika među API serverima Vratiti konzistentnu poslednju dobru konfiguraciju i proveriti sve endpoint-e Staged rollout, HA issuer, monitoring i game-day rotacije
Whoami pokazuje neočekivano ime ili grupe Pogrešan claim mapping/prefix Zaustaviti dodelu novih prava i ispraviti mapiranje Test korisnici, negativni testovi i change kontrola claim ugovora
Autentikacija radi, radnja vraća 403 Nedostaje autorizacija Ne menjati autentikator; analizirati RBAC u narednoj lekciji Najmanje privilegije i periodični access review
Token je otkriven u logu Nezaštićen debug ili CI izlaz Prekinuti izlaganje, ukloniti log pristup i opozvati/sačekati istek prema tipu tokena Redakcija, secret scanning i zabrana verbose HTTP logovanja

Integrisani praktikum: dokaz identiteta, kratkotrajni sertifikat i granice pristupa

Poslovni i tehnički kontekst.

Platform tim uvodi novog read-only laboratorijskog korisnika. Cilj nije dodela širokih prava, već dokaz celog lanca: generisanje privatnog ključa, kontrola CSR-a, kratkotrajno izdavanje sertifikata, izolovan kubeconfig, potvrda identiteta i razlikovanje 401 od 403. Minimalni Role/RoleBinding koristi se samo kao test fixture; detaljno projektovanje RBAC-a sledi u lekciji 35.

Topologija i preduslovi.

Rizik je srednji: odobren CSR izdaje stvarni kredencijal koji API server prihvata. Vežba se izvodi samo u laboratoriji, sa rokom od jednog sata i bez privilegovanih grupa. Pre početka potvrditi context; kod produkcionog sistema proces mora imati ticket, razdvojene dužnosti i identitetsku proveru van klastera.

  1. Pripremite izolovan prostor i početno stanje.
    umask 077
    mkdir -p identity-lab
    cd identity-lab
    kubectl config current-context
    kubectl auth whoami
    kubectl auth can-i create certificatesigningrequests.certificates.k8s.io
    kubectl auth can-i update certificatesigningrequests.certificates.k8s.io/approval
    kubectl auth can-i create rolebindings.rbac.authorization.k8s.io \
      --namespace identity-lab

    Očekivani rezultat i validacija: context mora biti laboratorijski; whoami prikazuje odobrenog administratora, a potrebne can-i provere vraćaju yes. Ako odobravanje nije dozvoljeno, ne proširivati sebi prava: eskalirati ovlašćenom approver-u.

  2. Kreirajte namespace i minimalni autorizacioni test fixture.
    apiVersion: v1
    kind: Namespace
    metadata:
      name: identity-lab
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: Role
    metadata:
      name: pod-reader
      namespace: identity-lab
    rules:
    - apiGroups: [""]
      resources: ["pods"]
      verbs: ["get", "list", "watch"]
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: RoleBinding
    metadata:
      name: lab-reader-pods
      namespace: identity-lab
    subjects:
    - kind: User
      name: lab-reader
      apiGroup: rbac.authorization.k8s.io
    roleRef:
      kind: Role
      name: pod-reader
      apiGroup: rbac.authorization.k8s.io
    kubectl apply -f access-fixture.yaml
    kubectl get role,rolebinding -n identity-lab

    Napomena: kind: User u RoleBinding subject-u nije kreiranje User objekta; to je string koji se poredi sa autentikovanim korisničkim imenom. Komanda apply menja stanje. Rollback ovog koraka je kubectl delete -f access-fixture.yaml.

  3. Generišite privatni ključ i CSR lokalno.
    openssl genpkey -algorithm RSA \
      -pkeyopt rsa_keygen_bits:3072 \
      -out lab-reader.key
    
    openssl req -new \
      -key lab-reader.key \
      -out lab-reader.csr \
      -subj "/CN=lab-reader/O=platform-readers"
    
    chmod 600 lab-reader.key
    openssl req -in lab-reader.csr -noout -subject -text

    Validacija: subject mora biti tačno CN=lab-reader, O=platform-readers, ključ mora biti čitljiv samo vlasniku, a CSR ne sme sadržati privatni ključ. Grupa ovde namerno nema binding i kasnije služi za negativni test.

  4. Kreirajte Kubernetes CSR sa rokom od jednog sata.
    CSR_REQUEST=$(base64 -w 0 lab-reader.csr)
    sed "s|CSR_REQUEST_BASE64|${CSR_REQUEST}|" \
      lab-reader-csr.template.yaml > lab-reader-csr.yaml
    unset CSR_REQUEST
    kubectl apply -f lab-reader-csr.yaml
    apiVersion: certificates.k8s.io/v1
    kind: CertificateSigningRequest
    metadata:
      name: lab-reader-2026-07
    spec:
      request: CSR_REQUEST_BASE64
      signerName: kubernetes.io/kube-apiserver-client
      expirationSeconds: 3600
      usages:
      - client auth

    Očekivani rezultat: CSR postoji u stanju Pending. GNU base64 koristi -w 0; na sistemima bez te opcije koristi se ekvivalent koji ne umeće nove redove. Generisani YAML sadrži javni CSR, ali se ipak čuva kao radni artefakt.

  5. Odvojeno pregledajte i odobrite zahtev.
    kubectl get csr lab-reader-2026-07 -o yaml
    kubectl get csr lab-reader-2026-07 \
      -o jsonpath='{.spec.request}' | base64 -d | \
      openssl req -noout -subject -text
    
    # State-changing: izvršava samo ovlašćeni approver posle provere
    kubectl certificate approve lab-reader-2026-07
    kubectl get csr lab-reader-2026-07

    Kontrolna tačka: proveriti requestor, signer, usages, expiration i dekodirani subject. Ime CSR objekta nije dokaz sadržaja. Ako bilo koji atribut odstupa, koristi se kubectl certificate deny lab-reader-2026-07, beleži razlog i pravi novi zahtev; denied CSR se ne „popravlja” naknadnim odobravanjem.

  6. Preuzmite izdat sertifikat i proverite ga.
    kubectl get csr lab-reader-2026-07 \
      -o jsonpath='{.status.certificate}' | base64 -d \
      > lab-reader.crt
    
    test -s lab-reader.crt
    openssl x509 -in lab-reader.crt -noout \
      -subject -issuer -serial -dates -ext extendedKeyUsage
    
    openssl x509 -in lab-reader.crt -pubkey -noout | sha256sum
    openssl pkey -in lab-reader.key -pubout | sha256sum

    Očekivani rezultat: CSR ima uslov Approved i popunjen status.certificate; subject i clientAuth namena su ispravni, rok nije duži od politike, a hash vrednosti javnih ključeva se poklapaju. Approved bez sertifikata upućuje na signer/kube-controller-manager problem, pa se pregledaju njegovi logovi; ne odobrava se nasumično novi zahtev.

  7. Napravite zaseban kubeconfig bez menjanja administratorskog.
    APISERVER=$(kubectl config view --minify \
      -o jsonpath='{.clusters[0].cluster.server}')
    kubectl config view --raw --minify \
      -o jsonpath='{.clusters[0].cluster.certificate-authority-data}' \
      | base64 -d > cluster-ca.crt
    
    kubectl --kubeconfig=lab-reader.kubeconfig config set-cluster lab-cluster \
      --server="${APISERVER}" \
      --certificate-authority=cluster-ca.crt \
      --embed-certs=true
    kubectl --kubeconfig=lab-reader.kubeconfig config set-credentials lab-reader \
      --client-certificate=lab-reader.crt \
      --client-key=lab-reader.key \
      --embed-certs=true
    kubectl --kubeconfig=lab-reader.kubeconfig config set-context lab-reader@lab-cluster \
      --cluster=lab-cluster --user=lab-reader --namespace=identity-lab
    kubectl --kubeconfig=lab-reader.kubeconfig config use-context \
      lab-reader@lab-cluster
    chmod 600 lab-reader.kubeconfig

    Rizik: --embed-certs=true čini fajl prenosivim, ali u njega ugrađuje privatni ključ. Ne prikazivati ga sa --raw, ne kopirati ga u Git i ne spajati sa svakodnevnim kubeconfig-om tokom testa.

  8. Dokažite autentikaciju i granicu autorizacije.
    kubectl --kubeconfig=lab-reader.kubeconfig auth whoami -o yaml
    kubectl --kubeconfig=lab-reader.kubeconfig auth can-i list pods \
      --namespace identity-lab
    kubectl --kubeconfig=lab-reader.kubeconfig get pods \
      --namespace identity-lab
    
    # Negativni testovi: očekuje se no/Forbidden
    kubectl --kubeconfig=lab-reader.kubeconfig auth can-i create pods \
      --namespace identity-lab
    kubectl --kubeconfig=lab-reader.kubeconfig get secrets \
      --namespace identity-lab
    kubectl --kubeconfig=lab-reader.kubeconfig get pods \
      --namespace kube-system

    Merljivi rezultat: server prikazuje username lab-reader, grupu platform-readers i system:authenticated. Listanje podova u identity-lab uspeva, dok kreiranje podova, čitanje Secret-a i listanje podova u kube-system ne uspevaju. Time je dokazano da sertifikat autentikuje identitet, a RoleBinding daje samo eksplicitno pravo.

  9. Simulirajte bezbedan kvar bez oštećenja control plane-a.
    cp lab-reader.kubeconfig expired-test.kubeconfig
    kubectl --kubeconfig=expired-test.kubeconfig \
      config set-cluster lab-cluster \
      --server=https://127.0.0.1:1
    kubectl --kubeconfig=expired-test.kubeconfig get pods \
      --request-timeout=5s

    Tumačenje: ovaj test proizvodi problem konekcije, ne 401. Vratite originalni endpoint ili obrišite test fajl. Za realan test isteka koristi se poseban sertifikat minimalnog roka koji signer dozvoljava i čeka se njegov istek; ne menja se vreme noda niti API servera. Pogrešan endpoint, TLS greška, 401 i 403 moraju ostati odvojene dijagnostičke grane.

  10. Pregledajte trag i uklonite laboratoriju.
    kubectl get csr lab-reader-2026-07 -o yaml
    kubectl delete namespace identity-lab
    kubectl delete csr lab-reader-2026-07
    
    # Lokalno uklanjanje poverljivih laboratorijskih fajlova
    shred -u lab-reader.key lab-reader.kubeconfig 2>/dev/null || \
      rm -f lab-reader.key lab-reader.kubeconfig
    rm -f lab-reader.csr lab-reader.crt cluster-ca.crt \
      expired-test.kubeconfig lab-reader-csr.yaml

    Rollback i završetak: brisanje CSR objekta ne opoziva već preuzet sertifikat, zato se prvo uklanja njegov RBAC binding brisanjem namespace-a i zatim lokalni ključ/kubeconfig. shred ne garantuje fizičko brisanje na SSD-u, copy-on-write ili snapshot fajl sistemu; ključ je od početka kratkotrajan i čuva se u namenskom bezbednom prostoru. Završetak je potvrđen kada namespace i CSR više ne postoje, laboratorijski kubeconfig ne radi, a administratorski context nije menjan.

Proširena vežba: validacija OIDC dizajna bez izlaganja tokena

Ova vežba je read-only pregled postojećeg, odobrenog OIDC okruženja. Ne zahteva generičko instaliranje identity provider-a niti menjanje API servera. Cilj je dokazati ugovor između provider-a i Kubernetes-a pre produkcione promene.

  1. Dokumentovati tačan issuer URL, Kubernetes audience/client ID, username, UID i groups claim, prefikse i maksimalni vek tokena.
  2. Sa control-plane mrežne putanje proveriti HTTPS i discovery/JWKS dostupnost bez čuvanja tokena u komandnoj liniji ili ticket-u.
  3. Test korisnikom izvršiti kubectl auth whoami -o yaml i uporediti rezultat sa odobrenim claim mapping-om.
  4. Potvrditi jedan dozvoljen i najmanje dva zabranjena zahteva; 403 je očekivan dokaz najmanjih privilegija, ne kvar prijave.
  5. Proveriti audit zapis po vremenu i audit ID-u, kao i ponašanje posle uklanjanja korisnika iz test grupe i isteka postojećeg tokena.
  6. Pre rollout-a definisati rollback, rezervni pristup, vlasnika IdP-a i kriterijum prekida: rast 401 odgovora, greška učitavanja konfiguracije ili različit identitet na HA endpoint-ima.

Kriterijum završetka je matrica koja povezuje izvorni claim sa serverovim username/UID/groups atributima, RBAC subjektom, pozitivnim i negativnim testom i audit dokazom. Ako UID nije dostupan u starijem načinu OIDC konfiguracije ili konkretnom klijentu, ograničenje se dokumentuje i ne nadoknađuje nestabilnim claim-om.

Administratorske prakse

Završna kontrolna tačka

Zaključak

Kubernetes autentikacija nije baza korisničkih naloga, već granica poverenja na kojoj API server prihvata dokaz i pretvara ga u atribute identiteta. Ljudski životni ciklus najčešće ostaje u OIDC provider-u ili PKI-ju, dok Kubernetes izvorno upravlja ServiceAccount identitetima. X.509, OIDC, TokenRequest, webhook i proxy nisu međusobno zamenljive prečice: svaki ima drugačiji model izdavanja, roka, opoziva, dostupnosti i auditovanja.

Administrator mora umeti da dokaže šta server vidi, da zaštiti kubeconfig i privatni ključ, da ne odobri CSR samo na osnovu njegovog imena i da OIDC claim ugovor tretira kao produkcioni API između identitetskog sistema i klastera. Jednako je važno prepoznati granicu: uspešna autentikacija ne daje pravo na radnju. Ta odluka pripada autorizaciji i biće sistematično obrađena kroz RBAC u narednoj lekciji.

Najveći rizici nastaju kada se kredencijali dele, traju predugo, koriste izvan svoje audience vrednosti, završavaju u logovima ili kada se promena autentikatora istovremeno primeni na sve API servere bez rezervnog pristupa. Odgovoran administrator svaku promenu povezuje sa monitoringom, auditom, rollback-om i jasnim vlasništvom nad spoljašnjim zavisnostima. Cilj nije samo da se korisnik prijavi, već da identitet bude jedinstven, proverljiv, vremenski ograničen i dovoljno pouzdan da naredni autorizacioni sloj može doneti ispravnu odluku.

← Prethodna lekcija Povratak na sadržaj Sledeća lekcija →