Demistifying Kubernetes Security
Sangam Biradar
Principal Security Advocate at Tenable
Docker Community Leader
AWS/CDF Community Builder
@sangamtwts
1. Secure Design and code
Static Analysis
Security Testing (SAST)
- security code is free of bug , specifically security bugs
- unsafe programming practices leads to security bugs
- Write secure code in first place
- Use scanners output to locate unsafe code blocks
- Complete the feedback loop
Software Composition Analysis (SBOM)
Identifying security issues in open-source and commercial software components
Dynamic Application Security Testing(DAST)
Privilege Escalation
Minimum Privileges
- No blanket privileges beyond subject's role
- User Instruction in Dockerfile
- Without user instruction , Container runs as a root
- Most application containers doesn't need root access
setuid
setguid
setuid bit on causes process to run with permissions of file owner
# Example: setuid bit on vs off
ls -l /etc/passwd
-rwsr-xr roor root 6421 Jun 20 2020 /etc/passwd <----- ON
ls -l /home/user/readme.txt
-rw-r--r-- user user 6424 Jun 2020 /home/user/readme.txt <---- Off
Unwanted objects in an image
- Inevitably unwanted active threats and vulnerabilities will appear
- Malware
- Secrets
Security
Vulnerability
Secrets
Malware
Scanner
Image Scanning
- New Vulnerabilities emerge frequently
- A clean image yesterday may not be clean today
- Scan in CI pipeline after building the image
- Scan image registries
Image Signing :-
https://github.com/sigstore/cosign
TUF & Notary
Authenticate Subjects
- Encryption of network does not prevent from malicious user
- Permit only authenticated users
Code
Build
Stage
Test
Deploy
Code
Build
Stage
Test
Deploy
Code
Build
Stage
Test
Deploy
Continuous Integration
Continuous Delivery
Continuous Deployment
Use Correct Image
<hasing algorithm>:<hash value>
sha256:287379gaggfaghagja....
Tag: human-friendly way to identify image version
Example : ngnix:latest
1. Use immutable tags
a. Orchestrator will pull an image with a unique identifier
2. Keep using mutable(latest) tag but augment with automated mechanism
3.Use digest instead of tags
Securing Hosts and Container Working Environment
Running a Container as Root
- User interaction in Dockerfile Set user ID for a Container
$ docker run --user 0 myImage
Override image instruction by starting a container as root with
$ docker run --user command
Privileged Containers
- Container running as root ≠ Privileged container
- Open Container Initiative (OCI) specification default capabilities
https://github.com/opencontainers/runc/blob/main/libcontainer/SPEC.md#security
$ docker run --privileged myImage
- Privileged containers pierce the wall of security between OS and Containers
- Most application containers do not need to run in privileged mode
Container Networking
Standalone Containers
- multiple network drivers facilitate container communication
- Bridge
- special : Host, None
- Underlay networks
- overlay networks
Underlaying Network
- Container Communication by leveraging underlying physical interface
- Media access control virtual area network (Macvlan)
- Internet Protocol VLAN (ipvlan)
Overlay Networks
- Container communication by leveraging a virtual network
- Virtual network sits above host networks
Container Ports
- Containers are not directly routable from outside their cluster
- Map host port to target container port
-
$ docker run -p 8088:8080/tcp
Privileged Ports
- Docker automatically maps containers ports to available host port range (49153-65535)
- No restrictions on assigning privileged host ports(1-1024)
- Review of Dockerfile and audit of running containers
Docker Socket
process with access to socket file
can send any command to daemon
Do not mount socket inside a container
Default Network Bridge Security
every container has read access to traffic
Disable setting in docker daemon configuration file
Create a new bridge network and attach
only containers that need to communicate
Host OS Protection
Potential for error & fraud
New attack vector
Configuration drift
Run Immutable host
Minimise Direct access to host
- lets k8s run and manage your containers
- treat your hosts as cattle , not pets
Host OS Vulnerabilities
- Use standardised and approved VM images for the hosts
- Continuously scan for security vulnerabilities
Host file system
- Protect host file system from malicious containers
- Mount host file system as read only to container
- Reduce attack spillover
- Containers not tied to a host
Securing Application In Kubernetes
Access Management
Authentication
- service accounts managed within Kubernetes
- User account managed outside of Kubernetes
Authentication Methods
- Static authentication or token file
- X.509 client certificate
- OpenID Connect Tokens
- Service Account Tokens
others
Information is stored in a file
Password, username , and user ID
Base64-encoded value of user:password
Method should not be used in enterprise env
Based on OAuth 2.0 spec
Mechanism for generation and refreshing tokens
Service account
- Authenticating application using ServiceAccount
- Each pod is assigned a ServiceAccount by Default
- ServiceAccount allows controlling which resources a pod can access
$ kubectl create serviceaccount mySvcAct
#Pod Spec With a Custom Service Account
apiVersion: v1
Kind: Pod
spec:
ServiceAccountName: mySvcAct
Authorization
- weather request operation is permitted
- by default , all permission are denied
- verbs: create , update , delete and get
- Granular validation by admission controller
Role-based access control
- Recommendation Strategy: RBAC
- Grant or Deny access to operation based on subject's role
get | create | update | Delete | |
---|---|---|---|---|
a | x | |||
b | x | x | ||
c | x | x | x |
- Intercepts request and validates
- Over 30 different admission controller plugins
$ kube-apiserver --enable-admission-plugins+<...>
Why Security Context and Policies
- Access Control is required but ....
- Containers share a thin wall with the OS
- with Kubernetes , need a mechanism
- Security Context and Security Policies
Security Content vs Security policy
Security Context
- Mechanism for Developer
Security Policy
- Mechanism for admins
- Implemented via admission contrillers
Security Context in Pod Specification
# setting security context at container level
apiVersion: v1
Kind : Pod
spec:
Containers:
SecurityContext:
runAsNonRoot: true
privileged: true
...
...
# setting security context at pod level
apiVersion: v1
Kind : Pod
spec:
SecurityContext:
runAsUser: 999
Security Policy
# pod security policy
apiVersion: v1
Kind : PodSecurityPolicy
spec:
runAsUser:
rule: runAsAny
privileged: false
readOnlyRootFileSystem: true
- enable admins
- Prevent pods(containers) that violate
security policies
Security Controls with PodSecurityPolicy
privileged: false
runAsUser
Rule: MustRunAsNonRoot
readOnlyFileSyatem: true
Containers not permitted to run as privileged containers
Containers must not run as root
Containers must only run with a read-only root file system
allowedCapabilities:
SYS_TIME
requiredDropCapabilities:
SYS_ADMIN
Containers may add from only allowed capabilities
Containers must drop these capabilities
Kubernetes Network Security
- Kubernetes networking is different
- Designed to be backward compatible
- Every Pod can talk to other pods
- Pod Networking implemented via networking plugins
- Simplicity leads to network security challenges
Network Policies
- Not all pods need to talk to each other
- Segment your network
- Network Policies let you control inter-pod traffic
- Network plugin must support network policies
# Network Policy
kind: NetworkPolicy
spec:
podSelector:
matchLabels:
svcType: catalog
policyTypes:
- Ingress
- Egress
...
Network policy Example
- use labels to select pods the policy applied to
- Ingress : Incoming traffic
- Egress: outgoing traffic
# Network Policy
kind: NetworkPolicy
spec:
podSelector:
matchLabels:
svcType: inventory
ingress:
- from:
- podSelector:
matchlabels:
svcType: order
- Applies to pod matching label
- Allows only incoming traffic from matching pods
Secrets
- allow pods to get access to secrets
- Kubernetes components need access to secrets
- Secret object: key-value pair
- Stored in etcd as base64 encoded
kind: Pod
spec:
containers:
volumeMounts:
- name: mySecrets
mountPath: /etc/data
volumes:
- name: mySecrets
secret:
secretName: mykeys
# Pod specification
kind: Pod
spec:
containers:
env:
- name: MY_VAULT_KEY //env variable
valueFrom:
name: mykeys
key: myVautkey
Secrets
- Preferred approach : use secret volume
- Values may be stored in log files
- child process inherits environment of parent process
Hunt for threats in production platforms, and rank them based on their risk-of-exploit.
give a git start for ThreatMapper !
Cloud-Native Application Protection Platform
ETCD Security
- Pain text data storage
- Transport Security with HTTPS
- Authentication with HTTPS certificate
ETCD
api server
hey etcd
store this data
name:sangam
ETCD
hacker
etcd dump
ETCD_VER=v3.5.1
# choose either URL
GOOGLE_URL=https://storage.googleapis.com/etcd
GITHUB_URL=https://github.com/etcd-io/etcd/releases/download
DOWNLOAD_URL=${GOOGLE_URL}
rm -f /tmp/etcd-${ETCD_VER}-darwin-amd64.zip
rm -rf /tmp/etcd-download-test && mkdir -p /tmp/etcd-download-test
curl -L ${DOWNLOAD_URL}/${ETCD_VER}/etcd-${ETCD_VER}-darwin-amd64.zip -o /tmp/etcd-${ETCD_VER}-darwin-amd64.zip
unzip /tmp/etcd-${ETCD_VER}-darwin-amd64.zip -d /tmp && rm -f /tmp/etcd-${ETCD_VER}-darwin-amd64.zip
mv /tmp/etcd-${ETCD_VER}-darwin-amd64/* /tmp/etcd-download-test && rm -rf mv /tmp/etcd-${ETCD_VER}-darwin-amd64
/tmp/etcd-download-test/etcd --version
/tmp/etcd-download-test/etcdctl version
/tmp/etcd-download-test/etcdutl version
mv /tmp/etcd-download-test/etcd /usr/local/bin/
etcd
etcdctl put mykey "this is awesome"
etcdctl get mykey
etcd_version=v3.4.16
curl -L https://github.com/coreos/etcd/releases/download/$etcd_version/etcd-$etcd_version-linux-amd64.tar.gz
-o etcd-$etcd_version-linux-amd64.tar.gz
tar xzvf etcd-$etcd_version-linux-amd64.tar.gz
rm etcd-$etcd_version-linux-amd64.tar.gz
cp etcd-$etcd_version-linux-amd64/etcdctl /usr/local/bin/
rm -rf etcd-$etcd_version-linux-amd64
etcdctl version
Install etcdctl On Ubuntu 16.04/18.04
Get etcd information
kubectl describe pod etcd-master -n kube-system
master1_ip=172.60.70.150
master1_ip=172.60.70.151
master1_ip=172.60.70.152
export endpoint="https://172.60.70.150:2379,${master2_ip}:2379,${master3_ip}:2379"
export flags="--cacert=/etc/kubernetes/pki/etcd/ca.crt \
--cert=/etc/kubernetes/pki/etcd/server.crt \
--key=/etc/kubernetes/pki/etcd/server.key"
endpoints=$(sudo ETCDCTL_API=3 etcdctl member list $flags --endpoints=${endpoint} \
--write-out=json | jq -r '.members | map(.clientURLs) | add | join(",")')
check etcd server on master nodes
verify with these commands
sudo ETCDCTL_API=3 etcdctl $flags --endpoints=${endpoints} member list
sudo ETCDCTL_API=3 etcdctl $flags --endpoints=${endpoints} endpoint status
sudo ETCDCTL_API=3 etcdctl $flags --endpoints=${endpoints} endpoint health
sudo ETCDCTL_API=3 etcdctl $flags --endpoints=${endpoints} alarm list
etcdctl member list $flags --endpoints=${endpoint} --write-out=table
etcdctl endpoint status $flags --endpoints=${endpoint} --write-out=table
ETCDCTL_API=3 etcdctl --endpoints=[ENDPOINT] --cacert=[CA CERT] --cert=[ETCD SERVER CERT]
--key=[ETCD SERVER KEY] snapshot save [BACKUP FILE NAME]
Backup | Restore etcd
Commnads pattern:
Sample command:
ETCDCTL_API=3 etcdctl --endpoints ${endpoints} $flags snapshot save kubeme-test
ETCDCTL_API=3 etcdctl --endpoints ${endpoints} $flags snapshot status kubeme-test
ETCDCTL_API=3 etcdctl --endpoints ${endpoints} $flags snapshot restore kubeme-test
A Kubernetes CronJob to Back Up the etcd Data
apiVersion: batch/v1beta1
kind: CronJob
metadata:
name: backup
namespace: kube-system
spec:
# Run every six hours.
schedule: "0 */6 * * *"
jobTemplate:
spec:
template:
spec:
containers:
- name: backup
# Same image as in /etc/kubernetes/manifests/etcd.yaml
image: k8s.gcr.io/etcd-amd64:3.1.12
env:
- name: ETCDCTL_API
value: "3"
command: ["/bin/sh"]
args: ["-c", "etcdctl --endpoints=https://127.0.0.1:2379 --cacert=/etc/kubernetes/pki/etcd/ca.crt --cert=/etc/kubernetes/pki/etcd/healthcheck-client.crt --key=/etc/kubernetes/pki/etcd/healthcheck-client.key snapshot save /backup/etcd-snapshot-$(date +%Y-%m-%d_%H:%M:%S_%Z).db"]
volumeMounts:
- mountPath: /etc/kubernetes/pki/etcd
name: etcd-certs
readOnly: true
- mountPath: /backup
name: etcd-backup-dir
restartPolicy: OnFailure
nodeSelector:
node-role.kubernetes.io/master: ""
tolerations:
- effect: NoSchedule
operator: Exists
hostNetwork: true
volumes:
- name: etcd-certs
hostPath:
path: /etc/kubernetes/pki/etcd
type: DirectoryOrCreate
- name: etcd-backup-dir
hostPath:
path: /opt/etcd-backup
type: DirectoryOrCreate
A Kubernetes CronJob to Back Up the etcd Data
export ETCDCTL_API=3
export ETCDCTL_CACERT=/etc/kubernetes/pki/etcd/ca.crt
export ETCDCTL_CERT=/etc/kubernetes/pki/etcd/healthcheck-client.crt
export ETCDCTL_KEY=/etc/kubernetes/pki/etcd/healthcheck-client.key
etcdctl get /registry/services/specs/default/kubernetes
etcd cheet sheet
kubectl create job --from=cronjob/<cronjob-name> <job-name>
run job from cronjob
Demistifying Kubernetes Security
By Sangam Biradar
Demistifying Kubernetes Security
- 1,303