Seccomp in Kubernetes: Та анхнаасаа мэдэх ёстой 7 зүйл

Анхаарна уу. орчуулга.: Английн ASOS.com компанийн хэрэглээний аюулгүй байдлын ахлах инженерийн нийтлэлийн орчуулгыг та бүхэнд толилуулж байна. Үүний тусламжтайгаар тэрээр seccomp ашиглан Кубернетес дэх аюулгүй байдлыг сайжруулахад зориулагдсан цуврал нийтлэлүүдийг эхлүүлж байна. Хэрэв уншигчдад танилцуулга таалагдвал бид зохиогчийг дагаж, энэ сэдвээр түүний цаашдын материалыг үргэлжлүүлэх болно.

Seccomp in Kubernetes: Та анхнаасаа мэдэх ёстой 7 зүйл

Энэ нийтлэл нь ид шид, ид шид хэрэглэхгүйгээр SecDevOps-ийн сүнсээр seccomp профайлыг хэрхэн үүсгэх тухай цуврал нийтлэлүүдийн эхнийх юм. XNUMX-р хэсэгт би Kubernetes-д seccomp-ийг хэрэгжүүлэх үндсэн болон дотоод дэлгэрэнгүй мэдээллийг авч үзэх болно.

Кубернетес экосистем нь савыг хамгаалах, тусгаарлах олон төрлийн аргыг санал болгодог. Энэхүү нийтлэл нь Secure Computing Mode буюу аюулгүй тооцооллын горимын тухай юм секкомпьютер. Үүний мөн чанар нь гүйцэтгэх боломжтой системийн дуудлагуудыг контейнерээр шүүх юм.

Яагаад чухал вэ? Контейнер нь зөвхөн тодорхой машин дээр ажилладаг процесс юм. Мөн бусад програмуудын нэгэн адил цөмийг ашигладаг. Хэрэв контейнерууд ямар нэгэн системийн дуудлага хийх боломжтой байсан бол тун удахгүй хортой програм хангамж нь үүнийг ашиглан контейнер тусгаарлалтыг тойрч, бусад програмуудад нөлөөлнө: мэдээллийг таслах, системийн тохиргоог өөрчлөх гэх мэт.

seccomp профайл нь ямар системийн дуудлагыг зөвшөөрөх эсвэл идэвхгүй болгохыг тодорхойлдог. Контейнерийн ажиллах хугацаа нь эхлэх үед тэдгээрийг идэвхжүүлдэг бөгөөд ингэснээр цөм нь тэдгээрийн гүйцэтгэлийг хянах боломжтой болно. Ийм профайлыг ашиглах нь танд халдлагын векторыг хязгаарлаж, хэрэв контейнер доторх ямар нэгэн програм (өөрөөр хэлбэл таны хамаарал эсвэл тэдгээрийн хамаарал) хийхийг хориглосон зүйлийг хийж эхэлбэл хохирлыг багасгах боломжийг олгоно.

Үндсэн зүйл рүү орох

Үндсэн seccomp профайл нь гурван элементийг агуулдаг: defaultAction, architectures (эсвэл archMap) болон syscalls:

{
    "defaultAction": "SCMP_ACT_ERRNO",
    "architectures": [
        "SCMP_ARCH_X86_64",
        "SCMP_ARCH_X86",
        "SCMP_ARCH_X32"
    ],
    "syscalls": [
        {
            "names": [
                "arch_prctl",
                "sched_yield",
                "futex",
                "write",
                "mmap",
                "exit_group",
                "madvise",
                "rt_sigprocmask",
                "getpid",
                "gettid",
                "tgkill",
                "rt_sigaction",
                "read",
                "getpgrp"
            ],
            "action": "SCMP_ACT_ALLOW"
        }
    ]
}

(дундаж үндсэн-seccomp.json)

defaultAction хэсэгт заагаагүй аливаа системийн дуудлагын анхдагч хувь заяаг тодорхойлдог syscalls. Бүх зүйлийг хөнгөвчлөхийн тулд ашиглах хоёр үндсэн үнэ цэнэд анхаарлаа хандуулцгаая.

  • SCMP_ACT_ERRNO - системийн дуудлагын гүйцэтгэлийг блоклох;
  • SCMP_ACT_ALLOW - зөвшөөрдөг.

хэсэг architectures зорилтот архитектуруудыг жагсаасан болно. Цөмийн түвшинд хэрэглэгдэх шүүлтүүр өөрөө профайлд заасан нэрсээс бус системийн дуудлагын танигчаас хамаардаг тул энэ нь чухал юм. Ашиглахын өмнө контейнер ажиллах хугацаа нь тэдгээрийг танигчтай тааруулна. Системийн дуудлага нь системийн архитектураас хамааран огт өөр ID-тай байж болно гэсэн санаа юм. Жишээлбэл, системийн дуудлага recvfrom (сокетаас мэдээлэл хүлээн авахад ашигладаг) нь x64 систем дээр ID = 64, x517 дээр ID = 86 байна. энд та x86-x64 архитектурын бүх системийн дуудлагын жагсаалтыг олох боломжтой.

хэсэгт syscalls бүх системийн дуудлагуудыг жагсааж, тэдэнтэй юу хийхийг зааж өгнө. Жишээлбэл, та тохируулснаар цагаан жагсаалт үүсгэж болно defaultAction тухай SCMP_ACT_ERRNO, мөн хэсэг дэх дуудлага syscalls томилох SCMP_ACT_ALLOW. Тиймээс та зөвхөн энэ хэсэгт заасан дуудлагыг зөвшөөрнө syscalls, бусад бүх зүйлийг хориглох. Хар жагсаалтын хувьд та утгыг өөрчлөх хэрэгтэй defaultAction болон эсрэг талын үйлдлүүд.

Одоо бид тийм ч тод биш нюансын талаар хэдэн үг хэлэх хэрэгтэй. Доорх зөвлөмжүүд нь таныг Kubernetes дээр бизнесийн шугамын програмуудыг байршуулж байгаа бөгөөд тэдгээрийг аль болох бага давуу эрхтэйгээр ажиллуулахыг хүсэж байгааг анхаарна уу.

1. AllowPrivilegeEscalation=худал

В securityContext саванд параметр байна AllowPrivilegeEscalation. Хэрэв суулгасан бол false, савнууд (-аас эхэлнэ)on) бит no_new_priv. Энэ параметрийн утга нь нэрнээс нь тодорхой харагдаж байна: энэ нь контейнер өөрөөсөө илүү давуу эрх бүхий шинэ процессуудыг эхлүүлэхээс сэргийлдэг.

Энэ тохируулгын гаж нөлөө true (анхдагч) нь контейнер ажиллуулах хугацаа нь эхлүүлэх процессын эхэнд seccomp профайлыг ашигладаг. Тиймээс дотоод ажиллах үеийн процессуудыг ажиллуулахад шаардлагатай бүх системийн дуудлагууд (жишээ нь хэрэглэгч/бүлгийн ID-г тохируулах, тодорхой чадавхийг хасах) профайл дээр идэвхжсэн байх ёстой.

Өчүүхэн зүйл хийдэг сав руу echo hi, дараах зөвшөөрөл шаардлагатай болно:

{
    "defaultAction": "SCMP_ACT_ERRNO",
    "architectures": [
        "SCMP_ARCH_X86_64",
        "SCMP_ARCH_X86",
        "SCMP_ARCH_X32"
    ],
    "syscalls": [
        {
            "names": [
                "arch_prctl",
                "brk",
                "capget",
                "capset",
                "chdir",
                "close",
                "execve",
                "exit_group",
                "fstat",
                "fstatfs",
                "futex",
                "getdents64",
                "getppid",
                "lstat",
                "mprotect",
                "nanosleep",
                "newfstatat",
                "openat",
                "prctl",
                "read",
                "rt_sigaction",
                "statfs",
                "setgid",
                "setgroups",
                "setuid",
                "stat",
                "uname",
                "write"
            ],
            "action": "SCMP_ACT_ALLOW"
        }
    ]
}

(hi-pod-seccomp.json)

... эдгээрийн оронд:

{
    "defaultAction": "SCMP_ACT_ERRNO",
    "architectures": [
        "SCMP_ARCH_X86_64",
        "SCMP_ARCH_X86",
        "SCMP_ARCH_X32"
    ],
    "syscalls": [
        {
            "names": [
                "arch_prctl",
                "brk",
                "close",
                "execve",
                "exit_group",
                "futex",
                "mprotect",
                "nanosleep",
                "stat",
                "write"
            ],
            "action": "SCMP_ACT_ALLOW"
        }
    ]
}

(hi-container-seccomp.json)

Гэхдээ дахин хэлэхэд энэ нь яагаад асуудал болоод байна вэ? Би хувьдаа дараах системийн дуудлагуудыг цагаан жагсаалтад оруулахаас зайлсхийх болно (хэрэв үнэхээр хэрэгцээ байхгүй бол): capset, set_tid_address, setgid, setgroups и setuid. Гэсэн хэдий ч, жинхэнэ сорилт бол танд ямар ч хяналт тавих боломжгүй процессуудыг зөвшөөрснөөр та профайлуудыг контейнерийн ажиллах цагийн хэрэгжилтэд холбож байгаа явдал юм. Өөрөөр хэлбэл, нэг өдөр та контейнер ажиллах орчныг шинэчилсэний дараа (таны эсвэл үүлэн үйлчилгээ үзүүлэгчийн зүгээс) гэнэт ажиллахаа больж байгааг олж мэдэх болно.

Зөвлөлийн дугаар 1: Контейнерүүдийг ажиллуул AllowPrivilegeEscaltion=false. Энэ нь seccomp профайлын хэмжээг багасгаж, тэдгээрийг контейнер ажиллах цагийн орчны өөрчлөлтөд бага мэдрэмтгий болгоно.

2. Савны түвшинд seccomp профайлыг тохируулах

Seccomp профайлыг pod түвшинд тохируулж болно:

annotations:
  seccomp.security.alpha.kubernetes.io/pod: "localhost/profile.json"

... эсвэл савны түвшинд:

annotations:
  container.security.alpha.kubernetes.io/<container-name>: "localhost/profile.json"

Kubernetes seccomp үед дээрх синтакс өөрчлөгдөх болно гэдгийг анхаарна уу GA болно (энэ үйл явдал нь Kubernetes-ийн дараагийн хувилбарт хүлээгдэж байна - 1.18 - ойролцоогоор.).

Кубернетес үргэлж ийм байсан гэдгийг цөөхөн хүн мэддэг алдааЭнэ нь seccomp профайлыг ашиглахад хүргэсэн түр зогсоох сав. Ажиллах орчин нь энэ дутагдлыг хэсэгчлэн нөхдөг боловч энэ контейнер нь дэд бүтцийг нь тохируулахад ашиглагддаг тул савнаас алга болдоггүй.

Асуудал нь энэ сав үргэлж эхэлдэг AllowPrivilegeEscalation=true, 1-р зүйлд дурдсан асуудлуудад хүргэж байгаа бөгөөд үүнийг өөрчлөх боломжгүй.

Савны түвшинд seccomp профайлыг ашигласнаар та энэ бэрхшээлээс зайлсхийж, тодорхой саванд тохируулсан профайлыг үүсгэж болно. Хөгжүүлэгчид алдаагаа засч, шинэ хувилбар (магадгүй 1.18?) хүн бүрт боломжтой болох хүртэл үүнийг хийх шаардлагатай болно.

Зөвлөлийн дугаар 2: Контейнерын түвшинд seccomp профайлыг тохируулах.

Практик утгаараа энэ дүрэм нь ихэвчлэн асуултын бүх нийтийн хариулт болдог: "Миний seccomp профайл яагаад ажилладаг вэ? docker runгэхдээ Kubernetes кластерт байршуулсны дараа ажиллахгүй байна уу?

3. Ажиллах цагийг/өгөгдмөлийг зөвхөн эцсийн арга болгон ашигла

Kubernetes-д суулгасан профайл хийх хоёр сонголт байна: runtime/default и docker/default. Хоёуланг нь Кубернетес биш харин контейнер ажиллах хугацаанд хэрэгжүүлдэг. Тиймээс тэдгээр нь ашигласан ажиллах орчин болон түүний хувилбараас хамаарч өөр өөр байж болно.

Өөрөөр хэлбэл, ажиллах цагийг өөрчилсний үр дүнд контейнер нь ашиглах эсвэл ашиглахгүй байж болох өөр системийн дуудлагуудад хандах боломжтой болно. Ихэнх ажлын цагийг ашигладаг Докерын хэрэгжилт. Хэрэв та энэ профайлыг ашиглахыг хүсвэл энэ нь танд тохирсон эсэхийг шалгана уу.

Хувийн мэдээлэл харж байна docker/default Kubernetes 1.11-ээс хойш хуучирсан тул үүнийг ашиглахаас зайлсхий.

Миний бодлоор профайл runtime/default үүсгэсэн зорилгодоо бүрэн тохирсон: командыг гүйцэтгэхтэй холбоотой эрсдэлээс хэрэглэгчдийг хамгаалах docker run тэдний машинууд дээр. Гэсэн хэдий ч, Kubernetes кластерууд дээр ажилладаг бизнесийн програмуудын тухайд би ийм профайл хэтэрхий нээлттэй бөгөөд хөгжүүлэгчид өөрсдийн хэрэглээний (эсвэл төрлийн програмууд) профайл үүсгэхэд анхаарлаа хандуулах ёстой гэж би маргаж зүрхлэх болно.

Зөвлөлийн дугаар 3: Тодорхой програмуудад зориулсан seccomp профайл үүсгэх. Хэрэв энэ боломжгүй бол програмын төрлүүдэд зориулж профайл үүсгэнэ үү, жишээлбэл, Golang програмын бүх вэб API-г агуулсан дэвшилтэт профайл үүсгэ. Зөвхөн хамгийн сүүлчийн арга болгон ажиллах цаг/өгөгдмөлийг ашиглана уу.

Ирээдүйн нийтлэлүүдэд би SecDevOps-с санаа авсан seccomp профайлыг хэрхэн үүсгэх, тэдгээрийг автоматжуулах, дамжуулах хоолойд турших талаар ярих болно. Өөрөөр хэлбэл, програмын тусгай профайл руу шинэчлэхгүй байх шалтгаан танд байхгүй болно.

4. Хязгааргүй бол сонголт БИШ.

Эхлээд анхны Kubernetes аюулгүй байдлын аудит Энэ нь анхдагчаар болсон seccomp идэвхгүй болсон. Энэ нь хэрэв та тохируулаагүй бол гэсэн үг юм PodSecurityPolicy, энэ нь кластерт үүнийг идэвхжүүлэх бөгөөд seccomp профайл тодорхойлогдоогүй бүх pods-д ажиллах болно. seccomp=unconfined.

Энэ горимд ажиллах нь кластерийг хамгаалдаг тусгаарлагчийн бүхэл давхарга алдагдана гэсэн үг юм. Энэ аргыг аюулгүй байдлын мэргэжилтнүүд зөвлөдөггүй.

Зөвлөлийн дугаар 4: Кластерт ямар ч сав ажиллах ёсгүй seccomp=unconfined, ялангуяа үйлдвэрлэлийн орчинд.

5. "Аудитын горим"

Энэ цэг нь зөвхөн Кубернетесэд хамаарах зүйл биш боловч "эхлэхээсээ өмнө мэдэх ёстой зүйлс" ангилалд багтдаг.

Ийм байдлаар seccomp профайл үүсгэх нь үргэлж сорилттой байсан бөгөөд туршилт, алдаанаас ихээхэн хамаардаг. Баримт нь хэрэглэгчдэд програмыг "унагах" эрсдэлгүйгээр үйлдвэрлэлийн орчинд турших боломж байдаггүй.

Линуксийн цөмийн 4.14 хувилбарыг гаргасны дараа профайлын хэсгүүдийг аудитын горимд ажиллуулж, системийн бүх дуудлагын талаарх мэдээллийг syslog-д бүртгэх боломжтой болсон, гэхдээ тэдгээрийг хаахгүйгээр. Та параметрийг ашиглан энэ горимыг идэвхжүүлж болно SCMT_ACT_LOG:

SCMP_ACT_LOG: seccomp нь шүүлтүүрийн дүрэмд тохирохгүй бол системийн дуудлагыг хийж буй хэлхээнд нөлөөлөхгүй, харин системийн дуудлагын талаарх мэдээллийг бүртгэнэ.

Энэ функцийг ашиглах ердийн стратеги энд байна:

  1. Шаардлагатай системийн дуудлагыг зөвшөөрөх.
  2. Ашиггүй гэдгийг мэддэг системээс дуудлагыг блокло.
  3. Бусад бүх дуудлагын талаарх мэдээллийг бүртгэлд тэмдэглэ.

Хялбаршуулсан жишээ дараах байдалтай байна.

{
    "defaultAction": "SCMP_ACT_LOG",
    "architectures": [
        "SCMP_ARCH_X86_64",
        "SCMP_ARCH_X86",
        "SCMP_ARCH_X32"
    ],
    "syscalls": [
        {
            "names": [
                "arch_prctl",
                "sched_yield",
                "futex",
                "write",
                "mmap",
                "exit_group",
                "madvise",
                "rt_sigprocmask",
                "getpid",
                "gettid",
                "tgkill",
                "rt_sigaction",
                "read",
                "getpgrp"
            ],
            "action": "SCMP_ACT_ALLOW"
        },
        {
            "names": [
                "add_key",
                "keyctl",
                "ptrace"
            ],
            "action": "SCMP_ACT_ERRNO"
        }
    ]
}

(дунд-холимог-seccomp.json)

Гэхдээ та ашиглахгүй, кластерт хор хөнөөл учруулж болзошгүй бүх дуудлагыг хаах хэрэгтэй гэдгийг санаарай. Жагсаалтыг бүрдүүлэх сайн үндэс нь албан ёсны юм Докерын баримт бичиг. Энэ нь анхдагч профайл дээр ямар системийн дуудлагууд хаагдсан, яагаад гэдгийг нарийвчлан тайлбарладаг.

Гэсэн хэдий ч нэг барьц бий. Хэдийгээр SCMT_ACT_LOG 2017 оны сүүлээс хойш Линукс цөмөөр дэмжигдсэн бөгөөд Кубернетес экосистемд харьцангуй саяхан нэвтэрсэн. Тиймээс энэ аргыг ашиглахын тулд танд Linux цөм 4.14 ба runC хувилбараас доошгүй хувилбар хэрэгтэй болно v1.0.0-rc9.

Зөвлөлийн дугаар 5: Хар ба цагаан жагсаалтыг нэгтгэснээр үйлдвэрлэлд туршилт хийх аудитын горимын профайлыг үүсгэж, бүх үл хамаарах зүйлийг бүртгэж болно.

6. Цагаан жагсаалтыг ашиглах

Зөвшөөрөгдсөн жагсаалтад оруулах нь нэмэлт хүчин чармайлт шаарддаг, учир нь та аппликешнд хэрэгтэй байж болох дуудлага бүрийг тодорхойлох шаардлагатай боловч энэ арга нь аюулгүй байдлыг ихээхэн сайжруулдаг:

Илүү энгийн бөгөөд найдвартай тул цагаан жагсаалтын аргыг ашиглахыг зөвлөж байна. Аюултай байж болзошгүй системийн дуудлага (эсвэл хар жагсаалтад байгаа бол аюултай туг/сонголт) нэмэгдэх бүрд хар жагсаалтыг шинэчлэх шаардлагатай болно. Нэмж дурдахад параметрийн дүрслэлийг мөн чанарыг нь өөрчлөхгүйгээр өөрчлөх боломжтой бөгөөд ингэснээр хар жагсаалтын хязгаарлалтыг тойрч гарах боломжтой.

Go програмуудын хувьд би програмыг дагалдаж, гүйцэтгэх явцад хийсэн бүх дуудлагыг цуглуулдаг тусгай хэрэгсэл боловсруулсан. Жишээлбэл, дараах програмын хувьд:

package main

import "fmt"

func main() {
	fmt.Println("test")
}

... эхлүүлцгээе gosystract тийм:

go install https://github.com/pjbgf/gosystract
gosystract --template='{{- range . }}{{printf ""%s",n" .Name}}{{- end}}' application-path

... мөн бид дараах үр дүнг авна.

"sched_yield",
"futex",
"write",
"mmap",
"exit_group",
"madvise",
"rt_sigprocmask",
"getpid",
"gettid",
"tgkill",
"rt_sigaction",
"read",
"getpgrp",
"arch_prctl",

Одоохондоо энэ бол зүгээр л нэг жишээ бөгөөд хэрэглүүрүүдийн талаарх дэлгэрэнгүй мэдээллийг дагаж мөрдөх болно.

Зөвлөлийн дугаар 6: Зөвхөн танд үнэхээр хэрэгтэй байгаа дуудлагуудыг зөвшөөрч, бусад бүх дуудлагыг блокло.

7. Зөв суурийг тавих (эсвэл гэнэтийн зан үйлд бэлтгэх)

Цөм нь таны бичсэн зүйлээс үл хамааран профайлыг хэрэгжүүлэх болно. Хэдийгээр энэ нь таны хүссэн зүйл биш байсан ч гэсэн. Жишээлбэл, хэрэв та дуудлагад хандах хандалтыг хаасан бол exit буюу exit_group, чингэлэг нь зөв унтрах боломжгүй, тэр ч байтугай энгийн тушаал гэх мэт echo hi түүнийг өлгөo тодорхойгүй хугацаагаар. Үүний үр дүнд та кластерт CPU-ийн өндөр хэрэглээг авах болно:

Seccomp in Kubernetes: Та анхнаасаа мэдэх ёстой 7 зүйл

Ийм тохиолдолд хэрэгсэл нь аврах ажилд ирж болно strace - Энэ нь ямар асуудал байж болохыг харуулах болно:

Seccomp in Kubernetes: Та анхнаасаа мэдэх ёстой 7 зүйл
sudo strace -c -p 9331

Профайлууд нь програмын ажиллах үед шаардлагатай бүх системийн дуудлагуудыг агуулж байгаа эсэхийг шалгаарай.

Зөвлөлийн дугаар 7: Нарийвчилсан мэдээлэлд анхаарлаа хандуулж, шаардлагатай бүх системийн дуудлагуудыг цагаан жагсаалтад оруулсан эсэхийг шалгаарай.

Энэ нь SecDevOps-ийн сүнсээр Kubernetes-д seccomp ашиглах тухай цуврал нийтлэлийн эхний хэсгийг дуусгаж байна. Дараах хэсгүүдэд энэ нь яагаад чухал вэ, үйл явцыг хэрхэн автоматжуулах талаар ярилцах болно.

Орчуулагчийн жич

Мөн манай блог дээрээс уншина уу:

Эх сурвалж: www.habr.com

сэтгэгдэл нэмэх