Kubernetes Security
Deze post behandeldt de beveiliging van Kubernetes, inclusief het beveiligen van nodes, toegang tot de API en authenticatie van gebruikers d.m.v. tokens of certificaten. Onderwerpen als RBAC, ABAC en TLS en het beheren van rechten met een ServiceAccount of NetworkPolicy wordt ook besproken.
Basic Security
Security van een Kuberneters cluster begint bij de Nodes waar het cluster op draait. Denk hierbij aan passwordless authentication, opzetten van een zo strak mogelijk afgestelde firewall en dergelijken. Als een node compromised raakt, is het cluster namelijk compromised, en dat wil je altijd voorkomen
Ook is het belangrijk om te bepalen wie bij het cluster mag, en wat ze mogen doen, om zo de KubeAPI te beschermen. Wie er toegang kan krijgen tot een cluster kan worden geregeld met de volgende resources:
- Gebruikersnaam en Wachtwoord
- Gebruikersnaam en Tokens
- Certificaten
- LDAP
- Service Account
Wat ze kunnen doen wordt gedefinieerd via:
- RBAC
- ABAC
- Node Authorization
- Webhook modes
TLS
Om een Certificate Authority (CA) voor Kubernetes op te zetten, begin je met het genereren van een private key:
openssl genrsa -out ca.key 2048
vervolgens maak je een Certificate Signing Request (CSR):
openssl req -new -key ca.key -subj "/CN=KUBERNETES-CA"
tenslote teken je het certificaat:
openssl x509 -req -in ca.csr -signkey ca.key -out ca.crt
De CA vormt vervolgens de basis voor de beveiliging met TLS in je cluster, en is belangrijk voor authenticatie van gebruikers in het cluster. Admins en Users ontvangen certificaten van de CA, waarmee ze de rechten en toegang tot de Kubernetes API ontvangen. Tijdens het authenticatieproces gebruikt de API server het certificaat van de gebruiker en controleert of deze is ondertekend door de CA.
Kubeconfig
Kubeconfig gebruikt het kubeconfig bestand in ~/.kube/config om te bepalen welk cluster er gebruikt moet worden. Dit bestand bestaat ui drie onderdelen: Clusters, Users en Contexts.
Clusters
In de clusters worden de kubernetes clusters gedefinieerd zoals dfevelopment, staging en productie. Voor elk cluster is een naam, URL en certificaat nodig, zodat kubectl weet waar de verbinding gezogd kan worden
Users
De Users bevat de authenticatiegegevens voor de gebruikers die toegang hebbebn tot de clusters. Hierin worden credentails opgeslagen, zoals tokens, gebruikersnaam/wachtwoorden of client-certificaten met bijbehorende sleutels. Met deze informatie kan de authenticatie uitgevoerd worden op het cluster
Contexts
Een context is de samenvoeging van de clusters en users. De context bepaalt welke gebruiker toegang krijgt tot welk cluster. Bijvoorbeeld, de context Thomas@Development
geeft aan kubectl door dat de user Thomas verbinding moet maken met het development-cluster.
apiVersion: v1
kind: Config
clusters:
- name: Development
cluster:
server: https://development.thomasmldejong.nl
certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0t...
- name: Staging
cluster:
server: https://staging.thomasmldejong.nl
certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0t...
- name: Production
cluster:
server: https://production.thomasmldejong.nl
certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0t...
contexts:
- name: Thomas@Development
context:
cluster: Development
user: Thomas
namespace: default
- name: Remco@Production
context:
cluster: Production
user: Remco
namespace: default
- name: Jasper@Staging
context:
cluster: Staging
user: Jasper
namespace: default
current-context: Thomas@Development
users:
- name: Thomas
user:
token: "abc123def456"
- name: Remco
user:
token: "def456ghi789"
- name: Jasper
user:
token: "ghi789jkl012"
API group
De Kubernetes API is een REST API, die bereikbaar is via de URL https://<masternode>:6443
. De API bestaat uit verschillende paden, met elk hun eigen doel.
- /: De root PAI en levert een overzicht van de API-versies en discovery-informatie.
- /metrics: Bevat metrics over performance en resource gebruik. monitoring tools zoals Prometheus maken hier vaak gebruik van om gegevens over de API-server te verzamelen
- /healthz: Dit endpoint geeft de status van de API-server, dit is zo simpel als een ‘ok’
- /version: Geeft inforamtie over de versie van de API-server.
- /api: Legacy gedeelte van de kubernetes API en bevat resources zoals namespaces, pods, services, secrets en events.
- /apis: Bevat de named API-groepen, waarbij elke set weer gerelateerde resources bevat. de API groepen zijn apps, batch, networking.k8s.io en nog een aantal anderen
Authorizatie
In Kubernetes bestaand verschillende manieren om te bepalen welke rechten een gebruiker of component heeft binnen het cluster. De drie belangrijkste methodes worden in dit kopje behandeld.=
Node Authorizer
Deze methode beperct de acties van kubelets tot alleen het noodzakelijke. Kubelets mogen bijvoorbeeld alleen lezen en schrijven aan hun eigen node-objecten en de pods die op hun node draaien.
ABAC
ABAC verleent toegang op basis van vooraf gedefinieerde regels die dingen zoals gebruikersnaam, groep, resource type en namespaces kunnen bevatten. Deze regels worden vastgelegd in JSON format.
Webhook
Bij webhook authenticatie stuurt Kubernetes autorisatieverzoeken naar een externe service. De externe service beslist of een actie is toegestaan, wat dynamisch en centraal beheer van autorisatieregels mogelijk maakt.
RBAC
Role Based Access Control (RBAC) in Kubernetes maakt het mogelijk om rechten binnen het cluster te beheren door rollen te definiëren en deze aan gebruikers of groepen toe te wijzen. Hierdoor kunnen de rechten van bijvoorbeeld developers, admins en manager gescheiden worden.
Roles
Een rol wordt aangemaakt met een lijst aan rechten binnen een namespace. In het manifest hieronder is de rol developer te zien, dit in dit geval de mogelijk heeft tot het beheren van pods en deployments.
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: developer
namespace: default
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["list", "get", "create", "update", "delete"]
- apiGroups: ["apps"]
resources: ["deployments"]
verbs: ["list", "get", "create", "update", "delete"]
RoleBinding
Om een rol aan een gebruiker te koppelen, is een RoleBinding nodig. Hieronder is een manifest te zien die de rol developer linkt aan de gebruiker Thomas.
apiVersion: rbac.authorization.k8s.io/v1
kind: Rolebinding
metadata:
name: thomas-developer-binding
subjects:
- kind: User
name: Thomas
apiGroup: rbac.authirzation.k8s.io
roleRef:
kind: Role
name: developer
apiGroup: rbac.authorization.k8s.io
ClusterRole
Een role en rolebinding zijn namespace specifiek, maar al wil je rechten aan een user toevoegen voor over het gehele cluster, bestaan er ClusterRoles en ClusterRoleBindings. Deze werken met hezelfde principe als roles, maar zijn niet gebonden aan een namespace.
ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: cluster-admin
rules:
- apiGroups: [""]
resources: ["nodes"]
verbs: ["list", "get", "create", "delete"]
ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1`
kind: ClusterRole
metadata:
name: thomas-developer-cluster-role-binding
subjects:
- kind: User
name: Thomas
apiGroup: rbac.authoirzation.k8s.io
roleRef:
kind: ClusterRole
name: cluster-admin
apiGroup: rbac.authorization.k8s.io
bovenstaande manifests maken een clusterrole aan voor een clusteradmin, en linken deze clusterrole aan de user Thomas.
ServiceAccounts
Een ServiceAccount is een account gemaakt voor bijvoorbeeld applicaties om met de KubeAPI-server te communiceren.
Wanneer er een namespace wordt aangemaakt wordt er automatisch een default
serviceaccount aangemaakt in deze namespace, aan dit serviceaccount worden alle pods gewezen die niet beschikken over een eigen serviceaccount name. De rechten van een serviceaccount worden beheerd via (Cluster)Roles en de bijbehorende bindings.
apiVersion: v1
kind: ServiceAccount
metadata:
name: nginx-serviceaccount
namespace: webserver
Om een service accoutn aan een pod toe te voegen, kan de serviceAccountName
geconfigureerd worden in het manifest.
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
serviceAccountName: nginx-serviceaccount
containers:
- name: nginx-container
image: nginx:latest
Network Policies
Network policies worden gebruik om netwerkverkeer tuseen pods en dergelijken te beheren. Een Network policie kan gedefinieerd worden welk inkomend en uitgaand verkeer wel en niet mag. Standaard zijn er geen network policies gedefinieerd en kan een pod dus communiceren met alles binnen het cluster, zodra een policy wordt aangemaakt kan alleen de communicatie nog die wordt toegestaan, een network policy werkt dus met een default deny.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-frontend
namespace: webserver
spec:
podSelector:
matchLabels:
app: nginx
type: frontend
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: nginx
type: frontend
ports:
- protocol: TCP
port: 80