Goglides Dev 🌱

Cover image for Stop using kubeconfig with admin access | Service account no longer auto-generate secret
Balkrishna Pandey
Balkrishna Pandey

Posted on • Updated on

Stop using kubeconfig with admin access | Service account no longer auto-generate secret

Note: This blog is modified to support v1.25 version of kubernetes, which is the latest at the time of writing.
There are some breaking changes in this latest version. Follow this twitter conversation for more information.

Service account no longer auto-generate secret

Anyone who doesn’t know about kubeconfig file, its a file which is used to configure access to a cluster. kubectl, helm like kubernetes client use this file to access kubernetes and perform operation.

Creating kubeconfig file with limited access

In this exercise I am going to use RBAC configuration and service account to generate kubeconfig file which has limited access.

Kubernetes RBAC

Create ServiceAccount, Role and RoleBinding

cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Namespace
metadata:
  name: goglides
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: goglides-sa
  namespace: goglides
---
apiVersion: v1
kind: Secret
metadata:
  name: goglides-sa-secret
  namespace: goglides
  annotations:
    kubernetes.io/service-account.name: goglides-sa
type: kubernetes.io/service-account-token
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: goglides-role
  namespace: goglides
rules:
- apiGroups: ["apps"]
  resources: ["deployments"]
  verbs: ["get", "list", "watch", "create", "delete", "update", "patch"]

- apiGroups: [""] # "" indicates the core API group
  resources: ["configmaps", "secrets"]
  verbs: ["get", "list", "watch", "create", "delete", "update", "patch"]

- apiGroups: [""] # "" indicates the core API group
  resources: ["pods"]
  verbs: ["get", "list", "watch"]

---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: goglides-rolebinding
  namespace: goglides
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: goglides-role
subjects:
- kind: ServiceAccount
  name: goglides-sa
  namespace: goglides
EOF
Enter fullscreen mode Exit fullscreen mode

Once you create the Service Account we can use kubectl command to fetch certificate-authority and authentication token for user goglides-sa as follows,

export serviceAccount=goglides-sa
export namespace=goglides
export secretName=goglides-sa-secret
export name=kind-multinode
Enter fullscreen mode Exit fullscreen mode

Get ca.crt from secret (using OSX base64 with -D flag for decode)

kubectl get secret $secretName -n $namespace -o custom-columns=CA:'.data.ca\.crt' --no-headers | base64 -D > ca.crt
Enter fullscreen mode Exit fullscreen mode

Get ServiceAccount token from secret

export userToken=$(kubectl get secret $secretName -n $namespace -o custom-columns=CA:'.data.token' --no-headers | base64 -D)
Enter fullscreen mode Exit fullscreen mode

Get endpoint of current context

export endpoint=$(kubectl config view -o jsonpath="{.clusters[?(@.name == '$name')].cluster.server}")
Enter fullscreen mode Exit fullscreen mode
  • Once you follow above steps you have all the information required to create kubeconfig file. Lets start by creating basic skeleton,
kubectl config --kubeconfig=config-demo set-cluster development
Enter fullscreen mode Exit fullscreen mode

Output:

Cluster "development" set.
Enter fullscreen mode Exit fullscreen mode
cat config-demo
Enter fullscreen mode Exit fullscreen mode

Output:

apiVersion: v1
clusters:
- cluster:
    server: ""
  name: development
contexts: []
current-context: ""
kind: Config
preferences: {}
users: []
Enter fullscreen mode Exit fullscreen mode

Set cluster (run in directory where ca.crt is stored)

kubectl config --kubeconfig=config-demo set-cluster development \
  --embed-certs=true \
  --server=$endpoint \
  --certificate-authority=./ca.crt

cat config-demo
Enter fullscreen mode Exit fullscreen mode

Output:

apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUN5RENDQWJDZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFWTVJNd0VRWURWUVFERXdwcmRXSmwKY201bGRHVnpNQjRYRFRJd01ERXlNekl3TWpjeU0xb1hEVE13TURFeU1ESXdNamN5TTFvd0ZURVRNQkVHQTFVRQpBeE1LYTNWaVpYSnVaWFJsY3pDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBTUJXCnI2eUR0bXhIcEZwbHE2NTVEWHBpR3FIczVpY3BCN3l5K21CMEhQTUl0ZDc2RW9GK0JudWVZSnpvdjk1VWJzVlkKNVFGSU9mTHBISGhIbitEVnM4ZFNPRFA1SUhGMFdOMUNYT0JTR1lZeGFGNHlTQkxwaURSZ1k1dHdvVTVtT2laZwoxTStJa0Rjck5QVWNmemlXc1o4a0NzdDdranNLZzNhSHYvNEY3UGZidkFQcTIvaGtRK3l3ZWZOck8wN2l3N1h0ClUxdkY5d3dOTGZkdWQwZWZxaW1CcFVUWXVITThpUXRjakRCb09jc2FNYk56ZEM5SUFTcW5jbEpEdFFpYlp6MDgKaVhrUml0RmZ4VitVRE5RWGRiRE5JbmgyWGtlQ1JpTGg3V2ZvYi9YOTBPVUhva1g0M0J6c0VlZzA4dEZzVm1BSQpUekQvOU5SVHFJSHF0MEdKYVpjQ0F3RUFBYU1qTUNFd0RnWURWUjBQQVFIL0JBUURBZ0trTUE4R0ExVWRFd0VCCi93UUZNQU1CQWY4d0RRWUpLb1pJaHZjTkFRRUxCUUFEZ2dFQkFBeCs5alFSZkY3Snp2dUVWdTMrbjNVWjc0ckYKUmVrd2xscnVIVVpLTldRNHY5VkdNYmtpR3NQK0xJQitLOXZpRGNzV0NTSkY4NGtLbzhkQ3RkcVlJcmpqUFYrVAowOTFGOGhMR1NqZ1AyNUZCSmxSR2pMNnoyeUY0L1ZISUdoemtoSHpjdko0bnBQNXBLQWNLcFhRQldVWW5DWWo1Cjc5cUpVdFM4eXAzUmozTkMwTmxZQWEyR1dJMDA3WGQzQzh5SlVXUUJIQkZJMGpESDdsaGJCTVpad0FqcnJLZzMKUXdpZ1VkWVlJd3c5V1N2Uit3MGlPT3lUTEdLVEpkQ2l6OEUxRGsxcnlFTkRCd3IxWWl3WC9jS1RVOWxRamlWbAp2SzlaUEpyZ1hkWVcwR0lWcFNndEZSWFB4VC8yUmw2RW03Nmw2cGN6NE5pN0lGcGxmcjNnTTdUWWJOST0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=
    server: [https://kubernetes.docker.internal:6443](https://kubernetes.docker.internal:6443)
  name: development
contexts: []
current-context: ""
kind: Config
preferences: {}
users: []
Enter fullscreen mode Exit fullscreen mode

Add user details to your configuration file:

kubectl config --kubeconfig=config-demo set-credentials $serviceAccount --token=$userToken
Enter fullscreen mode Exit fullscreen mode

Output:

User "goglides-sa" set.
Enter fullscreen mode Exit fullscreen mode
cat config-demo
Enter fullscreen mode Exit fullscreen mode

Output:

apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUN5RENDQWJDZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFWTVJNd0VRWURWUVFERXdwcmRXSmwKY201bGRHVnpNQjRYRFRJd01ERXlNekl3TWpjeU0xb1hEVE13TURFeU1ESXdNamN5TTFvd0ZURVRNQkVHQTFVRQpBeE1LYTNWaVpYSnVaWFJsY3pDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBTUJXCnI2eUR0bXhIcEZwbHE2NTVEWHBpR3FIczVpY3BCN3l5K21CMEhQTUl0ZDc2RW9GK0JudWVZSnpvdjk1VWJzVlkKNVFGSU9mTHBISGhIbitEVnM4ZFNPRFA1SUhGMFdOMUNYT0JTR1lZeGFGNHlTQkxwaURSZ1k1dHdvVTVtT2laZwoxTStJa0Rjck5QVWNmemlXc1o4a0NzdDdranNLZzNhSHYvNEY3UGZidkFQcTIvaGtRK3l3ZWZOck8wN2l3N1h0ClUxdkY5d3dOTGZkdWQwZWZxaW1CcFVUWXVITThpUXRjakRCb09jc2FNYk56ZEM5SUFTcW5jbEpEdFFpYlp6MDgKaVhrUml0RmZ4VitVRE5RWGRiRE5JbmgyWGtlQ1JpTGg3V2ZvYi9YOTBPVUhva1g0M0J6c0VlZzA4dEZzVm1BSQpUekQvOU5SVHFJSHF0MEdKYVpjQ0F3RUFBYU1qTUNFd0RnWURWUjBQQVFIL0JBUURBZ0trTUE4R0ExVWRFd0VCCi93UUZNQU1CQWY4d0RRWUpLb1pJaHZjTkFRRUxCUUFEZ2dFQkFBeCs5alFSZkY3Snp2dUVWdTMrbjNVWjc0ckYKUmVrd2xscnVIVVpLTldRNHY5VkdNYmtpR3NQK0xJQitLOXZpRGNzV0NTSkY4NGtLbzhkQ3RkcVlJcmpqUFYrVAowOTFGOGhMR1NqZ1AyNUZCSmxSR2pMNnoyeUY0L1ZISUdoemtoSHpjdko0bnBQNXBLQWNLcFhRQldVWW5DWWo1Cjc5cUpVdFM4eXAzUmozTkMwTmxZQWEyR1dJMDA3WGQzQzh5SlVXUUJIQkZJMGpESDdsaGJCTVpad0FqcnJLZzMKUXdpZ1VkWVlJd3c5V1N2Uit3MGlPT3lUTEdLVEpkQ2l6OEUxRGsxcnlFTkRCd3IxWWl3WC9jS1RVOWxRamlWbAp2SzlaUEpyZ1hkWVcwR0lWcFNndEZSWFB4VC8yUmw2RW03Nmw2cGN6NE5pN0lGcGxmcjNnTTdUWWJOST0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=
    server: [https://kubernetes.docker.internal:6443](https://kubernetes.docker.internal:6443)
  name: development
contexts: []
current-context: ""
kind: Config
preferences: {}
users:
- name: goglides-sa
  user:
    token: eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJnb2dsaWRlcyIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJnb2dsaWRlcy1zYS10b2tlbi1ncGdqNiIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50Lm5hbWUiOiJnb2dsaWRlcy1zYSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6IjhjOTA1MjViLWJlNGItNDczOC05Y2M2LTYzMWZiMGM3ZmY1NyIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDpnb2dsaWRlczpnb2dsaWRlcy1zYSJ9.VdkL9tSRNknbP5mYSXSv9jOM2KcBEAjeoo5f8MuExd1M8lP5R9re1l1JcZy0cP_lKjJ34toJY9ROlwoIxG7pZTe5BaDRVNEN2r41R3deTdkfAQj82Le5KvsIBRPTQ0dZKIxbWp9oqiH6CyuWhO6AYNm_z-vU9X0l_gofz6RWCjq_PgHDU8pmRO1o339xcU01xMJz7pVdkyVbx23egFabmnjCONDgtMwJ0cIvxK9yfhuuKFJxt2vHjdDerTFG4QuNoiHpZxwhSJjPgzdCwaaaGkz8UN_M8lO905pXFHXE1MmVvK_Anglp3B1l-hSLKGNoVYU4YgLUOaIi3jQJBZ2aiA
Enter fullscreen mode Exit fullscreen mode

Add context details to your configuration file:

kubectl config --kubeconfig=config-demo \
    set-context goglides-namespace --cluster=development \
    --user $serviceAccount --namespace $namespace

cat config-demo
Enter fullscreen mode Exit fullscreen mode

Output:

apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUN5RENDQWJDZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFWTVJNd0VRWURWUVFERXdwcmRXSmwKY201bGRHVnpNQjRYRFRJd01ERXlNekl3TWpjeU0xb1hEVE13TURFeU1ESXdNamN5TTFvd0ZURVRNQkVHQTFVRQpBeE1LYTNWaVpYSnVaWFJsY3pDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBTUJXCnI2eUR0bXhIcEZwbHE2NTVEWHBpR3FIczVpY3BCN3l5K21CMEhQTUl0ZDc2RW9GK0JudWVZSnpvdjk1VWJzVlkKNVFGSU9mTHBISGhIbitEVnM4ZFNPRFA1SUhGMFdOMUNYT0JTR1lZeGFGNHlTQkxwaURSZ1k1dHdvVTVtT2laZwoxTStJa0Rjck5QVWNmemlXc1o4a0NzdDdranNLZzNhSHYvNEY3UGZidkFQcTIvaGtRK3l3ZWZOck8wN2l3N1h0ClUxdkY5d3dOTGZkdWQwZWZxaW1CcFVUWXVITThpUXRjakRCb09jc2FNYk56ZEM5SUFTcW5jbEpEdFFpYlp6MDgKaVhrUml0RmZ4VitVRE5RWGRiRE5JbmgyWGtlQ1JpTGg3V2ZvYi9YOTBPVUhva1g0M0J6c0VlZzA4dEZzVm1BSQpUekQvOU5SVHFJSHF0MEdKYVpjQ0F3RUFBYU1qTUNFd0RnWURWUjBQQVFIL0JBUURBZ0trTUE4R0ExVWRFd0VCCi93UUZNQU1CQWY4d0RRWUpLb1pJaHZjTkFRRUxCUUFEZ2dFQkFBeCs5alFSZkY3Snp2dUVWdTMrbjNVWjc0ckYKUmVrd2xscnVIVVpLTldRNHY5VkdNYmtpR3NQK0xJQitLOXZpRGNzV0NTSkY4NGtLbzhkQ3RkcVlJcmpqUFYrVAowOTFGOGhMR1NqZ1AyNUZCSmxSR2pMNnoyeUY0L1ZISUdoemtoSHpjdko0bnBQNXBLQWNLcFhRQldVWW5DWWo1Cjc5cUpVdFM4eXAzUmozTkMwTmxZQWEyR1dJMDA3WGQzQzh5SlVXUUJIQkZJMGpESDdsaGJCTVpad0FqcnJLZzMKUXdpZ1VkWVlJd3c5V1N2Uit3MGlPT3lUTEdLVEpkQ2l6OEUxRGsxcnlFTkRCd3IxWWl3WC9jS1RVOWxRamlWbAp2SzlaUEpyZ1hkWVcwR0lWcFNndEZSWFB4VC8yUmw2RW03Nmw2cGN6NE5pN0lGcGxmcjNnTTdUWWJOST0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=
    server: [https://kubernetes.docker.internal:6443](https://kubernetes.docker.internal:6443)
  name: development
contexts:
- context:
    cluster: development
    namespace: goglides
    user: goglides-sa
  name: goglides-namespace
current-context: ""
kind: Config
preferences: {}
users:
- name: goglides-sa
  user:
    token: eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJnb2dsaWRlcyIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJnb2dsaWRlcy1zYS10b2tlbi1ncGdqNiIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50Lm5hbWUiOiJnb2dsaWRlcy1zYSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6IjhjOTA1MjViLWJlNGItNDczOC05Y2M2LTYzMWZiMGM3ZmY1NyIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDpnb2dsaWRlczpnb2dsaWRlcy1zYSJ9.VdkL9tSRNknbP5mYSXSv9jOM2KcBEAjeoo5f8MuExd1M8lP5R9re1l1JcZy0cP_lKjJ34toJY9ROlwoIxG7pZTe5BaDRVNEN2r41R3deTdkfAQj82Le5KvsIBRPTQ0dZKIxbWp9oqiH6CyuWhO6AYNm_z-vU9X0l_gofz6RWCjq_PgHDU8pmRO1o339xcU01xMJz7pVdkyVbx23egFabmnjCONDgtMwJ0cIvxK9yfhuuKFJxt2vHjdDerTFG4QuNoiHpZxwhSJjPgzdCwaaaGkz8UN_M8lO905pXFHXE1MmVvK_Anglp3B1l-hSLKGNoVYU4YgLUOaIi3jQJBZ2aiA
Enter fullscreen mode Exit fullscreen mode

Ok lets validate,

kubectl config get-contexts --kubeconfig=config-demo
CURRENT NAME CLUSTER AUTHINFO NAMESPACE
          goglides-namespace development goglides-sa goglides
Enter fullscreen mode Exit fullscreen mode

Switch current-context to goglides-namespace for the user

export KUBECONFIG=config-demo
kubectl config use-context goglides-namespace
Enter fullscreen mode Exit fullscreen mode

Let's run some unauthorized operations based on rbac permission (take a look on yaml definition above)

kubectl get nodes
Enter fullscreen mode Exit fullscreen mode

You should see output, similar to this.

Error from server (Forbidden): nodes is forbidden: User "system:serviceaccount:goglides:goglides-sa" cannot list resource "nodes" in API group "" at the cluster scope
Enter fullscreen mode Exit fullscreen mode

Now try some authorized operation based on rbac permission.

kubectl create secret generic my-secret --from-literal=key1=supersecret --from-literal=key2=topsecret
Enter fullscreen mode Exit fullscreen mode

Output:

secret/my-secret created
Enter fullscreen mode Exit fullscreen mode
kubectl delete secret my-secret
Enter fullscreen mode Exit fullscreen mode

Output:

secret "my-secret" deleted
Enter fullscreen mode Exit fullscreen mode

This confirms your kubeconfig with custom rbac permission is working.


Top comments (0)