Ha Kubernetes-t uzemeltetek az EU-ban, a NIS2 ram is vonatkozik. Az iranyelvek 2024 oktobere ota hatalyosak, es a tagallamok azota ultetik at a nemzeti jogba. Az elmult honapokban tobb klasztert is atneztem megfeleles szempontbol, es ebbol osszeraktam, mi az, ami tenyleg szamit a gyakorlatban.
Ez nem jogi elemzes. Inkabb az a technikai checklista, amit en is sokkal hamarabb szerettem volna kezbe kapni.
Mit jelent a NIS2 K8s uzemeltetoknek (roviden)
A NIS2 boviti az eredeti NIS iranyelv hatalyat. Ha a ceg, ahol dolgozom, “alapveto” vagy “fontos” szervezetnek minosul (energia, kozlekedes, egeszsegugy, digitalis infrastruktura es meg sok mas), akkor tudnom kell igazolni:
- Kockazatkezelesi intezkedeseket az IT rendszereidre
- Incidenseszlelest es jelentest (24 ora korai figyelmeztetesre, 72 ora teljes jelentesre)
- Ellatasilancbiztonsagot
- Uzletfolytonossagi tervezest
- Audit logolast megorzesi idovel
A Kubernetes mindegyiket erinti, ugyhogy vegigmegyek rajtuk egyenkent.
1. Network Policy-k: a lateralis mozgas megallitasa
Alapertelmezetten minden pod beszelhet minden mas poddal egy Kubernetes klaszterben. Ezt en compliance oldalrol konkretan vallalhatatlannak latom. A NIS2 halozati szegmentalast es hozzaferes-vezerlest kovetel meg.
En mindig egy default-deny szaballyal kezdek minden namespace-ben:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
namespace: production
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
Utana explicit engedelyezem, aminek tenyleg kommunikalnia kell:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-frontend-to-api
namespace: production
spec:
podSelector:
matchLabels:
app: api
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: frontend
ports:
- protocol: TCP
port: 8080
Azt is mindig leellenorzom, hogy a szabaly tenyleg ervenyesul:
# Gyors teszt - ennek timeout-olnia kell, ha a deny-all mukodik
kubectl run test-pod --rm -it --image=busybox --restart=Never \
-n production -- wget -qO- --timeout=3 http://api:8080
Arra kulon figyelek, hogy a CNI tenyleg tamogassa a NetworkPolicy-t. A Flannel nem ervenyesiti, a Calico, Cilium es Weave igen.
2. RBAC audit: ki mit csinalhat
A NIS2 hozzaferes-vezerlest es legkisebb jogosultsag elvet var el. Kubernetesben ez nalam rendszeres RBAC auditot jelent.
Tulterjeszkedett service accountok keresese:
# Cluster-admin jogosultsagu ClusterRoleBinding-ok listazasa
kubectl get clusterrolebindings -o json | \
jq -r '.items[] | select(.roleRef.name=="cluster-admin") |
.metadata.name + " -> " + (.subjects[]? | .kind + "/" + .name)'
Kockazatos jogosultsagok keresese:
# Olyan role-ok keresese, amelyek exec-et engednek podokba
kubectl get roles,clusterroles -A -o json | \
jq -r '.items[] | select(.rules[]? |
.resources[]? == "pods/exec") | .metadata.name'
Mindig keszitsen egy dedikalt RBAC audit scriptet es havonta futtasd:
#!/bin/bash
echo "=== Cluster Admin Binding-ok ==="
kubectl get clusterrolebindings -o json | \
jq -r '.items[] | select(.roleRef.name=="cluster-admin") | .metadata.name'
echo -e "\n=== Wildcard jogosultsagok ==="
kubectl get clusterroles -o json | \
jq -r '.items[] | select(.rules[]? |
(.verbs[]? == "*") or (.resources[]? == "*")) | .metadata.name'
echo -e "\n=== Secret-ekhez fero Service Accountok ==="
kubectl get roles,clusterroles -A -o json | \
jq -r '.items[] | select(.rules[]? |
.resources[]? == "secrets") |
.metadata.namespace + "/" + .metadata.name'
3. Image scanning Trivy-vel
Az ellatasilancbiztonsag a NIS2 egyik fo pillere. Nekem tudnom kell, mi van az image-ekben, es a sebezhetosegeket meg produkcio elott szeretnem megfogni.
Telepitsd a Trivy-t es scanneld az image-eket:
# Egy adott image scannelese
trivy image --severity HIGH,CRITICAL your-registry.io/app:latest
# Minden jelenleg futo image scannelese a klaszterben
kubectl get pods -A -o jsonpath='{range .items[*]}{range .spec.containers[*]}{.image}{"\n"}{end}{end}' | \
sort -u | while read img; do
echo "Scanneles: $img"
trivy image --severity HIGH,CRITICAL --quiet "$img"
done
Folyamatos scannelehez telepitsd a Trivy Operatort:
helm repo add aqua https://aquasecurity.github.io/helm-charts/
helm install trivy-operator aqua/trivy-operator \
--namespace trivy-system \
--create-namespace \
--set trivy.severity="HIGH,CRITICAL"
Ez VulnerabilityReport CRD-ket hoz letre minden workloadhoz:
# Sebezhetosegi reportok megtekintese
kubectl get vulnerabilityreports -A \
-o jsonpath='{range .items[*]}{.metadata.namespace}/{.metadata.name}: Critical={.report.summary.criticalCount} High={.report.summary.highCount}{"\n"}{end}'
4. Runtime biztonsag Falco-val
A NIS2 valos ideju fenyegeteseszlelest kovetel. En erre Falco-t rakok fel, mert rendszerhivas szinten figyel es gyorsan jelez, ha valami gyanus.
Falco telepitese Helm-mel:
helm repo add falcosecurity https://falcosecurity.github.io/charts
helm install falco falcosecurity/falco \
--namespace falco \
--create-namespace \
--set falcosidekick.enabled=true \
--set falcosidekick.config.slack.webhookurl="https://hooks.slack.com/services/YOUR/WEBHOOK" \
--set driver.kind=ebpf
A Falco jo alapertelmezettsegekkel jon, de en szoktam hozzaadni egyedi szabalyokat NIS2-specifikus helyzetekre:
# custom-rules.yaml
- rule: Sensitive File Access in Container
desc: Erzekeny fajlok olvasasanak eszlelese, ami adatlopasra utalhat
condition: >
container and open_read and
(fd.name startswith /etc/shadow or
fd.name startswith /etc/passwd or
fd.name startswith /run/secrets)
output: >
Erzekeny fajl megnyitva konterben
(file=%fd.name user=%user.name container=%container.name
image=%container.image.repository pod=%k8s.pod.name ns=%k8s.ns.name)
priority: WARNING
tags: [nis2, data_access]
- rule: Unexpected Outbound Connection
desc: Kontener varatlan kulso IP-re csatlakozik
condition: >
container and evt.type=connect and fd.typechar=4 and
fd.ip != "0.0.0.0" and not fd.snet in (rfc_1918_addresses)
output: >
Varatlan kimeno kapcsolat
(dest=%fd.name user=%user.name container=%container.name
pod=%k8s.pod.name ns=%k8s.ns.name)
priority: NOTICE
tags: [nis2, network]
5. Policy enforcement Kyverno-val
Szukseg van olyan vedokorlatokra, amik mar admission idoben megfogjak a rossz konfiguraciokat. En Kyverno-t hasznalok, mert sima Kubernetes YAML-lel lehet dolgozni, nem kell hozza uj policy nyelv.
Telepites:
helm repo add kyverno https://kyverno.github.io/kyverno/
helm install kyverno kyverno/kyverno \
--namespace kyverno \
--create-namespace
Ezeket a szabalyokat ervenyesitem NIS2 megfeleleshez:
# Non-root kontenerek kovetelmenye
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: require-non-root
spec:
validationFailureAction: Enforce
rules:
- name: check-non-root
match:
any:
- resources:
kinds:
- Pod
validate:
message: "Root-kent valo futtatás nem engedelyezett NIS2 megfelelesseg miatt"
pattern:
spec:
containers:
- securityContext:
runAsNonRoot: true
---
# Csak jovahagyott registry-kbol lehessen image-et huzni
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: restrict-image-registries
spec:
validationFailureAction: Enforce
rules:
- name: validate-registries
match:
any:
- resources:
kinds:
- Pod
validate:
message: "Az image-eknek jovahagyott registry-bol kell szarmazniuk"
pattern:
spec:
containers:
- image: "your-registry.io/*"
---
# Resource limitek kovetelmenye (zajos szomszed DoS megelozese)
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: require-resource-limits
spec:
validationFailureAction: Enforce
rules:
- name: check-limits
match:
any:
- resources:
kinds:
- Pod
validate:
message: "Resource limitek megadasa kotelezo"
pattern:
spec:
containers:
- resources:
limits:
memory: "?*"
cpu: "?*"
6. Audit logolas es megorzesi ido
A NIS2 megkoveteli, hogy legyenek visszanezheto logok incidensvizsgalathoz. A Kubernetes audit logok pontosan ezt adjak, latom bennuk, ki mit es mikor csinalt.
Keszits audit policy-t:
# audit-policy.yaml
apiVersion: audit.k8s.io/v1
kind: Policy
rules:
# Pod, deployment, secret valtozasok logolasa
- level: RequestResponse
resources:
- group: ""
resources: ["pods", "secrets", "configmaps"]
- group: "apps"
resources: ["deployments", "statefulsets", "daemonsets"]
verbs: ["create", "update", "patch", "delete"]
# Hitelesitesi dontesek logolasa
- level: Metadata
resources:
- group: "authentication.k8s.io"
# RBAC valtozasok logolasa
- level: RequestResponse
resources:
- group: "rbac.authorization.k8s.io"
# Zajos csak-olvasasi keresek kihagyasa
- level: None
verbs: ["get", "list", "watch"]
resources:
- group: ""
resources: ["events"]
Engedelyezd az API szerveren (kubeadm klaszterenel add hozza a /etc/kubernetes/manifests/kube-apiserver.yaml-hoz):
spec:
containers:
- command:
- kube-apiserver
- --audit-policy-file=/etc/kubernetes/audit-policy.yaml
- --audit-log-path=/var/log/kubernetes/audit.log
- --audit-log-maxage=90
- --audit-log-maxbackup=10
- --audit-log-maxsize=100
Centralizalt logolashoz kuldd tovabb a SIEM-edbe. En Fluent Bit-et hasznalok:
helm repo add fluent https://fluent.github.io/helm-charts
helm install fluent-bit fluent/fluent-bit \
--namespace logging \
--create-namespace \
--set config.outputs="[OUTPUT]\n Name es\n Match *\n Host elasticsearch.logging.svc\n Port 9200\n Index k8s-audit\n Retry_Limit 5"
A NIS2 nem ad meg pontos megorzesi idot, de a legtobb nemzeti implementacio legalabb 12-18 honapot ker. En ennek megfeleloen allitom be az Elasticsearch ILM policy-t.
7. Incidenskezeles: a 24/72 oras hataridok betartasa
A NIS2 szigoru jelentesi hataridoket ir elo:
- 24 ora: Korai figyelmeztetes a nemzeti CSIRT-nek, miutan tudomast szerzek egy jelentos incidensrol
- 72 ora: Teljes incidensjelentes kezdeti ertekelssel
- 1 honap: Zarojelentes
Ehhez olyan riasztasi folyamat kell, ami tenyleg gyorsan jelez. Nalam igy van osszekotve a Falco az incidenskezelesi pipeline-nal:
# falcosidekick values incidensriasztashoz
config:
slack:
webhookurl: "https://hooks.slack.com/services/YOUR/WEBHOOK"
minimumpriority: "warning"
webhook:
address: "https://your-incident-api.internal/falco"
minimumpriority: "critical"
pagerduty:
routingkey: "YOUR_ROUTING_KEY"
minimumpriority: "critical"
Prometheus alerteket is beallitok klaszterszintu anomaliakra:
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
name: nis2-security-alerts
namespace: monitoring
spec:
groups:
- name: nis2-compliance
rules:
- alert: UnauthorizedAPIAccess
expr: |
sum(rate(apiserver_audit_event_total{verb=~"create|update|delete",code=~"4.."}[5m])) > 10
for: 2m
labels:
severity: critical
compliance: nis2
annotations:
summary: "Magas aranyú jogosulatlan API hivasok eszlelve"
runbook: "Ellenorizd az audit logokat, NIS2 24 oras ertesites szukseges lehet"
- alert: PodSecurityViolation
expr: |
sum(increase(falco_events{priority=~"Critical|Emergency"}[10m])) > 0
for: 1m
labels:
severity: critical
compliance: nis2
annotations:
summary: "Falco kritikus biztonsagi esemenyt eszlelt"
A folyamatot dokumentalom, es rendszeresen vegigvesszuk a csapattal, ki mit csinal riasztas eseten. A korai figyelmeztetes sablont is automatizalom, hogy kritikus esetben 24 oran belul ki lehessen kuldeni.
8. Ellatasilancbiztonsag: SBOM-ok es alairásas image-ek
A NIS2 konkretan kiterjed az ellatasilancbiztonsag kockazatkezelesere. Konteneres workloadoknal ez nalam ket dolgot jelent: tudom, mi van az image-ben (SBOM), es igazolom, hogy nem nyultak hozza (alairas).
SBOM generlas Syft-tel
# SBOM generaals egy image-hez
syft your-registry.io/app:latest -o spdx-json > app-sbom.spdx.json
# SBOM csatolasa az image-hez a registry-ben
cosign attach sbom --sbom app-sbom.spdx.json your-registry.io/app:latest
Image alairas Cosign/Sigstore-ral
# Kulcspar generalas (egyszer csinalod, a privat kulcsot tarold biztonságosan)
cosign generate-key-pair
# Image alairas build utan
cosign sign --key cosign.key your-registry.io/app:latest
# Alairas ellenorzese
cosign verify --key cosign.pub your-registry.io/app:latest
Kulcs nelkuli alairashoz (ajanlott CI/CD-hez) hasznald a Sigstore Fulcio-jat:
# CI pipeline-ban - OIDC identitassal ir ala, nem kell kulcsokat kezelni
cosign sign your-registry.io/app:latest
Alairas ellenorzes ervenyesitese Kyverno-val:
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: verify-image-signatures
spec:
validationFailureAction: Enforce
rules:
- name: check-signature
match:
any:
- resources:
kinds:
- Pod
verifyImages:
- imageReferences:
- "your-registry.io/*"
attestors:
- entries:
- keys:
publicKeys: |-
-----BEGIN PUBLIC KEY-----
YOUR_COSIGN_PUBLIC_KEY_HERE
-----END PUBLIC KEY-----
Megfelelessegi checklista
Itt a tomoritett checklistam. En ezt szoktam vegigvinni minden erintett klaszteren:
- Default-deny NetworkPolicy-k minden namespace-ben
- RBAC audit elvegezve, nincs felesleges wildcard cluster-admin
- Image scanning a CI/CD pipeline-ban (Trivy)
- Folyamatos scanning a klaszterben (Trivy Operator)
- Runtime eszleles telepitve (Falco)
- Admission policy-k ervenyesitve (Kyverno vagy OPA Gatekeeper)
- Kubernetes audit logolas bekapcsolva 12+ honapos megorzesi idovel
- Centralizalt logolas Fluent Bit-tel vagy hasonloval
- Riasztasi pipeline ugyeletes rotacioval
- Incidenskezelesi runbook NIS2 jelentesi sablonokkal
- SBOM generaals minden production image-hez
- Image alairas a CI/CD-ben
- Alairas ellenorzes az admission controlban
- Rendszeres penetracios tesztek (legalabb evente)
Osszefoglalas
A NIS2 megfeleles nekem nem egyetlen tool, es nem is egy egyszeri pipa. Ez folyamatos hardening, monitorozas es reagalas. A jo oldala az, hogy Kubernetesben mar ott vannak az eszkozok, tobbnyire fegyelmezett konfiguraciorol van szo, nem nagy egyedi fejlesztesrol.
En mindig a legnagyobb hatasu lepesekkel kezdek: network policy-k, RBAC audit es image scanning. Erre jon ra a runtime eszleles es a policy enforcement. Utana zarom le a temat audit logolassal es stabil incidenskezelesi folyamattal.
A 24 oras jelentesi hatarido az, ami a legtobb csapatot meglepi. Emiatt a riasztasi pipeline-t erdemes most rendbe rakni, nem akkor, amikor mar tenyleges incidens van.
Ha van sajat tapasztalatod NIS2 es Kubernetes teren, szivesen osszevetem az enyemmel. Ebben a temaban en is folyamatosan tanulok.