Kubernetes Basics

Tip

Μάθετε & εξασκηθείτε στο AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Μάθετε & εξασκηθείτε στο GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Μάθετε & εξασκηθείτε στο Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Υποστηρίξτε το HackTricks

Ο αρχικός συγγραφέας αυτής της σελίδας είναι Jorge (διαβάστε την αρχική του ανάρτηση εδώ)

Architecture & Basics

Τι κάνει το Kubernetes;

  • Επιτρέπει την εκτέλεση κοντέινερ/ων σε μια μηχανή κοντέινερ.
  • Ο προγραμματισμός επιτρέπει την αποστολή κοντέινερ με αποδοτικό τρόπο.
  • Διατηρεί τα κοντέινερ ενεργά.
  • Επιτρέπει τις επικοινωνίες μεταξύ κοντέινερ.
  • Επιτρέπει τεχνικές ανάπτυξης.
  • Διαχειρίζεται όγκους πληροφοριών.

Architecture

  • Node: λειτουργικό σύστημα με pod ή pods.
  • Pod: Περιτύλιγμα γύρω από ένα κοντέινερ ή πολλαπλά κοντέινερ. Ένα pod θα πρέπει να περιέχει μόνο μία εφαρμογή (έτσι συνήθως, ένα pod εκτελεί μόνο 1 κοντέινερ). Το pod είναι ο τρόπος που το kubernetes αφαιρεί την τεχνολογία κοντέινερ που εκτελείται.
  • Service: Κάθε pod έχει 1 εσωτερική διεύθυνση IP από την εσωτερική περιοχή του κόμβου. Ωστόσο, μπορεί επίσης να εκτεθεί μέσω μιας υπηρεσίας. Η υπηρεσία έχει επίσης μια διεύθυνση IP και ο στόχος της είναι να διατηρεί την επικοινωνία μεταξύ των pods, έτσι ώστε αν ένα πεθάνει, η νέα αντικατάσταση (με διαφορετική εσωτερική IP) θα είναι προσβάσιμη εκτεθειμένη στην ίδια IP της υπηρεσίας. Μπορεί να ρυθμιστεί ως εσωτερική ή εξωτερική. Η υπηρεσία λειτουργεί επίσης ως ισοκατανομητής φορτίου όταν 2 pods είναι συνδεδεμένα στην ίδια υπηρεσία.
    Όταν μια υπηρεσία είναι δημιουργημένη, μπορείτε να βρείτε τα endpoints κάθε υπηρεσίας εκτελώντας kubectl get endpoints
  • Kubelet: Κύριος πράκτορας κόμβου. Το στοιχείο που καθορίζει την επικοινωνία μεταξύ του κόμβου και του kubectl, και μπορεί να εκτελεί μόνο pods (μέσω του API server). Ο kubelet δεν διαχειρίζεται κοντέινερ που δεν δημιουργήθηκαν από το Kubernetes.
  • Kube-proxy: είναι η υπηρεσία που είναι υπεύθυνη για τις επικοινωνίες (υπηρεσίες) μεταξύ του apiserver και του κόμβου. Η βάση είναι ένα IPtables για τους κόμβους. Οι πιο έμπειροι χρήστες θα μπορούσαν να εγκαταστήσουν άλλους kube-proxies από άλλους προμηθευτές.
  • Sidecar container: Τα κοντέινερ sidecar είναι τα κοντέινερ που θα πρέπει να εκτελούνται μαζί με το κύριο κοντέινερ στο pod. Αυτό το μοτίβο sidecar επεκτείνει και ενισχύει τη λειτουργικότητα των τρεχόντων κοντέινερ χωρίς να τα αλλάξει. Σήμερα, γνωρίζουμε ότι χρησιμοποιούμε την τεχνολογία κοντέινερ για να περιτυλίξουμε όλες τις εξαρτήσεις ώστε η εφαρμογή να εκτελείται οπουδήποτε. Ένα κοντέινερ κάνει μόνο ένα πράγμα και το κάνει πολύ καλά.
  • Master process:
  • Api Server: Είναι ο τρόπος που οι χρήστες και τα pods χρησιμοποιούν για να επικοινωνούν με τη διαδικασία master. Μόνο οι αυθεντικοποιημένες αιτήσεις θα πρέπει να επιτρέπονται.
  • Scheduler: Ο προγραμματισμός αναφέρεται στη διασφάλιση ότι τα Pods αντιστοιχίζονται σε Nodes ώστε ο Kubelet να μπορεί να τα εκτελέσει. Έχει αρκετή νοημοσύνη για να αποφασίσει ποιος κόμβος έχει περισσότερους διαθέσιμους πόρους και να αναθέσει το νέο pod σε αυτόν. Σημειώστε ότι ο προγραμματιστής δεν ξεκινά νέα pods, απλώς επικοινωνεί με τη διαδικασία Kubelet που εκτελείται μέσα στον κόμβο, η οποία θα εκκινήσει το νέο pod.
  • Kube Controller manager: Ελέγχει πόρους όπως σύνολα αναπαραγωγής ή αναπτύξεις για να ελέγξει αν, για παράδειγμα, ο σωστός αριθμός pods ή κόμβων εκτελούνται. Σε περίπτωση που ένα pod λείπει, θα επικοινωνήσει με τον προγραμματιστή για να ξεκινήσει ένα νέο. Ελέγχει την αναπαραγωγή, τα tokens και τις υπηρεσίες λογαριασμού στο API.
  • etcd: Αποθήκευση δεδομένων, μόνιμη, συνεπής και κατανεμημένη. Είναι η βάση δεδομένων του Kubernetes και η αποθήκευση κλειδιού-τιμής όπου διατηρεί την πλήρη κατάσταση των κλάστερ (κάθε αλλαγή καταγράφεται εδώ). Στοιχεία όπως ο Scheduler ή ο Controller manager εξαρτώνται από αυτά τα δεδομένα για να γνωρίζουν ποιες αλλαγές έχουν συμβεί (διαθέσιμοι πόροι των κόμβων, αριθμός εκτελούμενων pods…)
  • Cloud controller manager: Είναι ο συγκεκριμένος ελεγκτής για ροές ελέγχου και εφαρμογές, δηλαδή: αν έχετε κλάστερ σε AWS ή OpenStack.

Σημειώστε ότι καθώς μπορεί να υπάρχουν αρκετοί κόμβοι (που εκτελούν αρκετά pods), μπορεί επίσης να υπάρχουν αρκετές διαδικασίες master των οποίων η πρόσβαση στον Api server είναι ισοκατανεμημένη και το etcd συγχρονισμένο.

Volumes:

Όταν ένα pod δημιουργεί δεδομένα που δεν θα πρέπει να χαθούν όταν το pod εξαφανιστεί, θα πρέπει να αποθηκευτούν σε έναν φυσικό όγκο. Το Kubernetes επιτρέπει την προσθήκη ενός όγκου σε ένα pod για να διατηρηθούν τα δεδομένα. Ο όγκος μπορεί να είναι στη τοπική μηχανή ή σε μια απομακρυσμένη αποθήκευση. Εάν εκτελείτε pods σε διαφορετικούς φυσικούς κόμβους, θα πρέπει να χρησιμοποιήσετε μια απομακρυσμένη αποθήκευση ώστε όλα τα pods να μπορούν να έχουν πρόσβαση σε αυτήν.

Άλλες ρυθμίσεις:

  • ConfigMap: Μπορείτε να ρυθμίσετε URLs για να έχετε πρόσβαση σε υπηρεσίες. Το pod θα αποκτήσει δεδομένα από εδώ για να γνωρίζει πώς να επικοινωνεί με τις υπόλοιπες υπηρεσίες (pods). Σημειώστε ότι αυτό δεν είναι το προτεινόμενο μέρος για να αποθηκεύσετε διαπιστευτήρια!
  • Secret: Αυτό είναι το μέρος για να αποθηκεύσετε μυστικά δεδομένα όπως κωδικούς πρόσβασης, API keys… κωδικοποιημένα σε B64. Το pod θα μπορεί να έχει πρόσβαση σε αυτά τα δεδομένα για να χρησιμοποιήσει τα απαιτούμενα διαπιστευτήρια.
  • Deployments: Αυτό είναι το μέρος όπου υποδεικνύονται τα στοιχεία που θα εκτελούνται από το kubernetes. Ένας χρήστης συνήθως δεν θα εργάζεται απευθείας με pods, τα pods είναι αφαιρεμένα σε ReplicaSets (αριθμός ίδιων pods που αναπαράγονται), τα οποία εκτελούνται μέσω αναπτύξεων. Σημειώστε ότι οι αναπτύξεις είναι για stateless εφαρμογές. Η ελάχιστη ρύθμιση για μια ανάπτυξη είναι το όνομα και η εικόνα που θα εκτελείται.
  • StatefulSet: Αυτό το στοιχείο προορίζεται ειδικά για εφαρμογές όπως βάσεις δεδομένων που χρειάζονται πρόσβαση στην ίδια αποθήκευση.
  • Ingress: Αυτή είναι η ρύθμιση που χρησιμοποιείται για να εκθέσει την εφαρμογή δημόσια με μια URL. Σημειώστε ότι αυτό μπορεί επίσης να γίνει χρησιμοποιώντας εξωτερικές υπηρεσίες, αλλά αυτός είναι ο σωστός τρόπος για να εκθέσετε την εφαρμογή.
  • Εάν υλοποιήσετε ένα Ingress, θα χρειαστεί να δημιουργήσετε Ingress Controllers. Ο Ingress Controller είναι ένα pod που θα είναι το endpoint που θα δέχεται τα αιτήματα και θα τα ελέγχει και θα τα ισοκατανέμει στις υπηρεσίες. Ο ingress controller θα στείλει το αίτημα με βάση τους κανόνες ingress που έχουν ρυθμιστεί. Σημειώστε ότι οι κανόνες ingress μπορούν να δείχνουν σε διαφορετικούς διαδρομές ή ακόμη και υποτομείς σε διαφορετικές εσωτερικές υπηρεσίες kubernetes.
  • Μια καλύτερη πρακτική ασφάλειας θα ήταν να χρησιμοποιήσετε έναν ισοκατανομητή φορτίου cloud ή έναν διακομιστή proxy ως σημείο εισόδου για να μην εκτεθεί καμία μέρος του κλάστερ Kubernetes.
  • Όταν ληφθεί ένα αίτημα που δεν ταιριάζει με κανέναν κανόνα ingress, ο ingress controller θα το κατευθύνει στο “Default backend”. Μπορείτε να describe τον ingress controller για να αποκτήσετε τη διεύθυνση αυτού του παραμέτρου.
  • minikube addons enable ingress

PKI infrastructure - Certificate Authority CA:

  • CA είναι η αξιόπιστη ρίζα για όλα τα πιστοποιητικά μέσα στο κλάστερ.
  • Επιτρέπει στα στοιχεία να επικυρώνουν το ένα το άλλο.
  • Όλα τα πιστοποιητικά του κλάστερ υπογράφονται από την CA.
  • Το ETCd έχει το δικό του πιστοποιητικό.
  • τύποι:
  • πιστοποιητικό apiserver.
  • πιστοποιητικό kubelet.
  • πιστοποιητικό scheduler.

Basic Actions

Minikube

Minikube μπορεί να χρησιμοποιηθεί για να εκτελέσετε μερικές γρήγορες δοκιμές στο kubernetes χωρίς να χρειάζεται να αναπτύξετε ένα ολόκληρο περιβάλλον kubernetes. Θα εκτελεί τις διαδικασίες master και node σε μία μηχανή. Το Minikube θα χρησιμοποιήσει το virtualbox για να εκτελέσει τον κόμβο. Δείτε εδώ πώς να το εγκαταστήσετε.

$ minikube start
😄  minikube v1.19.0 on Ubuntu 20.04
✨  Automatically selected the virtualbox driver. Other choices: none, ssh
💿  Downloading VM boot image ...
> minikube-v1.19.0.iso.sha256: 65 B / 65 B [-------------] 100.00% ? p/s 0s
> minikube-v1.19.0.iso: 244.49 MiB / 244.49 MiB  100.00% 1.78 MiB p/s 2m17.
👍  Starting control plane node minikube in cluster minikube
💾  Downloading Kubernetes v1.20.2 preload ...
> preloaded-images-k8s-v10-v1...: 491.71 MiB / 491.71 MiB  100.00% 2.59 MiB
🔥  Creating virtualbox VM (CPUs=2, Memory=3900MB, Disk=20000MB) ...
🐳  Preparing Kubernetes v1.20.2 on Docker 20.10.4 ...
▪ Generating certificates and keys ...
▪ Booting up control plane ...
▪ Configuring RBAC rules ...
🔎  Verifying Kubernetes components...
▪ Using image gcr.io/k8s-minikube/storage-provisioner:v5
🌟  Enabled addons: storage-provisioner, default-storageclass
🏄  Done! kubectl is now configured to use "minikube" cluster and "default" namespace by defaul

$ minikube status
host: Running
kubelet: Running
apiserver: Running
kubeconfig: Configured

---- ONCE YOU HAVE A K8 SERVICE RUNNING WITH AN EXTERNAL SERVICE -----
$ minikube service mongo-express-service
(This will open your browser to access the service exposed port)

$ minikube delete
🔥  Deleting "minikube" in virtualbox ...
💀  Removed all traces of the "minikube" cluster

Kubectl Basics

Kubectl είναι το εργαλείο γραμμής εντολών για τα clusters του kubernetes. Επικοινωνεί με τον διακομιστή Api της κύριας διαδικασίας για να εκτελεί ενέργειες στο kubernetes ή για να ζητά δεδομένα.

kubectl version #Get client and server version
kubectl get pod
kubectl get services
kubectl get deployment
kubectl get replicaset
kubectl get secret
kubectl get all
kubectl get ingress
kubectl get endpoints

#kubectl create deployment <deployment-name> --image=<docker image>
kubectl create deployment nginx-deployment --image=nginx
#Access the configuration of the deployment and modify it
#kubectl edit deployment <deployment-name>
kubectl edit deployment nginx-deployment
#Get the logs of the pod for debbugging (the output of the docker container running)
#kubectl logs <replicaset-id/pod-id>
kubectl logs nginx-deployment-84cd76b964
#kubectl describe pod <pod-id>
kubectl describe pod mongo-depl-5fd6b7d4b4-kkt9q
#kubectl exec -it <pod-id> -- bash
kubectl exec -it mongo-depl-5fd6b7d4b4-kkt9q -- bash
#kubectl describe service <service-name>
kubectl describe service mongodb-service
#kubectl delete deployment <deployment-name>
kubectl delete deployment mongo-depl
#Deploy from config file
kubectl apply -f deployment.yml

Minikube Dashboard

Ο πίνακας ελέγχου σας επιτρέπει να βλέπετε πιο εύκολα τι εκτελεί το minikube, μπορείτε να βρείτε το URL για να το αποκτήσετε στη:

minikube dashboard --url


🔌  Enabling dashboard ...
▪ Using image kubernetesui/dashboard:v2.3.1
▪ Using image kubernetesui/metrics-scraper:v1.0.7
🤔  Verifying dashboard health ...
🚀  Launching proxy ...
🤔  Verifying proxy health ...
http://127.0.0.1:50034/api/v1/namespaces/kubernetes-dashboard/services/http:kubernetes-dashboard:/proxy/

YAML configuration files examples

Κάθε αρχείο διαμόρφωσης έχει 3 μέρη: metadata, specification (τι χρειάζεται να εκκινήσει), status (επιθυμητή κατάσταση).
Μέσα στη specification του αρχείου διαμόρφωσης ανάπτυξης μπορείτε να βρείτε το πρότυπο που ορίζεται με μια νέα δομή διαμόρφωσης που καθορίζει την εικόνα που θα εκτελείται:

Example of Deployment + Service declared in the same configuration file (from here)

Καθώς μια υπηρεσία συνήθως σχετίζεται με μια ανάπτυξη, είναι δυνατόν να δηλωθούν και οι δύο στο ίδιο αρχείο διαμόρφωσης (η υπηρεσία που δηλώνεται σε αυτή τη διαμόρφωση είναι προσβάσιμη μόνο εσωτερικά):

apiVersion: apps/v1
kind: Deployment
metadata:
name: mongodb-deployment
labels:
app: mongodb
spec:
replicas: 1
selector:
matchLabels:
app: mongodb
template:
metadata:
labels:
app: mongodb
spec:
containers:
- name: mongodb
image: mongo
ports:
- containerPort: 27017
env:
- name: MONGO_INITDB_ROOT_USERNAME
valueFrom:
secretKeyRef:
name: mongodb-secret
key: mongo-root-username
- name: MONGO_INITDB_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: mongodb-secret
key: mongo-root-password
---
apiVersion: v1
kind: Service
metadata:
name: mongodb-service
spec:
selector:
app: mongodb
ports:
- protocol: TCP
port: 27017
targetPort: 27017

Παράδειγμα ρύθμισης εξωτερικής υπηρεσίας

Αυτή η υπηρεσία θα είναι προσβάσιμη εξωτερικά (ελέγξτε τα χαρακτηριστικά nodePort και type: LoadBlancer):

---
apiVersion: v1
kind: Service
metadata:
name: mongo-express-service
spec:
selector:
app: mongo-express
type: LoadBalancer
ports:
- protocol: TCP
port: 8081
targetPort: 8081
nodePort: 30000

Note

Αυτό είναι χρήσιμο για δοκιμές, αλλά για παραγωγή θα πρέπει να έχετε μόνο εσωτερικές υπηρεσίες και ένα Ingress για να εκθέσετε την εφαρμογή.

Παράδειγμα αρχείου ρύθμισης Ingress

Αυτό θα εκθέσει την εφαρμογή στο http://dashboard.com.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: dashboard-ingress
namespace: kubernetes-dashboard
spec:
rules:
- host: dashboard.com
http:
paths:
- backend:
serviceName: kubernetes-dashboard
servicePort: 80

Παράδειγμα αρχείου ρυθμίσεων μυστικών

Σημειώστε πώς οι κωδικοί πρόσβασης είναι κωδικοποιημένοι σε B64 (το οποίο δεν είναι ασφαλές!)

apiVersion: v1
kind: Secret
metadata:
name: mongodb-secret
type: Opaque
data:
mongo-root-username: dXNlcm5hbWU=
mongo-root-password: cGFzc3dvcmQ=

Παράδειγμα ConfigMap

Ένα ConfigMap είναι η ρύθμιση που παρέχεται στα pods ώστε να γνωρίζουν πώς να εντοπίζουν και να έχουν πρόσβαση σε άλλες υπηρεσίες. Σε αυτή την περίπτωση, κάθε pod θα γνωρίζει ότι το όνομα mongodb-service είναι η διεύθυνση ενός pod με το οποίο μπορούν να επικοινωνούν (αυτό το pod θα εκτελεί ένα mongodb):

apiVersion: v1
kind: ConfigMap
metadata:
name: mongodb-configmap
data:
database_url: mongodb-service

Στη συνέχεια, μέσα σε μια deployment config αυτή η διεύθυνση μπορεί να καθοριστεί με τον εξής τρόπο ώστε να φορτωθεί μέσα στο env του pod:

[...]
spec:
[...]
template:
[...]
spec:
containers:
- name: mongo-express
image: mongo-express
ports:
- containerPort: 8081
env:
- name: ME_CONFIG_MONGODB_SERVER
valueFrom:
configMapKeyRef:
name: mongodb-configmap
key: database_url
[...]

Παράδειγμα διαμόρφωσης όγκου

Μπορείτε να βρείτε διάφορα παραδείγματα αρχείων διαμόρφωσης αποθήκευσης yaml στο https://gitlab.com/nanuchi/youtube-tutorial-series/-/tree/master/kubernetes-volumes.
Σημειώστε ότι οι όγκοι δεν βρίσκονται μέσα σε namespaces

Namespaces

Το Kubernetes υποστηρίζει πολλαπλούς εικονικούς κλάδους που υποστηρίζονται από τον ίδιο φυσικό κλάδο. Αυτοί οι εικονικοί κλάδοι ονομάζονται namespaces. Αυτοί προορίζονται για χρήση σε περιβάλλοντα με πολλούς χρήστες που είναι διασκορπισμένοι σε πολλές ομάδες ή έργα. Για κλάδους με λίγους έως δεκάδες χρήστες, δεν θα πρέπει να χρειάζεται να δημιουργήσετε ή να σκεφτείτε καθόλου namespaces. Πρέπει να αρχίσετε να χρησιμοποιείτε namespaces μόνο για να έχετε καλύτερο έλεγχο και οργάνωση κάθε μέρους της εφαρμογής που έχει αναπτυχθεί στο Kubernetes.

Τα namespaces παρέχουν ένα πεδίο για ονόματα. Τα ονόματα των πόρων πρέπει να είναι μοναδικά εντός ενός namespace, αλλά όχι σε όλη την έκταση των namespaces. Τα namespaces δεν μπορούν να είναι φωλιασμένα το ένα μέσα στο άλλο και κάθε πόρος του Kubernetes μπορεί να είναι σε ένα namespace μόνο.

Υπάρχουν 4 namespaces από προεπιλογή αν χρησιμοποιείτε minikube:

kubectl get namespace
NAME              STATUS   AGE
default           Active   1d
kube-node-lease   Active   1d
kube-public       Active   1d
kube-system       Active   1d
  • kube-system: Δεν προορίζεται για χρήση από τους χρήστες και δεν θα πρέπει να το αγγίζετε. Είναι για τις διαδικασίες master και kubectl.
  • kube-public: Δημόσια προσβάσιμα δεδομένα. Περιέχει ένα configmap που περιέχει πληροφορίες του cluster.
  • kube-node-lease: Καθορίζει τη διαθεσιμότητα ενός κόμβου.
  • default: Ο χώρος ονομάτων που θα χρησιμοποιήσει ο χρήστης για να δημιουργήσει πόρους.
#Create namespace
kubectl create namespace my-namespace

Note

Σημειώστε ότι οι περισσότερες πόροι Kubernetes (π.χ. pods, services, replication controllers και άλλοι) βρίσκονται σε κάποια namespaces. Ωστόσο, άλλοι πόροι όπως οι πόροι namespace και οι χαμηλού επιπέδου πόροι, όπως οι nodes και persistenVolumes δεν βρίσκονται σε ένα namespace. Για να δείτε ποιοι πόροι Kubernetes είναι και δεν είναι σε ένα namespace:

kubectl api-resources --namespaced=true #Σε ένα namespace
kubectl api-resources --namespaced=false #Όχι σε ένα namespace

Μπορείτε να αποθηκεύσετε το namespace για όλες τις επόμενες εντολές kubectl σε αυτό το πλαίσιο.

kubectl config set-context --current --namespace=<insert-namespace-name-here>

Helm

Το Helm είναι ο διαχειριστής πακέτων για το Kubernetes. Επιτρέπει τη συσκευασία αρχείων YAML και τη διανομή τους σε δημόσιες και ιδιωτικές αποθήκες. Αυτά τα πακέτα ονομάζονται Helm Charts.

helm search <keyword>

Helm είναι επίσης μια μηχανή προτύπων που επιτρέπει τη δημιουργία αρχείων ρυθμίσεων με μεταβλητές:

Kubernetes μυστικά

Ένα Secret είναι ένα αντικείμενο που περιέχει ευαίσθητα δεδομένα όπως ένας κωδικός πρόσβασης, ένα token ή ένα κλειδί. Τέτοιες πληροφορίες θα μπορούσαν διαφορετικά να τοποθετηθούν σε μια προδιαγραφή Pod ή σε μια εικόνα. Οι χρήστες μπορούν να δημιουργήσουν Secrets και το σύστημα δημιουργεί επίσης Secrets. Το όνομα ενός αντικειμένου Secret πρέπει να είναι έγκυρο DNS subdomain name. Διαβάστε εδώ the official documentation.

Τα μυστικά μπορεί να είναι πράγματα όπως:

  • API, SSH Keys.
  • OAuth tokens.
  • Credentials, Passwords (plain text ή b64 + κρυπτογράφηση).
  • Πληροφορίες ή σχόλια.
  • Κωδικός σύνδεσης βάσης δεδομένων, συμβολοσειρές… .

Υπάρχουν διαφορετικοί τύποι μυστικών στο Kubernetes

Builtin TypeUsage
Opaqueτυχαία δεδομένα που ορίζονται από τον χρήστη (Default)
kubernetes.io/service-account-tokenservice account token
kubernetes.io/dockercfgserialized ~/.dockercfg file
kubernetes.io/dockerconfigjsonserialized ~/.docker/config.json file
kubernetes.io/basic-authcredentials for basic authentication
kubernetes.io/ssh-authcredentials for SSH authentication
kubernetes.io/tlsdata for a TLS client or server
bootstrap.kubernetes.io/tokenbootstrap token data

Note

Ο τύπος Opaque είναι ο προεπιλεγμένος, το τυπικό ζεύγος κλειδιού-τιμής που ορίζεται από τους χρήστες.

Πώς λειτουργούν τα μυστικά:

Το παρακάτω αρχείο ρυθμίσεων ορίζει ένα secret που ονομάζεται mysecret με 2 ζεύγη κλειδιού-τιμής username: YWRtaW4= και password: MWYyZDFlMmU2N2Rm. Ορίζει επίσης ένα pod που ονομάζεται secretpod που θα έχει το username και το password που ορίζονται στο mysecret εκτεθειμένα στις μεταβλητές περιβάλλοντος SECRET_USERNAME __ και __ SECRET_PASSWOR. Θα τοποθετήσει επίσης το μυστικό username μέσα στο mysecret στη διαδρομή /etc/foo/my-group/my-username με δικαιώματα 0640.

apiVersion: v1
kind: Secret
metadata:
name: mysecret
type: Opaque
data:
username: YWRtaW4=
password: MWYyZDFlMmU2N2Rm
---
apiVersion: v1
kind: Pod
metadata:
name: secretpod
spec:
containers:
- name: secretpod
image: nginx
env:
- name: SECRET_USERNAME
valueFrom:
secretKeyRef:
name: mysecret
key: username
- name: SECRET_PASSWORD
valueFrom:
secretKeyRef:
name: mysecret
key: password
volumeMounts:
- name: foo
mountPath: "/etc/foo"
restartPolicy: Never
volumes:
- name: foo
secret:
secretName: mysecret
items:
- key: username
path: my-group/my-username
mode: 0640
kubectl apply -f <secretpod.yaml>
kubectl get pods #Wait until the pod secretpod is running
kubectl exec -it  secretpod -- bash
env | grep SECRET && cat /etc/foo/my-group/my-username && echo

Secrets in etcd

etcd είναι μια συνεπής και εξαιρετικά διαθέσιμη αποθήκη κλειδιών-τιμών που χρησιμοποιείται ως αποθήκη υποστήριξης του Kubernetes για όλα τα δεδομένα του κλάστερ. Ας αποκτήσουμε πρόσβαση στα μυστικά που αποθηκεύονται στο etcd:

cat /etc/kubernetes/manifests/kube-apiserver.yaml | grep etcd

Θα δείτε ότι τα πιστοποιητικά, τα κλειδιά και οι διευθύνσεις URL βρίσκονται στο FS. Μόλις τα αποκτήσετε, θα μπορείτε να συνδεθείτε στο etcd.

#ETCDCTL_API=3 etcdctl --cert <path to client.crt> --key <path to client.ket> --cacert <path to CA.cert> endpoint=[<ip:port>] health

ETCDCTL_API=3 etcdctl --cert /etc/kubernetes/pki/apiserver-etcd-client.crt --key /etc/kubernetes/pki/apiserver-etcd-client.key --cacert /etc/kubernetes/pki/etcd/etcd/ca.cert endpoint=[127.0.0.1:1234] health

Μόλις επιτύχετε να εδραιώσετε την επικοινωνία, θα είστε σε θέση να αποκτήσετε τα μυστικά:

#ETCDCTL_API=3 etcdctl --cert <path to client.crt> --key <path to client.ket> --cacert <path to CA.cert> endpoint=[<ip:port>] get <path/to/secret>

ETCDCTL_API=3 etcdctl --cert /etc/kubernetes/pki/apiserver-etcd-client.crt --key /etc/kubernetes/pki/apiserver-etcd-client.key --cacert /etc/kubernetes/pki/etcd/etcd/ca.cert endpoint=[127.0.0.1:1234] get /registry/secrets/default/secret_02

Προσθήκη κρυπτογράφησης στο ETCD

Από προεπιλογή, όλα τα μυστικά αποθηκεύονται σε απλό κείμενο μέσα στο etcd, εκτός αν εφαρμόσετε μια στρώση κρυπτογράφησης. Το παρακάτω παράδειγμα βασίζεται στο https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/

apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
- resources:
- secrets
providers:
- aescbc:
keys:
- name: key1
secret: cjjPMcWpTPKhAdieVtd+KhG4NN+N6e3NmBPMXJvbfrY= #Any random key
- identity: {}

Μετά από αυτό, πρέπει να ορίσετε την παράμετρο --encryption-provider-config στον kube-apiserver για να δείξετε την τοποθεσία του δημιουργηθέντος αρχείου ρυθμίσεων. Μπορείτε να τροποποιήσετε το /etc/kubernetes/manifest/kube-apiserver.yaml και να προσθέσετε τις παρακάτω γραμμές:

containers:
- command:
- kube-apiserver
- --encriyption-provider-config=/etc/kubernetes/etcd/<configFile.yaml>

Κάντε κύλιση προς τα κάτω στα volumeMounts:

- mountPath: /etc/kubernetes/etcd
name: etcd
readOnly: true

Κάντε κύλιση προς τα κάτω στα volumeMounts για hostPath:

- hostPath:
path: /etc/kubernetes/etcd
type: DirectoryOrCreate
name: etcd

Επιβεβαίωση ότι τα δεδομένα είναι κρυπτογραφημένα

Τα δεδομένα κρυπτογραφούνται όταν γράφονται στο etcd. Μετά την επανεκκίνηση του kube-apiserver, οποιοδήποτε νέο ή ενημερωμένο μυστικό θα πρέπει να είναι κρυπτογραφημένο όταν αποθηκεύεται. Για να ελέγξετε, μπορείτε να χρησιμοποιήσετε το πρόγραμμα γραμμής εντολών etcdctl για να ανακτήσετε το περιεχόμενο του μυστικού σας.

  1. Δημιουργήστε ένα νέο μυστικό με το όνομα secret1 στο namespace default:
kubectl create secret generic secret1 -n default --from-literal=mykey=mydata
  1. Χρησιμοποιώντας την εντολή etcdctl, διαβάστε αυτό το μυστικό από το etcd:

ETCDCTL_API=3 etcdctl get /registry/secrets/default/secret1 [...] | hexdump -C

όπου [...] πρέπει να είναι τα επιπλέον επιχειρήματα για τη σύνδεση με τον διακομιστή etcd.

  1. Επιβεβαιώστε ότι το αποθηκευμένο μυστικό έχει πρόθεμα k8s:enc:aescbc:v1:, το οποίο υποδεικνύει ότι ο πάροχος aescbc έχει κρυπτογραφήσει τα αποτελέσματα δεδομένα.
  2. Επιβεβαιώστε ότι το μυστικό αποκρυπτογραφείται σωστά όταν ανακτάται μέσω του API:
kubectl describe secret secret1 -n default

θα πρέπει να ταιριάζει με mykey: bXlkYXRh, τα mydata είναι κωδικοποιημένα, ελέγξτε decoding a secret για να αποκωδικοποιήσετε πλήρως το μυστικό.

Δεδομένου ότι τα μυστικά είναι κρυπτογραφημένα κατά την εγγραφή, η εκτέλεση μιας ενημέρωσης σε ένα μυστικό θα κρυπτογραφήσει αυτό το περιεχόμενο:

kubectl get secrets --all-namespaces -o json | kubectl replace -f -

Τελικές συμβουλές:

Αναφορές

kubesectips v1 | sickrov.github.io

- YouTube

Tip

Μάθετε & εξασκηθείτε στο AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Μάθετε & εξασκηθείτε στο GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Μάθετε & εξασκηθείτε στο Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Υποστηρίξτε το HackTricks