Secure Bootstrapping: Hardening Kubernetes from Day Zero

Secure Bootstrapping: Hardening Kubernetes from Day Zero

Introduction

By mid-2023, security-first bootstrapping had become a critical requirement for Kubernetes deployments. With increasing regulatory compliance requirements and sophisticated threat landscapes, teams could no longer afford to harden clusters after deployment—security had to be built in from day zero.

This mattered because retroactive security hardening is expensive, error-prone, and often incomplete. Building security into the bootstrapping process ensures that clusters start with strong security defaults, reducing the attack surface from the moment they’re created and making compliance audits significantly easier.

Historical note: The CIS Kubernetes Benchmark had been available since 2018, but 2023 saw increased adoption of automated security hardening tools and kubeadm security configurations that made secure bootstrapping more accessible.

Security-First Bootstrapping Principles

Defense in Depth

  • Multiple Security Layers: Network policies, RBAC, Pod Security Standards, and encryption.
  • Least Privilege: Default deny, explicit allow policies.
  • Zero Trust: Assume breach, verify everything.
  • Audit Everything: Comprehensive logging and monitoring from day one.

Secure Defaults

  • RBAC Enabled: Role-Based Access Control enabled by default.
  • Network Policies: Network isolation enabled from cluster creation.
  • Pod Security: Pod Security Standards enforced.
  • Encryption: Encryption at rest and in transit enabled.

CIS Kubernetes Benchmark Integration

Automated Benchmarking

Tools like kube-bench can validate cluster security:

# Install kube-bench
curl -L https://github.com/aquasecurity/kube-bench/releases/download/v0.6.10/kube-bench_0.6.10_linux_amd64.tar.gz -o kube-bench.tar.gz
tar -xzf kube-bench.tar.gz
sudo mv kube-bench /usr/local/bin/

# Run CIS benchmark
kube-bench run --targets master,node,etcd,policies

kubeadm Security Configuration

# kubeadm-config-secure.yaml
apiVersion: kubeadm.k8s.io/v1beta3
kind: ClusterConfiguration
kubernetesVersion: v1.28.0
apiServer:
  extraArgs:
    # Enable audit logging
    audit-log-path: /var/log/audit.log
    audit-log-maxage: "30"
    audit-log-maxbackup: "10"
    audit-log-maxsize: "100"
    # Enable admission controllers
    enable-admission-plugins: "NodeRestriction,PodSecurityPolicy"
    # Disable insecure ports
    insecure-port: "0"
    # Enable RBAC
    authorization-mode: "Node,RBAC"
  extraVolumes:
  - name: "audit"
    hostPath: "/var/log/audit"
    mountPath: "/var/log/audit"
    readOnly: false
controllerManager:
  extraArgs:
    # Enable Pod Security Standards
    feature-gates: "PodSecurity=true"
scheduler:
  extraArgs:
    # Enable Pod Security Standards
    feature-gates: "PodSecurity=true"
---
apiVersion: kubeadm.k8s.io/v1beta3
kind: InitConfiguration
nodeRegistration:
  kubeletExtraArgs:
    # Enable kubelet authentication
    authentication-token-webhook: "true"
    authorization-mode: "Webhook"
    # Enable seccomp
    seccomp-default: "true"

Pod Security Standards

Enforce Pod Security

# Enable Pod Security Standards during bootstrap
apiVersion: v1
kind: Namespace
metadata:
  name: production
  labels:
    pod-security.kubernetes.io/enforce: restricted
    pod-security.kubernetes.io/audit: restricted
    pod-security.kubernetes.io/warn: restricted
---
# Apply to all namespaces
apiVersion: v1
kind: Namespace
metadata:
  name: default
  labels:
    pod-security.kubernetes.io/enforce: baseline
    pod-security.kubernetes.io/audit: restricted
    pod-security.kubernetes.io/warn: restricted

Pod Security Policy (Legacy)

For clusters still using Pod Security Policy:

apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
  name: restricted
spec:
  privileged: false
  allowPrivilegeEscalation: false
  requiredDropCapabilities:
    - ALL
  volumes:
    - 'configMap'
    - 'emptyDir'
    - 'projected'
    - 'secret'
    - 'downwardAPI'
    - 'persistentVolumeClaim'
  hostNetwork: false
  hostIPC: false
  hostPID: false
  runAsUser:
    rule: 'MustRunAsNonRoot'
  seLinux:
    rule: 'RunAsAny'
  fsGroup:
    rule: 'RunAsAny'
  readOnlyRootFilesystem: false

Network Security

Network Policies

Enable network isolation from day zero:

# Default deny all traffic
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-all
  namespace: default
spec:
  podSelector: {}
  policyTypes:
  - Ingress
  - Egress
---
# Allow DNS
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-dns
  namespace: default
spec:
  podSelector: {}
  policyTypes:
  - Egress
  egress:
  - to:
    - namespaceSelector:
        matchLabels:
          name: kube-system
    ports:
    - protocol: UDP
      port: 53

CNI Security Features

Enable CNI-specific security features:

# Calico with network policies
apiVersion: operator.tigera.io/v1
kind: Installation
metadata:
  name: default
spec:
  calicoNetwork:
    ipPools:
    - blockSize: 26
      cidr: 10.244.0.0/16
      encapsulation: VXLANCrossSubnet
      natOutgoing: true
  # Enable network policies
  typha:
    replicas: 2

Encryption

Encryption at Rest

# Enable encryption at rest for etcd
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
  - resources:
    - secrets
    providers:
    - aescbc:
        keys:
        - name: key1
          secret: <BASE64-ENCODED-SECRET>
    - identity: {}

Encryption in Transit

# kubeadm automatically configures TLS
# Verify TLS configuration
kubectl get configmap cluster-info -n kube-public -o yaml

RBAC Configuration

Secure RBAC Defaults

# Disable default service account token mounting
apiVersion: v1
kind: ServiceAccount
metadata:
  name: default
  namespace: default
automountServiceAccountToken: false
---
# Create least-privilege roles
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: pod-reader
  namespace: default
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: pod-reader-binding
  namespace: default
subjects:
- kind: User
  name: developer
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: pod-reader
  apiGroup: rbac.authorization.k8s.io

Audit Logging

Comprehensive Audit Configuration

# kubeadm-config with audit logging
apiVersion: kubeadm.k8s.io/v1beta3
kind: ClusterConfiguration
apiServer:
  extraArgs:
    audit-log-path: /var/log/audit/audit.log
    audit-log-maxage: "30"
    audit-log-maxbackup: "10"
    audit-log-maxsize: "100"
    audit-policy-file: /etc/kubernetes/audit-policy.yaml
  extraVolumes:
  - name: "audit"
    hostPath: "/var/log/audit"
    mountPath: "/var/log/audit"
    readOnly: false
  - name: "audit-policy"
    hostPath: "/etc/kubernetes/audit-policy.yaml"
    mountPath: "/etc/kubernetes/audit-policy.yaml"
    readOnly: true

Audit Policy

# /etc/kubernetes/audit-policy.yaml
apiVersion: audit.k8s.io/v1
kind: Policy
rules:
  # Log all requests
  - level: Metadata
  # Log sensitive operations
  - level: RequestResponse
    verbs: ["create", "update", "patch", "delete"]
    resources:
    - group: ""
      resources: ["secrets", "configmaps"]
    - group: "rbac.authorization.k8s.io"
      resources: ["roles", "rolebindings", "clusterroles", "clusterrolebindings"]

Comparison: Secure Defaults Across Installers

Security FeaturekubeadmkopsManaged Services
RBACEnabled by defaultEnabled by defaultEnabled by default
Network PoliciesManual (CNI-dependent)Manual (CNI-dependent)Varies by provider
Pod SecurityManual configurationManual configurationVaries by provider
Encryption at RestManual configurationManual configurationVaries by provider
Audit LoggingManual configurationManual configurationProvider-managed
CIS ComplianceManual (kube-bench)Manual (kube-bench)Provider-specific

Compliance-Ready Bootstrapping

Automated Security Hardening

Tools like kubespray with security hardening:

# kubespray security configuration
kube_apiserver_audit_log: true
kube_apiserver_audit_log_maxage: 30
kube_apiserver_audit_log_maxbackup: 10
kube_apiserver_audit_log_maxsize: 100
kube_apiserver_enable_admission_plugins:
  - NodeRestriction
  - PodSecurityPolicy
kube_apiserver_insecure_port: 0

Security Scanning

# Scan cluster for vulnerabilities
trivy k8s cluster --severity HIGH,CRITICAL

# Scan container images
trivy image k8s.gcr.io/kube-apiserver:v1.28.0

Practical Considerations

Security Checklist

Before deploying production clusters:

  1. RBAC: Enable RBAC, create least-privilege roles.
  2. Network Policies: Enable network isolation, create default deny policies.
  3. Pod Security: Enforce Pod Security Standards or Pod Security Policies.
  4. Encryption: Enable encryption at rest and in transit.
  5. Audit Logging: Configure comprehensive audit logging.
  6. Image Scanning: Scan all container images for vulnerabilities.
  7. Secret Management: Use external secret management (Vault, AWS Secrets Manager).
  8. Compliance: Run CIS benchmark, document compliance status.

Ongoing Security

  • Regular Audits: Run security audits regularly (kube-bench, trivy).
  • Update Management: Keep Kubernetes and components updated.
  • Policy Enforcement: Use policy engines (OPA, Kyverno) for ongoing enforcement.
  • Monitoring: Monitor security events and anomalies.

Caveats & Lessons Learned

  • Performance Impact: Security features (encryption, audit logging) can impact performance; test and tune.
  • Compatibility: Some security features may break applications; test thoroughly.
  • Complexity: Secure configurations are more complex; document and automate.
  • Maintenance: Security configurations require ongoing maintenance and updates.

Common Failure Modes

  • “RBAC too restrictive”: Applications fail due to insufficient permissions; create appropriate roles.
  • “Network policies block traffic”: Applications can’t communicate; create allow policies.
  • “Pod Security blocks workloads”: Pods fail to start; adjust security policies.

Conclusion

Secure bootstrapping in 2023 had become a non-negotiable requirement for production Kubernetes deployments. With increasing regulatory compliance requirements and sophisticated threat landscapes, teams could no longer afford to harden clusters after deployment—security had to be built in from day zero.

The tools and patterns that emerged in 2023—CIS Kubernetes Benchmark integration, kubeadm security configurations, and automated security hardening—made secure bootstrapping more accessible and reliable. Teams could now deploy clusters with strong security defaults from the start, reducing the attack surface and making compliance audits significantly easier.

For organizations requiring secure, compliant Kubernetes deployments, secure bootstrapping represented the foundation of a defense-in-depth security strategy. It demonstrated that Kubernetes security didn’t have to be retroactive—it could be proactive, built-in, and automated from day zero.