|
| 1 | +--- |
| 2 | +reviewers: |
| 3 | +- xirehat |
| 4 | +title: محدود کردن دسترسی کانتینر به منابع با AppArmor |
| 5 | +content_type: tutorial |
| 6 | +weight: 30 |
| 7 | +--- |
| 8 | + |
| 9 | +<!-- overview --> |
| 10 | + |
| 11 | +{{< feature-state feature_gate_name="AppArmor" >}} |
| 12 | + |
| 13 | +این صفحه به شما نشان میدهد که چگونه پروفایلهای AppArmor را روی گرههای خود بارگذاری کنید و آن پروفایلها را در Pods اعمال کنید. برای کسب اطلاعات بیشتر در مورد اینکه چگونه Kubernetes میتواند Pods را با استفاده از AppArmor محدود کند، به [محدودیتهای امنیتی هسته لینوکس برای پادها و کانتینرها](/docs/concepts/security/linux-kernel-security-constraints/#apparmor) مراجعه کنید. |
| 14 | + |
| 15 | +## {{% heading "objectives" %}} |
| 16 | + |
| 17 | + |
| 18 | +* مثالی از نحوه بارگذاری یک پروفایل در یک گره را ببینید |
| 19 | +* یاد بگیرید که چگونه پروفایل را در یک پاد اجرا کنید |
| 20 | +* یاد بگیرید که چگونه بررسی کنید که پروفایل بارگذاری شده است |
| 21 | +* ببینید چه اتفاقی میافتد وقتی یک پروفایل نقض میشود |
| 22 | +* ببینید چه اتفاقی میافتد وقتی یک پروفایل نمیتواند بارگذاری شود |
| 23 | + |
| 24 | + |
| 25 | +## {{% heading "prerequisites" %}} |
| 26 | + |
| 27 | + |
| 28 | +AppArmor یک ماژول اختیاری هسته و قابلیتی در کوبرنتیز است؛ بنابراین پیش از ادامه، مطمئن شوید که روی |
| 29 | +گرههای شما پشتیبانی میشود: |
| 30 | + |
| 31 | +1. ماژول هسته AppArmor فعال است — برای آنکه هسته لینوکس بتواند یک پروفایل AppArmor را اعمال کند، |
| 32 | + ماژول هسته AppArmor باید نصب و فعال باشد. چندین توزیع این ماژول را بهصورت پیشفرض فعال میکنند، |
| 33 | + مانند Ubuntu و SUSE، و بسیاری دیگر پشتیبانی اختیاری ارائه میدهند. برای بررسی فعال بودن ماژول، |
| 34 | + فایل `/sys/module/apparmor/parameters/enabled` را بررسی کنید: |
| 35 | + |
| 36 | + ```shell |
| 37 | + cat /sys/module/apparmor/parameters/enabled |
| 38 | + Y |
| 39 | + ``` |
| 40 | + |
| 41 | + kubelet پیش از پذیرش پادی که بهطور صریح با AppArmor پیکربندی شده باشد، |
| 42 | + بررسی میکند که AppArmor روی میزبان فعال باشد. |
| 43 | + |
| 44 | +1. زمان اجرای کانتینر از AppArmor پشتیبانی میکند — همهٔ زماناجرایهای کانتینری |
| 45 | + متداول که کوبرنتیز پشتیبانی میکند باید از AppArmor پشتیبانی کنند، از جمله |
| 46 | + {{< glossary_tooltip term_id="containerd" >}} و |
| 47 | + {{< glossary_tooltip term_id="cri-o" >}}. لطفاً به مستندات زمانِ اجرای مربوطه |
| 48 | + مراجعه کرده و اطمینان حاصل کنید که کلاستر شرایط لازم برای استفاده از AppArmor |
| 49 | + را دارد. |
| 50 | + |
| 51 | +1. پروفایل بارگذاری شده است — AppArmor با مشخصکردن پروفایل AppArmor برای هر |
| 52 | + کانتینر روی یک پاد اعمال میشود. اگر هر یک از پروفایلهای تعیینشده در هسته |
| 53 | + بارگذاری نشده باشد، kubelet پاد را رد میکند. میتوانید با بررسی فایل |
| 54 | + `/sys/kernel/security/apparmor/profiles` ببینید کدام پروفایلها روی یک گره |
| 55 | + بارگذاری شدهاند. برای مثال: |
| 56 | + |
| 57 | + ```shell |
| 58 | + ssh gke-test-default-pool-239f5d02-gyn2 "sudo cat /sys/kernel/security/apparmor/profiles | sort" |
| 59 | + ``` |
| 60 | + ``` |
| 61 | + apparmor-test-deny-write (enforce) |
| 62 | + apparmor-test-audit-write (enforce) |
| 63 | + docker-default (enforce) |
| 64 | + k8s-nginx (enforce) |
| 65 | + ``` |
| 66 | + |
| 67 | + برای جزئیات بیشتر دربارهٔ بارگذاری پروفایلها روی گرهها، به |
| 68 | + [راهاندازی گرهها با پروفایل](#setting-up-nodes-with-profiles) مراجعه کنید. |
| 69 | + |
| 70 | +<!-- lessoncontent --> |
| 71 | + |
| 72 | +## ایمنسازی یک پاد |
| 73 | + |
| 74 | +{{< note >}} |
| 75 | +پیش از Kubernetes نسخهٔ v1.30، AppArmor از طریق annotationها مشخص میشد. با استفاده از انتخابگر نسخهٔ |
| 76 | +مستندات، میتوانید مستندات مربوط به این API منسوخشده را مشاهده کنید. |
| 77 | +{{< /note >}} |
| 78 | + |
| 79 | +پروفایلهای AppArmor را میتوان در سطح pod یا سطح container مشخص کرد. پروفایل AppArmor کانتینر بر پروفایل pod اولویت دارد. |
| 80 | + |
| 81 | +```yaml |
| 82 | +securityContext: |
| 83 | + appArmorProfile: |
| 84 | + type: <profile_type> |
| 85 | +``` |
| 86 | +
|
| 87 | +در اینجا مقدار `<profile_type>` میتواند یکی از گزینههای زیر باشد: |
| 88 | + |
| 89 | +* `RuntimeDefault` برای استفاده از پروفایل پیشفرض زماناجرا |
| 90 | +* `Localhost` برای استفاده از پروفایلی که روی میزبان بارگذاری شده است (نگاه کنید به پایین) |
| 91 | +* `Unconfined` برای اجرا بدون AppArmor |
| 92 | + |
| 93 | +برای آگاهی از جزئیات کامل API پروفایل AppArmor، به |
| 94 | +[مشخصکردن محدودسازی AppArmor](#specifying-apparmor-confinement) مراجعه کنید. |
| 95 | + |
| 96 | +برای اطمینان از اینکه پروفایل اعمال شده است، میتوانید با بررسی ویژگی proc |
| 97 | +فرآیند ریشهٔ کانتینر، ببینید که با پروفایل درست اجرا میشود: |
| 98 | + |
| 99 | +```shell |
| 100 | +kubectl exec <pod_name> -- cat /proc/1/attr/current |
| 101 | +``` |
| 102 | + |
| 103 | +خروجی باید چیزی شبیه به این باشد: |
| 104 | + |
| 105 | +``` |
| 106 | +cri-containerd.apparmor.d (enforce) |
| 107 | +``` |
| 108 | + |
| 109 | +## مثال |
| 110 | + |
| 111 | +*این مثال فرض میکند که شما قبلاً کلاستری با پشتیبانی از AppArmor راهاندازی کردهاید.* |
| 112 | + |
| 113 | +ابتدا، پروفایلی را که میخواهید استفاده کنید روی گرههای خود بارگذاری کنید. این پروفایل همهٔ عملیات نوشتن روی فایل را مسدود میکند: |
| 114 | + |
| 115 | +``` |
| 116 | +#include <tunables/global> |
| 117 | +
|
| 118 | +profile k8s-apparmor-example-deny-write flags=(attach_disconnected) { |
| 119 | + #include <abstractions/base> |
| 120 | +
|
| 121 | + file, |
| 122 | +
|
| 123 | + # Deny all file writes. |
| 124 | + deny /** w, |
| 125 | +} |
| 126 | +``` |
| 127 | + |
| 128 | +پروفایل باید روی همه گرهها بارگذاری شود، زیرا نمیدانید پاد در کدام گره زمانبندی خواهد شد. |
| 129 | +در این مثال میتوانید از SSH برای نصب پروفایلها استفاده کنید، اما رویکردهای دیگری نیز |
| 130 | +در [راهاندازی گرهها با پروفایل](#setting-up-nodes-with-profiles) مطرح شدهاند. |
| 131 | + |
| 132 | +```shell |
| 133 | +# این مثال فرض میکند که نام گرهها با نام میزبانها مطابقت دارد و از طریق SSH قابل دسترسی هستند. |
| 134 | +NODES=($( kubectl get node -o jsonpath='{.items[*].status.addresses[?(.type == "Hostname")].address}' )) |
| 135 | +
|
| 136 | +for NODE in ${NODES[*]}; do ssh $NODE 'sudo apparmor_parser -q <<EOF |
| 137 | +#include <tunables/global> |
| 138 | +
|
| 139 | +profile k8s-apparmor-example-deny-write flags=(attach_disconnected) { |
| 140 | + #include <abstractions/base> |
| 141 | +
|
| 142 | + file, |
| 143 | +
|
| 144 | + # Deny all file writes. |
| 145 | + deny /** w, |
| 146 | +} |
| 147 | +EOF' |
| 148 | +done |
| 149 | +``` |
| 150 | + |
| 151 | +سپس، یک پاد سادهی "Hello AppArmor" را با پروفایل deny-write اجرا کنید: |
| 152 | + |
| 153 | +{{% code_sample file="pods/security/hello-apparmor.yaml" %}} |
| 154 | + |
| 155 | +```shell |
| 156 | +kubectl create -f hello-apparmor.yaml |
| 157 | +``` |
| 158 | + |
| 159 | +شما میتوانید با بررسی `/proc/1/attr/current` تأیید کنید که کانتینر واقعاً با آن پروفایل در حال اجرا است: |
| 160 | + |
| 161 | +```shell |
| 162 | +kubectl exec hello-apparmor -- cat /proc/1/attr/current |
| 163 | +``` |
| 164 | + |
| 165 | +خروجی باید این باشد: |
| 166 | +``` |
| 167 | +k8s-apparmor-example-deny-write (enforce) |
| 168 | +``` |
| 169 | + |
| 170 | +در نهایت، میتوانید ببینید اگر با نوشتن در یک فایل، پروفایل را نقض کنید چه اتفاقی میافتد: |
| 171 | + |
| 172 | +```shell |
| 173 | +kubectl exec hello-apparmor -- touch /tmp/test |
| 174 | +``` |
| 175 | +``` |
| 176 | +touch: /tmp/test: Permission denied |
| 177 | +error: error executing remote command: command terminated with non-zero exit code: Error executing in Docker Container: 1 |
| 178 | +``` |
| 179 | +
|
| 180 | +برای جمعبندی، ببینید اگر سعی کنید نمایهای را مشخص کنید که بارگذاری نشده است، چه اتفاقی میافتد: |
| 181 | +
|
| 182 | +```shell |
| 183 | +kubectl create -f /dev/stdin <<EOF |
| 184 | +apiVersion: v1 |
| 185 | +kind: Pod |
| 186 | +metadata: |
| 187 | + name: hello-apparmor-2 |
| 188 | +spec: |
| 189 | + securityContext: |
| 190 | + appArmorProfile: |
| 191 | + type: Localhost |
| 192 | + localhostProfile: k8s-apparmor-example-allow-write |
| 193 | + containers: |
| 194 | + - name: hello |
| 195 | + image: busybox:1.28 |
| 196 | + command: [ "sh", "-c", "echo 'Hello AppArmor!' && sleep 1h" ] |
| 197 | +EOF |
| 198 | +``` |
| 199 | +``` |
| 200 | +pod/hello-apparmor-2 created |
| 201 | +``` |
| 202 | + |
| 203 | +اگرچه Pod با موفقیت ایجاد شد، بررسی بیشتر نشان میدهد که در وضعیت pending گیر کرده است: |
| 204 | + |
| 205 | +```shell |
| 206 | +kubectl describe pod hello-apparmor-2 |
| 207 | +``` |
| 208 | +``` |
| 209 | +Name: hello-apparmor-2 |
| 210 | +Namespace: default |
| 211 | +Node: gke-test-default-pool-239f5d02-x1kf/10.128.0.27 |
| 212 | +Start Time: Tue, 30 Aug 2016 17:58:56 -0700 |
| 213 | +Labels: <none> |
| 214 | +Annotations: container.apparmor.security.beta.kubernetes.io/hello=localhost/k8s-apparmor-example-allow-write |
| 215 | +Status: Pending |
| 216 | +... |
| 217 | +Events: |
| 218 | + Type Reason Age From Message |
| 219 | + ---- ------ ---- ---- ------- |
| 220 | + Normal Scheduled 10s default-scheduler Successfully assigned default/hello-apparmor to gke-test-default-pool-239f5d02-x1kf |
| 221 | + Normal Pulled 8s kubelet Successfully pulled image "busybox:1.28" in 370.157088ms (370.172701ms including waiting) |
| 222 | + Normal Pulling 7s (x2 over 9s) kubelet Pulling image "busybox:1.28" |
| 223 | + Warning Failed 7s (x2 over 8s) kubelet Error: failed to get container spec opts: failed to generate apparmor spec opts: apparmor profile not found k8s-apparmor-example-allow-write |
| 224 | + Normal Pulled 7s kubelet Successfully pulled image "busybox:1.28" in 90.980331ms (91.005869ms including waiting) |
| 225 | +``` |
| 226 | + |
| 227 | +یک رویداد، پیام خطا را به همراه دلیل آن ارائه میدهد، که نحوهی بیان آن وابسته به زمان اجرا است: |
| 228 | +``` |
| 229 | + Warning Failed 7s (x2 over 8s) kubelet Error: failed to get container spec opts: failed to generate apparmor spec opts: apparmor profile not found |
| 230 | +``` |
| 231 | + |
| 232 | +## اداره کردن |
| 233 | + |
| 234 | +### راهاندازی گرهها با پروفایلها |
| 235 | + |
| 236 | +Kubernetes {{< skew currentVersion >}} هیچ سازوکار داخلی برای بارگذاری پروفایلهای AppArmor روی |
| 237 | +گرهها در اختیار نمیگذارد. میتوان پروفایلها را از طریق زیرساخت سفارشی یا ابزارهایی مانند |
| 238 | +[Kubernetes Security Profiles Operator](https://github.com/kubernetes-sigs/security-profiles-operator) |
| 239 | +بارگذاری کرد. |
| 240 | + |
| 241 | +زمانبند از اینکه کدام پروفایل روی کدام گره بارگذاری شده است آگاه نیست؛ بنابراین مجموعهٔ کامل |
| 242 | +پروفایلها باید روی هر گره بارگذاری شود. رویکرد جایگزین این است که برای هر پروفایل (یا دستهای |
| 243 | +از پروفایلها) یک برچسب گره اضافه کنید و با استفاده از |
| 244 | +[node selector](/docs/concepts/scheduling-eviction/assign-pod-node/) |
| 245 | +اطمینان حاصل کنید که پاد روی گرهای اجرا شود که پروفایل مورد نیاز را دارد. |
| 246 | + |
| 247 | +## ایجاد پروفایلها |
| 248 | + |
| 249 | +دریافت و مشخصکردن صحیح پروفایلهای AppArmor میتواند کار دشواری باشد. خوشبختانه ابزارهایی برای کمک به این کار وجود دارد: |
| 250 | + |
| 251 | +* `aa-genprof` و `aa-logprof` با نظارت بر فعالیت برنامه و لاگها، قوانین پروفایل را ایجاد کرده و اقداماتی را که انجام میشود مجاز میکنند. دستورالعملهای بیشتر در [مستندات AppArmor](https://gitlab.com/apparmor/apparmor/wikis/Profiling_with_tools) ارائه شده است. |
| 252 | +* [bane](https://github.com/jfrazelle/bane) یک تولیدکنندهٔ پروفایل AppArmor برای Docker است که از زبان پروفایل سادهشده استفاده میکند. |
| 253 | + |
| 254 | +برای اشکالزدایی مشکلات AppArmor میتوانید لاگهای سیستم را بررسی کنید تا ببینید دقیقاً چه عملی رد شده است. AppArmor پیامهای مفصلی را در `dmesg` ثبت میکند و خطاها معمولاً در لاگهای سیستم یا از طریق `journalctl` قابل یافتن هستند. اطلاعات بیشتر در [خرابیهای AppArmor](https://gitlab.com/apparmor/apparmor/wikis/AppArmor_Failures) موجود است. |
| 255 | + |
| 256 | + |
| 257 | +## مشخصکردن محدودسازی AppArmor |
| 258 | + |
| 259 | +{{< caution >}} |
| 260 | +پیش از Kubernetes نسخهٔ v1.30، AppArmor از طریق annotationها مشخص میشد. با استفاده از انتخابگر نسخهٔ مستندات میتوانید مستندات مربوط به این API منسوخشده را مشاهده کنید. |
| 261 | +{{< /caution >}} |
| 262 | + |
| 263 | +### پروفایل AppArmor درون securityContext {#appArmorProfile} |
| 264 | + |
| 265 | +میتوانید `appArmorProfile` را در `securityContext` یک کانتینر یا در `securityContext` یک پاد مشخص کنید. |
| 266 | +اگر پروفایل در سطح پاد تنظیم شود، بهعنوان پروفایل پیشفرض برای همهٔ کانتینرهای پاد (شامل init، sidecar و ephemeral containerها) به کار میرود. |
| 267 | +اگر هم در سطح پاد و هم در سطح کانتینر پروفایل AppArmor تعیین شده باشد، پروفایل کانتینر ملاک خواهد بود. |
| 268 | + |
| 269 | +یک پروفایل AppArmor دو فیلد دارد: |
| 270 | + |
| 271 | +`type` _(required)_ — تعیین میکند چه نوع پروفایل AppArmor اعمال خواهد شد. گزینههای معتبر: |
| 272 | + |
| 273 | +`Localhost` |
| 274 | +: پروفایلی که از پیش روی گره بارگذاری شده است (بهوسیلهٔ `localhostProfile` مشخص میشود). |
| 275 | + |
| 276 | +`RuntimeDefault` |
| 277 | +: پروفایل پیشفرض زماناجرای کانتینر. |
| 278 | + |
| 279 | +`Unconfined` |
| 280 | +: بدون اِعمال محدودیتهای AppArmor. |
| 281 | + |
| 282 | +`localhostProfile` — نام پروفایلی که روی گره بارگذاری شده و باید استفاده شود. |
| 283 | +پروفایل باید از پیش روی گره پیکربندی شده باشد. این گزینه دقیقاً زمانی باید ارائه شود که مقدار `type` برابر `Localhost` باشد. |
| 284 | + |
| 285 | + |
| 286 | +## {{% heading "whatsnext" %}} |
| 287 | + |
| 288 | +منابع بیشتر: |
| 289 | + |
| 290 | +* [راهنمای سریع زبان پروفایل AppArmor](https://gitlab.com/apparmor/apparmor/wikis/QuickProfileLanguage) |
| 291 | +* [مرجع سیاستهای اصلی AppArmor](https://gitlab.com/apparmor/apparmor/wikis/Policy_Layout) |
0 commit comments