Vai al contenuto

Creare un service account

Attualmente il nostro Kubernetes Management presenta un problema di persistenza degli account utente creati tramite il portale. Questa pagina è dedicata a questo problema e propone una soluzione alternativa per creare service account persistenti.

Ottenere la configurazione admin dal portale

Acceda al Cloud-Portal e apra la sua Kubernetes Dashboard.
Se dispone già di un Kubernetes, può scaricare il kubeconfig di questo cluster. image
Clicchi su Download Kubeconfig

image
Poi clicchi su Download Admin Kubeconfig

Scaricare e installare Kubectl

Scarichi kubectl da K8s.io

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

rendere kubectl utilizzabile

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

Copiare la configurazione admin in .kube/config

Per accedere al cluster con kubectl, deve creare una directory .kube nella sua home e copiarvi la sua configurazione.

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

Esempio con uno script Bash

salvi lo script bash in addUser.sh

bash addUser.sh --user testuser --role cluster-admin
salvi l'output nel suo .kube/admin

Esempio di output dello 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

Scaricare addUser.sh

Installi il pacchetto jq per lo 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)