Aller au contenu

Créer un service account

Notre Kubernetes Management rencontre actuellement un problème de persistance des comptes utilisateurs créés via le portail. Cette page est consacrée à ce problème et propose une solution de contournement pour créer des service accounts persistants.

Obtenir la configuration admin depuis le portail

Connectez-vous au Cloud-Portal et ouvrez votre Kubernetes Dashboard.
Si vous disposez déjà d'un Kubernetes, vous pouvez télécharger le kubeconfig de ce cluster. image
Cliquez sur Download Kubeconfig

image
Cliquez ensuite sur Download Admin Kubeconfig

Télécharger et installer Kubectl

Téléchargez kubectl depuis K8s.io

curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"

rendre kubectl utilisable

sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl    

Copier la configuration admin vers .kube/config

Pour accéder au cluster avec kubectl, vous devez créer un répertoire .kube dans votre home et y copier votre configuration.

cd ~
mkdir .kube
cp admin-kube.yml .kube/config

Exemple avec un script Bash

enregistrez le script bash dans addUser.sh

bash addUser.sh --user testuser --role cluster-admin
enregistrez la sortie dans votre .kube/admin

Exemple de sortie du 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

Script Bash

Télécharger addUser.sh

Veuillez installer le paquet jq pour le script bash

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

Script Python

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)