You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

138 lines
6.5 KiB

  1. # Cluster Hardening
  2. If you want to improve the security on your cluster and make it compliant with the [CIS Benchmarks](https://learn.cisecurity.org/benchmarks), here you can find a configuration to harden your **kubernetes** installation.
  3. To apply the hardening configuration, create a file (eg. `hardening.yaml`) and paste the content of the following code snippet into that.
  4. ## Minimum Requirements
  5. The **kubernetes** version should be at least `v1.23.6` to have all the most recent security features (eg. the new `PodSecurity` admission plugin, etc).
  6. **N.B.** Some of these configurations have just been added to **kubespray**, so ensure that you have the latest version to make it works properly. Also, ensure that other configurations doesn't override these.
  7. `hardening.yaml`:
  8. ```yaml
  9. # Hardening
  10. ---
  11. ## kube-apiserver
  12. authorization_modes: ['Node', 'RBAC']
  13. # AppArmor-based OS
  14. # kube_apiserver_feature_gates: ['AppArmor=true']
  15. kube_apiserver_request_timeout: 120s
  16. kube_apiserver_service_account_lookup: true
  17. # enable kubernetes audit
  18. kubernetes_audit: true
  19. audit_log_path: "/var/log/kube-apiserver-log.json"
  20. audit_log_maxage: 30
  21. audit_log_maxbackups: 10
  22. audit_log_maxsize: 100
  23. tls_min_version: VersionTLS12
  24. tls_cipher_suites:
  25. - TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
  26. - TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
  27. - TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305
  28. # enable encryption at rest
  29. kube_encrypt_secret_data: true
  30. kube_encryption_resources: [secrets]
  31. kube_encryption_algorithm: "secretbox"
  32. kube_apiserver_enable_admission_plugins:
  33. - EventRateLimit
  34. - AlwaysPullImages
  35. - ServiceAccount
  36. - NamespaceLifecycle
  37. - NodeRestriction
  38. - LimitRanger
  39. - ResourceQuota
  40. - MutatingAdmissionWebhook
  41. - ValidatingAdmissionWebhook
  42. - PodNodeSelector
  43. - PodSecurity
  44. kube_apiserver_admission_control_config_file: true
  45. # EventRateLimit plugin configuration
  46. kube_apiserver_admission_event_rate_limits:
  47. limit_1:
  48. type: Namespace
  49. qps: 50
  50. burst: 100
  51. cache_size: 2000
  52. limit_2:
  53. type: User
  54. qps: 50
  55. burst: 100
  56. kube_profiling: false
  57. ## kube-controller-manager
  58. kube_controller_manager_bind_address: 127.0.0.1
  59. kube_controller_terminated_pod_gc_threshold: 50
  60. # AppArmor-based OS
  61. # kube_controller_feature_gates: ["RotateKubeletServerCertificate=true", "AppArmor=true"]
  62. kube_controller_feature_gates: ["RotateKubeletServerCertificate=true"]
  63. ## kube-scheduler
  64. kube_scheduler_bind_address: 127.0.0.1
  65. # AppArmor-based OS
  66. # kube_scheduler_feature_gates: ["AppArmor=true"]
  67. ## etcd
  68. etcd_deployment_type: kubeadm
  69. ## kubelet
  70. kubelet_authorization_mode_webhook: true
  71. kubelet_authentication_token_webhook: true
  72. kube_read_only_port: 0
  73. kubelet_rotate_server_certificates: true
  74. kubelet_protect_kernel_defaults: true
  75. kubelet_event_record_qps: 1
  76. kubelet_rotate_certificates: true
  77. kubelet_streaming_connection_idle_timeout: "5m"
  78. kubelet_make_iptables_util_chains: true
  79. kubelet_feature_gates: ["RotateKubeletServerCertificate=true", "SeccompDefault=true"]
  80. kubelet_seccomp_default: true
  81. kubelet_systemd_hardening: true
  82. # In case you have multiple interfaces in your
  83. # control plane nodes and you want to specify the right
  84. # IP addresses, kubelet_secure_addresses allows you
  85. # to specify the IP from which the kubelet
  86. # will receive the packets.
  87. kubelet_secure_addresses: "192.168.10.110 192.168.10.111 192.168.10.112"
  88. # additional configurations
  89. kube_owner: root
  90. kube_cert_group: root
  91. # create a default Pod Security Configuration and deny running of insecure pods
  92. # kube_system namespace is exempted by default
  93. kube_pod_security_use_default: true
  94. kube_pod_security_default_enforce: restricted
  95. ```
  96. Let's take a deep look to the resultant **kubernetes** configuration:
  97. * The `anonymous-auth` (on `kube-apiserver`) is set to `true` by default. This is fine, because it is considered safe if you enable `RBAC` for the `authorization-mode`.
  98. * The `enable-admission-plugins` has not the `PodSecurityPolicy` admission plugin. This because it is going to be definitely removed from **kubernetes** `v1.25`. For this reason we decided to set the newest `PodSecurity` (for more details, please take a look here: <https://kubernetes.io/docs/concepts/security/pod-security-admission/>). Then, we set the `EventRateLimit` plugin, providing additional configuration files (that are automatically created under the hood and mounted inside the `kube-apiserver` container) to make it work.
  99. * The `encryption-provider-config` provide encryption at rest. This means that the `kube-apiserver` encrypt data that is going to be stored before they reach `etcd`. So the data is completely unreadable from `etcd` (in case an attacker is able to exploit this).
  100. * The `rotateCertificates` in `KubeletConfiguration` is set to `true` along with `serverTLSBootstrap`. This could be used in alternative to `tlsCertFile` and `tlsPrivateKeyFile` parameters. Additionally it automatically generates certificates by itself, but you need to manually approve them or at least using an operator to do this (for more details, please take a look here: <https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet-tls-bootstrapping/>).
  101. * If you are installing **kubernetes** in an AppArmor-based OS (eg. Debian/Ubuntu) you can enable the `AppArmor` feature gate uncommenting the lines with the comment `# AppArmor-based OS` on top.
  102. * The `kubelet_systemd_hardening`, both with `kubelet_secure_addresses` setup a minimal firewall on the system. To better understand how these variables work, here's an explanatory image:
  103. ![kubelet hardening](img/kubelet-hardening.png)
  104. Once you have the file properly filled, you can run the **Ansible** command to start the installation:
  105. ```bash
  106. ansible-playbook -v cluster.yml \
  107. -i inventory.ini \
  108. -b --become-user=root \
  109. --private-key ~/.ssh/id_ecdsa \
  110. -e "@vars.yaml" \
  111. -e "@hardening.yaml"
  112. ```
  113. **N.B.** The `vars.yaml` contains our general cluster information (SANs, load balancer, dns, etc..) and `hardening.yaml` is the file described above.
  114. Once completed the cluster deployment, don't forget to approve the generated certificates (check them with `kubectl get csr`, approve with `kubectl certificate approve <csr_name>`). This action is necessary because the `secureTLSBootstrap` option and `RotateKubeletServerCertificate` feature gate for `kubelet` are enabled (CIS [4.2.11](https://www.tenable.com/audits/items/CIS_Kubernetes_v1.20_v1.0.0_Level_1_Worker.audit:05af3dfbca8e0c3fb3559c6c7de29191), [4.2.12](https://www.tenable.com/audits/items/CIS_Kubernetes_v1.20_v1.0.0_Level_1_Worker.audit:5351c76f8c5bff8f98c29a5200a35435)).