امنیت در Kubernetes – بخش اول
یکی از موارد مهم در امنیت کوبرنتیز بحث مربوط به secretها در کوبرنتیز است. در این مقاله به معرفی object مربوط به secret و انواع آن با ذکر مثالهای مختلف خواهیم پرداخت
موارد و مولفههای زیادی در امنیت کوبرنتیز دارای اهمیت هستند، یکی از موارد مهم در امنیت کوبرنتیز بحث مربوط به secretها در کوبرنتیز است. در این مقاله به معرفی object مربوط به secret و انواع آن با ذکر مثالهای مختلف خواهیم پرداخت. قطعا مطالعه این مقاله برای به کارگیری و استفاده از آن نیازمند آشنایی با داکر و کوبرنتیز است که در مقالههای مختلف آکادمیابری به آنها پرداخته شده است.
Object مربوط به secret در kubernetes
Secret در کوبرنتیز به ما اجازه میدهد تا اطلاعات حساس خود را مدیریت و ذخیره کنیم. اطلاعات حساس و مهمیمانند passwordها و OAuth tokens و کلید SSH را میتوان در secret تعریف و نگهداری کرد. ذخیره سازی اطلاعات محرمانه در secret نسبت به قرار دادن کلمه به کلمه آن در ساختار pod یا image کانتینر امنتر و انعطاف پذیرتر است. در این مقاله به معماری و طراحیهای مختلف Secret در کوبرنتیز خواهیم پرداخت.
Secret در Kubernetes مفهومیبه نام Object است که شامل اطلاعاتی حساسی از قبیل رمز وToken و کلید (Key) است. اگر این اطلاعات حساس و مهم نبودند میتوانستیم آنها را در ساختار Podهای کوبرنتیز یا imageهایی که Deploy میکنیم پیاده سازی کنیم.
برای استفاده ایمن از Secretها تیم کوبرنتیز موارد زیر را توصیه کرده است
1-رمز نگاری secretها با استفاده از kind به نام EncryptionConfiguration در ساختار yaml (فعال کردن Enable Encryption at Rest برای secretها )
با استفاده از Kind به نام EncryptionConfiguration میتوان secretها و دادهها را رمز نگاری کرد که در نمونه yaml زیر میتوان به مثالی در این خصوص اشاره کرد.
apiVersion: apiserver. config. k8s. io/v1 kind: EncryptionConfiguration resources: - resources: - secrets providers: - identity: {} - aesgcm: keys: - name: key1 secret: c2VjcmV0IGlzIHNlY3VyZQ== - name: key2 secret: dGhpcyBpcyBwYXNzd29yZA== - aescbc: keys: - name: key1 secret: c2VjcmV0IGlzIHNlY3VyZQ== - name: key2 secret: dGhpcyBpcyBwYXNzd29yZA== - secretbox: keys: - name: key1 secret: YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoxMjM0NTY=
2-فعال کردن و استفاده از configure RBAC rules
میتوان خواندن و نوشتن Secretها را با این قابلیت محدود کرد، Secretها میتوانند توسط هر شخصی که دسترسی به ایجاد کردن Podها را داشته باشد، به دست آورده شود.
استفاده و فراخوانی از Secret در kindهای مختلف
Secret-1 میتواند در یک یا چندین کانتینر به عنوان فایل در volumeهای mount شده kubernetes مورد استفاده قرار گرفته شود.(در قسمت دوم مقاله مثالها ارائه خواهد شد )
2-Secret میتواند به عنوان environment variable در کانتینرها مورد استفاده قرار گرفته شود. (در قسمت دوم مقاله مثالها ارائه خواهد شد )
3-Secret میتواند توسط Kubelet زمانیکه در حال Pull کردن imageها برای Pod است، استفاده شود. (در قسمت دوم مقاله مثالها ارائه خواهد شد )
نام secret باید valid و معتبر و مطابق با ساختار نام گذاری DNS subdomain name باشد. که ساختار این نامگذاری در RFC 1123 مشخص شده است. در ساختار yaml فایلها که Kind آنها secret باشد دو فیلد به نامهای stringData و data وجود دارند که میتوان از آنها استفاده کرد. استفاده از این فیلدها اختیاری و بر حسب نیاز است. تمام مقادیر و کلیدهایی که برای فیلد data مورد استفاده قرار میگیرند میبایست به صورت base64-encoded شده باشند و در صورتیکه تمایل به base64-encoded کردن دیتاها نداشته باشیم میتوانیم از فیلد stringData در ساختار yaml خود بهرهمند شویم. دیتا و اطلاعات موجود در فیلدهای Data و stringData باید از نوع alphanumeric و شامل – (dash) و _ (under line) و یا. (dot) باشند. اگر یک KEY یکسان در فیلدهای stringData و data تعریف شده باشند، مقادیر stringData دارای الویت است. زمانیکه میخواهیم secret ایجاد کنیم (ساختار yaml با kind از نوع secretداشته باشیم) میتوانیم نوع Secret خود را در فیلدی به نام type مشخص کنیم. به عبارتی دیگر secretهای دارای typeهای مختلفی هستند، typeهای مختلف در secret با توجه به نوع نیاز استفاده از آن میتوانند مورد استفاده قرار گرفته شوند. کوبرنتیز برای استفاده از سناریوهای مختلف رایج typeهای مختلفی برای secret معرفی کرده است که بسته به نیاز میتوان از هر یک استفاده کرد که محدودیتها و validationsهای کوبرنتیز برای هر type استفاده شده در secret متفاوت است. در جدول زیر میتوانیم typeهای مختلف secret در کوبرنتیز را مشاهده کنیم.
نکته : بر حسب نیاز در صورتیکه بخواهیم محتویاتی را به base64 کد کنیم و در فیلد string مربوط به secret خود قرار دهیم میتوانیم با کمک دستور echo محتویات فایل خود را base64 کنیم.
echo -n "password" | base64
در خروجی کامند بالا عبارت password به صورت base64 کد خواهد شد. که خروجی آن مطابق با تصویر زیر است.
کوبرنتیز محدودیتی در نام گذاری secretها ندارد اما با توجه به اینکه از چه type از secretها استفاده میکنیم میبایست الزمات و syntax مربوط به آن type را در ساختار yaml مربوط به secret خود رعایت کنیم.
شرح انواع مختلف secret درKubernetes
Opaque
ما در کوبرنتیز میتوانیم usage های مشخص شدهای با تعریف secret از نوع Opaque داشته باشیم.
برای انجام این کار با کامند Kubectl به صورت زیر اقدام میکنیم.
kubectl create secret generic empty-secret
با توجه به استفاده از subcommand مربوط به generic نوع یا type مربوط به secret ایجاد شده Opaque خواهد بود که با کامند زیر میتوانیم اطلاعات secret ایجاد شده خود را مشاهده کنیم.
kubectl get secret empty-secret
همانطور که در خروجی کامند زیر مشخص است type مربوط به secret ایجاد شده Opaque است.
NAME TYPE DATA AGE empty-secret Opaque 0 2m6s service account secret kubernetes. io/service-account-token
این نوع secret برای ذخیره سازی token جهت شناسایی service account در کوبرنتیز مورد استفاده قرار گرفته میشود. زمانیکه از این نوع secret استفاده میکنیم باید اطمینان حاصل کنیم که annotation مشخصی در ساختار yaml آن استفاده شده باشد. این نوع secret حتما میبایست ازannotation که مقدار دقیق آن kubernetes. io/service-account. name است استفاده کرده باشد که value دقیق آن نیز میبایست هم نام با سرویس اکانتی باشد که برای آن secret تعریف کردهایم.
به عنوان مثال ما یک سرویس اکانت به نام xaas ایجاد کرده ایم که میخواهیم برای این سرویس اکانت secret از نوع
kubernetes. io/service-account-token
ایجاد کنیم. حتما میبایست در این secret مقدارannotation معادل زیر را داشته باشیم.
kubernetes. io/service-account. name: "xaas"
نمونه yaml زیر یک مثال برای ایجاد secret به جهت استفاده برای سرویس اکانتی به نام xaas است.
apiVersion: v1 kind: Secret metadata: name: secret-xaas-sample annotations: kubernetes. io/service-account. name: "xaas" type: kubernetes. io/service-account-token data: # You can include additional key value pairs as you do with Opaque Secrets extra: YmFyCg==
زمانیکه در کوبرنتیز یک pod ساخته میشود کوبرنتیز به صورت اتوماتیک یک service account Secret ایجاد میکند و به صورت اتومات پاد ایجاد شده از secret ایجاد شده استفاده خواهد کرد.
service account token Secret شامل credentials برای دسترسی به API کوبرنتیز است.
عملکرد و کاربردهای سرویس اکانت و service account token نیز در مقالات آینده مورد بررسی قرار خواهد گرفت.
Docker config Secrets
دو نوع type مربوط به secret در کوبرنتیز وجود دارد که از آنها برای ذخیره سازی credentials جهت دسترسی داکر رجیستری برای image استفاده میشود.
kubernetes. io/dockercfg1-
زمانی که از این نوع secret استفاده میکنیم میبایست مطمئن باشیم که مقادیر فیلد data شامل کلید. dockercfg به صورت رمز نگاری base64 در فایل dockercfg باشند.
kubernetes. io/dockerconfigjson2-
فرمت جدید مورد استفاده است که به صورت json است و محتوای فیلد data از رمز نگاری base64 استفاده میکند.
نمونه زیر ساختار yaml برای secret مربوط به docker است.
apiVersion: v1 kind: Secret metadata: name: secret-dockercfg type: kubernetes. io/dockercfg data: . dockercfg: | ""
همانطور که در مثال مشخص است مسیر فایل حاوری secret با رمزگاری base64 در آن استفاده شده است. در صورتیکه تمایل به رمزنگاری نداشتیم باشیم میتوانیم به جای فیلد data از stringDataاستفاده کنیم.
هنگامیکه از این نوع manifest در ساختار yaml فایلهای خود استفاده میکنیم API سرور بررسی میکند که آیا کلید مود انتظار در فیلد data وجود دارد یا خیر.
درصورتی که فایل داکری حاوی secret موجود نباشد و یا به هر دلیلی نیاز به ساخت secret به صورت کامندی باشد میتوانیم طبق مثال زیر اقدام به Docker registry Secret نماییم.
kubectl create secret docker-registry secret-tiger-docker \ --docker-username=tiger \ --docker-password=pass113 \ --docker-email=tiger@acme. com
در قسمت دوم مقاله که به زودی منتشر خواهد شد به ادامه معرفی typeهای secret با ذکر مثال خواهیم پرداخت.