๐Ÿ” ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค ํด๋Ÿฌ์Šคํ„ฐ ๋ณด์•ˆ [securityContext, Network Policiy, Audit, Trivy, Kube-bench]

๊น€์„ฑ์ธยท2023๋…„ 10์›” 22์ผ
0

[DevOps] ๐ŸณDocker & Kubernetes

๋ชฉ๋ก ๋ณด๊ธฐ
53/62

https://kubernetes.io/docs/tasks/configure-pod-container/security-context/

๋ณด์•ˆ ์ปจํ…์ŠคํŠธ (securityContext)

ํฌ๋“œ ๋˜๋Š” ์ปจํ…Œ์ด๋„ˆ์— ๋Œ€ํ•œ ๊ถŒํ•œ ๋ฐ ์•ก์„ธ์Šค ์ œ์–ด ์„ค์ •์„ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค.

  • ์ž„์˜์  ์ ‘๊ทผ ์ œ์–ด: ํŒŒ์ผ๊ณผ ๊ฐ™์€ ๊ฐ์ฒด์— ๋Œ€ํ•œ ์ ‘๊ทผ ๊ถŒํ•œ์€ ์‚ฌ์šฉ์ž ID(UID)์™€ ๊ทธ๋ฃน ID(GID)๋ฅผ ๊ธฐ์ค€์œผ๋กœ ๊ฒฐ์ •๋ฉ๋‹ˆ๋‹ค .
  • SELinux(๋ณด์•ˆ ๊ฐ•ํ™” Linux) : ๊ฐœ์ฒด์— ๋ณด์•ˆ ๋ ˆ์ด๋ธ”์ด ํ• ๋‹น๋ฉ๋‹ˆ๋‹ค.
  • ํŠน๊ถŒ ๋˜๋Š” ๋น„ํŠน๊ถŒ์œผ๋กœ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.
  • Linux ๊ธฐ๋Šฅ : ํ”„๋กœ์„ธ์Šค์— ์ผ๋ถ€ ๊ถŒํ•œ์„ ๋ถ€์—ฌํ•˜์ง€๋งŒ ๋ฃจํŠธ ์‚ฌ์šฉ์ž์˜ ๋ชจ๋“  ๊ถŒํ•œ์„ ๋ถ€์—ฌํ•˜์ง€๋Š” ์•Š์Šต๋‹ˆ๋‹ค.
  • AppArmor : ํ”„๋กœ๊ทธ๋žจ ํ”„๋กœํ•„์„ ์‚ฌ์šฉํ•˜์—ฌ ๊ฐœ๋ณ„ ํ”„๋กœ๊ทธ๋žจ์˜ ๊ธฐ๋Šฅ์„ ์ œํ•œํ•ฉ๋‹ˆ๋‹ค.
  • Seccomp : ํ”„๋กœ์„ธ์Šค์˜ ์‹œ์Šคํ…œ ํ˜ธ์ถœ์„ ํ•„ํ„ฐ๋งํ•ฉ๋‹ˆ๋‹ค.
  • readOnlyRootFilesystem: ์ปจํ…Œ์ด๋„ˆ์˜ ๋ฃจํŠธ ํŒŒ์ผ ์‹œ์Šคํ…œ์„ ์ฝ๊ธฐ ์ „์šฉ์œผ๋กœ ๋งˆ์šดํŠธํ•ฉ๋‹ˆ๋‹ค.
apiVersion: v1
kind: Pod
metadata:
  name: security-context-demo
spec:
  securityContext:
    runAsUser: 1000 # ์ปจํ…Œ์ด๋„ˆ UID 
    runAsGroup: 3000 # ์ปจํ…Œ์ด๋„ˆ GID
    fsGroup: 2000 # ๋ณด์กฐ์  ๊ทธ๋ฃน
  volumes:
  - name: sec-ctx-vol
    emptyDir: {}
  containers:
  - name: sec-ctx-demo
    image: busybox:1.28
    command: [ "sh", "-c", "sleep 1h" ]
    volumeMounts:
    - name: sec-ctx-vol
      mountPath: /data/demo
    securityContext:
      allowPrivilegeEscalation: false
  • allowPrivilegeEscalation: ํ”„๋กœ์„ธ์Šค๊ฐ€ ์ƒ์œ„ ํ”„๋กœ์„ธ์Šค๋ณด๋‹ค ๋” ๋งŽ์€ ๊ถŒํ•œ์„ ์–ป์„ ์ˆ˜ ์žˆ๋Š”์ง€ ์—ฌ๋ถ€๋ฅผ ์ œ์–ดํ•ฉ๋‹ˆ๋‹ค. no_new_privs ์ด bool์€ ํ”Œ๋ž˜๊ทธ๊ฐ€ ์ปจํ…Œ์ด๋„ˆ ํ”„๋กœ์„ธ์Šค์— ์„ค์ •๋˜๋Š”์ง€ ์—ฌ๋ถ€๋ฅผ ์ง์ ‘ ์ œ์–ดํ•ฉ๋‹ˆ๋‹ค.
    allowPrivilegeEscalation์ปจํ…Œ์ด๋„ˆ๊ฐ€ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ฒฝ์šฐ์—๋Š” ํ•ญ์ƒ true์ž…๋‹ˆ๋‹ค.
    • true์ผ ๊ฒฝ์šฐ ํŠน๊ถŒ ๋ชจ๋“œ๋กœ ์‹คํ–‰๋˜๊ฑฐ๋‚˜
    • CAP_SYS_ADMIN์„ ๊ฐ€์ง
  • false: ๋ถ€๋ชจํ”„๋กœ์„ธ์Šค๋ณด๋‹ค ๊ถŒํ•œ์„ ๋” ๊ฐ–์ง€ ๋ชปํ•˜๋„๋กํ•จ, Privileage Escalation ์„ ๋ฐฉ์ง€ํ•จ

์ปจํ…Œ์ด๋„ˆ ๋‚ด๋ถ€ ๋ณด์•ˆ ์ปจํ…์ŠคํŠธ

apiVersion: v1
kind: Pod
metadata:
  name: security-context-demo-2
spec:
  securityContext:
    runAsUser: 1000
  containers:
  - name: sec-ctx-demo-2
    image: gcr.io/google-samples/node-hello:1.0
    securityContext:
      runAsUser: 2000 # ํ•ด๋‹น ์ปจํ…Œ์ด๋„ˆ์—์„œ ์šฐ์„ ์ˆœ์œ„ ๋” ๋†’์Œ
      allowPrivilegeEscalation: false

spec.containers.securityContext : ์ปจํ…Œ์ด๋„ˆ ๋‚ด๋ถ€ UID
spec.seucirtyContext: ํŒŒ๋“œ ๋‚ด๋ถ€ UID

๊ถŒํ•œ ๋ถ€์—ฌ

apiVersion: v1
kind: Pod
metadata:
  name: security-context-demo-4
spec:
  containers:
  - name: sec-ctx-4
    image: gcr.io/google-samples/node-hello:1.0
    securityContext:
      capabilities:
        add: ["NET_ADMIN", "SYS_TIME"]

๋‚ด๋ถ€ ์ปจํ…Œ์ด๋„ˆ ๊ถŒํ•œ ๋ถ€์—ฌ : capabilities

์ ์šฉ

์™ธ๋ถ€์—์„œ ํŒŒ๋“œ ๋‚ด๋ถ€ ๋˜๋Š” ์ปจํ…Œ์ด๋„ˆ์— ์ ‘๊ทผํ–ˆ์„ ๋•Œ, ๋‚ด๋ถ€์—์„œ ๋™์ž‘ ๊ฐ€๋Šฅํ•œ ๋ฒ”์œ„๋ฅผ ์‚ฌ์ „์— ์ •ํ•ด๋‘” UID๋“ฑ ์œ ์ € ๊ถŒํ•œ ์„ค์ •์„ ์ œํ•œํ•˜์—ฌ ๋‚ด๋ถ€์— ๊ณต๊ฒฉ ๋ฐ ํ”ผํ•ด๋ฅผ ๋ฐฉ์ง€ ๊ฐ€๋Šฅํ•˜๋‹ค.


๋„คํŠธ์›Œํฌ ์ •์ฑ… (Network Policies)

https://kubernetes.io/ko/docs/concepts/services-networking/network-policies/

๋„คํŠธ์›Œํฌ ์ •์ฑ…์„ ํ†ตํ•ด ํŒŒ๋“œ๊ฐ„ ํ†ต์‹  ์„ค์ •

  • ๋„คํŠธ์›Œํฌ ๋‚ด์— ์กด์žฌํ•˜๋Š” ์—”๋“œํฌ์ธํŠธ ํŒŒ๋“œ๊ฐ„์˜ ํ†ต์‹  ๋ฐฉ๋ฒ•์—๋งŒ ์ ์šฉ
    • ํ—ˆ์šฉ๋˜๋Š” ๋‹ค๋ฅธ ํŒŒ๋“œ(์˜ˆ์™ธ: ํŒŒ๋“œ๋Š” ์ž์‹ ์— ๋Œ€ํ•œ ์ ‘๊ทผ์„ ์ฐจ๋‹จํ•  ์ˆ˜ ์—†์Œ)
    • ํ—ˆ์šฉ๋˜๋Š” ๋„ค์ž„์ŠคํŽ˜์ด์Šค
    • IP ๋ธ”๋ก(์˜ˆ์™ธ: ํŒŒ๋“œ ๋˜๋Š” ๋…ธ๋“œ์˜ IP ์ฃผ์†Œ์™€ ๊ด€๊ณ„์—†์ด ํŒŒ๋“œ๊ฐ€ ์‹คํ–‰ ์ค‘์ธ ๋…ธ๋“œ์™€์˜ ํŠธ๋ž˜ํ”ฝ์€ ํ•ญ์ƒ ํ—ˆ์šฉ๋จ)
  • ํŒŒ๋“œ์— ํ—ˆ์šฉ๋˜๋Š” ํŠธ๋ž˜ํ”ฝ ๊ทœ์น™์„ ์ •์˜ ๋ฐ ์ œํ•œ
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: test-network-policy
  namespace: default
spec:
  podSelector: # ์ •์ฑ…์„ ์ ์šฉํ•  ํŒŒ๋“œ
    matchLabels:
      role: db
  policyTypes:
    - Ingress
    - Egress
  ingress: # role: db์ธ ํŒŒ๋“œ์— ์ ์šฉํ•  ์ธ๊ทธ๋ ˆ์Šค ํ™”์ดํŠธ๋ฆฌ์ŠคํŠธ
    - from:
        - ipBlock:
            cidr: 172.17.0.0/16
            except:
              - 172.17.1.0/24
        - namespaceSelector: #๋„ค์ž„์ŠคํŽ˜์ด์Šค์— ํ• ๋‹น๋œ ๋ ˆ์ด๋ธ”
            matchLabels:
              project: myproject
        - podSelector: # ํŠน์ •ํ•œ ํฌ๋“œ์— ํ• ๋‹น๋œ ๋ ˆ์ด๋ธ” ๋งค์น˜
            matchLabels:
              role: frontend
      ports:
        - protocol: TCP
          port: 6379
  egress: # ์™ธ๋ถ€๋กœ ๋‚˜๊ฐ€๋Š” ํ†ต์‹ ์„ ์ œํ•œ์‹œํ‚ค๋„๋ก ์„ค์ • (ingress์™€ ์กฐ๊ฑด ๋™์ผ)
    - to:
        - ipBlock:
            cidr: 10.0.0.0/24
      ports:
        - protocol: TCP
          port: 5978

egress

๋‚˜๊ฐ€๋Š” ํŠธ๋ž˜ํ”ฝ์— ๋Œ€ํ•œ ์ •์ฑ… ์„ค์ •
๊ฐ ๋„คํŠธ์›Œํฌํด๋ฆฌ์‹œ์—๋Š” ํ™”์ดํŠธ๋ฆฌ์ŠคํŠธ egress ๊ทœ์น™์ด ํฌํ•จ๋  ์ˆ˜ ์žˆ๋‹ค. ๊ฐ ๊ทœ์น™์€ to ์™€ ports ๋ถ€๋ถ„๊ณผ ๋ชจ๋‘ ์ผ์น˜ํ•˜๋Š” ํŠธ๋ž˜ํ”ฝ์„ ํ—ˆ์šฉํ•œ๋‹ค.
(ํ™”์ดํŠธ๋ฆฌ์ŠคํŠธ - ๋ธ”๋ž™๋ฆฌ์ŠคํŠธ์˜ ๋ฐ˜๋Œ€)

  • namespace๊ฐ€ defualt ์ด๊ณ 
  • role=db ๋ ˆ์ด๋ธ”์„ ๊ฐ€์ง„ ๋ชจ๋“  ํŒŒ๋“œ์—์„œ TCPํฌํŠธ 5978 ์˜ CIDR 10.0.0.0/24 ๋กœ์˜ ์—ฐ๊ฒฐ์„ ํ—ˆ์šฉํ•จ

ingress

๋“ค์–ด์˜ค๋Š” ํŠธ๋ž˜ํ”ฝ์— ๋Œ€ํ•œ ์ •์ฑ… ์„ค์ •
๊ฐ ๋„คํŠธ์›Œํฌํด๋ฆฌ์‹œ์—๋Š” ํ™”์ดํŠธ๋ฆฌ์ŠคํŠธ ingress ๊ทœ์น™ ๋ชฉ๋ก์ด ํฌํ•จ๋  ์ˆ˜ ์žˆ๋‹ค. ๊ฐ ๊ทœ์น™์€ from ๊ณผ ports ๋ถ€๋ถ„๊ณผ ๋ชจ๋‘ ์ผ์น˜ํ•˜๋Š” ํŠธ๋ž˜ํ”ฝ์„ ํ—ˆ์šฉํ•œ๋‹ค.

  • "role=db" ๋ ˆ์ด๋ธ”์„ ์‚ฌ์šฉํ•˜๋Š” "default" ๋„ค์ž„์ŠคํŽ˜์ด์Šค์˜ ๋ชจ๋“  ํŒŒ๋“œ์— ๋Œ€ํ•ด์„œ TCP ํฌํŠธ 6379๋กœ์˜ ์—ฐ๊ฒฐ์„ ํ—ˆ์šฉํ•œ๋‹ค. ์ธ๊ทธ๋ ˆ์Šค์„ ํ—ˆ์šฉ ํ•  ๋Œ€์ƒ์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

    • ์•„๋ž˜๋Š” ๋ชจ๋‘ ํ•˜๋‚˜๋ผ๋„ ๋งŒ์กฑํ•˜๋ฉด ํ†ต๊ณผ๋จ (or์—ฐ์‚ฐ)
    • "role=frontend" ๋ ˆ์ด๋ธ”์ด ์žˆ๋Š” "default" ๋„ค์ž„์ŠคํŽ˜์ด์Šค์˜ ๋ชจ๋“  ํŒŒ๋“œ(ingress ๋Œ€์ƒํฌ๋“œ)
    • ๋„ค์ž„์ŠคํŽ˜์ด์Šค์™€ "project=myproject" ๋ฅผ ๋ ˆ์ด๋ธ”๋กœ ๊ฐ€์ง€๋Š” ๋ชจ๋“  ํŒŒ๋“œ(ingress ์š”์ฒญํฌ๋“œ)
    • 172.17.0.0โ€“172.17.0.255 ์™€ 172.17.2.0โ€“172.17.255.255 ์˜ ๋ฒ”์œ„๋ฅผ ๊ฐ€์ง€๋Š” IP ์ฃผ์†Œ(์˜ˆ: 172.17.0.0/16 ์ „์ฒด์—์„œ 172.17.1.0/24 ๋ฅผ ์ œ์™ธ)

์ •์ฑ… ๊ฒน์น ์‹œ

or ์—ฐ์‚ฐ ํ—ˆ์šฉ -> group3 ์—๋Š” ๋ง‰์•„๋†จ๋Š”๋ฐ group2์—์„œ ํ—ˆ์šฉํ•˜๋ฉด ํ†ต์‹  ๊ฐ€๋Šฅ


Audit

https://kubernetes.io/ko/docs/tasks/debug/debug-cluster/audit/

์ฟ ๋ฒ„๋„คํ‹ฐ์Šค ๊ฐ์‚ฌ(auditing)๋Š” ํด๋Ÿฌ์Šคํ„ฐ์˜ ์ž‘์—… ์ˆœ์„œ๋ฅผ ๋ฌธ์„œํ™”ํ•˜๋Š” ๋ณด์•ˆ ๊ด€๋ จ ์‹œ๊ฐ„๋ณ„ ๋ ˆ์ฝ”๋“œ ์„ธํŠธ๋ฅผ ์ œ๊ณตํ•œ๋‹ค. ํด๋Ÿฌ์Šคํ„ฐ๋Š” ์‚ฌ์šฉ์ž, ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค API๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋ฐ ์ปจํŠธ๋กค ํ”Œ๋ ˆ์ธ ์ž์ฒด์—์„œ ์ƒ์„ฑ๋œ ํ™œ๋™์„ ๊ฐ์‚ฌํ•œ๋‹ค.

๊ฐ์‚ฌ๋ฅผ ํ†ตํ•ด ํด๋Ÿฌ์Šคํ„ฐ ๊ด€๋ฆฌ์ž๋Š” ๋‹ค์Œ ์งˆ๋ฌธ์— ๋‹ตํ•  ์ˆ˜ ์žˆ๋‹ค.

  • ๋ฌด์Šจ ์ผ์ด ์ผ์–ด๋‚ฌ๋Š”์ง€?
  • ์–ธ์ œ ์ผ์–ด๋‚œ ์ผ์ธ์ง€?
  • ๋ˆ„๊ฐ€ ์‹œ์ž‘ํ–ˆ๋Š”์ง€?
  • ์–ด๋–ค ์ผ์ด ์žˆ์—ˆ๋Š”์ง€?
  • ์–ด๋””์„œ ๊ด€์ฐฐ๋˜์—ˆ๋Š”์ง€?
  • ์–ด๋””์„œ๋ถ€ํ„ฐ ์‹œ์ž‘๋˜์—ˆ๋Š”์ง€?
  • ๊ทธ๋ž˜์„œ ์–ด๋””๊นŒ์ง€ ๊ฐ”๋Š”์ง€?

1. ๊ฐ์‚ฌ ๊ธฐ๋ก

์–ธ์ œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ธฐ๋กํ• ์ง€

๊ฐ์‚ฌ ๊ธฐ๋ก์€ kube-apiserver ์ปดํฌ๋„ŒํŠธ ๋‚ด์—์„œ ์ˆ˜๋ช…์ฃผ๊ธฐ๋ฅผ ์‹œ์ž‘ํ•œ๋‹ค. ์‹คํ–‰์˜ ๊ฐ ๋‹จ๊ณ„์—์„œ ๊ฐ ์š”์ฒญ์€ ๊ฐ์‚ฌ ์ด๋ฒคํŠธ๋ฅผ ์ƒ์„ฑํ•˜๊ณ , ๊ฐ์‚ฌ ์ด๋ฒคํŠธ๋Š” ํŠน์ • ์ •์ฑ…์— ๋”ฐ๋ผ ์‚ฌ์ „ ์ฒ˜๋ฆฌ๋˜๊ณ  ๋ฐฑ์—”๋“œ์— ๊ธฐ๋ก๋œ๋‹ค. ์ •์ฑ…์€ ๊ธฐ๋ก๋œ ๋‚ด์šฉ์„ ๊ฒฐ์ •ํ•˜๊ณ  ๋ฐฑ์—”๋“œ๋Š” ๊ธฐ๋ก์„ ์œ ์ง€ํ•œ๋‹ค. ํ˜„์žฌ ๋ฐฑ์—”๋“œ ๊ตฌํ˜„์—๋Š” ๋กœ๊ทธ ํŒŒ์ผ ๋ฐ ์›นํ›…์ด ํฌํ•จ๋œ๋‹ค.

๊ฐ ์š”์ฒญ๋“ค์€ ์—ฐ๊ด€๋œ ๋‹จ๊ณ„(stage) ์™€ ํ•จ๊ป˜ ๊ธฐ๋ก๋  ์ˆ˜ ์žˆ๋‹ค. ์ •์˜๋œ ๋‹จ๊ณ„๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

  • RequestReceived - ๊ฐ์‚ฌ ํ•ธ๋“ค๋Ÿฌ๊ฐ€ ์š”์ฒญ์„ ์ˆ˜์‹ ํ•œ ์งํ›„, ๊ทธ๋ฆฌ๊ณ  ํ•ธ๋“ค๋Ÿฌ ์ฒด์ธ์œผ๋กœ ์œ„์ž„๋˜๊ธฐ ์ „์— ์ƒ์„ฑ๋˜๋Š” ์ด๋ฒคํŠธ์— ๋Œ€ํ•œ ๋‹จ๊ณ„์ด๋‹ค.
  • ResponseStarted - ์‘๋‹ต ํ—ค๋”๋Š” ์ „์†ก๋˜์—ˆ์ง€๋งŒ, ์‘๋‹ต ๋ณธ๋ฌธ(body)์€ ์ „์†ก๋˜๊ธฐ ์ „์ธ ๋‹จ๊ณ„์ด๋‹ค. ์ด ๋‹จ๊ณ„๋Š” ์˜ค๋ž˜ ์‹คํ–‰๋˜๋Š” ์š”์ฒญ(์˜ˆ: watch)์— ๋Œ€ํ•ด์„œ๋งŒ ์ƒ์„ฑ๋œ๋‹ค.
  • ResponseComplete - ์‘๋‹ต ๋‚ด์šฉ์ด ์™„๋ฃŒ๋˜์—ˆ์œผ๋ฉฐ, ๋” ์ด์ƒ ๋ฐ”์ดํŠธ๊ฐ€ ์ „์†ก๋˜์ง€ ์•Š์„ ๋•Œ์˜ ๋‹จ๊ณ„์ด๋‹ค.
  • Panic - ํŒจ๋‹‰์ด ๋ฐœ์ƒํ–ˆ์„ ๋•Œ ์ƒ์„ฑ๋˜๋Š” ์ด๋ฒคํŠธ์ด๋‹ค.

๊ฐ์‚ฌ ๋กœ๊น… ๊ธฐ๋Šฅ์€ ๊ฐ์‚ฌ์— ํ•„์š”ํ•œ ์ผ๋ถ€ ์ปจํ…์ŠคํŠธ๊ฐ€ ์š”์ฒญ๋งˆ๋‹ค ์ €์žฅ๋˜๊ธฐ ๋•Œ๋ฌธ์— API ์„œ๋ฒ„์˜ ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰์„ ์ฆ๊ฐ€์‹œํ‚จ๋‹ค. ๋ฉ”๋ชจ๋ฆฌ ์†Œ๋น„๋Ÿ‰์€ ๊ฐ์‚ฌ ๋กœ๊น… ๊ตฌ์„ฑ์— ๋”ฐ๋ผ ๋‹ค๋ฅด๋‹ค.

2. ๊ฐ์‚ฌ ์ •์ฑ…

์–ด๋–ค ๋ฐ์ดํ„ฐ๋ฅผ ๊ธฐ๋กํ• ์ง€

๊ฐ์‚ฌ ์ •์ฑ…์€ ๊ธฐ๋กํ•ด์•ผ ํ•˜๋Š” ์ด๋ฒคํŠธ์™€ ํฌํ•จํ•ด์•ผ ํ•˜๋Š” ๋ฐ์ดํ„ฐ์— ๋Œ€ํ•œ ๊ทœ์น™์„ ์ •์˜ํ•œ๋‹ค. ๊ฐ์‚ฌ ์ •์ฑ… ์˜ค๋ธŒ์ ํŠธ ๊ตฌ์กฐ๋Š” audit.k8s.io API ๊ทธ๋ฃน์— ์ •์˜๋˜์–ด ์žˆ๋‹ค. ์ด๋ฒคํŠธ๊ฐ€ ์ฒ˜๋ฆฌ๋˜๋ฉด ๊ทœ์น™ ๋ชฉ๋ก๊ณผ ์ˆœ์„œ๋Œ€๋กœ ๋น„๊ต๋œ๋‹ค. ์ฒซ๋ฒˆ์งธ ์ผ์น˜ ๊ทœ์น™์€ ์ด๋ฒคํŠธ์˜ ๊ฐ์‚ฌ ์ˆ˜์ค€(audit level)์„ ์„ค์ •ํ•œ๋‹ค.

  • None - ์ด ๊ทœ์น™์— ํ•ด๋‹น๋˜๋Š” ์ด๋ฒคํŠธ๋Š” ๋กœ๊น…ํ•˜์ง€ ์•Š๋Š”๋‹ค.
  • Metadata - ์š”์ฒญ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ(์š”์ฒญํ•˜๋Š” ์‚ฌ์šฉ์ž, ํƒ€์ž„์Šคํƒฌํ”„, ๋ฆฌ์†Œ์Šค, ๋™์‚ฌ(verb) ๋“ฑ)๋Š” ๋กœ๊น…ํ•˜์ง€๋งŒ ์š”์ฒญ/์‘๋‹ต ๋ณธ๋ฌธ์€ ๋กœ๊น…ํ•˜์ง€ ์•Š๋Š”๋‹ค.
  • Request - ์ด๋ฒคํŠธ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ๋ฐ ์š”์ฒญ ๋ณธ๋ฌธ์„ ๋กœ๊น…ํ•˜์ง€๋งŒ ์‘๋‹ต ๋ณธ๋ฌธ์€ ๋กœ๊น…ํ•˜์ง€ ์•Š๋Š”๋‹ค. ๋ฆฌ์†Œ์Šค ์™ธ์˜ ์š”์ฒญ์—๋Š” ์ ์šฉ๋˜์ง€ ์•Š๋Š”๋‹ค.
  • RequestResponse - ์ด๋ฒคํŠธ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ๋ฐ ์š”์ฒญ/์‘๋‹ต ๋ณธ๋ฌธ์„ ๋กœ๊น…ํ•œ๋‹ค. ๋ฆฌ์†Œ์Šค ์™ธ์˜ ์š”์ฒญ์—๋Š” ์ ์šฉ๋˜์ง€ ์•Š๋Š”๋‹ค.

--audit-policy-file ํ”Œ๋ž˜๊ทธ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ •์ฑ…์ด ํฌํ•จ๋œ ํŒŒ์ผ์„ kube-apiserver์— ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ๋‹ค. ํ”Œ๋ž˜๊ทธ๋ฅผ ์ƒ๋žตํ•˜๋ฉด ์ด๋ฒคํŠธ๊ฐ€ ๊ธฐ๋ก๋˜์ง€ ์•Š๋Š”๋‹ค. ๊ฐ์‚ฌ ์ •์ฑ… ํŒŒ์ผ์— rules ํ•„๋“œ๊ฐ€ ๋ฐ˜๋“œ์‹œ ์ œ๊ณต๋˜์–ด์•ผ ํ•œ๋‹ค. ๊ทœ์น™์ด ์—†๋Š”(0๊ฐœ์ธ) ์ •์ฑ…์€ ์ ์ ˆํ•˜์ง€ ์•Š์€(illegal) ๊ฒƒ์œผ๋กœ ๊ฐ„์ฃผ๋œ๋‹ค.

audit/audit-policy.yaml

apiVersion: audit.k8s.io/v1 # ํ•„์ˆ˜์‚ฌํ•ญ์ž„.
kind: Policy
# Request Received ๋‹จ๊ณ„์˜ ๋ชจ๋“  ์š”์ฒญ์— ๋Œ€ํ•ด ๊ฐ์‚ฌ ์ด๋ฒคํŠธ๋ฅผ ์ƒ์„ฑํ•˜์ง€ ์•Š์Œ.
omitStages:
  - "RequestReceived"
rules:
  # RequestResponse ์ˆ˜์ค€์—์„œ ํŒŒ๋“œ ๋ณ€๊ฒฝ ์‚ฌํ•ญ ๊ธฐ๋ก
  - level: RequestResponse
    resources:
    - group: ""
      # ๋ฆฌ์†Œ์Šค "ํŒŒ๋“œ" ๊ฐ€ RBAC ์ •์ฑ…๊ณผ ๋ถ€ํ•ฉํ•˜๋Š” ํŒŒ๋“œ์˜ ํ•˜์œ„ ๋ฆฌ์†Œ์Šค์— ๋Œ€ํ•œ
      # ์š”์ฒญ๊ณผ ์ผ์น˜ํ•˜์ง€ ์•Š์Œ.
      resources: ["pods"]
  # ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ์ˆ˜์ค€์—์„œ "pods/log", "pods/status"๋ฅผ ๊ธฐ๋กํ•จ.
  - level: Metadata
    resources:
    - group: ""
      resources: ["pods/log", "pods/status"]

  # "controller-leader" ๋ผ๋Š” ์ปจํ”ผ๊ทธ๋งต์— ์š”์ฒญ์„ ๊ธฐ๋กํ•˜์ง€ ์•Š์Œ."
  - level: None
    resources:
    - group: ""
      resources: ["configmaps"]
      resourceNames: ["controller-leader"]

  # ์—”๋“œํฌ์ธํŠธ ๋˜๋Š” ์„œ๋น„์Šค์˜ "system:kube-proxy"์— ์˜ํ•œ ๊ฐ์‹œ ์š”์ฒญ ๊ธฐ๋กํ•˜์ง€ ์•Š์Œ.
  - level: None
    users: ["system:kube-proxy"]
    verbs: ["watch"]
    resources:
    - group: "" # ํ•ต์‹ฌ API ๊ทธ๋ฃน
      resources: ["endpoints", "services"]

  # ์ธ์ฆ๋œ ์š”์ฒญ์„ ํŠน์ • ๋ฆฌ์†Œ์Šค๊ฐ€ ์•„๋‹Œ URL ๊ฒฝ๋กœ์— ๊ธฐ๋กํ•˜์ง€ ์•Š์Œ.
  - level: None
    userGroups: ["system:authenticated"]
    nonResourceURLs:
    - "/api*" # ์™€์ผ๋“œ์นด๋“œ ๋งค์นญ(wildcard matching).
    - "/version"

  # kube-system์— ์ปจํ”ผ๊ทธ๋งต ๋ณ€๊ฒฝ ์‚ฌํ•ญ์˜ ์š”์ฒญ ๋ณธ๋ฌธ์„ ๊ธฐ๋กํ•จ.
  - level: Request
    resources:
    - group: "" # ํ•ต์‹ฌ API ๊ทธ๋ฃน
      resources: ["configmaps"]
    # ์ด ์ •์ฑ…์€ "kube-system" ๋„ค์ž„์ŠคํŽ˜์ด์Šค์˜ ๋ฆฌ์†Œ์Šค์—๋งŒ ์ ์šฉ๋จ.
    # ๋นˆ ๋ฌธ์ž์—ด "" ์€ ๋„ค์ž„์ŠคํŽ˜์ด์Šค๊ฐ€ ์—†๋Š” ๋ฆฌ์†Œ์Šค๋ฅผ ์„ ํƒํ•˜๋Š”๋ฐ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Œ.
    namespaces: ["kube-system"]

  # ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ์ˆ˜์ค€์—์„œ ๋‹ค๋ฅธ ๋ชจ๋“  ๋„ค์ž„์ŠคํŽ˜์ด์Šค์˜ ์ปจํ”ผ๊ทธ๋งต๊ณผ ์‹œํฌ๋ฆฟ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ๊ธฐ๋กํ•จ.
  - level: Metadata
    resources:
    - group: "" # ํ•ต์‹ฌ API ๊ทธ๋ฃน
      resources: ["secrets", "configmaps"]

  # ์š”์ฒญ ์ˆ˜์ค€์—์„œ ์ฝ”์–ด ๋ฐ ํ™•์žฅ์— ์žˆ๋Š” ๋‹ค๋ฅธ ๋ชจ๋“  ๋ฆฌ์†Œ์Šค๋ฅผ ๊ธฐ๋กํ•จ.
  - level: Request
    resources:
    - group: "" # ํ•ต์‹ฌ API ๊ทธ๋ฃน
    - group: "extensions" # ๊ทธ๋ฃน์˜ ๋ฒ„์ „์„ ๊ธฐ์žฌํ•˜๋ฉด ์•ˆ ๋œ๋‹ค.

  # ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ์ˆ˜์ค€์—์„œ ๋‹ค๋ฅธ ๋ชจ๋“  ์š”์ฒญ์„ ๊ธฐ๋กํ•˜๊ธฐ ์œ„ํ•œ ๋ชจ๋“  ์ˆ˜์ง‘ ์ •์ฑ….
  - level: Metadata
    # ์ด ์ •์ฑ…์— ํ•ด๋‹นํ•˜๋Š” ๊ฐ์‹œ์ž์™€ ๊ฐ™์€ ์žฅ๊ธฐ ์‹คํ–‰ ์š”์ฒญ์€
    # RequestReceived์—์„œ ๊ฐ์‚ฌ ์ด๋ฒคํŠธ๋ฅผ ์ƒ์„ฑํ•˜์ง€ ์•Š์Œ.
    omitStages:
      - "RequestReceived"

3. ๊ฐ์‚ฌ ๋ฐฑ์—”๋“œ

๊ฐ์‚ฌ ๋ฐฑ์—”๋“œ๋Š” ๊ฐ์‚ฌ ์ด๋ฒคํŠธ๋ฅผ ์™ธ๋ถ€ ์ €์žฅ์†Œ์— ์œ ์ง€ํ•œ๋‹ค. ๊ธฐ๋ณธ์ ์œผ๋กœ kube-apiserver๋Š” ๋‘ ๊ฐ€์ง€ ๋ฐฑ์—”๋“œ๋ฅผ ์ œ๊ณตํ•œ๋‹ค.

  • ์ด๋ฒคํŠธ๋ฅผ ํŒŒ์ผ ์‹œ์Šคํ…œ์— ๊ธฐ๋กํ•˜๋Š” ๋กœ๊ทธ ๋ฐฑ์—”๋“œ
  • ์ด๋ฒคํŠธ๋ฅผ ์™ธ๋ถ€ HTTP API๋กœ ๋ณด๋‚ด๋Š” Webhook ๋ฐฑ์—”๋“œ

4. ๋กœ๊ทธ ๋ฐฑ์—”๋“œ

--audit-policy-file ํ”Œ๋ž˜๊ทธ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ •์ฑ…์ด ํฌํ•จ๋œ ํŒŒ์ผ์„ kube-apiserver์— ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ๋‹ค. ํ”Œ๋ž˜๊ทธ๋ฅผ ์ƒ๋žตํ•˜๋ฉด ์ด๋ฒคํŠธ๊ฐ€ ๊ธฐ๋ก๋˜์ง€ ์•Š๋Š”๋‹ค. ๊ฐ์‚ฌ ์ •์ฑ… ํŒŒ์ผ์— rules ํ•„๋“œ๊ฐ€ ๋ฐ˜๋“œ์‹œ ์ œ๊ณต๋˜์–ด์•ผ ํ•œ๋‹ค. ๊ทœ์น™์ด ์—†๋Š”(0๊ฐœ์ธ) ์ •์ฑ…์€ ์ ์ ˆํ•˜์ง€ ์•Š์€(illegal) ๊ฒƒ์œผ๋กœ ๊ฐ„์ฃผ๋œ๋‹ค.

๋กœ๊ทธ ๋ฐฑ์—”๋“œ๋Š” ๊ฐ์‚ฌ์ด๋ฒคํŠธ๋ฅผ JSONlines ํ˜•์‹์œผ๋กœ ํŒŒ์ผ์— ๊ธฐ๋กํ•œ๋‹ค. ๋‹ค์Œ์˜ kube-apiserver ํ”Œ๋ž˜๊ทธ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋กœ๊ทธ ๊ฐ์‚ฌ ๋ฐฑ์—”๋“œ๋ฅผ ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.

  • --audit-log-path ๋Š” ๋กœ๊ทธ ๋ฐฑ์—”๋“œ๊ฐ€ ๊ฐ์‚ฌ ์ด๋ฒคํŠธ๋ฅผ ์“ฐ๋Š” ๋ฐ ์‚ฌ์šฉํ•˜๋Š” ๋กœ๊ทธ ํŒŒ์ผ ๊ฒฝ๋กœ๋ฅผ ์ง€์ •ํ•œ๋‹ค. ์ด ํ”Œ๋ž˜๊ทธ๋ฅผ ์ง€์ •ํ•˜์ง€ ์•Š์œผ๋ฉด ๋กœ๊ทธ ๋ฐฑ์—”๋“œ๊ฐ€ ๋น„ํ™œ์„ฑํ™”๋œ๋‹ค. - ๋Š” ํ‘œ์ค€ ์ถœ๋ ฅ์„ ์˜๋ฏธํ•œ๋‹ค.
  • --audit-log-maxage ๋Š” ์˜ค๋ž˜๋œ ๊ฐ์‚ฌ ๋กœ๊ทธ ํŒŒ์ผ์„ ๋ณด๊ด€ํ•  ์ตœ๋Œ€ ์ผ์ˆ˜๋ฅผ ์ •์˜ํ•œ๋‹ค.
  • --audit-log-maxbackup ์€ ๋ณด๊ด€ํ•  ๊ฐ์‚ฌ ๋กœ๊ทธ ํŒŒ์ผ์˜ ์ตœ๋Œ€ ์ˆ˜๋ฅผ ์ •์˜ํ•œ๋‹ค.
  • --audit-log-maxsize ๋Š” ๊ฐ์‚ฌ ๋กœ๊ทธ ํŒŒ์ผ์ด ๋กœํ…Œ์ดํŠธ ๋˜๊ธฐ ์ „์˜ ์ตœ๋Œ€ ํฌ๊ธฐ(MB)๋ฅผ ์ •์˜ํ•œ๋‹ค.

ํด๋Ÿฌ์Šคํ„ฐ์˜ ์ปจํŠธ๋กค ํ”Œ๋ ˆ์ธ์ด kube-apiserver๋ฅผ ํŒŒ๋“œ๋กœ ์‹คํ–‰ํ•˜๋Š” ๊ฒฝ์šฐ ๊ฐ์‚ฌ ๋ ˆ์ฝ”๋“œ๊ฐ€ ์ง€์†๋˜๋„๋ก ์ •์ฑ… ํŒŒ์ผ ๋ฐ ๋กœ๊ทธ ํŒŒ์ผ์˜ ์œ„์น˜์— hostPath ๋ฅผ ๋งˆ์šดํŠธ ํ•ด์•ผํ•œ๋‹ค. ์˜ˆ๋ฅผ ๋“ค๋ฉด

/etc/kubernetes/manifests/kube-apiserver.yaml

--audit-policy-file=/etc/kubernetes/pki/audit.conf
--audit-log-path=/var/log/audit.log

๋ถˆ๋ฅจ ๋งˆ์šดํŠธ

/etc/kubernetes/manifests/kube-apiserver.yaml

...
volumeMounts:
  - mountPath: /etc/kubernetes/audit-policy.yaml
    name: audit
    readOnly: true
  - mountPath: /var/log/kubernetes/audit/
    name: audit-log
    readOnly: false
...
volumes:
- name: audit
  hostPath:
    path: /etc/kubernetes/audit-policy.yaml
    type: File

- name: audit-log
  hostPath:
    path: /var/log/kubernetes/audit/
    type: DirectoryOrCreate

Trivy

https://aquasecurity.github.io/trivy/v0.46/

์ปจํ…Œ์ด๋„ˆ ์ทจ์•ฝ์  ์ง„๋‹จ

๋„์ปค ์ด๋ฏธ์ง€/ ์ปจํ…Œ์ด๋„ˆ ๋‚ด๋ถ€์˜ ๋ชจ๋“ˆ์„ ์ฝ์–ด์„œ ํ•ด๋‹น ๋ชจ๋“ˆ๋“ค์˜ ์ทจ์•ฝ์ ์„ ๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค๋กœ ๊ฐ€์ ธ์™€์„œ ๋ชจ๋‹ˆํ„ฐ๋ง

https://aquasecurity.github.io/trivy/v0.46/docs/target/container_image/


kube-bench

์ฟ ๋ฒ„๋„คํ‹ฐ์Šค ๋ณด์•ˆ ์ ๊ฒ€ ๋ฒค์น˜๋งˆํฌ: https://www.cisecurity.org/
https://aquasecurity.github.io/kube-bench/v0.6.15/

kube-bench ์„ค์น˜

curl -L https://github.com/aquasecurity/kube-bench/releases/download/v0.6.2/kube-bench_0.6.2_linux_amd64.deb -o kube-bench_0.6.2_linux_amd64.deb

sudo apt install ./kube-bench_0.6.2_linux_amd64.deb -f

git hub ์„ค์น˜

git clone https://github.com/aquasecurity/kube-bench.git
cd kube-bench

configํŒŒ์ผ ๊ธฐ์ค€ ๋ณด์•ˆ ์ ๊ฒ€ ํ™•์ธ

./kube-bench --config-dir `pwd`/cfg --config `pwd`/cfg/config.yaml : configuration ๋””๋ ‰ํ„ฐ๋ฆฌ ๋ฐ ํŒŒ์ผ ์„ค์ • (ํ˜„์žฌ ํ™˜๊ฒฝ์— ๋”ฐ๋ฅธ ๋™์ž‘ ์ •์˜๋œ ํŒŒ์ผ)


falco

์ฟ ๋ฒ„๋„คํ‹ฐ์Šค ์ปจํ…Œ์ด๋„ˆ ๋ณด์•ˆ ๋ชจ๋‹ˆํ„ฐ๋ง

ํŠน์ • ์ด๋ฒคํŠธ ํƒ์ง€ ๊ฐ€๋Šฅ

  • kubernetes ์œ„ํ˜‘ ํƒ์ง€ ์—”์ง„
  • ๋Ÿฐํƒ€์ž„ ๋ณด์•ˆ ํ”„๋กœ์ ํŠธ (๋Ÿฐํƒ€์ž„์—์„œ ๋™์ž‘ํ•˜๋Š” ๊ฒƒ์„ ์‹ค์‹œ๊ฐ„์œผ๋กœ ๋ชจ๋‹ˆํ„ฐ๋ง)

์„ค์น˜

https://falco.org/ko/docs/installation/

falco on ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค

https://falco.org/ko/docs/getting-started/falco-kubernetes-quickstart/

falco ์ƒ์„ฑ ๋กœ๊ทธ ๋งค์นญ ํ•„๋“œ

https://falco.org/ko/docs/reference/rules/supported-fields/

falco ์‹คํ–‰

systemctl start falco
systemctl status falco
systemctl restart falco

๋กœ๊ทธํŒŒ์ผ ํ™•์ธ

/etc/falco/falco.yaml : falco ์„ค์ • ํŒŒ์ผ

  • file_output.filename: /var/log/events.log ๋ฅผ ํ†ตํ•ด์„œ ๋กœ๊ทธํŒŒ์ผ ์œ„์น˜ ์„ค์ • ๊ฐ€๋Šฅ
    cat /var/log/events.log | grep falco

๋ฃฐ ์ถ”๊ฐ€

vi /etc/falco/falco_rules.yaml
vi /etc/falco/faco_rules.local.yaml : ์‚ฌ์šฉ์ž ์ •์˜ ๋ฃฐ

0๊ฐœ์˜ ๋Œ“๊ธ€