VMware & Tanzu

Treći deo: Produkcioni rad, bezbednost i upravljanje životnim ciklusom
Sigurnost image-a – skeniranje, poverenje i kontrola kontejnerskih slika
X. Bezbednost i usklađenost Tanzu platforme
41. Image security, admission politike i software supply chain – od registra do dozvoljenog workload-a

Kontejnerski image je izvršni artefakt koji ulazi u produkcioni klaster sa aplikacionim kodom, sistemskim bibliotekama, paketima, alatima i podrazumevanom konfiguracijom. Zbog toga odluka da se image dozvoli nije samo odluka o verziji aplikacije. Administrator istovremeno prihvata poreklo artefakta, sadržaj njegovih slojeva, poznate ranjivosti, identitet procesa koji ga je napravio i mogućnost da je artefakt promenjen nakon bezbednosne provere.

Produkcioni model zaštite zato ne sme da se zasniva na jednoj kontroli. Skeniranje otkriva poznate probleme u sadržaju, kriptografski potpis potvrđuje integritet i identitet potpisnika, digest vezuje deployment za tačno određeni artefakt, a admission politika sprečava da nepouzdan image uopšte postane Pod. Tek kombinacija ovih kontrola formira proverljiv lanac od build procesa do izvršavanja u Tanzu Kubernetes klasteru.

Šta obuhvata sigurnost kontejnerskog image-a

Sigurnost image-a obuhvata ceo životni ciklus artefakta: izbor baznog image-a, preuzimanje zavisnosti, build, generisanje softverskog inventara, skeniranje, potpisivanje, objavljivanje u registry, promociju između okruženja i proveru pri prijemu workload-a u klaster. Problem u bilo kojoj tački može proizvesti image koji radi funkcionalno, ali nije prihvatljiv za produkciju.

Administrator mora da razlikuje četiri odvojena pitanja:

Nijedna od ovih kontrola ne zamenjuje ostale. Potpisan image može sadržati kritičnu ranjivost jer potpis potvrđuje ko ga je potpisao, a ne da je bezbedan. Image bez poznatih CVE nalaza može biti nepoverljiv ako je nastao iz nepoznatog build procesa. Referenca sa digestom sprečava neprimetnu zamenu sadržaja, ali ne dokazuje da je originalni sadržaj prihvatljiv.

Model pretnji u lancu isporuke image-a

Najčešća administrativna greška jeste posmatranje registry-ja kao pasivnog skladišta. Registry je kritična komponenta lanca isporuke. Kompromitovan nalog sa pravom upisa, pogrešno podešen javni projekat, nezaštićen CI token ili preširoka administratorska privilegija mogu omogućiti objavljivanje zlonamernog artefakta pod nazivom koji izgleda legitimno.

Važne pretnje uključuju kompromitovan bazni image, zavisnost preuzetu iz nepouzdanog izvora, tajnu slučajno upisanu u image sloj, zamenu taga nakon uspešnog testa, krađu signing ključa, manipulisanje build agentom i deployment direktno sa javnog registry-ja. Posebno je opasna upotreba promenljivih tagova kao što su latest, stable ili production. Tag je pokazivač koji se može premestiti na drugi manifest, dok puni SHA-256 digest identifikuje konkretan OCI manifest.

Pretnja nije ograničena na namerni napad. Zastareo operativni sistem u baznom image-u, paket bez podrške ili razvojni alat ostavljen u finalnom sloju povećavaju površinu napada i broj nalaza. Čak i kada aplikacija ne koristi ranjivu funkciju biblioteke, administrator mora imati dokumentovanu procenu rizika, vlasnika odluke i rok za ponovnu evaluaciju.

Skeniranje ranjivosti i značenje rezultata

Skeneri kao što je Trivy analiziraju operativne pakete i zavisnosti podržanih programskih ekosistema, a mogu generisati i SBOM, proveravati konfiguracione fajlove i tražiti obrasce koji liče na tajne. U Harbor okruženju skener može biti integrisan sa registry-jem, tako da se analiza pokreće nakon push operacije ili periodično ponavlja kada se osveži baza ranjivosti.

Rezultat skeniranja nije apsolutna potvrda da je image bezbedan. Skener prepoznaje samo klase problema za koje poseduje detekciju i dovoljno metapodataka. Nova ranjivost možda još nije objavljena, paket može biti nepravilno identifikovan, a ozbiljnost se može razlikovati između proizvođača distribucije i opštih baza. Zato administrator proverava izvor ocene, dostupnu popravljenu verziju, status paketa, ekspoziciju aplikacije i stvarnu mogućnost iskorišćavanja.

Rezultat Značenje Administratorska odluka
CRITICAL ili HIGH sa dostupnom zakrpom Postoji novija verzija paketa ili baznog image-a koja otklanja problem. Zaustaviti promociju, ponovo izgraditi image i ponoviti testove.
CRITICAL ili HIGH bez zakrpe Problem je poznat, ali dobavljač još nema ispravku ili paket više nije podržan. Procena ekspozicije, kompenzacione kontrole, vremenski ograničen izuzetak ili zamena komponente.
UNKNOWN Skener nema pouzdanu klasifikaciju ozbiljnosti. Ne tretirati automatski kao bezopasno; proveriti vendor advisory i vlasništvo paketa.
Nema nalaza U korišćenim izvorima i trenutnoj bazi nema prepoznatih problema. Proveriti starost baze, uspeh skena, podržanost operativnog sistema i obuhvat skenera.

Opcija koja ignoriše ranjivosti bez dostupne zakrpe može biti korisna za poseban izveštaj o neposredno popravljivim problemima, ali nije odgovarajuća kao jedini produkcioni kriterijum. Ona može sakriti ozbiljne nalaze koje organizacija mora da prati kompenzacionim kontrolama. Bezbedniji model je da se svi nalazi sačuvaju, a da se izuzeci vode kroz verzionisanu allowlist evidenciju sa razlogom, vlasnikom i datumom isteka.

SBOM, poreklo i potvrde o build procesu

Software Bill of Materials predstavlja inventar komponenti sadržanih u artefaktu. SBOM ubrzava odgovor kada se objavi nova ranjivost jer bez ponovnog ručnog pregleda omogućava pretragu image-a koji sadrže pogođenu biblioteku. Međutim, SBOM nije sken i nije dokaz bezbednosti. On opisuje sastav; skener taj sastav poredi sa podacima o ranjivostima.

Provenance ili potvrda o poreklu odgovara na druga pitanja: koji izvorni commit je korišćen, koji builder je izvršio postupak, koja build definicija je primenjena i koji artefakt je nastao. Standardizovane potvrde, poput SLSA provenance zapisa, treba vezivati za digest konkretnog artefakta. Time se smanjuje rizik da se valjan izveštaj ili potvrda priloži drugom image-u sa sličnim nazivom.

U zrelom sistemu CI proces proizvodi image, SBOM, izveštaj skeniranja i potpis ili attestation. Produkcioni administrator ne mora da veruje svakom nalogu koji može da izvrši docker push; on veruje određenom build identitetu, odobrenom registry projektu i pravilima koja se proveravaju pri deployment-u.

Potpisivanje, digest i poverenje

Cosign može da potpisuje OCI artefakte korišćenjem privatnog ključa, ključa u KMS ili keyless modela zasnovanog na OIDC identitetu i kratkotrajnom sertifikatu. Za enterprise produkciju privatni signing ključ ne treba čuvati na administratorskom laptopu niti u Git repozitorijumu. Preporučeni cilj je HSM ili KMS, odnosno identitet kontrolisanog CI workload-a. Lokalni par ključeva je prihvatljiv za laboratoriju i demonstraciju toka, uz strogo ograničena prava nad privatnim ključem.

Potpis se proverava nad digestom. Ako se promeni bilo koji sloj ili manifest, menja se digest i prethodni potpis više ne potvrđuje novi sadržaj. Zbog toga deployment manifest treba da koristi oblik:

harbor.tashizza.local/prod/tashizza-api@sha256:PRECIZAN_DIGEST

Kubernetes pri kreiranju objekta određuje imagePullPolicy, ali politika povlačenja ne predstavlja sigurnosnu verifikaciju. Vrednost Always zahteva razrešavanje reference preko registry-ja, dok lokalni slojevi i dalje mogu biti iskorišćeni kada odgovaraju istom digestu. Ona ne potvrđuje potpis, ne skenira sadržaj i ne sprečava korišćenje neodobrenog registry-ja.

Kontrola pri prijemu workload-a u klaster

Skeniranje u CI procesu smanjuje broj loših artefakata koji stižu do registry-ja, ali nije dovoljna završna kontrola. Korisnik sa Kubernetes pravima može pokušati da navede drugi image, javni registry ili nepotpisanu verziju. Admission kontroler zato proverava zahtev pre nego što API server trajno prihvati resurs.

Politika treba da obuhvati najmanje regularne kontejnere, init kontejnere i, gde platforma podržava njihovo korišćenje, ephemeral kontejnere. Takođe mora biti jasno da se deployment kontroleri na kraju pretvaraju u Pod zahteve. Politika koja proverava Pod-ove štiti izvršni trenutak čak i kada je inicijalni zahtev bio Deployment, StatefulSet, Job ili drugi kontroler.

U referentnom rešenju koristi se Kyverno ImageValidatingPolicy za proveru Cosign potpisa. U aktuelnoj Kyverno dokumentaciji CEL zasnovani resurs koristi API policies.kyverno.io/v1. Ranija izdanja koristila su razvojni v1alpha1, dok legacy ClusterPolicy model koristi verifyImages; ta dva modela nemaju istu šemu. Zato administrator pre primene proverava verziju kontrolera, CRD resurs i polja komandom kubectl explain imagevalidatingpolicy.spec. Kyverno je dodatna komponenta workload klastera, a ne mogućnost koju treba pretpostaviti samo zato što je klaster VMware Tanzu/VKS.

Verzijska i licencna granica. Harbor, Trivy, Cosign i Kyverno imaju sopstvene matrice kompatibilnosti i životne cikluse. Dostupnost Harbor skenera, SBOM prikaza, immutable tag pravila, retention funkcija i enterprise integracija zavisi od konkretnog Harbor izdanja i načina pakovanja u organizaciji. Broadcom/VMware podrška za VKS/Tanzu ne znači automatski podršku za svaku samostalno instaliranu verziju policy engine-a; pre produkcije proveravaju se VKS release notes, podržana Kubernetes verzija i support boundary dodatnih komponenti.

Politika može raditi u audit režimu pre prelaska na blokiranje. To je važan operativni korak jer otkriva postojeće workload-e koji ne ispunjavaju zahtev. Međutim, audit nije krajnja produkciona zaštita: zahtev se beleži, ali nije zaustavljen. Nakon sanacije postojećih izuzetaka, akcija se postavlja na Deny, a failurePolicy se bira u skladu sa rizikom. Za kritičnu kontrolu potpisa u produkciji uobičajen je fail-closed model, uz visoku dostupnost admission kontrolera i prethodno testiran postupak oporavka.

Referentna enterprise arhitektura

Praktikum koristi Tanzu Kubernetes workload klaster tkg-prod-01, namespace payments-prod, Harbor registry harbor.tashizza.local i projekat prod. Aplikacioni image ima naziv tashizza-api. Administratorska radna stanica koristi direktorijum /opt/tashizza/image-security. Trivy radi kao CI bezbednosna kontrola, Cosign potpisuje odobreni digest, a Kyverno proverava potpis pre prijema Pod-a.

Tok odobravanja izgleda ovako:

  1. CI izgradi image sa nepromenljivim tagom povezanim sa Git commitom.
  2. Trivy generiše JSON izveštaj i CycloneDX SBOM; CRITICAL i HIGH nalazi prekidaju promociju prema usvojenoj politici.
  3. Uspešno provereni image se šalje u Harbor i identifikuje punim digestom.
  4. Odobreni CI identitet potpisuje digest.
  5. Deployment referencira image po digestu.
  6. Kyverno admission kontrola proverava potpis i odbija nepotpisan ili neodobren artefakt.

Ova arhitektura ne rešava runtime izolaciju, privilegije procesa, mrežne politike, upravljanje Secret objektima niti ranjivosti same aplikacione logike. Image bezbednost je jedan sloj odbrane, a ne zamena za zaštitu klastera i workload-a.

Integrisani praktikum – od skeniranja do blokiranja nepotpisanog image-a

Poslovni i tehnički kontekst. Tim za plaćanja želi da postavi verziju aplikacije u produkciju. Organizacija dozvoljava samo image-e iz internog Harbor projekta prod, bez CRITICAL i popravljivih HIGH ranjivosti, potpisane kontrolisanim Cosign ključem i navedene punim digestom. Administrator mora dokazati da odobreni image prolazi, a nepotpisani image biva odbijen pre kreiranja Pod-a.

Cilj. Skenirati image, sačuvati izveštaj i SBOM, objaviti i potpisati tačan digest, aktivirati admission politiku i sprovesti pozitivan i negativan test.

Referentno okruženje. Radna stanica ima instalirane docker, trivy, cosign i kubectl. Harbor koristi pouzdan TLS sertifikat. Kyverno je već instaliran u klasteru. Primer koristi laboratorijski lokalni signing ključ; u produkciji ga treba zameniti KMS/HSM ključem ili odobrenim keyless CI identitetom.

Potrebna prava. Korisnik registry-ja mora imati push pravo samo u projektu prod. Kubernetes operator mora moći da čita namespace i workload objekte. Za kreiranje klasterske admission politike potrebna je posebno odobrena privilegija nad Kyverno policy resursima. Aplikacionom timu nije potrebno pravo izmene klasterske politike.

Preduslovi. DNS i TLS pristup adresi harbor.tashizza.local moraju raditi; projekat prod i namespace payments-prod moraju postojati; Trivy baza mora biti ažurirana; promenljiva HARBOR_USER mora sadržati korisničko ime, dok se lozinka unosi interaktivno ili preuzima iz odobrenog secrets sistema.

  1. Napraviti radni direktorijum i potvrditi kontekst. Pre bilo kakve promene administrator proverava da komande ciljaju klaster tkg-prod-01 i da postoje potrebni resursi. Pogrešan Kubernetes kontekst predstavlja realan produkcioni rizik.
    sudo install -d -m 0750 -o "$USER" -g "$(id -gn)" /opt/tashizza/image-security
    cd /opt/tashizza/image-security
    
    kubectl config current-context
    kubectl get namespace payments-prod
    kubectl get crd imagevalidatingpolicies.policies.kyverno.io
    kubectl -n kyverno get deployments,pods
    Validacija: trenutni kontekst mora biti tkg-prod-01, namespace mora imati status Active, CRD mora postojati, a Kyverno Pod-ovi moraju biti Running i spremni. Ako CRD ne postoji, manifest iz ovog praktikuma se ne primenjuje dok se ne proveri kompatibilna Kyverno verzija.
  2. Definisati dosledne promenljive artefakta. Ne koristi se promenljivi tag latest. Verzija 1.4.0 predstavlja izdanje koje je već prošlo aplikacione testove.
    export REGISTRY="harbor.tashizza.local"
    export PROJECT="prod"
    export APP="tashizza-api"
    export VERSION="1.4.0"
    export IMAGE="${REGISTRY}/${PROJECT}/${APP}:${VERSION}"
    
    printf 'Target image: %s\n' "$IMAGE"
    Validacija: ispis mora biti harbor.tashizza.local/prod/tashizza-api:1.4.0. Ove vrednosti se koriste u svim sledećim koracima.
  3. Prijaviti se u registry bez zapisivanja lozinke u shell istoriju. Lozinka se ne navodi kao argument komande jer bi mogla ostati vidljiva u istoriji ili listi procesa.
    printf 'Harbor password: '
    read -r -s HARBOR_PASSWORD
    printf '\n'
    printf '%s' "$HARBOR_PASSWORD" | docker login "$REGISTRY" \
      --username "$HARBOR_USER" \
      --password-stdin
    unset HARBOR_PASSWORD
    Validacija: komanda mora prijaviti uspešnu autentikaciju. Neuspeh sa porukom x509 ukazuje na problem poverenja u TLS lanac; ne treba ga zaobilaziti podešavanjem nesigurnog registry-ja, već instalirati ispravan CA sertifikat.
  4. Izgraditi referentni image minimalnog sadržaja. Kreiraju se jednostavna aplikaciona datoteka i Dockerfile. Bazni image je namerno jasno verzionisan; u produkciji bi i on trebalo da bude pinovan digestom i preuzet kroz kontrolisani mirror.
    cat > index.html <<'EOF'
    <!doctype html>
    <html lang="sr">
    <head><meta charset="utf-8"><title>Tashizza API</title></head>
    <body><h1>tashizza-api 1.4.0</h1></body>
    </html>
    EOF
    
    cat > Dockerfile <<'EOF'
    FROM nginxinc/nginx-unprivileged:1.27.5-alpine
    COPY index.html /usr/share/nginx/html/index.html
    USER 101
    EXPOSE 8080
    EOF
    
    docker build --pull --no-cache -t "$IMAGE" .
    Validacija: lokalni image mora postojati, a istorija slojeva treba da odgovara očekivanom Dockerfile-u.
    docker image inspect "$IMAGE" \
      --format 'ID={{.Id}} Created={{.Created}} User={{.Config.User}}'
    docker history --no-trunc "$IMAGE"
    Očekuje se korisnik 101. Napomena: podrazumevani NGINX image i konkretna non-root konfiguracija moraju biti funkcionalno provereni; samo postavljanje direktive USER ne garantuje da aplikacija može da piše u potrebne direktorijume ili sluša na privilegovanom portu.
  5. Pokrenuti bezbednosni scan i sačuvati dokaz. Prvi scan generiše kompletan JSON za audit. Drugi služi kao CI gate i vraća nenulti izlazni kod kada postoje HIGH ili CRITICAL nalazi. Nalazi bez zakrpe se ne skrivaju.
    trivy image \
      --scanners vuln,secret \
      --format json \
      --output trivy-report.json \
      "$IMAGE"
    
    trivy image \
      --scanners vuln,secret \
      --severity HIGH,CRITICAL \
      --exit-code 1 \
      "$IMAGE"
    Validacija: druga komanda mora završiti kodom 0. Ako završi kodom 1, promocija se prekida. Administrator u trivy-report.json proverava ID ranjivosti, paket, instaliranu verziju, popravljenu verziju i izvor ozbiljnosti. Samo ponovno pokretanje komande bez izmene image-a nije sanacija.
  6. Generisati SBOM i proveriti da datoteke nisu prazne. CycloneDX SBOM ostaje vezan za izdanje kao inventar komponenti.
    trivy image \
      --format cyclonedx \
      --output tashizza-api-1.4.0.cdx.json \
      "$IMAGE"
    
    test -s trivy-report.json
    test -s tashizza-api-1.4.0.cdx.json
    sha256sum trivy-report.json tashizza-api-1.4.0.cdx.json \
      > evidence.sha256
    cat evidence.sha256
    Validacija: obe datoteke moraju imati sadržaj, a evidence.sha256 dva kontrolna zbira. U produkciji se izveštaj, SBOM i kontrolni zbirovi čuvaju u kontrolisanom artifact sistemu sa pravilima retencije, a ne samo na radnoj stanici.
  7. Objaviti image i utvrditi registry digest. Lokalni image ID nije zamena za OCI registry digest. Tek nakon push operacije dobija se referenca koju deployment i potpis treba da koriste.
    docker push "$IMAGE"
    
    DIGEST="$(docker buildx imagetools inspect "$IMAGE" \
      --format '{{json .Manifest.Digest}}' | tr -d '"')"
    IMAGE_BY_DIGEST="${REGISTRY}/${PROJECT}/${APP}@${DIGEST}"
    
    printf 'Digest: %s\nImmutable reference: %s\n' \
      "$DIGEST" "$IMAGE_BY_DIGEST"
    Validacija: DIGEST mora početi sa sha256:, a nepromenljiva referenca mora sadržati znak @. Ako korišćena Docker verzija ne podržava dati format, digest se proverava odgovarajućim OCI alatom ili Harbor API-jem, ali se ne prepisuje ručno iz nepouzdanog izvora.
  8. Kreirati laboratorijski Cosign ključ. Upozorenje: privatni ključ omogućava izdavanje poverljivih potpisa. Sledeći postupak je samo za kontrolisani laboratorijski scenario. U produkciji koristiti KMS/HSM ili workload identitet CI sistema.
    umask 077
    export COSIGN_PASSWORD='LAB_ONLY_REPLACE_WITH_SECRET_MANAGER_VALUE'
    cosign generate-key-pair
    
    chmod 0600 cosign.key
    chmod 0644 cosign.pub
    ls -l cosign.key cosign.pub
    Validacija: privatni ključ mora imati prava 0600, a javni ključ može biti čitljiv. Vrednost COSIGN_PASSWORD se ne sme čuvati u shell profilu, Git-u ili manifestu. U realnom toku preuzima se kratkotrajno iz secrets sistema.
  9. Potpisati isključivo provereni digest. Potpisivanje taga ostavlja prostor da tag kasnije pokaže na drugi sadržaj. Zato se potpisuje IMAGE_BY_DIGEST.
    cosign sign \
      --key cosign.key \
      --yes \
      "$IMAGE_BY_DIGEST"
    Validacija: potpis se odmah proverava javnim ključem.
    cosign verify \
      --key cosign.pub \
      "$IMAGE_BY_DIGEST" \
      > cosign-verification.json
    
    test -s cosign-verification.json
    grep -F "$DIGEST" cosign-verification.json
    Provera mora biti uspešna i izlaz mora biti vezan za očekivani digest. Potpisivanje nije odobrenje ako prethodni bezbednosni gate nije prošao; CI mora tehnički onemogućiti preskakanje redosleda.
  10. Kreirati admission politiku sa javnim ključem. Javni ključ se ugrađuje u manifest politike. Prvo se generiše lokalna datoteka, zatim se radi serverska provera pre stvarne promene.
    PUBKEY_INDENTED="$(sed 's/^/              /' cosign.pub)"
    
    cat > verify-tashizza-images.yaml <<EOF
    apiVersion: policies.kyverno.io/v1
    kind: ImageValidatingPolicy
    metadata:
      name: verify-tashizza-prod-images
    spec:
      failurePolicy: Fail
      webhookConfiguration:
        timeoutSeconds: 15
      evaluation:
        background:
          enabled: false
      validationActions:
        - Deny
      matchConstraints:
        namespaceSelector:
          matchLabels:
            tashizza.local/image-trust: enforced
        resourceRules:
          - apiGroups:
              - ""
            apiVersions:
              - v1
            operations:
              - CREATE
              - UPDATE
            resources:
              - pods
      matchImageReferences:
        - glob: "harbor.tashizza.local/prod/tashizza-api*"
      attestors:
        - name: tashizzaCosignKey
          cosign:
            key:
              data: |
    ${PUBKEY_INDENTED}
      validationConfigurations:
        required: true
        verifyDigest: true
        mutateDigest: false
      validations:
        - expression: >-
            images.containers.map(image,
            verifyImageSignatures(image,
            [attestors.tashizzaCosignKey])).all(result, result > 0)
          message: "Image mora imati važeći potpis odobrenog Tashizza Cosign ključa."
    EOF
    
    kubectl apply --server-side --dry-run=server \
      -f verify-tashizza-images.yaml
    Validacija: serverski dry-run mora prihvatiti objekat bez greške šeme. Ako API odbije polje, ne treba nasumično menjati manifest; proveravaju se instalirana Kyverno verzija i njena odgovarajuća API referenca. Tek nakon uspešne provere politika se primenjuje:
    kubectl apply --server-side -f verify-tashizza-images.yaml
    kubectl get imagevalidatingpolicy verify-tashizza-prod-images -o yaml
  11. Označiti samo ciljni namespace za enforcement. Selektor sprečava nenamerno obuhvatanje celog klastera tokom prve implementacije. Promena labele je kontrolisana tačka aktiviranja politike.
    kubectl label namespace payments-prod \
      tashizza.local/image-trust=enforced \
      --overwrite
    
    kubectl get namespace payments-prod --show-labels
    Validacija: namespace mora prikazati labelu tashizza.local/image-trust=enforced. Pre šire primene treba napraviti inventar sistemskih i poslovnih namespace-ova jer neki vendor workload-i mogu imati poseban model potpisivanja.
  12. Postaviti potpisani image punim digestom. Kreira se Deployment koji koristi isti nepromenljivi artefakt koji je skeniran i potpisan.
    cat > tashizza-api-deployment.yaml <<EOF
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: tashizza-api
      namespace: payments-prod
      labels:
        app.kubernetes.io/name: tashizza-api
    spec:
      replicas: 2
      selector:
        matchLabels:
          app.kubernetes.io/name: tashizza-api
      template:
        metadata:
          labels:
            app.kubernetes.io/name: tashizza-api
        spec:
          containers:
            - name: api
              image: ${IMAGE_BY_DIGEST}
              imagePullPolicy: IfNotPresent
              ports:
                - name: http
                  containerPort: 8080
              securityContext:
                allowPrivilegeEscalation: false
                capabilities:
                  drop:
                    - ALL
                runAsNonRoot: true
              resources:
                requests:
                  cpu: 50m
                  memory: 64Mi
                limits:
                  cpu: 250m
                  memory: 128Mi
    EOF
    
    kubectl apply --server-side -f tashizza-api-deployment.yaml
    kubectl -n payments-prod rollout status \
      deployment/tashizza-api \
      --timeout=180s
    Validacija: API server mora prihvatiti zahtev, a Deployment mora dobiti dve dostupne replike. Ako admission provera uspe, ali Pod-ovi nisu spremni, problem više nije nužno potpis: proveravaju se Events, registry autentikacija, port, prava nad filesystem-om i aplikacioni logovi.
    kubectl -n payments-prod get deployment,pods -o wide
    kubectl -n payments-prod describe deployment tashizza-api
    kubectl -n payments-prod get events \
      --sort-by=.metadata.creationTimestamp | tail -n 20
  13. Sprovesti negativni test sa nepotpisanim image-om. Test dokazuje da kontrola blokira zahtev, a ne samo da valjani image može da radi. Koristi se drugi image iz istog registry obrasca koji nije potpisan odobrenim ključem.
    printf '\n<!-- unsigned negative test -->\n' >> index.html
    docker build --no-cache \
      -t "${REGISTRY}/${PROJECT}/${APP}:unsigned-test" .
    docker push "${REGISTRY}/${PROJECT}/${APP}:unsigned-test"
    
    UNSIGNED_DIGEST="$(docker buildx imagetools inspect \
      "${REGISTRY}/${PROJECT}/${APP}:unsigned-test" \
      --format '{{json .Manifest.Digest}}' | tr -d '"')"
    test "$UNSIGNED_DIGEST" != "$DIGEST"
    
    kubectl -n payments-prod run unsigned-test \
      --image="${REGISTRY}/${PROJECT}/${APP}@${UNSIGNED_DIGEST}" \
      --restart=Never
    Očekivani rezultat: poslednja komanda mora biti odbijena admission porukom koja ukazuje da zahtevani potpis nije pronađen ili nije potvrđen od odobrenog attestor-a. Pod unsigned-test ne sme postojati.
    kubectl -n payments-prod get pod unsigned-test
    Očekuje se NotFound. Ako Pod postoji, kriterijum prihvatanja nije ispunjen i deployment zaštita se smatra neispravnom bez obzira na uspešan pozitivan test.
  14. Pregledati logove i razlikovati tip problema. Kyverno admission logovi pokazuju rezultat evaluacije politike, greške pristupa registry-ju, timeout i neuspešnu verifikaciju. Kubernetes Events pokazuju probleme koji nastaju nakon prijema, kao što su ImagePullBackOff ili ErrImagePull.
    kubectl -n kyverno logs \
      -l app.kubernetes.io/component=admission-controller \
      --since=15m \
      --all-containers=true \
      | grep -E 'verify-tashizza-prod-images|unsigned-test|error|denied'
    
    kubectl -n payments-prod get events \
      --sort-by=.metadata.creationTimestamp | tail -n 30
    Tumačenje: admission denial znači da objekat nije prihvaćen. ImagePullBackOff znači da je Pod prihvaćen, ali kubelet nije uspeo da preuzme image. CrashLoopBackOff znači da je image preuzet i proces pokrenut, ali se kontejner ruši. Ove situacije zahtevaju različite reakcije.
  15. Dokumentovati dokaz o prihvatanju. Čuvaju se digest, politika, scan izveštaj, SBOM, rezultat verifikacije i izlaz pozitivnog i negativnog testa.
    kubectl get imagevalidatingpolicy verify-tashizza-prod-images \
      -o yaml > applied-image-policy.yaml
    
    kubectl -n payments-prod get deployment tashizza-api \
      -o yaml > deployed-tashizza-api.yaml
    
    printf '%s\n' "$IMAGE_BY_DIGEST" > approved-image.txt
    
    sha256sum approved-image.txt \
      applied-image-policy.yaml \
      deployed-tashizza-api.yaml \
      trivy-report.json \
      tashizza-api-1.4.0.cdx.json \
      cosign-verification.json \
      > final-evidence.sha256
    Validacija: sve navedene datoteke moraju postojati, a kontrolni zbirovi moraju moći ponovo da se provere komandom sha256sum -c final-evidence.sha256. Evidencija promene treba da sadrži broj change zahteva, vlasnika aplikacije, odobreni digest i rezultat negativnog testa.

Rollback i cleanup

Rollback aplikacije ne znači automatsko isključivanje sigurnosne politike. Ako nova verzija ima funkcionalni problem, vraća se prethodni odobreni i potpisani digest. Deployment history je koristan, ali administrator pre rollback-a proverava da li prethodni ReplicaSet i dalje referencira artefakt koji zadovoljava aktuelnu politiku.

kubectl -n payments-prod rollout history deployment/tashizza-api
kubectl -n payments-prod rollout undo deployment/tashizza-api
kubectl -n payments-prod rollout status deployment/tashizza-api --timeout=180s

Ako sama admission politika izaziva incident, prvo se procenjuje da li je problem nedostupnost registry-ja, Kyverno kvar, pogrešan ključ ili greška selektora. Bezbedniji privremeni rollback obuhvata uklanjanje enforcement labele samo sa pogođenog namespace-a, uz incident zapis i vremenski ograničenu odluku:

kubectl label namespace payments-prod \
  tashizza.local/image-trust-

kubectl get namespace payments-prod --show-labels

Brisanje klasterske politike ima širi uticaj i ne treba ga koristiti kao prvi odgovor. Laboratorijski cleanup uklanja test objekte, ali ne briše produkcioni deployment:

kubectl -n payments-prod delete pod unsigned-test \
  --ignore-not-found
rm -f cosign.key
unset COSIGN_PASSWORD

Upozorenje: brisanje privatnog ključa bez sigurnosne kopije može onemogućiti buduće potpisivanje istim identitetom. U produkciji se lifecycle ključa vodi kroz formalnu rotaciju, opoziv i KMS/HSM politiku, a ne kroz ručno brisanje datoteke.

Tipične greške i dijagnostika

Dijagnostika počinje read-only proverama: zabeležiti vreme i korisnika zahteva, Kubernetes kontekst, tačnu image referencu, digest, poslednju promenu politike i odgovor API servera. Tek zatim se korelišu Kyverno admission logovi, Kubernetes audit zapis, Harbor access/audit trag i CI evidencija. Ne treba odmah menjati failurePolicy, ključ ili namespace labelu, jer se time uklanja dokaz i može proširiti incident.

Simptom i obim Neposredni uzrok koji se proverava Osnovni uzrok i dokaz Bezbedna korekcija i potvrda
Samo novi Pod-ovi u označenom namespace-u dobijaju admission denial. Potpis nedostaje, digest se razlikuje ili registry nije dostupan kontroleru. Uporediti digest iz zahteva, cosign verify rezultat, policy glob i Kyverno log u istom vremenskom prozoru. Ponovo izgraditi i potpisati pravi digest ili ispraviti usko ograničenu policy grešku; ponoviti pozitivan i negativan test.
Svi admission zahtevi kasne ili se odbijaju. Webhook nema spremne endpoint-e, istekao je TLS sertifikat ili verifikacija registry-ja prelazi timeout. Proveriti Deployment, EndpointSlice, Events, webhook sertifikat, mrežnu putanju, DNS i metrike latencije. Oporaviti visoko dostupne replike ili TLS lanac. Break-glass izuzeće mora biti vremenski ograničeno i obuhvatiti samo pogođeni namespace.
Pod je prihvaćen, ali je u stanju ImagePullBackOff. Kubelet nema registry kredencijale, DNS/TLS putanju ili artefakt ne postoji. Admission je već prošao; dokaz su Pod Events i odsustvo denial zapisa. Proveriti imagePullSecrets i postojanje istog digest-a. Ispraviti registry pristup bez gašenja politike potpisa; potvrditi uspešno povlačenje i Ready stanje.
Ranije odobren image dobija novi CRITICAL nalaz. Osvežena baza ranjivosti prepoznala je ranije nepoznat CVE. SBOM, novi scan, vendor advisory i inventar aktivnih Pod digest-a potvrđuju obim. Procena ekspozicije, kompenzacione kontrole i hitan rebuild; opozvati poverenje ili blokirati digest kada rizik to zahteva.

Kriterijumi prihvatanja

Administratorske prakse

Kontinuirano ponovno skeniranje. Registry image-i se ponovo skeniraju nakon svakog ažuriranja vulnerability baze i najmanje jednom dnevno za produkcione projekte. Proveravaju se Harbor scan status, Trivy job logovi i broj novih CRITICAL/HIGH nalaza. Novi CRITICAL nalaz ili neuspešan scan zahteva otvaranje incidenta ili security zadatka, identifikovanje svih aktivnih digest-a i obaveštavanje vlasnika aplikacije. U CMDB-u ili vulnerability sistemu dokumentuju se digest, CVE, ekspozicija, odluka i rok sanacije. Uspešnost se meri vremenom od objave nalaza do identifikacije pogođenih workload-a i vremenom do ponovnog build-a.

Kontrola starosti baznih image-a. Posle svakog release-a i najmanje mesečno proveravaju se datum baznog image-a, status podrške distribucije i dostupnost novog odobrenog digest-a. CI izveštaj ili SBOM pokazuje OS porodicu i pakete, dok registry evidencija pokazuje vreme push-a. EOL operativni sistem ili bazni image stariji od internog praga zahteva plan migracije. Dokumentuju se vlasnik baznog image-a, planirana verzija i datum ponovnog build-a. Praksa je uspešna kada nijedan produkcioni image ne koristi nepodržanu bazu bez formalnog izuzetka.

Praćenje admission kontrole. Kontinuirano se prate dostupnost Kyverno Pod-ova, restart count, webhook latencija, broj denied zahteva i greške pristupa registry-ju. Nakon upgrade-a klastera, Kyverno-a, registry-ja ili CA sertifikata obavezno se sprovode pozitivan i negativan test. Timeout, rast grešaka ili nedostupna replika zahteva prvo proveru Events, admission logova, mrežne putanje i TLS lanca. Rezultati se beleže u operativnom dnevniku i monitoringu. Uspešnost znači da negativni test ostaje blokiran, a legitimni zahtev prolazi unutar dogovorenog vremena.

Rotacija signing identiteta. Ključevi se inventarišu i rotiraju prema politici organizacije, kao i odmah nakon sumnje na kompromitovanje. Proveravaju se KMS audit logovi, dozvole CI identiteta i lista javnih ključeva prihvaćenih u admission politici. Neočekivana signing operacija ili korišćenje ključa van odobrenog pipeline-a zahteva obustavu promocije, opoziv poverenja i istragu svih digest-a potpisanih u pogođenom periodu. Dokumentuju se fingerprint ključa, vlasnik, datum aktivacije, datum povlačenja i pogođene politike. Uspešnost se potvrđuje testom da novi ključ prolazi, a povučeni više ne prolazi.

Upravljanje izuzecima. Svaki CVE ili policy izuzetak mora imati tehničko obrazloženje, poslovnog vlasnika, kompenzacione kontrole i datum isteka. Lista se proverava nedeljno i nakon objave zakrpe. Istekao izuzetak, odsustvo vlasnika ili dostupna popravljena verzija zahteva prekid promocije i ponovno otvaranje sanacije. Evidencija se vodi u centralnom risk ili ticket sistemu, ne u privatnoj tabeli administratora. Uspešnost se meri procentom izuzetaka sa važećim rokom i smanjenjem prosečnog trajanja izuzetka.

Backup i oporavak dokaza i konfiguracije. Čuvaju se registry baza i konfiguracija prema Harbor backup proceduri, policy manifesti u verzionisanom Git repozitorijumu, javni ključevi, SBOM, scan izveštaji i audit zapisi. Privatni ključevi se čuvaju kroz KMS/HSM backup i recovery mehanizam dobavljača, nikada kao nezaštićena kopija. Backup se radi prema RPO zahtevu platforme, a integritet se proverava kontrolnim zbirovima i periodičnim probnim restore-om u izolovanom okruženju. Restore je uspešan tek kada je moguće pronaći artefakt po digestu, proveriti njegov potpis, učitati policy konfiguraciju i uspešno izvršiti pozitivan i negativan admission test.

Završna kontrolna lista

Zaključak

Administrator nakon ove lekcije treba da razume da bezbednost image-a nije jednokratno skeniranje pre deployment-a. Pouzdan tok zahteva nepromenljivu identifikaciju digestom, proveru poznatih ranjivosti, inventar komponenti, dokaz o odobrenom poreklu, kriptografski potpis i tehničko sprovođenje pravila na ulazu u klaster.

Praktična odgovornost administratora obuhvata proveru tačnog artefakta, čuvanje dokaza, validaciju admission politike, razlikovanje admission greške od problema povlačenja ili pokretanja image-a i bezbedan rollback na prethodni odobreni digest. Posebno mora prepoznati da potpis ne potvrđuje odsustvo ranjivosti, da scan ne potvrđuje identitet proizvođača i da tag nije nepromenljivi identifikator.

Promena poverljivih ključeva, globalnih policy pravila, registry sigurnosnih pragova i fail-open/fail-closed ponašanja prevazilazi rutinsko aplikaciono administriranje i zahteva formalno odobrenje vlasnika platforme i bezbednosti. Sumnja na krađu signing ključa, kompromitovanje build sistema, neobjašnjiv potpis ili nemogućnost utvrđivanja porekla aktivnog image-a razlog su za neposrednu eskalaciju, zaustavljanje promocije i kontrolisanu istragu lanca isporuke.

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