I suggest binding all kubernetes components to a localhost instead of all interfaces by default.
Having port 8080/tcp (kube-proxy -> kubernetes api server) exposed across all the interfaces completely compromises the system it is running this snap, in case the system does not have strict firewall rules.
Likely the same for 6443/tcp as the certificates are known, IIUC.
$ sudo netstat -tulpan |grep LISTEN |grep kube
tcp 0 0 127.0.0.1:10248 0.0.0.0:* LISTEN 30263/kubelet
tcp 0 0 127.0.0.1:10249 0.0.0.0:* LISTEN 29203/kube-proxy
tcp 0 0 127.0.0.1:42779 0.0.0.0:* LISTEN 30263/kubelet
tcp6 0 0 :::10250 :::* LISTEN 30263/kubelet
tcp6 0 0 :::36555 :::* LISTEN 29203/kube-proxy
tcp6 0 0 :::6443 :::* LISTEN 29224/kube-apiserve
tcp6 0 0 :::10251 :::* LISTEN 29196/kube-schedule
tcp6 0 0 :::10252 :::* LISTEN 29205/kube-controll
tcp6 0 0 :::10255 :::* LISTEN 30263/kubelet
tcp6 0 0 :::8080 :::* LISTEN 29224/kube-apiserve
tcp6 0 0 :::10256 :::* LISTEN 29203/kube-proxy
tcp6 0 0 :::46261 :::* LISTEN 29203/kube-proxy
tcp6 0 0 :::30842 :::* LISTEN 29203/kube-proxy
I am not sure if someone is planning to change this, but at least this deserves a security note in the main readme file and, preferably, before or right after someone runs snap install microk8s so the users are aware of this.
I would like to see a snap config option to select the interface to bind to, with the default being the loopback.
There is a use-case for having microk8s accessible on an interface other than the loopback; I currently use this for testing Juju k8s integration, and this was the motivation for the microk8s.config wrapper. However, it would be cleaner to be able to specify explicitly that I want it to be accessible (and having it not be by default) and have the actual config reflect that choice (so that microk8s.kubectl config view --raw does the right thing and microk8s.config can either go away or remain just as a shortcut).
I think we require accessibility from local lxd containers, but we do need to stop exposing things via public interfaces. $public_ip:8080/logs exposes your system logs, and there are likely other ways to escalate remotely.
Configuring the API server to bind to the localhost only is doable but introduces some annoyances. Services running inside the kubernetes cluster are not able to access the API server because 127.0.0.1 is the pods localhost and not the hosts (actually 127.0.0.1 is an invalid endpoint for the kubernetes service so you are not even able to use it here):
microk8s.kubectl describe service kubernetes
Name: kubernetes
...
Type: ClusterIP
IP: 10.152.183.1
Endpoints: 172.31.14.56:6443
...
This means that services like DNS and the dashboard will not function properly.
What we should do is to first make sure we use the localhost to bind as many services as we can and for the 6443 of the API server to issue certificates at microk8s deploy time.
Another option is to create a virtual interface and use that for binding the API server.
With the updates that went in the past months, the opened ports look like this:
$ sudo netstat -tulpan |grep LISTEN |grep kube
tcp 0 0 127.0.0.1:10251 0.0.0.0:* LISTEN 17850/kube-schedule
tcp 0 0 127.0.0.1:10252 0.0.0.0:* LISTEN 17895/kube-controll
tcp 0 0 127.0.0.1:8080 0.0.0.0:* LISTEN 18387/kube-apiserve
tcp 0 0 127.0.0.1:10256 0.0.0.0:* LISTEN 17915/kube-proxy
tcp 0 0 127.0.0.1:10248 0.0.0.0:* LISTEN 17831/kubelet
tcp 0 0 127.0.0.1:10249 0.0.0.0:* LISTEN 17915/kube-proxy
tcp6 0 0 :::10250 :::* LISTEN 17831/kubelet
tcp6 0 0 :::10255 :::* LISTEN 17831/kubelet
tcp6 0 0 :::10257 :::* LISTEN 17895/kube-controll
tcp6 0 0 :::10259 :::* LISTEN 17850/kube-schedule
tcp6 0 0 :::16443 :::* LISTEN 18387/kube-apiserve
The exposed ports are made secure by other means with the exception of the kubelet read-only one. I am going to close this issue. Please, open a separate issue against a specific port you would like us to investigate if we can have it restricted by default.
Most helpful comment
I think we require accessibility from local lxd containers, but we do need to stop exposing things via public interfaces. $public_ip:8080/logs exposes your system logs, and there are likely other ways to escalate remotely.