From d487b2f927965782f45f1f8ddfcce11f52dac9c6 Mon Sep 17 00:00:00 2001
From: Matthew Mosesohn <matthew.mosesohn@gmail.com>
Date: Sun, 15 Oct 2017 20:41:17 +0100
Subject: [PATCH] Security best practice fixes (#1783)

* Disable basic and token auth by default

* Add recommended security params

* allow basic auth to fail in tests

* Enable TLS authentication for kubelet
---
 docs/getting-started.md                                     | 6 +++++-
 inventory/group_vars/k8s-cluster.yml                        | 4 ++--
 roles/kubernetes/master/defaults/main.yml                   | 4 ++--
 roles/kubernetes/master/templates/kubeadm-config.yaml.j2    | 2 +-
 .../master/templates/manifests/kube-apiserver.manifest.j2   | 5 +++++
 .../templates/manifests/kube-controller-manager.manifest.j2 | 4 +++-
 .../master/templates/manifests/kube-scheduler.manifest.j2   | 1 +
 roles/kubernetes/node/templates/kubelet.standard.env.j2     | 3 +++
 tests/testcases/010_check-apiserver.yml                     | 2 +-
 9 files changed, 23 insertions(+), 8 deletions(-)

diff --git a/docs/getting-started.md b/docs/getting-started.md
index 95f9c222a..67b6132af 100644
--- a/docs/getting-started.md
+++ b/docs/getting-started.md
@@ -93,7 +93,8 @@ the Kubernetes [documentation](https://kubernetes.io/docs/tasks/access-applicati
 Accessing Kubernetes Dashboard
 ------------------------------
 
-If the variable `dashboard_enabled` is set (default is true), then you can
+If the variable `dashboard_enabled` is set (default is true) as well as
+kube_basic_auth (default is false), then you can
 access the Kubernetes Dashboard at the following URL:
 
   https://kube:_kube-password_@_host_:6443/ui/
@@ -102,6 +103,9 @@ To see the password, refer to the section above, titled *Connecting to
 Kubernetes*. The host can be any kube-master or kube-node or loadbalancer
 (when enabled).
 
+To access the Dashboard with basic auth disabled, follow the instructions here:
+https://kubernetes.io/docs/tasks/access-application-cluster/web-ui-dashboard/#command-line-proxy
+
 Accessing Kubernetes API
 ------------------------
 
diff --git a/inventory/group_vars/k8s-cluster.yml b/inventory/group_vars/k8s-cluster.yml
index a1d98ec14..9c6a281a0 100644
--- a/inventory/group_vars/k8s-cluster.yml
+++ b/inventory/group_vars/k8s-cluster.yml
@@ -50,8 +50,8 @@ kube_users:
 
 ## It is possible to activate / deactivate selected authentication methods (basic auth, static token auth)
 #kube_oidc_auth: false
-#kube_basic_auth: true
-#kube_token_auth: true
+#kube_basic_auth: false
+#kube_token_auth: false
 
 
 ## Variables for OpenID Connect Configuration https://kubernetes.io/docs/admin/authentication/
diff --git a/roles/kubernetes/master/defaults/main.yml b/roles/kubernetes/master/defaults/main.yml
index d86088623..487414e7b 100644
--- a/roles/kubernetes/master/defaults/main.yml
+++ b/roles/kubernetes/master/defaults/main.yml
@@ -52,8 +52,8 @@ kube_api_runtime_config:
   - admissionregistration.k8s.io/v1alpha1
 
 ## Enable/Disable Kube API Server Authentication Methods
-kube_basic_auth: true
-kube_token_auth: true
+kube_basic_auth: false
+kube_token_auth: false
 kube_oidc_auth: false
 
 ## Variables for OpenID Connect Configuration https://kubernetes.io/docs/admin/authentication/
diff --git a/roles/kubernetes/master/templates/kubeadm-config.yaml.j2 b/roles/kubernetes/master/templates/kubeadm-config.yaml.j2
index f5571a87d..2bc56cdeb 100644
--- a/roles/kubernetes/master/templates/kubeadm-config.yaml.j2
+++ b/roles/kubernetes/master/templates/kubeadm-config.yaml.j2
@@ -48,7 +48,7 @@ apiServerExtraArgs:
 {% endif %}
   storage-backend: {{ kube_apiserver_storage_backend }}
 {% if kube_api_runtime_config is defined %}
-  runtime-config: {{ kube_api_runtime_config }}
+  runtime-config: {{ kube_api_runtime_config | join(',') }}
 {% endif %}
   allow-privileged: "true"
 controllerManagerExtraArgs:
diff --git a/roles/kubernetes/master/templates/manifests/kube-apiserver.manifest.j2 b/roles/kubernetes/master/templates/manifests/kube-apiserver.manifest.j2
index e3fa8fc6f..8de5fb66c 100644
--- a/roles/kubernetes/master/templates/manifests/kube-apiserver.manifest.j2
+++ b/roles/kubernetes/master/templates/manifests/kube-apiserver.manifest.j2
@@ -40,6 +40,11 @@ spec:
     - --service-cluster-ip-range={{ kube_service_addresses }}
     - --service-node-port-range={{ kube_apiserver_node_port_range }}
     - --client-ca-file={{ kube_cert_dir }}/ca.pem
+    - --profiling=false
+    - --repair-malformed-updates=false
+    - --kubelet-client-certificate={{ kube_cert_dir }}/node-{{ inventory_hostname }}.pem
+    - --kubelet-client-key={{ kube_cert_dir }}/node-{{ inventory_hostname }}-key.pem
+    - --service-account-lookup=true
 {% if kube_basic_auth|default(true) %}
     - --basic-auth-file={{ kube_users_dir }}/known_users.csv
 {% endif %}
diff --git a/roles/kubernetes/master/templates/manifests/kube-controller-manager.manifest.j2 b/roles/kubernetes/master/templates/manifests/kube-controller-manager.manifest.j2
index 9be67c01d..705ad6d52 100644
--- a/roles/kubernetes/master/templates/manifests/kube-controller-manager.manifest.j2
+++ b/roles/kubernetes/master/templates/manifests/kube-controller-manager.manifest.j2
@@ -37,9 +37,11 @@ spec:
     - --node-monitor-grace-period={{ kube_controller_node_monitor_grace_period }}
     - --node-monitor-period={{ kube_controller_node_monitor_period }}
     - --pod-eviction-timeout={{ kube_controller_pod_eviction_timeout }}
+    - --profiling=false
+    - --terminated-pod-gc-threshold=12500
     - --v={{ kube_log_level }}
 {% if rbac_enabled %}
-    - --use-service-account-credentials
+    - --use-service-account-credentials=true
 {% endif %}
 {% if cloud_provider is defined and cloud_provider in ["openstack", "azure", "vsphere"] %}
     - --cloud-provider={{cloud_provider}}
diff --git a/roles/kubernetes/master/templates/manifests/kube-scheduler.manifest.j2 b/roles/kubernetes/master/templates/manifests/kube-scheduler.manifest.j2
index 6353ca102..d50c10ed7 100644
--- a/roles/kubernetes/master/templates/manifests/kube-scheduler.manifest.j2
+++ b/roles/kubernetes/master/templates/manifests/kube-scheduler.manifest.j2
@@ -28,6 +28,7 @@ spec:
     - scheduler
     - --leader-elect=true
     - --kubeconfig={{ kube_config_dir }}/kube-scheduler-kubeconfig.yaml
+    - --profiling=false
     - --v={{ kube_log_level }}
 {% if kube_feature_gates %}
     - --feature-gates={{ kube_feature_gates|join(',') }}
diff --git a/roles/kubernetes/node/templates/kubelet.standard.env.j2 b/roles/kubernetes/node/templates/kubelet.standard.env.j2
index 801e4a8e5..03e7da8a0 100644
--- a/roles/kubernetes/node/templates/kubelet.standard.env.j2
+++ b/roles/kubernetes/node/templates/kubelet.standard.env.j2
@@ -14,6 +14,9 @@ KUBELET_HOSTNAME="--hostname-override={{ kube_override_hostname }}"
 --pod-infra-container-image={{ pod_infra_image_repo }}:{{ pod_infra_image_tag }} \
 --node-status-update-frequency={{ kubelet_status_update_frequency }} \
 --docker-disable-shared-pid={{ kubelet_disable_shared_pid }} \
+--client-ca-file={{ kube_cert_dir }}/ca.pem \
+--tls-cert-file={{ kube_cert_dir }}/node-{{ inventory_hostname }}.pem \
+--tls-private-key-file={{ kube_cert_dir }}/node-{{ inventory_hostname }}-key.pem \
 {% if kube_version | version_compare('v1.6', '>=') %}
 {# flag got removed with 1.7.0 #}
 {% if kube_version | version_compare('v1.7', '<') %}
diff --git a/tests/testcases/010_check-apiserver.yml b/tests/testcases/010_check-apiserver.yml
index b86a537fa..504023b59 100644
--- a/tests/testcases/010_check-apiserver.yml
+++ b/tests/testcases/010_check-apiserver.yml
@@ -8,5 +8,5 @@
       user: kube
       password: "{{ lookup('password', '../../credentials/kube_user length=15 chars=ascii_letters,digits') }}"
       validate_certs: no
-      status_code: 200
+      status_code: 200,401
     when: not kubeadm_enabled|default(false)
-- 
GitLab