Kubernet'lerde Güvenliğin ABC'si: Kimlik Doğrulama, Yetkilendirme, Denetim

Kubernet'lerde Güvenliğin ABC'si: Kimlik Doğrulama, Yetkilendirme, Denetim

Er ya da geç, herhangi bir sistemin işleyişinde güvenlik sorunu ortaya çıkar: kimlik doğrulamanın sağlanması, hakların ayrılması, denetim ve diğer görevler. Zaten Kubernetes için oluşturuldu birçok çözüm, çok zorlu ortamlarda bile standartlara uyum sağlamanıza olanak tanır... Aynı materyal, K8'lerin yerleşik mekanizmaları içinde uygulanan güvenliğin temel yönlerine de ayrılmıştır. Her şeyden önce, güvenlikle ilgili konuları incelemek için bir başlangıç ​​​​noktası olarak Kubernetes'i tanımaya başlayanlar için faydalı olacaktır.

kimlik doğrulama

Kubernetes'te iki tür kullanıcı vardır:

  • Keşfedin ve Koruyun — Kubernetes API tarafından yönetilen hesaplar;
  • Kullanıcılar — Harici, bağımsız hizmetler tarafından yönetilen “normal” kullanıcılar.

Bu türler arasındaki temel fark, Kubernetes API'sinde Hizmet Hesapları için özel nesnelerin bulunmasıdır (bunlara şöyle denir - ServiceAccounts), bir ad alanına ve Gizli türdeki nesnelerde kümede depolanan bir dizi yetkilendirme verisine bağlıdır. Bu tür kullanıcıların (Hizmet Hesapları) öncelikli olarak Kubernetes kümesinde çalışan işlemlerin Kubernetes API'sine erişim haklarını yönetmesi amaçlanır.

Sıradan Kullanıcıların Kubernetes API'sinde girişleri yoktur; bunların harici mekanizmalar tarafından yönetilmesi gerekir. Kümenin dışında yaşayan insanlara veya süreçlere yöneliktirler.

Her API isteği bir Hizmet Hesabıyla veya bir Kullanıcıyla ilişkilendirilir veya anonim olarak kabul edilir.

Kullanıcı kimlik doğrulama verileri şunları içerir:

  • Kullanıcı Adı — kullanıcı adı (büyük/küçük harfe duyarlı!);
  • UID - "kullanıcı adından daha tutarlı ve benzersiz" olan, makine tarafından okunabilen bir kullanıcı tanımlama dizisi;
  • Gruplar — kullanıcının ait olduğu grupların listesi;
  • ekstra — yetkilendirme mekanizması tarafından kullanılabilecek ek alanlar.

Kubernetes çok sayıda kimlik doğrulama mekanizması kullanabilir: X509 sertifikaları, Taşıyıcı belirteçleri, kimlik doğrulama proxy'si, HTTP Temel Kimlik Doğrulaması. Bu mekanizmaları kullanarak çok sayıda yetkilendirme şeması uygulayabilirsiniz: şifreli statik bir dosyadan OpenID OAuth2'ye kadar.

Ayrıca birden fazla yetkilendirme şemasının aynı anda kullanılması mümkündür. Varsayılan olarak küme şunları kullanır:

  • hizmet hesabı belirteçleri - Hizmet Hesapları için;
  • X509 - Kullanıcılar için.

ServiceAccount'ları yönetmeyle ilgili soru bu makalenin kapsamı dışındadır, ancak bu konuyu daha ayrıntılı olarak öğrenmek isteyenler için şu adresle başlamanızı öneririm: resmi dokümantasyon sayfaları. X509 sertifikalarının nasıl çalıştığı konusuna daha yakından bakacağız.

Kullanıcılara yönelik sertifikalar (X.509)

Sertifikalarla çalışmanın klasik yolu şunları içerir:

  • anahtar nesil:
    mkdir -p ~/mynewuser/.certs/
    openssl genrsa -out ~/.certs/mynewuser.key 2048
  • bir sertifika isteği oluşturma:
    openssl req -new -key ~/.certs/mynewuser.key -out ~/.certs/mynewuser.csr -subj "/CN=mynewuser/O=company"
  • Kubernetes kümesi CA anahtarlarını kullanarak bir sertifika isteğinin işlenmesi, bir kullanıcı sertifikası alınması (sertifika almak için, varsayılan olarak Kubernetes kümesi CA anahtarına erişimi olan bir hesap kullanmanız gerekir. /etc/kubernetes/pki/ca.key):
    openssl x509 -req -in ~/.certs/mynewuser.csr -CA /etc/kubernetes/pki/ca.crt -CAkey /etc/kubernetes/pki/ca.key -CAcreateserial -out ~/.certs/mynewuser.crt -days 500
  • bir yapılandırma dosyası oluşturma:
    • küme açıklaması (belirli bir küme kurulumu için CA sertifika dosyasının adresini ve konumunu belirtin):
      kubectl config set-cluster kubernetes --certificate-authority=/etc/kubernetes/pki/ca.crt --server=https://192.168.100.200:6443
    • veya nasıl hayırönerilen seçenek - kök sertifikayı belirtmeniz gerekmez (bu durumda kubectl, kümenin api sunucusunun doğruluğunu kontrol etmez):
      kubectl config set-cluster kubernetes  --insecure-skip-tls-verify=true --server=https://192.168.100.200:6443
    • yapılandırma dosyasına bir kullanıcı ekleme:
      kubectl config set-credentials mynewuser --client-certificate=.certs/mynewuser.crt  --client-key=.certs/mynewuser.key
    • bağlam ekleme:
      kubectl config set-context mynewuser-context --cluster=kubernetes --namespace=target-namespace --user=mynewuser
    • varsayılan içerik ataması:
      kubectl config use-context mynewuser-context

Yukarıdaki işlemlerden sonra dosyada .kube/config bunun gibi bir yapılandırma oluşturulacak:

apiVersion: v1
clusters:
- cluster:
    certificate-authority: /etc/kubernetes/pki/ca.crt
    server: https://192.168.100.200:6443
  name: kubernetes
contexts:
- context:
    cluster: kubernetes
    namespace: target-namespace
    user: mynewuser
  name: mynewuser-context
current-context: mynewuser-context
kind: Config
preferences: {}
users:
- name: mynewuser
  user:
    client-certificate: /home/mynewuser/.certs/mynewuser.crt
    client-key: /home/mynewuser/.certs/mynewuser.key

Hesaplar ve sunucular arasında yapılandırma aktarımını kolaylaştırmak için aşağıdaki anahtarların değerlerini düzenlemek yararlı olacaktır:

  • certificate-authority
  • client-certificate
  • client-key

Bunu yapmak için, içinde belirtilen dosyaları base64 kullanarak kodlayabilir ve anahtarların adına sonek ekleyerek bunları config'e kaydedebilirsiniz. -datayani almış olmak certificate-authority-data vb

kubeadm içeren sertifikalar

Serbest bırakılmasıyla Kubernet'ler 1.15 desteğinin alfa sürümü sayesinde sertifikalarla çalışmak çok daha kolay hale geldi kubeadm yardımcı programı. Örneğin, kullanıcı anahtarlarıyla bir yapılandırma dosyası oluşturmak artık şu şekilde görünebilir:

kubeadm alpha kubeconfig user --client-name=mynewuser --apiserver-advertise-address 192.168.100.200

NB: Gerekli reklam adresi varsayılan olarak şurada bulunan api-server yapılandırmasında bulunabilir: /etc/kubernetes/manifests/kube-apiserver.yaml.

Ortaya çıkan yapılandırma stdout'a aktarılacaktır. İçinde kaydedilmesi gerekiyor ~/.kube/config kullanıcı hesabına veya ortam değişkeninde belirtilen bir dosyaya KUBECONFIG.

Daha derin kaz

Anlatılan konuları daha detaylı anlamak isteyenler için:

Yetki

Varsayılan yetkili hesabın kümede çalışma hakları yoktur. İzin vermek için Kubernetes bir yetkilendirme mekanizması uygular.

Sürüm 1.6'dan önce Kubernetes, adı verilen bir yetkilendirme türü kullanıyordu. ABAK (Öznitelik tabanlı erişim kontrolü). Bununla ilgili ayrıntılar şurada bulunabilir: resmi belgeler. Bu yaklaşımın şu anda eski olduğu kabul ediliyor ancak yine de diğer kimlik doğrulama türleriyle birlikte kullanabilirsiniz.

Erişim haklarını bir kümeye bölmenin mevcut (ve daha esnek) yöntemine denir RBAC (Rol tabanlı erişim kontrolü). Sürümden bu yana kararlı olduğu bildirildi Kubernet'ler 1.8. RBAC, açıkça izin verilmeyen her şeyin yasaklandığı bir haklar modeli uygulamaktadır.
RBAC'yi etkinleştirmek içinKubernetes api-server parametresini kullanarak başlatmanız gerekir. --authorization-mode=RBAC. Parametreler manifest dosyasında, varsayılan olarak yol boyunca yer alan api sunucusu yapılandırmasıyla ayarlanır. /etc/kubernetes/manifests/kube-apiserver.yaml, kısımda command. Ancak, RBAC varsayılan olarak zaten etkindir, bu nedenle büyük olasılıkla bu konuda endişelenmenize gerek yoktur: bunu değere göre doğrulayabilirsiniz. authorization-mode (daha önce bahsedilen kube-apiserver.yaml). Bu arada, anlamları arasında başka yetkilendirme türleri de olabilir (node, webhook, always allow), ancak bunların değerlendirilmesini materyalin kapsamı dışında bırakacağız.

Bu arada, zaten yayınladık Makale RBAC ile çalışmanın ilkeleri ve özelliklerinin oldukça ayrıntılı bir açıklamasıyla, bu nedenle kendimi temellerin ve örneklerin kısa bir listesiyle sınırlayacağım.

Aşağıdaki API varlıkları, Kubernetes'te RBAC aracılığıyla erişimi kontrol etmek için kullanılır:

  • Role и ClusterRole — erişim haklarını açıklamaya yarayan roller:
  • Role bir ad alanı içindeki hakları tanımlamanıza olanak tanır;
  • ClusterRole - düğümler, kaynak olmayan URL'ler (yani Kubernetes kaynaklarıyla ilgili olmayan - örneğin,) gibi kümeye özgü nesneler dahil olmak üzere küme içinde /version, /logs, /api*);
  • RoleBinding и ClusterRoleBinding - ciltlemek için kullanılır Role и ClusterRole bir kullanıcıya, kullanıcı grubuna veya ServiceAccount'a.

Rol ve RoleBinding varlıkları ad alanıyla sınırlıdır; aynı ad alanında olmalıdır. Ancak bir RoleBinding, bir dizi genel izin oluşturmanıza ve bunları kullanarak erişimi denetlemenize olanak tanıyan bir ClusterRole'a başvuruda bulunabilir.

Roller, aşağıdakileri içeren kural dizilerini kullanarak hakları tanımlar:

  • API grupları - bkz. resmi belgeler apiGroups ve çıktıya göre kubectl api-resources;
  • kaynaklar (kaynaklar: pod, namespace, deployment ve benzeri.);
  • Fiiller (fiiller: set, update vb.)
  • kaynak isimleri (resourceNames) - bu türdeki tüm kaynaklara değil, belirli bir kaynağa erişim sağlamanız gerektiğinde.

Kubernetes'te yetkilendirmenin daha ayrıntılı bir analizini sayfada bulabilirsiniz resmi belgeler. Bunun yerine (veya daha doğrusu buna ek olarak) onun çalışmalarını gösteren örnekler vereceğim.

RBAC varlıklarına örnekler

basit Role, bölmelerin listesini ve durumunu almanızı ve bunları ad alanında izlemenizi sağlar target-namespace:

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: target-namespace
  name: pod-reader
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "watch", "list"]

Örnek ClusterRole, bölmelerin listesini ve durumunu almanıza ve bunları küme genelinde izlemenize olanak tanır:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  # секции "namespace" нет, так как ClusterRole задействует весь кластер
  name: secret-reader
rules:
- apiGroups: [""]
  resources: ["secrets"]
  verbs: ["get", "watch", "list"]

Örnek RoleBindingkullanıcıya izin veren mynewuser Ad alanındaki bölmeleri "oku" my-namespace:

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: read-pods
  namespace: target-namespace
subjects:
- kind: User
  name: mynewuser # имя пользователя зависимо от регистра!
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role # здесь должно быть “Role” или “ClusterRole”
  name: pod-reader # имя Role, что находится в том же namespace,
                   # или имя ClusterRole, использование которой
                   # хотим разрешить пользователю
  apiGroup: rbac.authorization.k8s.io

Etkinlik denetimi

Kubernetes mimarisi şematik olarak şu şekilde temsil edilebilir:

Kubernet'lerde Güvenliğin ABC'si: Kimlik Doğrulama, Yetkilendirme, Denetim

İsteklerin işlenmesinden sorumlu temel Kubernetes bileşeni API sunucusu. Kümedeki tüm işlemler bunun üzerinden geçer. Bu iç mekanizmalar hakkında daha fazla bilgiyi “makalede okuyabilirsiniz”Kubectl run'u çalıştırdığınızda Kubernetes'te ne olur?'.

Sistem denetimi, Kubernetes'te varsayılan olarak devre dışı bırakılan ilginç bir özelliktir. Kubernetes API'sine yapılan tüm çağrıları kaydetmenize olanak tanır. Tahmin edebileceğiniz gibi Cluster'ın izlenmesi ve durumunun değiştirilmesi ile ilgili tüm işlemler bu API üzerinden gerçekleştirilmektedir. Yeteneklerinin iyi bir açıklaması (her zamanki gibi) şurada bulunabilir: resmi belgeler K8'ler. Daha sonra konuyu daha basit bir dille sunmaya çalışacağım.

Bu durumda, denetimi etkinleştirmek içinapi-server'daki konteynere aşağıda daha ayrıntılı olarak açıklanan üç gerekli parametreyi aktarmamız gerekiyor:

  • --audit-policy-file=/etc/kubernetes/policies/audit-policy.yaml
  • --audit-log-path=/var/log/kube-audit/audit.log
  • --audit-log-format=json

Bu üç gerekli parametreye ek olarak, denetimle ilgili birçok ek ayar vardır: günlük döndürmeden web kancası açıklamalarına kadar. Günlük döndürme parametrelerine örnek:

  • --audit-log-maxbackup=10
  • --audit-log-maxsize=100
  • --audit-log-maxage=7

Ancak bunların üzerinde daha ayrıntılı durmayacağız - tüm ayrıntıları şurada bulabilirsiniz: kube-apserver belgeleri.

Daha önce de belirtildiği gibi, tüm parametreler manifest dosyasında api sunucusu yapılandırmasıyla ayarlanır (varsayılan olarak /etc/kubernetes/manifests/kube-apiserver.yaml), bölümde command. Gerekli 3 parametreye dönelim ve bunları analiz edelim:

  1. audit-policy-file — denetim politikasını açıklayan YAML dosyasının yolu. İçeriğine daha sonra döneceğiz ancak şimdilik dosyanın api-server işlemi tarafından okunabilir olması gerektiğini belirteceğim. Bu nedenle, aşağıdaki kodu yapılandırmanın uygun bölümlerine ekleyebileceğiniz kabın içine monte etmek gerekir:
      volumeMounts:
        - mountPath: /etc/kubernetes/policies
          name: policies
          readOnly: true
      volumes:
      - hostPath:
          path: /etc/kubernetes/policies
          type: DirectoryOrCreate
        name: policies
  2. audit-log-path — günlük dosyasının yolu. Yolun api-sunucusu süreci tarafından da erişilebilir olması gerekir, dolayısıyla montajını da aynı şekilde açıklıyoruz:
      volumeMounts:
        - mountPath: /var/log/kube-audit
          name: logs
          readOnly: false
      volumes:
      - hostPath:
          path: /var/log/kube-audit
          type: DirectoryOrCreate
        name: logs
  3. audit-log-format — denetim günlüğü formatı. Varsayılan: json, ancak eski metin biçimi de mevcuttur (legacy).

Denetim Politikası

Şimdi günlüğe kaydetme politikasını açıklayan söz konusu dosya hakkında. Denetim politikasının ilk kavramı level, kayıt düzeyi. Bunlar aşağıdaki gibidir:

  • None - oturum açmayın;
  • Metadata — günlük isteği meta verileri: kullanıcı, istek zamanı, hedef kaynak (bölme, ad alanı vb.), eylem türü (fiil), vb.;
  • Request — meta verileri ve istek gövdesini günlüğe kaydedin;
  • RequestResponse — günlük meta verileri, istek gövdesi ve yanıt gövdesi.

Son iki seviye (Request и RequestResponse) kaynaklara erişmeyen istekleri günlüğe kaydetmeyin (kaynak olmayan URL'lere erişim).

Ayrıca tüm istekler yerine getirilir pek çok aşama:

  • RequestReceived - Talebin işlemci tarafından alındığı ve işlemci zinciri boyunca henüz iletilmediği aşama;
  • ResponseStarted — yanıt başlıkları gönderilir, ancak yanıt gövdesi gönderilmeden önce. Uzun süren sorgular için oluşturulur (örneğin, watch);
  • ResponseComplete — yanıt birimi gönderildi, başka bilgi gönderilmeyecek;
  • Panic — Anormal bir durum tespit edildiğinde olaylar üretilir.

Kullanabileceğiniz herhangi bir adımı atlamak için omitStages.

Bir politika dosyasında, farklı günlük kaydı düzeylerine sahip çeşitli bölümleri tanımlayabiliriz. Politika açıklamasında bulunan ilk eşleştirme kuralı uygulanacaktır.

Kubelet arka plan programı, api-server yapılandırmasıyla manifestteki değişiklikleri izler ve herhangi bir değişiklik tespit edilirse api-server ile konteyneri yeniden başlatır. Ancak önemli bir detay var: Politika dosyasındaki değişiklikler onun tarafından göz ardı edilecek. Politika dosyasında değişiklik yaptıktan sonra api sunucusunu manuel olarak yeniden başlatmanız gerekecektir. API-sunucusu olarak başlatıldığından beri statik bölme, takım kubectl delete yeniden başlatılmasına neden olmaz. Bunu manuel olarak yapmanız gerekecek docker stop denetim politikasının değiştirildiği kube-masters'da:

docker stop $(docker ps | grep k8s_kube-apiserver | awk '{print $1}')

Denetimi etkinleştirirken şunu unutmamak önemlidir: kube-apiserver üzerindeki yük artıyor. Özellikle istek içeriğini depolamak için bellek tüketimi artar. Günlüğe kaydetme yalnızca yanıt başlığı gönderildikten sonra başlar. Yük aynı zamanda denetim ilkesi yapılandırmasına da bağlıdır.

Politika örnekleri

Örnekleri kullanarak politika dosyalarının yapısına bakalım.

İşte basit bir dosya policyseviyedeki her şeyi günlüğe kaydetmek için Metadata:

apiVersion: audit.k8s.io/v1
kind: Policy
rules:
- level: Metadata

Politikada bir kullanıcı listesi belirleyebilirsiniz (Users и ServiceAccounts) ve kullanıcı grupları. Örneğin, sistem kullanıcılarını bu şekilde görmezden geleceğiz, ancak diğer her şeyi aynı seviyede günlüğe kaydedeceğiz. Request:

apiVersion: audit.k8s.io/v1
kind: Policy
rules:
  - level: None
    userGroups:
      - "system:serviceaccounts"
      - "system:nodes"
    users:
      - "system:anonymous"
      - "system:apiserver"
      - "system:kube-controller-manager"
      - "system:kube-scheduler"
  - level: Request

Hedefleri tanımlamak da mümkündür:

  • ad alanları (namespaces);
  • Fiiller (fiiller: get, update, delete ve diğerleri);
  • kaynaklar (kaynaklar, Aşağıdaki gibi: pod, configmaps vb.) ve kaynak grupları (apiGroups).

Dikkat! Kaynaklar ve kaynak grupları (API grupları, yani apiGroup'lar) ile bunların kümede kurulu sürümleri, şu komutlar kullanılarak elde edilebilir:

kubectl api-resources
kubectl api-versions

Aşağıdaki denetim politikası, en iyi uygulamaların bir göstergesi olarak sunulmaktadır. Alibaba Bulut belgeleri:

apiVersion: audit.k8s.io/v1beta1
kind: Policy
# Не логировать стадию RequestReceived
omitStages:
  - "RequestReceived"
rules:
  # Не логировать события, считающиеся малозначительными и не опасными:
  - level: None
    users: ["system:kube-proxy"]
    verbs: ["watch"]
    resources:
      - group: "" # это api group с пустым именем, к которому относятся
                  # базовые ресурсы Kubernetes, называемые “core”
        resources: ["endpoints", "services"]
  - level: None
    users: ["system:unsecured"]
    namespaces: ["kube-system"]
    verbs: ["get"]
    resources:
      - group: "" # core
        resources: ["configmaps"]
  - level: None
    users: ["kubelet"]
    verbs: ["get"]
    resources:
      - group: "" # core
        resources: ["nodes"]
  - level: None
    userGroups: ["system:nodes"]
    verbs: ["get"]
    resources:
      - group: "" # core
        resources: ["nodes"]
  - level: None
    users:
      - system:kube-controller-manager
      - system:kube-scheduler
      - system:serviceaccount:kube-system:endpoint-controller
    verbs: ["get", "update"]
    namespaces: ["kube-system"]
    resources:
      - group: "" # core
        resources: ["endpoints"]
  - level: None
    users: ["system:apiserver"]
    verbs: ["get"]
    resources:
      - group: "" # core
        resources: ["namespaces"]
  # Не логировать обращения к read-only URLs:
  - level: None
    nonResourceURLs:
      - /healthz*
      - /version
      - /swagger*
  # Не логировать сообщения, относящиеся к типу ресурсов “события”:
  - level: None
    resources:
      - group: "" # core
        resources: ["events"]
  # Ресурсы типа Secret, ConfigMap и TokenReview могут содержать  секретные данные,
  # поэтому логируем только метаданные связанных с ними запросов
  - level: Metadata
    resources:
      - group: "" # core
        resources: ["secrets", "configmaps"]
      - group: authentication.k8s.io
        resources: ["tokenreviews"]
  # Действия типа get, list и watch могут быть ресурсоёмкими; не логируем их
  - level: Request
    verbs: ["get", "list", "watch"]
    resources:
      - group: "" # core
      - group: "admissionregistration.k8s.io"
      - group: "apps"
      - group: "authentication.k8s.io"
      - group: "authorization.k8s.io"
      - group: "autoscaling"
      - group: "batch"
      - group: "certificates.k8s.io"
      - group: "extensions"
      - group: "networking.k8s.io"
      - group: "policy"
      - group: "rbac.authorization.k8s.io"
      - group: "settings.k8s.io"
      - group: "storage.k8s.io"
  # Уровень логирования по умолчанию для стандартных ресурсов API
  - level: RequestResponse
    resources:
      - group: "" # core
      - group: "admissionregistration.k8s.io"
      - group: "apps"
      - group: "authentication.k8s.io"
      - group: "authorization.k8s.io"
      - group: "autoscaling"
      - group: "batch"
      - group: "certificates.k8s.io"
      - group: "extensions"
      - group: "networking.k8s.io"
      - group: "policy"
      - group: "rbac.authorization.k8s.io"
      - group: "settings.k8s.io"
      - group: "storage.k8s.io"
  # Уровень логирования по умолчанию для всех остальных запросов
  - level: Metadata

Denetim politikasına bir başka güzel örnek ise GCE'de kullanılan profil.

Denetim olaylarına hızlı bir şekilde yanıt vermek mümkündür. webhook'u tanımla. Bu konu kapsamındadır resmi belgeler, onu bu makalenin kapsamı dışında bırakacağım.

sonuçlar

Makale, kişiselleştirilmiş kullanıcı hesapları oluşturmanıza, haklarını ayırmanıza ve eylemlerini kaydetmenize olanak tanıyan Kubernetes kümelerindeki temel güvenlik mekanizmalarına genel bir bakış sunmaktadır. Teoride veya pratikte bu tür sorunlarla karşılaşanlara faydalı olmasını dilerim. Ayrıca Kubernetes'te güvenlik konusuyla ilgili "PS" de verilen diğer materyallerin listesini de okumanızı tavsiye ederim - belki bunların arasında sizi ilgilendiren sorunlarla ilgili gerekli ayrıntıları bulacaksınız.

PS

Blogumuzda da okuyun:

Kaynak: habr.com

Yorum ekle