Create Service Account
There is currently a problem in our Kubernetes Management with the persistence of useraccounts created through the portal. This Page is dedicated to this problem with an workaround to create a service-accounts that are persistent.
Get Admin-Config from Portal
Log into the Cloud-Portal and go into your Kubernetes Dashboard.
If you already have an Kubernetes you are able to download the Kubeconfig for this Cluster.
Click on Download Kubeconfig
Then click on Download Admin Kubeconfig
Download and Install Kubectl
Download kubectl from K8s.io
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
make kubectl usable
sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl
Copy Admin Config to .kube/config
To access the cluster with kubectl you need to create a .kube
Dir in your home and paste your config into it.
cd ~
mkdir .kube
cp admin-kube.yml .kube/config
Example with Bash Script
save bash script into addUser.sh
bash addUser.sh --user testuser --role cluster-admin
Example Output from Script:
## KUBECONFIG generated on Wed Feb 5 09:10:03 CET 2025
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: XXXXXXXXXXX=
server: https://api.kube5.ewt9qdm.gardener.stage.ewcs.ch
name: garden-414d97167c7345de93300fd42872e325--<clustername>-external
contexts:
- context:
cluster: garden-414d97167c7345de93300fd42872e325--<clustername>-external
user: <username>-garden-414d97167c7345de93300fd42872e325--<clustername>-external
name: garden-414d97167c7345de93300fd42872e325--<clustername>-external
current-context: garden-414d97167c7345de93300fd42872e325--<clustername>-external
kind: Config
preferences: {}
users:
- name: <username>-garden-414d97167c7345de93300fd42872e325--<clustername>-external
user:
token: XXXXXX
Bash Script
Please install jq Package for the bash script
sudo apt install jq
#!/bin/bash
KUBECTL="/usr/local/bin/kubectl"
usage() {
echo "Usage: $0 --user USERNAME [--role ROLE] [--delete]"
exit 1
}
SERVICE_ACC_NAME=""
ROLE_NAME="view"
DELETE_IT=false
while [[ $# -gt 0 ]]; do
case "$1" in
--user)
SERVICE_ACC_NAME="$2"
shift 2
;;
--role)
ROLE_NAME="$2"
shift 2
;;
--delete)
DELETE_IT=true
shift
;;
*)
usage
;;
esac
done
if [ -z "$SERVICE_ACC_NAME" ]; then
usage
fi
if $DELETE_IT; then
$KUBECTL delete serviceaccount "$SERVICE_ACC_NAME"
$KUBECTL delete secret "$SERVICE_ACC_NAME-secret"
$KUBECTL delete clusterrolebinding "view-$SERVICE_ACC_NAME-global"
exit 0
fi
$KUBECTL create serviceaccount "$SERVICE_ACC_NAME" -n default -o json
cat <<EOF | $KUBECTL create -n default -o json -f -
apiVersion: v1
kind: Secret
metadata:
name: $SERVICE_ACC_NAME-secret
annotations:
kubernetes.io/service-account.name: $SERVICE_ACC_NAME
type: kubernetes.io/service-account-token
EOF
SECRET_JSON=$($KUBECTL get secret "$SERVICE_ACC_NAME-secret" -o json)
CA_CRT=$(echo "$SECRET_JSON" | jq -r '.data["ca.crt"]')
USER_TOKEN=$(echo "$SECRET_JSON" | jq -r '.data.token | @base64d')
KUBECONFIG_JSON=$($KUBECTL config view --minify -o json)
CLUSTER_API=$(echo "$KUBECONFIG_JSON" | jq -r '.clusters[0].cluster.server')
CLUSTER_NAME=$(echo "$KUBECONFIG_JSON" | jq -r '.clusters[0].name')
cat <<EOF | $KUBECTL create -n default -o json -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: view-$SERVICE_ACC_NAME-global
subjects:
- kind: ServiceAccount
name: $SERVICE_ACC_NAME
namespace: default
roleRef:
kind: ClusterRole
name: $ROLE_NAME
apiGroup: rbac.authorization.k8s.io
EOF
echo "## KUBECONFIG generated on $(date)"
cat <<EOF
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: $CA_CRT
server: $CLUSTER_API
name: $CLUSTER_NAME
contexts:
- context:
cluster: $CLUSTER_NAME
user: $SERVICE_ACC_NAME-$CLUSTER_NAME
name: $CLUSTER_NAME
current-context: $CLUSTER_NAME
kind: Config
preferences: {}
users:
- name: $SERVICE_ACC_NAME-$CLUSTER_NAME
user:
token: $USER_TOKEN
EOF
Python Script
import sys
import json
import subprocess
import base64
from datetime import datetime
def exec_command(args, std_input=None):
print("# " + " ".join(args))
result = subprocess.run(args, input=std_input, text=True, capture_output=True)
if result.returncode == 0:
try:
return json.loads(result.stdout)
except json.JSONDecodeError:
return result.stdout.strip()
else:
print(result.stderr, file=sys.stderr)
sys.exit(1)
KUBECTL = "/usr/bin/kubectl"
if len(sys.argv) < 2 or sys.argv[1] == "--delete":
print("please provide username as an argument, for example: python script.py USER_NAME [--delete]")
sys.exit(1)
service_acc_name = sys.argv[1]
role_name = sys.argv[2] if len(sys.argv) > 2 else "view"
delete_it = len(sys.argv) > 3 and sys.argv[3] == "--delete"
if delete_it:
exec_command([KUBECTL, "delete", "serviceaccount", service_acc_name])
exec_command([KUBECTL, "delete", "secret", f"{service_acc_name}-secret"])
exec_command([KUBECTL, "delete", "clusterrolebinding", f"view-{service_acc_name}-global"])
sys.exit(0)
exec_command([KUBECTL, "create", "serviceaccount", service_acc_name, "-o", "json"])
exec_command([KUBECTL, "create", "-o", "json", "-f", "-"], f"""apiVersion: v1
kind: Secret
metadata:
name: {service_acc_name}-secret
annotations:
kubernetes.io/service-account.name: {service_acc_name}
type: kubernetes.io/service-account-token""")
secret = exec_command([KUBECTL, "get", "secret", f"{service_acc_name}-secret", "-o", "json"])
ca_crt = secret["data"]["ca.crt"]
user_token = base64.b64decode(secret["data"]["token"]).decode()
kube_config = exec_command([KUBECTL, "config", "view", "--minify", "-o", "json"])
cluster_api = kube_config["clusters"][0]["cluster"]["server"]
cluster_name = kube_config["clusters"][0]["name"]
exec_command([KUBECTL, "create", "-o", "json", "-f", "-"], f"""apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: {role_name}-{service_acc_name}-global
subjects:
- kind: ServiceAccount
name: {service_acc_name}
namespace: default
roleRef:
kind: ClusterRole
name: {role_name}
apiGroup: rbac.authorization.k8s.io""")
kubeconfig_output = f"""
## KUBECONFIG generated on {datetime.now()}
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: {ca_crt}
server: {cluster_api}
name: {cluster_name}
contexts:
- context:
cluster: {cluster_name}
user: {service_acc_name}-{cluster_name}
name: {cluster_name}
current-context: {cluster_name}
kind: Config
preferences: {}
users:
- name: {service_acc_name}-{cluster_name}
user:
token: {user_token}
"""
print(kubeconfig_output)