در اکوسیستم کوبرنتیز، Kubernetes Secret شیئی است که اطلاعات حساس مانند کلیدها، رمزهای عبور و توکنها را در خود نگهداری میکند. در این نوشته Kubernetes Secrets به بررسی مفهوم آنها، انواع Kubernetes Secrets، نحوه ایجاد آنها و موارد بیشتر میپردازیم.
Kubernetes Secrets چیست؟
همانطور که در ابتدای این مطلب بیان شد، در اکوسیستم کوبرنتیز، Kubernetes Secret شیئی است که اطلاعات حساس مانند کلیدها، رمزهای عبور و توکنها را در خود نگهداری میکند. بهجای قرار دادن مستقیم این دادهها در یک پاد یا دیپلویمنت، ذخیره اطلاعاتی که میخواهید امن نگهداری شوند در یک Secret، باعث میشود سطح حمله کاهش یابد و شانس تغییر این اطلاعات حیاتی در چرخه عمر توسعه نرمافزار کمتر شود.
Kubernetes Secrets برای نگهداری امن اطلاعات حساس مانند رمزهای عبور، توکنها و گواهینامهها به کار میروند. دیپلویمنتها، پادها و سایر منابع Kubernetes که به این اطلاعات حساس نیاز دارند، میتوانند از Secrets استفاده کنند. همه ما به کسی یا چیزی نیاز داریم که رازهای ما را امن نگه دارد، در این مورد، این نقش برعهده Kubernetes است. شیءهای Secret جزئی از «Kubernetes v1 API» هستند و با استفاده از مانیفست زیر میتوان آنها را ایجاد کرد:
apiVersion: v1
kind: Secret
metadata:
name: file-credential
data:
.secret-file: dmFsdWUtMg0KDQo=
وقتی یک Secret ایجاد شد، باید در پاد خود به آن Secret ارجاع دهید. فایل کانفیگ زیر به پاد مربوطه دسترسی به Kubernetes Secret ایجاد شده در مانیفست بالا را میدهد:
apiVersion: v1
kind: Pod
metadata:
name: secret-files-pod
spec:
volumes:
- name: secret-volume
secret:
secretName: file-secret
containers:
- name: dotfile-test-container
image: registry.k8s.io/busybox
command:
- ls
- "-l"
- "/etc/secret-volume"
volumeMounts:
- name: secret-volume
readOnly: true
mountPath: "/etc/secret-volume"
در این مثال، فایل Secrets مربوطه در مسیر /etc/secret-volume
در سیستم فایل قرار میگیرد تا برنامه بتواند به آن دسترسی داشته باشد. (در تعریف volume mount، شما مشخص میکنید که مسیر فایل کجا خواهد بود.)
چطور از Kubernetes Secrets استفاده کنیم؟
به روشهای مختلفی میتوان از Secretها در یک کلاستر کوبرنتیز استفاده کرد. از جمله این روشها میتوان به موارد زیر اشاره داشت:
- متغیرهای محیطی در یک کانتینر
- فایلهایی داخل یک کانتینر
- آرگومانهای خط فرمان در داخل یک کانتینر
در ادامه هر یک از موارد فوق در زیربخشهایی شرح داده شدهاند.
متغیرهای محیطی در یک کانتینر
Secretها میتوانند برای ارسال دادههای حساس به کانتینرها/پادها بهعنوان متغیرهای محیطی استفاده شوند. این یک موردِ استفاده و کاربرد رایج برای Secretها است، زیرا به برنامه اجازه میدهد بهراحتی به این دادهها دسترسی پیدا کند.
فایلهایی داخل یک کانتینر
Secretها میتوانند بهصورت فایل در یک کانتینر mount شوند. به این ترتیب برنامه میتواند به دادهها بهصورت فایل دسترسی داشته باشد. این میتواند برای برنامههایی مفید باشد که انتظار دارند دادههای حساس در یک فایل ذخیره شوند.
آرگومانهای خط فرمان در داخل یک کانتینر
Secretها میتوانند بهعنوان آرگومانهای خط فرمان به یک کانتینر ارسال شوند. این ویژگی میتواند برای برنامههایی مفید باشد که انتظار دارند دادههای حساس بهعنوان آرگومان خط فرمان ارسال شوند.
مواردِ استفاده Kubernetes Secrets چیست؟
موارد زیر نمونههایی از کاربردهای متداول Secrets هستند:
- فراهم کردن متغیرهای محیطی برای کانتینرها: مقادیر محیطی میتوانند رفتار برنامه را کنترل کنند، بنابراین استفاده از Secrets برای ارائه این مقادیر توصیه میشود. این مقادیر محیطی کانتینر ممکن است شامل اطلاعات محرمانه مانند اعتبارنامهها (Credentials) باشد که برای فراخوانی برنامههای شخص ثالث (مثلاً درگاههای پرداخت) مورد استفاده قرار میگیرند.
- فراهم کردن اعتبارنامههایی مانند کلیدهای SSH، رمزهای عبور برای کانتینرها: Secrets میتوانند اعتبارنامههایی مانند کلیدهای SSH، رمزهای عبور، گواهینامههای TLS و موارد مشابه را به کانتینرها منتقل کنند. کلیدهای SSH و گواهینامههای TLS از نشانههای امنیتی مهمی هستند که میتوانند در برنامهها و از طریق Secrets ارسالی به آنها، مورد استفاده قرار گیرند.
- ایجاد امکان pull شدن ایمیجهای کانتینرها از رجیستری: Secrets همچنین برای اجازه دادن pull کردن تصاویر کانتینر از رجیستریها در گرههای کوبرنتیز به کار میروند. میتوانید اعتبارنامههای دسترسی رجیستری Docker را از طریق Secrets ارائه کنید تا Kubelet از آنها برای pull کردن تصاویر کانتینر ذخیره شده در رجیستری استفاده کند.
- ذخیره اطلاعات اضافه مثل جزئیات Helm: همانطور که Helm از Secrets برای ذخیره اطلاعات مربوط به خود استفاده میکند، سایر برنامهها نیز میتوانند از Secrets برای انجام عملکردهای خود بهره ببرند.
حالا در ادامه به سایر انواع Kubernetes Secrets میپردازیم.
انواع Kubernetes Secrets چیست؟
بر اساس مقادیر تعیین شده برای Secrets، آنها به انواع زیر تقسیم میشوند:
- Opaque: نوع پیشفرض و عمومی Secrets است که هر کسی میتواند آن را ایجاد و استفاده کند. این نوع، زوجهای کلید-مقدار ساده هستند؛ بنابراین اگر نوع آن را مشخص نکنید، یک Secret از نوع Opaque (با تعریف نوع opaque) ایجاد خواهد شد.
- توکنهای Service Account: برای شناسایی حسابهای سرویس استفاده میشوند. این توکنها به APIهای کوبرنتیز امکان دسترسی به پادها را میدهند. نوع این API، kubernetes.io/service-account-token است.
- SSH-auth: این نوع Secret برای ذخیره اطلاعات مورد نیاز بهمنظور احراز هویت SSH استفاده میشود. نوع آن
kubernetes.io/ssh-auth
است. - TLS: از این نوع Secret برای ذخیره گواهینامههای TLS و کلیدهای مرتبط با آنها استفاده میشود. نوع این
Secret kubernetes.io/tls
است. - Basic-auth: برای Secretهای «احراز هویت پایه» (basic auth)، نوع آن را
kubernetes.io/basic-auth
تعریف کنید. - Docker-cgf و Dockerconfigjson: پیکربندیهای مربوط به Docker و اعتبارنامههای رجیستری معمولاً در این دو نوع Secret ذخیره میشوند. برای استفاده از docker-cfg و dockerconfigjson، نوع را بهترتیب
kubernetes.io/dockercfg
یاkubernetes.io/dockerconfigjson
تعریف کنید. - توکن: این نوع Secret به توکنهای «راهاندازی» (bootstrap) اشاره دارد که برای اضافه کردن Nodeهای جدید به خوشه کوبرنتیز مورد استفاده قرار میگیرند. برای استفاده از این توکن در فرایند راهاندازی نود، نوع آن را
bootstrap.kubernetes.io/token
تعریف کنید.
چطور Kubernetes Secret بسازیم؟
در این بخش از مقاله هر یک از مراحل ایجاد و استفاده از Kubernetes Secrets شرح داده شده است.
گام اول: ایجاد و ساخت Kubernetes Secret
چند روش برای ایجاد Kubernetes Secret وجود دارد که آسانترین آن استفاده از دستور kubectl create secret
است. در ادامه مثالی برای این روش ارائه کردهایم:
kubectl create secret generic my-secret --from-literal=password=abc123
دستور بالا یک سیکرت عمومی یا همان جنریک با نام my-secret
ایجاد میکند و مقدار کلید password
را برابر abc123
قرار میدهد. همچنین میتوان با استفاده از آپشن — from-file
نیز یک Kubernetes Secret ایجاد کرد:
kubectl create secret generic my-secret --from-file=ssh-privatekey=/path/to/privatekey --from-file=ssh-publickey=/path/to/publickey
دستور بالا یک سکرت عمومی با نام my-secret
ایجاد میکند و مقادیر کلیدهای ssh-privatekey
و ssh-publickey
را برابر با محتویات فایلهای مشخص شده قرار میدهد.
گام دوم: استفاده از Kubernetes Secret در یک Pod
برای استفاده از یک Secret در یک Pod، باید volumeی را که به Secret ارجاع میدهد اضافه و سپس آن volume را به کانتینر وصل کنیم. در ادامه مثالی برای این مورد ارائه شده است.
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
containers:
- name: my-container
image: my-image
volumeMounts:
- name: my-secret
mountPath: /etc/my-secret
readOnly: true
volumes:
- name: my-secret
secret:
secretName: my-secret
این فایل YAML یک Pod تعریف میکند که یک کانتینر و یک volume دارد. volume یک Secret کوبرنتیز با نام my-secret
است که در مسیر /etc/my-secret
به کانتینر mount شده است.
گام سوم: استفاده از Kubernetes Secret در یک Deployment
برای استفاده از Secret در یک Deployment، میتوانیم یک متغیر محیطی که به Secret ارجاع میدهد را اضافه کنیم. در ادامه مثالی در این خصوص ارائه شده است.
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-deployment
spec:
replicas: 3
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: my-container
image: my-image
env:
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: my-secret
key: password
این فایل YAML یک Deployment را تعریف میکند که دارای یک کانتینر است. کانتینر یک متغیر محیطی به نام DB_PASSWORD
دارد که مقدار آن از کلید password
در سکرت my-secret
گرفته شده است.
گام چهارم: مشاهده Kubernetes Secrets
برای مشاهده یک سکرت موجود، از دستور زیر استفاده میکنیم:
kubectl get secret secret-name
سکرت توسط kubectl
با فرمت کدگذاری شده base64 نمایش داده میشود. برای رمزگشایی کامل Secret، از یک دیکُدر base64 خارجی (مانند برنامه base64 در لینوکس) استفاده و دستوراتی مانند دستور زیر را اجرا میکنیم:
echo $encoded_secret | base64 -d
توجه داشته باشید که اگر محدودیتهای RBAC را برای مشاهده سکرتها اعمال کردهاید، فقط کاربرانی که دارای مجوزهای لازم هستند میتوانند به این روش به سکرتها دسترسی داشته باشند. میتوانید برای بررسی موفقیتآمیز ایجاد سکرت، از دستور زیر استفاده کنید:
kubectl get secrets
دستور فوق، فهرست سکرتهای موجود را بههمراه نام، نوع، تعداد مقادیر دادهای که در آنها موجود است و عمر آنها را نمایش میدهد.
گام پنجم: ویرایش مشخصات یک سکرت K8s
برای تغییر مشخصات یک سکرت کوبرنتیز موجود، میتوانیم از دستور kubectl edit
استفاده کنیم. دستور زیر نشان میدهد که چطور میتوان یک Kubernetes Secret با نام production-secret
را ویرایش کرد:
kubectl edit secret production-secret
گام ششم: حذف یک Kubernetes Secret با استفاده از دستور kubectl
برای حذف یک سکرت، ابتدا با استفاده از دستورات cat
یا get
بررسی میکنیم که آیا سکرتهایی در کلاستر ما وجود دارد یا خیر. سپس با دستور describe
میتوانیم اطلاعات بیشتری در مورد یک سکرت خاص کسب کنیم. برای حذف سکرتهای کوبرنتیز از دستور kubectl delete
استفاده میشود:
kubectl delete secret production-secret
به این ترتیب اکنون یاد گرفتیم که چطور Kubernetes Secrets را ایجاد و از آنها استفاده کنیم.
Kubernetes Secrets چقدر ایمن هستند؟
سکرتهای کوبرنتیز برای امنیت طراحی شدهاند و مکانیزمی برای ذخیره و مدیریت امن دادههای حساس در داخل یک کلاستر کوبرنتیز فراهم میکنند. هنگامی که سکرتهای کوبرنتیز بهدرستی پیکربندی و استفاده شوند، میتوانند امنیت بالایی را برای دادههای حساس فراهم کنند.
Kubernetes Secrets بهصورت رمزگذاری شده در سرور API کوبرنتیز ذخیره میشوند و تنها کاربران یا سرویسهای مُجازی که مجوز لازم را دارند، میتوانند به آنها دسترسی داشته باشند. بهطور پیشفرض، Secretها با الگوریتم رمزنگاری AES-256 رمزگذاری میشوند و دسترسی به آنها توسط قوانین RBAC (کنترل دسترسی نقشمحور) کوبرنتیز کنترل میشود.
یک روش رایج این است که دسترسی ویرایش یا حذف به فردی که نیازی به آن ندارد، داده نشود. علاوه بر این، Kubernetes Secrets تنها زمانی که یک Pod از آنها استفاده میکند در حافظه ذخیره میشوند. پس از خاتمه پاد، Secretها برای همیشه از حافظه حذف میشوند که این امر لایه امنیتی افزودهای را فراهم میکند.
با این حال، مهم است که بدانید Kubernetes Secrets کاملاً امن نیستند و خطرهای امنیتی بالقوهای وجود دارد که میتواند امنیت Secretها را به خطر بیندازد. بهعنوان مثال، اگر یک مهاجم به کلاستر Kubernetes یا به پادی که از Secretها استفاده میکند دسترسی پیدا کند، ممکن است بتواند به Secretها هم دسترسی پیدا کند. در گذشته چنین مواردی رخ داده است، بنابراین باید با احتیاط عمل کرد؛ زیرا هیچ سیستمی در دنیا ۱۰۰ درصد امن نیست.
باید به خاطر داشت که نحوه ذخیره Kubernetes Secrets در etcd چندان امن نیست، زیرا رمزگذاری نمیشوند. بلکه بهصورت اشیاء رمزگذاریشده Base64 ذخیره میشوند. این به آن معناست که اگر کسی به این دادهها دسترسی پیدا کند، میتواند بهسرعت رشته Base64 را رمزگشایی و از تمام Secretها استفاده کند. تنها چیزی که نیاز دارد، دسترسی برای مشاهده اشیاء Secret Kubernetes است (میتوان از استفاده Base64 با بهرهگیری از فیلد stringData اجتناب کرد).
بهترین شیوهها در Kubernetes Secrets
برای کاهش خطرهای امنیتی Kubernetes Secrets، پیروی از شیوههای مناسب بهمنظور تامین امنیت خوشههای Kubernetes، مانند اعمال کنترلهای امنیتی شبکه، استفاده از سازوکارهای احراز هویت قوی و محدود کردن دسترسی به منابع حساس، ضروری است.
علاوه بر این، پیکربندی و استفاده صحیح از Kubernetes Secrets مانند اجتناب از ذخیره Secretها در متغیرهای محیطی و محدود کردن دسترسی به Secretها تنها برای پادهایی که به آنها نیاز دارند، ضروری است. توجه به این امر ضرورت دارد که شیوههای مناسب صنعت را دنبال کنیم، چرا که تمام نشتهای دادهای که تاکنون رخ دادهاند، به علت عدم پیروی از پروتکلهای امنیتی تایید شده بودهاند.
پیکربندی Kubernetes secrets بهمنظور افزایش امنیت در آنها
برای امنتر کردن Kubernetes secrets، میتوان موارد زیر را انجام داد:
- اعمال قوانین کنترل دسترسی نقشمحور (RBAC): کوبرنتیز از کنترل دسترسی نقشمحور و مبتنی بر سیاست به خوبی پشتیبانی میکند. میتوان بهراحتی کنترل کرد که چه کسی مجاز است به کدام اجزا در Kubernetes دسترسی داشته باشد، بنابراین میتوانیم استفاده از APIهای Secret را محدود و دسترسی به Secretها را از تمام کاربران حذف کرد. اطمینان از عدم دسترسی به Secretها از طریق ابزار خط فرمان Kubectl، اولین گام است.
- اجازه دسترسی به Secretهای خاص تنها برای کانتینرها: همانطور که میتوان دسترسی RBAC را برای کاربران کنترل کرد، میتوان دسترسی به Secretها را به مجموعهای خاص از برنامهها محدود کرد. به این ترتیب، Secretهای شما تنها برای برنامههایی در دسترس خواهند بود که مجاز به استفاده از آنها هستند.
فعال کردن رمزگذاری در حالت استراحت (Encryption at rest)
رمزگذاری در حالت استراحت (Encryption at rest) یک ویژگی است که میتوان آن را با استفاده از پرچم --encryption-provider-config
در سرور API فعال کرد. در این پرچم، شما به یک فایل اشاره میکنید که ارائهدهندگان رمزگذاری در حالت استراحت را مشخص میکند. محتوای این فایل YAML چیزی شبیه به این خواهد بود:
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
- resources:
- events
providers:
- identity: {} # do not encrypt Events even though *.* is specified below
- resources:
- '*.apps'
providers:
- aescbc:
keys:
- name: first_key
secret: c2VlkansaklnsxlanslxHsa1hUndklMgaXQ/Cg==
- resources:
- '*.*'
providers:
- aescbc:
keys:
- name: second_key
secret: c2VjcmV12ds2JJklY3vyZSwgSSB0aGluaw==
با نگاه به این فایل، میبینید که آرایهای از منابع وجود دارد که شرطهایی را برای آنها اعمال میکنیم. منبع events
«رمزگذاری در حالت استراحت» ندارد، زیرا هویت ارائه دهنده یک آرایه خالی است. سپس، مشخص کردهایم که منابع تحت اِیپیآی apps
باید در حالت استراحت رمزگذاری شوند. آخرین آرایه نشان میدهد که همه چیز در Kubernetes باید رمزگذاری شود.
ابزارهایی برای مدیریت پایدار Kubernetes secrets
با پیروی از نکات پیکربندی که تا اینجا ارائه شدند، میتوان اطمینان حاصل کرد که هیچ کاربر یا نهاد غیرمجازی نمیتواند به Secretهای ما دسترسی پیدا کند. با این حال، ارسال واقعی Secretها به Kubernetes نیز خطرات امنیتی را بههمراه دارد که نیازمند کنترل دسترسی نقشمحور و سایر بررسیها برای کاهش آن است. اینها ویژگیهای بومی Kubernetes نیستند، اما خوشبختانه ابزارهای موثر زیادی برای انتخاب وجود دارد.
در ادامه ابتدا به راهکارهای شخص ثالث برای مدیریت پایدار Kubernetes secrets میپردازیم.
راهکارهای شخص ثالث برای مدیریت پایدار Kubernetes secrets
- Vault: یک استاندارد صنعتی است که بهطور گسترده مورد استفاده قرار میگیرد. با استفاده از کانتینر Sidecar، امکاناتی مانند RBAC، ممیزی، چرخش Secretها و موتور Secretهای پویا را ارائه میدهد. میتوانید از Vault استفاده کنید و بدون نگرانی از امنیت، Secretها را به کانتینرهای خود ارسال کنید.
- Secrets Manager ارائه شده توسط AWS: سرویس AWS راهحلی بسیار مقرونبهصرفهتر است، اما بسیاری از ویژگیهای Vault، مانند تولید پویای Secretها و رابط کاربری RBAC را ندارد. با این حال، میتوانید RBAC را با استفاده از سیاستهای IAM بومی AWS پیادهسازی کنید.
- قابلیت Key Vault در Azure: این سرویس مشابه Secrets Manager AWS است و Secretها، گواهینامههای TLS، کلیدهای SSH و موارد دیگر را ایمن میکند. یک مزیت بزرگ شاید این باشد که میتوانید Key Vaultها را در دیتاسنترهای بینالمللی Azure ایجاد کنید تا Secretهای خود را امنتر نگه دارید و کارایی آنها را افزایش دهید.
راهکارهای اوپن سورس برای مدیریت پایدار Kubernetes secrets
- Helm secrets: برای مدیریت deploymentها در کوبرنتیز بهطور گسترده استفاده میشود و Helm Secrets یک راهحل ساده برای یکپارچهسازی است. گرچه امنیت آن به اندازه Vault نیست، اما با داشتن مجوزهای مناسب، Helm راهحلی متنباز و قابل قبول است.
- Open-source Vault: علاوه بر نسخه پولی که قبلاً بحث شد، Vault دارای یک توزیع متنباز نیز هست. میتوانید نسخه متنباز Vault را در خوشههای Kubernetes خود یا در یک ماشین مجازی بومی Deploy کنید و از آن برای ارسال Secretها به کانتینرهای خود استفاده کنید. این نسخه از Vault تقریباً تمام ویژگیهای نسخه ارتقا یافته را به غیر از پشتیبانگیری و بازیابی ارائه میدهد.
جمعبندی
Kubernetes Secret شیئی است که اطلاعات حساس مانند کلیدها، رمزهای عبور و توکنها را در خود نگهداری میکند. این Secrets میتوانند بهصورت متغیرهای محیطی، فایلها یا آرگومانهای خط فرمان در کانتینرها استفاده شوند. با پیروی از شیوههای مناسب مانند کنترل دسترسی و رمزگذاری، میتوان امنیت Secrets را افزایش داد. همچنین ابزارهای شخص ثالث و متنباز متعددی برای مدیریت پایدار Secrets در دسترس هستند.
Kubernetes secrets دارای برخی شکافهای امنیتی هستند، اما میتوان با پیروی از اصل کمترین امتیاز و پیادهسازی رمزنگاری در حالت استراحت، با این موارد مقابله کرد. ممیزی نیز روشی کلیدی برای محدود کردن سطح حمله است و تمام ابزارهای ذکر شده دارای یک یا چند روش برای تولید لاگهای ممیزی هستند.