K8s API access from POD without automountServiceAccountToken
Here we are going to explain How K8s API access from POD without automountServiceAccount Token. A service account token is typically used to authenticate the service account and authorize access to particular resources when the CNF (Cloud Native Function) is deployed and operating on Kubernetes (K8s). One such pod is connected to OAM.
A pod will automatically have access to the default service account token of the associated Service Account if the automountServiceAccountToken option is set to true in the specification of the pod. Instead of requiring manual configuration, the service account token is automatically mounted on a pod’s filesystem and provided to pods.
Actions may be taken in the related namespace using the default token of the service account. It has access to and control over resources in that namespace, including adding and removing services, pods, and configuration maps. It can also be used to request data from the Kubernetes API server, such as the status of the cluster’s nodes, pods, and services.
This can be a practical method for cluster-wide authentication and authorization, but it also raises several security problems:
- To ensure that all pods have access to the service account token, which is necessary for authentication and authorization to the Kubernetes API server, automount the token.
- A security risk can arise while mounting a service account token in a pod’s filesystem. An attacker can access the service account token and use it to gain unauthorized access to the Kubernetes cluster if they acquire access to the pod’s filesystem.
- Mounting the service account token in a pod’s filesystem increases the pod’s attack surface, making it more vulnerable to security risks.
Because of this, the automountServiceAccountToken parameter in the pod specification should be set to false in order to prevent using service account tokens with elevated privileges, according to the CNF best practice concept.
The Service Account token won’t be mounted in a pod’s filesystem automatically if automountServiceAccountToken is set to false. The token must instead be manually mounted or sent to the pod using a different means.
The automatic mounting of the Service Account token can be disabled for security reasons to decrease the attack surface of the pod and its susceptibility to security threats. Developers have more control over the Service Account token’s use and storage if the automatic mounting of the token is disabled.
Disabling the automated mounting of the Service Account token may increase security, but it may also complicate configuration, which can be difficult and time-consuming. Additionally, as the token needs to be mounted to the pod manually or by another means, this activity can lead to an increase in maintenance requirements.
In this blog post, we’ll look at how to increase security by using OpenShift bound service account tokens, implementing RBAC to service accounts in place of using default service account tokens, and setting the “automountServiceAccountToken” parameter to false for pods that require access to the Kubernetes API.
Bound Service Account Token Volumes
Three sources make up this projected volume:
- A ServiceAccountToken is obtained through the TokenRequest API from the kube-apiserver. By default, it will expire after an hour or when the pod is deleted. The audience is a kube-apiserver, and it is tied to the pod.
- A ConfigMap containing a CA bundle for kube-apiserver connection verification. The RootCAConfigMap feature gate, which distributes a “kube-root-ca.crt” ConfigMap to each namespace, is a prerequisite for this feature. With version 1.21, the RootCA ConfigMap feature gate graduated to GA and has a true default value. (In 1.22) this flag will be dropped from the —feature-gate arg.
- A DownwardAPI that makes use of the pod’s namespace.
Using the Bound Service Token and Project Volume, test and validate the automountServiceAccountToken set to false.
CREATE SERVICEACCOUNT
create-sa.yaml:
apiVersion: v1 kind: ServiceAccount metadata: name: ava-sa namespace: ava
$ oc apply -f create-sa.yaml
CREATE ROLE AND ROLEBINDING
Please modify the Role rules according to your requirements
create-sa-token-rbac.yaml:
apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: ava-token-role rules: - apiGroups: ["*"] resources: - pods - nodes - namespaces verbs: - get - list - watch --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: ava-token-role namespace: ava roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: ava-token-role subjects: - kind: ServiceAccount name: ava-sa namespace: ava
$ oc create -f create-sa-token-rbac.yaml
CREATE POD TO ACCESS KUBE-API USING THE DEPLOYMENT
create-sa-token-pod.yml:
apiVersion: apps/v1 kind: Deployment metadata: name: sa-token-deployment spec: selector: matchLabels: app: sa-token replicas: 1 template: metadata: labels: app: sa-token spec: automountServiceAccountToken: false serviceAccountName: ava-sa containers: - name: sa-token image: registry.redhat.io/openshift4/dpdk-base-rhel8:v4.9.0-7 command: ["/bin/sh", "-ec", "while :; do echo '.'; sleep infinity ; done"] volumeMounts: - mountPath: /var/run/secrets/kubernetes.io/serviceaccount name: kube-api-access readOnly: true env: - name: KUBERNETES_SERVICE_PORT value: "6443" - name: KUBERNETES_SERVICE_HOST value: "127.0.0.1" - name: NODE_NAME valueFrom: fieldRef: fieldPath: spec.nodeName volumes: - name: kube-api-access projected: defaultMode: 420 sources: - serviceAccountToken: expirationSeconds: 7200 path: token - configMap: items: - key: ca.crt path: ca.crt name: kube-root-ca.crt - downwardAPI: items: - fieldRef: apiVersion: v1 fieldPath: metadata.namespace path: namespace
$ oc apply -f create-sa-token-pod.yml
$ oc get po NAME READY STATUS RESTARTS AGE sa-token-deployment-57985d7db7-jfn6f 1/1 Running 0 5s $ oc exec -it sa-token-deployment-57985d7db7-jfn6f -- bash bash-4.4$ df -h|grep run tmpfs 155G 16K 155G 1% /run/secrets/kubernetes.io/serviceaccount bash-4.4$ ls -lrt /run/secrets/kubernetes.io/serviceaccount total 0 lrwxrwxrwx. 1 root 1000740000 12 Mar 9 23:05 token -> ..data/token lrwxrwxrwx. 1 root 1000740000 16 Mar 9 23:05 namespace -> ..data/namespace lrwxrwxrwx. 1 root 1000740000 13 Mar 9 23:05 ca.crt -> ..data/ca.crt
START TESTING THE KUBE-API ACCESS INSIDE POD
- Basic Kube-API access
bash-4.4$ APISERVER=https://$KUBERNETES_PORT_443_TCP_ADDR:$KUBERNETES_PORT_443_TCP_PORT bash-4.4$ SERVICEACCOUNT=/run/secrets/kubernetes.io/serviceaccount bash-4.4$ NAMESPACE=$(cat ${SERVICEACCOUNT}/namespace) bash-4.4$ TOKEN=$(cat ${SERVICEACCOUNT}/token) bash-4.4$ CACERT=${SERVICEACCOUNT}/ca.crt bash-4.4$ curl --cacert ${CACERT} --header "Authorization: Bearer ${TOKEN}" -X GET ${APISERVER}/api { "kind": "APIVersions", "versions": [ "v1" ], "serverAddressByClientCIDRs": [ { "clientCIDR": "0.0.0.0/0", "serverAddress": "192.168.24.111:6443" } ] }
- List the POD from specific namespace using Kube-API
$ curl --cacert ${CACERT} --header "Authorization: Bearer ${TOKEN}" -X GET ${APISERVER}/api/v1/namespaces/ava/pods/$HOSTNAME { "kind": "Pod", "apiVersion": "v1", "metadata": { "name": "sa-token-deployment-57985d7db7-jfn6f", "generateName": "sa-token-deployment-57985d7db7-", "namespace": "ava", "uid": "36f5427f-b189-4bdc-853e-1516f6c2af68", "resourceVersion": "193708503", "creationTimestamp": "2023-03-09T23:05:09Z", "labels": { "app": "sa-token", "pod-template-hash": "57985d7db7" }, ... "hostIP": "192.168.24.111", "podIP": "10.132.0.215", "podIPs": [ { "ip": "10.132.0.215" } ], "startTime": "2023-03-09T23:05:09Z", "containerStatuses": [ { "name": "sa-token", "state": { "running": { "startedAt": "2023-03-09T23:05:12Z" } },
Conclusion
The “automountServiceAccountToken” feature in Kubernetes deployments should be enabled or disabled based on the particular security needs and specifications of the application. While turning on this function enhances the pod’s attack surface while simultaneously offering convenience and security benefits. Disabling it, on the other side, minimizes the attack surface but demands more configuration and upkeep. So, before making a choice, the developer should carefully weigh the advantages and disadvantages.
Setting “automountServiceAccountToken” to false may not eliminate security vulnerabilities because the token and ca.crt is still mounted even with bound service account token Volumes and RBAC implementation to the service account. By managing the security constraints connected to the service account, RBAC and OpenShift Security Context Constraints (SCC) can be utilized to reduce the risks in this situation.
To further reduce needless security risks to the application, automountServiceAccountToken should be set to false for any pods that are not required to use the Kube-API. K8s API access from POD.