Skip to content

Instantly share code, notes, and snippets.

Last active January 29, 2024 23:00
Show Gist options
  • Save innovia/fbba8259042f71db98ea8d4ad19bd708 to your computer and use it in GitHub Desktop.
Save innovia/fbba8259042f71db98ea8d4ad19bd708 to your computer and use it in GitHub Desktop.
Create a service account and generate a kubeconfig file for it - this will also set the default namespace for the user
set -e
set -o pipefail
# Add user to k8s using service account, no RBAC (must create RBAC after this script)
if [[ -z "$1" ]] || [[ -z "$2" ]]; then
echo "usage: $0 <service_account_name> <namespace>"
exit 1
create_target_folder() {
echo -n "Creating target directory to hold files in ${TARGET_FOLDER}..."
mkdir -p "${TARGET_FOLDER}"
printf "done"
create_service_account() {
echo -e "\\nCreating a service account in ${NAMESPACE} namespace: ${SERVICE_ACCOUNT_NAME}"
kubectl create sa "${SERVICE_ACCOUNT_NAME}" --namespace "${NAMESPACE}"
get_secret_name_from_service_account() {
echo -e "\\nGetting secret of service account ${SERVICE_ACCOUNT_NAME} on ${NAMESPACE}"
SECRET_NAME=$(kubectl get sa "${SERVICE_ACCOUNT_NAME}" --namespace="${NAMESPACE}" -o json | jq -r .secrets[].name)
echo "Secret name: ${SECRET_NAME}"
extract_ca_crt_from_secret() {
echo -e -n "\\nExtracting ca.crt from secret..."
kubectl get secret --namespace "${NAMESPACE}" "${SECRET_NAME}" -o json | jq \
-r '.data["ca.crt"]' | base64 -D > "${TARGET_FOLDER}/ca.crt"
printf "done"
get_user_token_from_secret() {
echo -e -n "\\nGetting user token from secret..."
USER_TOKEN=$(kubectl get secret --namespace "${NAMESPACE}" "${SECRET_NAME}" -o json | jq -r '.data["token"]' | base64 -D)
printf "done"
set_kube_config_values() {
context=$(kubectl config current-context)
echo -e "\\nSetting current context to: $context"
CLUSTER_NAME=$(kubectl config get-contexts "$context" | awk '{print $3}' | tail -n 1)
echo "Cluster name: ${CLUSTER_NAME}"
ENDPOINT=$(kubectl config view \
-o jsonpath="{.clusters[?( == \"${CLUSTER_NAME}\")].cluster.server}")
echo "Endpoint: ${ENDPOINT}"
# Set up the config
echo -e "\\nPreparing k8s-${SERVICE_ACCOUNT_NAME}-${NAMESPACE}-conf"
echo -n "Setting a cluster entry in kubeconfig..."
kubectl config set-cluster "${CLUSTER_NAME}" \
--kubeconfig="${KUBECFG_FILE_NAME}" \
--server="${ENDPOINT}" \
--certificate-authority="${TARGET_FOLDER}/ca.crt" \
echo -n "Setting token credentials entry in kubeconfig..."
kubectl config set-credentials \
--kubeconfig="${KUBECFG_FILE_NAME}" \
echo -n "Setting a context entry in kubeconfig..."
kubectl config set-context \
--kubeconfig="${KUBECFG_FILE_NAME}" \
--cluster="${CLUSTER_NAME}" \
echo -n "Setting the current-context in the kubeconfig file..."
kubectl config use-context "${SERVICE_ACCOUNT_NAME}-${NAMESPACE}-${CLUSTER_NAME}" \
echo -e "\\nAll done! Test with:"
echo "KUBECONFIG=${KUBECFG_FILE_NAME} kubectl get pods"
echo "you should not have any permissions by default - you have just created the authentication part"
echo "You will need to create RBAC permissions"
Copy link

One gotcha I've encountered is that the service account's secret is not always available immediately after a successful create sa.

AFAICT, the SA token controller eventually creates it, so some may want to add polling logic (which is seen in the kubernetes test coverage of SA token creation).

I'm not sure if there are bash libs for that, but I've found useful in case anyone else references the above for creating a larger toolset in Go (e.g. with

Copy link

chaimfn commented Dec 15, 2019

It is prompt me for Username & Password

Copy link

brew install jq

Copy link

and this is how to do it with openshift :

Copy link

Hi, I create a complete project with a part of this wonderful script , don't hesitate to comment it!

Thank you

Copy link

It takes too much time, is it expected?

Copy link

Script almost finishes, but ends with:

Error from server (Forbidden): pods is forbidden: User "system:serviceaccount:default:helm-github-actions" cannot list resource "pods" in API group "" in the namespace "default"

Specifically this command:


Copy link

# permissions.yaml
kind: ClusterRoleBinding
  name: deliverybot-clusterrolebinding
  - kind: ServiceAccount
    name: deliverybot
    namespace: default
  kind: ClusterRole
  name: cluster-admin
  apiGroup: ""

Heres what I used to get access. You'll want to update the service account name to be whatever you used in ./setup command.

Heres how I did it. First I saved the above in a file names permissions.yaml and ran the following.

chmod +x
./ deliverybot default
kubectl apply -f permissions.yaml 
KUBECONFIG=/tmp/kube/k8s-deliverybot-default-conf kubectl get pods

Ah - this fixed it. Thanks!

Copy link

sdarwin commented Mar 13, 2023

Does this have an effect on the process?

Service Account Token Secrets In Kubernetes v1.24 and later, the LegacyServiceAccountTokenNoAutoGeneration feature gate prevents Kubernetes from automatically creating these tokens for ServiceAccounts. LegacyServiceAccountTokenNoAutoGeneration is enabled by default; in other words, Kubernetes does not create these tokens.

Here is an updated version which creates the api token manually.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment