چگونه با استفاده از Gitops به طور حرفه‌ای Secret ها را مدیریت کنیم

تهیه‌کننده مقاله : تیم دواپس

دسته بندی: دواپس
12 دقیقه زمان مطالعه
1400/12/18
1 نظر

یکی از زیرساختهای اصلی GitOps، استفاده از Git به عنوان source در کل سیستم است. بسیاری از برنامه نویسها با نحوه ذخیره سازی پروژه و source code در گیت آشنایی دارند اما GitOps حکم می‌کند که شما باید تمامی بخشهای اپلیکیشن خود مانند تنظیمات kubernetes manifests, db scripts, cluster definitions و… را نیز ذخیره کنید.
اما درباره secret چطور؟چگونه می‌توان با کمک GitOps از secret ها استفاده کرد؟  این سوال یکی از سوالات معروف تیم هایی است که از GitOps استفاده می‌کنند.
حقیقت این است که هیچ روش خاص یا روش واحدی برای مدیریت secret ها در GitOps وجود ندارد. اگر شما یک روش خوب و محکم مانند HashiCrop vault دارید، پس منطقی است که از آن استفاده کنید، حتی اگر از نظر فنی مخالف GitOps باشد.
اگر شما پروژه جدیدی را شروع می‌کنید، راه‌هایی وجود دارد که بتوانید secret ها را در Git ذخیره کنید و در عین حال می‌توانید آنها را با استفاده از GitOps principles مدیریت کنید. ناگفته نماند که هرگز نباید raw secrets ها در گیت commit شود.
تمامی راه حل‌هایی که secret ها را مدیریت می‌کنند، در اصل آن‌ها را در Git به صورت encrypt ذخیره می‌کنند secretها می‌توانند با GitOps مدیریت شوند و همین طور می‌شود آن‌ها را به صورت ایمن در داخل هر Git repository (حتی در repository های public ) قرار داد.

روش کار kubernetes secrets

در این مقاله ما در مورد دو نوع secrets صحبت خواهیم کرد؛  یکی built-in Kubernetes secrets (که در تمامی خوشه‌های Kubernetes وجود دارد) و دیگری اسرار مهر و موم شده‌ای، که توسط Bitnami Sealed secrets controller معرفی شد.
قبل از این که بخواهیم درمورد Sealed secrets صحبت کنیم اجازه دهید ابتدا در مورد plain secrets صحبت کنیم. در درون Kubernetes، یک منبع بومی secrets وجود دارد که شما می‌توانید از آن در اپلیکیشن خود استفاده کنید. به طور پیش‌فرض این secrets ها به هیچ وجه رمزگذاری (encrypted) نمی‌شوند و رمزگذاری‌هایی که بر مبنای base64 استفاده شده  است، هرگز نباید به عنوان ویژگی امنیتی در نظر گرفته شوند. با این  که راه‌هایی وجود دارند تا بتوان Kubernetes secrets ها را در کلاستر رمزگذاری  کرد، ما توصیه می‌کنیم که آن‌ها را بیرون از cluster ذخیره کنید، زیرا شما می‌توانید آنها را خارج از cluster در گیت ذخیره کنید، که این مطابق با یکی از اصول GitOps است  (همه چیز در Git ذخیره می‌شود).
استفاده از Kubernetes secrets بسیار راحت و آسان است. شما می‌توانید از مکانیزم‌های مشابهی مانند configmap استفاده و آن‌ها را به عنوان فایل در اپلیکیشن خود نصب ، یا به عنوان متغیر  در محیط خود ارسال کنید.
 
Sealed secrets ها فقط به عنوان یک extension در بالای Kubernetes قرار دارند . به این معنی که بعد از encryption/decryption تمامی secrets function ها به عنوان یک Kubernetes secrets ساده عمل می‌کنند و بدین ترتیب اپلیکیشن شما به آن‌ها دسترسی می‌دهد. اگر  علاقه‌ای به نحوه کارکردن Kubernetes secrets ها ندارید، باید به دنبال راه امنیتی جایگزین باشید.

مثال زیر یک اپلیکیشن به همراه secret ها را برای شما شرح می‌دهد

به عنوان یک مثال در حال اجرا، ما از یک برنامه ساده و کاربردی به آدرس https://github.com/codefresh-contrib/gitops-secrets-sample-app .  از kostis-codefresh استفاده خواهیم کرد. این یک وب اپلیکیشن است که لیستی از dummy secrets را می‌خواند و نمایش می‌دهد  (در حقیقت از آنها استفاده نمی‌کند.)
ما انتخاب کردیم که اپلیکیشن به جای استفاده secret  ها به عنوان variable، آن‌ها را به عنوان فایل بخواند (از آدرس /secrets/) . مسیرهایی که ما استفاده کردیم، به شرح زیر است:
[security]
# Path to key pair
private_key = /secrets/sign/key.private
public_key= /secrets/sign/key.pub

[paypal]
paypal_url = https://development.paypal.example.com
paypal_cert=/secrets/ssl/paypal.crt

[mysql]
db_con= /secrets/mysql/connection
db_user = /secrets/mysql/username
db_password = /secrets/mysql/password

این نکته مهم را در نظر بگیرید که این، یک اپلیکیشن ساده است و فقط secrets را از مسیر‌های مشخص شده می‌خواند و در اصل هیچ چیزی درباره Kubernetes, secret resources, volume mounts نمی‌داند.
شما باید آن را داخل Docker container (خارج از Kubernetes) اجرا کنید، سپس اگر مسیرهای صحیح (correct paths) در درون خود secret files داشت، به درستی کار می‌کند. به منظور نمایش بیش‌تر، application secret های مختلفی مانند username/password, public/private key, certificate را می‌خواند و  (load) می‌کند. ما تمامی آن‌ها را به یک روش مدیریت می‌کنیم.
The Bitnami sealed secret controller
این controller Kubernetes ها را در کلاستر نصب می‌کنید و یک کار را برای شما انجام می‌دهند؛  آن‌ها Sealed secrets (که می‌توانند در Git،commit شوند) را به plain secret (که می‌توانند در اپلیکیشن شما استفاده شوند)  تبدیل می‌کنند.
نصب controller به سادگی امکان پذیر است:
helm repo add sealed-secrets https://bitnami-labs.github.io/sealed-secrets
helm repo update
helm install sealed-secrets-controller sealed-secrets/sealed-secrets

پس از نصب، controller به تنهایی دو کلید ایجاد می‌کند:
۱.    کلید خصوصی (private key) که برای رمزگشایی مخفی (secret decryption)استفاده می‌شود. این کلید باید در cluster بماند و هرگز نباید آن را به کسی بدهید.
۲.    کلید عمومی که برای secret encryption استفاده می‌شود. این کلید می‌تواند در خارج از کلاستر بماند و استفاده شود؛ هیچ مشکلی ندارد که این کلید را به کسی بدهید.
زمانی که controller نصب شد،  می‌توانید برنامه خود را به روش استاندارد نصب و استفاده کنید. نیازی نیست که کدهای برنامه خود را تغییر دهید یا Kubernetes manifest های خود را دست کاری کنید. اگر برنامه شما قابلیت این را دارد که از vanilla Kubernetes secret ها استفاده کند، قابلیت این را دارد که با sealed secret ها نیز کار کند.
 
واضح است که controller به طور مستقیم با برنامه شما در تماس نیست. Sealed secretها  را به Kubernetes secrets تبدیل می‌کند و بعد از آن  به برنامه شما بستگی دارد  که چگونه از آن‌ها استفاده کند. اپلیکیشن شما حتی نمی‌داند که secret ها در ابتدا در Git رمزگذاری شده‌اند.
Secret های خود را چگونه رمزگذاری کنید؟
دیدیم ک ه چگونه controller ها  secret ها را رمز گذاری می‌کنند. اما در ابتدا چگونه secret ها را رمز گذاری کنیم؟ controller همراه با فایل اجرایی Kubernetes همراه است، که برای همین منظور ایجاد شده است.
یک single binary، شما می‌توانید با کپی کردن آن در directory دلخواه خود، آن را نصب کنید. (به احتمال زیاد در PATH variable خود)
wget https://github.com/bitnami-labs/sealed secrets/releases/download/v0.16.0/kubeseal-linux-amd64 -O kubeseal
sudo install -m 755 kubeseal /usr/local/bin/kubeseal

Kubernetes عمل مخالف controller ها را انجام می‌دهند، به این شکل که Kubernete های موجود را می‌گیرند و آن‌ها را رمزگذاری می‌کنند. Kubeseal کلید عمومی که در فرایند نصب ساخته شده است را از cluster درخواست می‌کند؛  سپس تمامی secret ها به همراه کلید آن را رمز‌گذاری می‌کند.
به این معنی که:
●    Kubeseal برای رمزگذاری secret ها نیاز به دسترسی به cluster دارد. (انتظار می‌رود یک kubeconfig مانند kubectl باشد.)
●    Secret های رمزگذاری شده فقط در داخل خوشه‌ای که برای پروسه encryption ساخته شده اند، قابل استفاده است.
آخرین نکته بسیار مهم است، زیرا نشان می‌دهد که تمامی secret های یک خوشه منحصر به فرد هستند. namespace برنامه ما به صورت پیش فرض استفاده می‌شود، بنابراین secret ها خوشه هستند و namespace ها خاص و ویژه.
اگر  می‌خواهید یک secret را برای cluster های مختلف استفاده کنید،  باید آن را به ازای هر cluster به صورت جداگانه رمزگذاری کنید.
برای استفاده از دستور Kubeseal، می‌توانید به صورت زیر secret های موجود را در قالبفرمت yaml یا json را دریافت کرده و و آن را رمزگذاری کنید
kubeseal -n my-namespace < .db-creds.yml > db-creds.json

این کد یک SealedSecret ایجاد می‌کند، که یک custom kubernets resourceبرای  controllerاست. این فایل برای commit در گیت، یا ذخیره کردن در سیستم های خارجی دیگر بسیار امن است.
شما می‌توانید secret را در داخل خوشه اجرا کنید.
kubectl apply -f db-creds.json -n my-namespace
 
این secret بخشی از cluster است و هر زمانی که یک اپلیکیشن به آن نیاز داشته باشد، controller به صورت خودکار آن را رمزگشایی می کند و در اختیار اپلیکیشن قرار می دهد
نمودار کامل encryption/decryption

 

فرآیند کامل به شرح زیر است:

۱.    شما plain Kubernetes secret را به صورت local ایجاد می‌کنید .دقت کنید که نباید آن را در هیچ جا commit کنید.
۲.    از Kubeseal برای رمز گذاری secret ها در SealedSecret استفاده ‌کنید.
۳.    Secret اصلی (original secret) را از workstation خود پاک  و sealed secret را روی خوشه اعمال کنید.
۴.    به صورت اختیاری Sealed secret را در Git خود commit کنید.
۵.    برنامه خود را همان طور که انتظار می‌رود normal Kubernetes secrets کار کند، اجرا کنید.
۶.    Controller تمامی Sealed secret ها را رمزگشایی کرده، سپس آن‌ها را به عنوان plain secrets به برنامه شما منتقل می‌کند.
۷.    برنامه طبق معمول کار می‌کند.

استفاده از sealed secrets با Codefresh GitOps

با استفاده از Sealed Secrets controller، در نهایت می‌توانیم تمامی secret  ها را در داخل Git (به صورت رمزگذاری شده) در هنگامconfiguration ذخیره کنیم.
در این repository
https://github.com/codefresh-contrib/gitops-secrets-sample-app/tree/main/safe-to-commit
می‌توانید تمامی manifest  های برنامه به همراه secret  ها را مشاهده کنید.
شما می‌توانید به سادگی codefresh GitOps UI را به این پوشه نشان دهید و برنامه را در یک مرحله اجرا کنید.
 
بعد از اتمام deployment، شما می‌توانید تمامی component های برنامه را در داشبورد GitOps مشاهده کنید.
 
اگر شما برنامه را اجرا کنید، می‌توانید مشاهده کنید که تمامی secret ها را به درستی خوانده است:
 
از اینجا به بعد، برنامه از اصول GitOps پیروی می‌کند. اگر  هر تغییری در ساختار Git (شامل تغییر در ساختار secrets ها نیز می‌شود ) دهید، خوشه شما update می‌شود  و اگر چیزی را در درون خوشه  تغییر دهید، (حتی  secret ها) Codefresh GitPos تغییرات را شناسایی می‌کنند.
جمع بندی
Secret rotation یک پروسه پیچیده است که نباید آن را ساده در نظر گرفت. در این مقاله ما موارد ابتدایی Sealed Secret ها را در GitOps شرح دادیم؛  اما اگر  قصد دارید controller ها را در production استفاده کنید، باید مستندات مورد نیاز را بخوانید و جنبه‌های دیگری مانند secret rotation و key handling را نیز در نظر بگیرید.
منبع

https://medium.com/containers-101/how-to-handle-secrets-like-a-pro-using-gitops-f3b812536434
مشاهده فرصت‌های شغلی در آسا مشاهده فرصت‌های شغلی در آسا