Creating a Kubeconfig with Limited Permissions
Create a Limited kubeconfig for internal use
Creating a full-access Kubeconfig for your Kubernetes cluster is simple — but not always the most secure approach. In many cases, especially when working with automation, CI/CD pipelines, or giving access to external services, it’s better to generate a more restricted Kubeconfig tailored to specific needs.
In this post, I’ll show you how to create a Kubeconfig with limited permissions, ideal for scenarios where you want to allow just enough access to restart workloads like Pods, Deployments, or StatefulSets — without exposing your entire cluster.
Limit the Kubeconfig as much as you can. A CI pipeline that can only
get/patchtwo resource types in one namespace is a pipeline that can’t do much damage if its secret ever leaks.
Prerequisites
Before getting started, make sure you have:
- Access to a Kubernetes cluster with admin privileges.
kubectlinstalled and configured.- A namespace (or namespaces) where the limited user will operate.
Step 1: Create the ServiceAccount
Create a ServiceAccount that will be used to generate the Kubeconfig.
1
2
3
4
5
apiVersion: v1
kind: ServiceAccount
metadata:
name: restart-bot
namespace: home-assistant
Step 2: Create the ClusterRole
Create the role. Here we’re only allowing it to restart Deployments and StatefulSets.
1
2
3
4
5
6
7
8
9
10
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: restart-any-workload
rules:
- apiGroups: ["apps"]
resources:
- deployments
- statefulsets
verbs: ["get", "patch"]
Step 3: Create the RoleBinding
1
2
3
4
5
6
7
8
9
10
11
12
13
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: restart-binding
namespace: home-assistant
subjects:
- kind: ServiceAccount
name: restart-bot
namespace: home-assistant
roleRef:
kind: ClusterRole
name: restart-any-workload
apiGroup: rbac.authorization.k8s.io
Step 4: Create the token for the ServiceAccount
1
2
3
4
5
6
7
8
apiVersion: v1
kind: Secret
metadata:
name: restart-bot-token
namespace: home-assistant
annotations:
kubernetes.io/service-account.name: restart-bot
type: kubernetes.io/service-account-token
Step 5: Build your Kubeconfig
certificate-authority-data: take the value from your original Kubeconfig.token: take the value from therestart-bot-tokensecret created above.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
apiVersion: v1
kind: Config
clusters:
- name: your-cluster
cluster:
server: https://cluster-ip:6443
certificate-authority-data: <your original certificate>
users:
- name: restart-bot-ha
user:
token: <your token>
contexts:
- name: restart-bot-ha-context
context:
cluster: your-cluster
user: restart-bot-ha
namespace: home-assistant
current-context: restart-bot-ha-context
Never commit the generated Kubeconfig to git, even in a private repo. Store the token as a proper CI secret (GitHub Actions secret, Azure DevOps variable group, etc.) and template the rest of the file at deploy time.
✅ Done
You now have a Kubeconfig scoped to exactly one thing: restarting Deployments and StatefulSets in a single namespace. Reuse this pattern (ServiceAccount → ClusterRole → RoleBinding → token) whenever a CI pipeline needs cluster access — swap the verbs and resources for whatever that specific job actually needs, nothing more.
I use exactly this restricted Kubeconfig in the Bastion-SSH deployment for Home Assistant.
