This directory contains helper scripts and examples for connecting various Kubernetes clusters to Velero Dashboard using token-based authentication.
Velero Dashboard supports two authentication methods:
- Kubeconfig File - Traditional method using kubeconfig
- Service Account Token - Token-based authentication (recommended for managed clusters)
Use token authentication when:
- Working with managed Kubernetes services (GKE, EKS, AKS)
- The kubeconfig uses exec plugins (gke-gcloud-auth-plugin, aws-iam-authenticator, etc.)
- You want more control over permissions
- You need long-lived credentials without CLI tools
Prerequisites:
gcloudCLI installed and authenticatedkubectlconfigured to access your GKE cluster- Velero installed in the cluster
Usage:
# Connect to your GKE cluster
gcloud container clusters get-credentials CLUSTER_NAME --zone ZONE --project PROJECT_ID
# Run the setup script
./examples/gke-setup.sh
# With custom options
./examples/gke-setup.sh -n velero -s velero-dashboardWhat it does:
- Creates a service account in the specified namespace
- Creates a ClusterRole with Velero permissions
- Binds the role to the service account
- Generates a long-lived token (10 years)
- Outputs API server URL, token, and CA certificate
Prerequisites:
awsCLI installed and configuredkubectlconfigured to access your EKS cluster- Velero installed in the cluster
Usage:
# Connect to your EKS cluster
aws eks update-kubeconfig --name CLUSTER_NAME --region REGION
# Run the setup script
./examples/eks-setup.sh
# With custom options
./examples/eks-setup.sh -n velero -s velero-dashboardIf you prefer manual setup or want to understand the process:
NAMESPACE=velero
SA_NAME=velero-dashboard
kubectl create namespace $NAMESPACE
kubectl create serviceaccount $SA_NAME -n $NAMESPACEcat <<EOF | kubectl apply -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: velero-dashboard
rules:
# Velero resources
- apiGroups: ["velero.io"]
resources: ["backups", "restores", "schedules", "backupstoragelocations", "volumesnapshotlocations"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
- apiGroups: ["velero.io"]
resources: ["backups/status", "restores/status", "schedules/status"]
verbs: ["get", "list", "watch"]
# Core resources
- apiGroups: [""]
resources: ["pods", "pods/log"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["namespaces", "persistentvolumes", "persistentvolumeclaims"]
verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: velero-dashboard
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: velero-dashboard
subjects:
- kind: ServiceAccount
name: ${SA_NAME}
namespace: ${NAMESPACE}
EOFcat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Secret
metadata:
name: ${SA_NAME}-token
namespace: ${NAMESPACE}
annotations:
kubernetes.io/service-account.name: ${SA_NAME}
type: kubernetes.io/service-account-token
EOF# API Server URL
API_SERVER=$(kubectl config view --minify -o jsonpath='{.clusters[0].cluster.server}')
echo "API Server: $API_SERVER"
# Bearer Token
TOKEN=$(kubectl get secret ${SA_NAME}-token -n ${NAMESPACE} -o jsonpath='{.data.token}' | base64 -d)
echo "Token: $TOKEN"
# CA Certificate (base64)
CA_CERT=$(kubectl get secret ${SA_NAME}-token -n ${NAMESPACE} -o jsonpath='{.data.ca\.crt}')
echo "CA Cert: $CA_CERT"- Navigate to
http://localhost:3001/clusters - Click "Add Cluster"
- Select "Service Account Token" as authentication method
- Fill in the form:
- Cluster Name: Choose a descriptive name (e.g.,
gke-production) - Velero Namespace: The namespace where Velero is installed (default:
velero) - API Server URL: The API server endpoint from above
- Bearer Token: The service account token
- CA Certificate: The base64-encoded CA certificate (optional but recommended)
- Skip TLS Verification: Only for development/testing (not recommended for production)
- Cluster Name: Choose a descriptive name (e.g.,
- Click "Add Cluster"
# Check if secret exists
kubectl get secret ${SA_NAME}-token -n ${NAMESPACE}
# Recreate token
kubectl delete secret ${SA_NAME}-token -n ${NAMESPACE}
# Re-run Step 3 above# Check ClusterRoleBinding
kubectl get clusterrolebinding velero-dashboard -o yaml
# Verify service account has correct permissions
kubectl auth can-i list backups.velero.io --as=system:serviceaccount:${NAMESPACE}:${SA_NAME}- Verify API server URL is correct and accessible
- Check if firewall rules allow access to the API server
- Ensure CA certificate is correct (or use Skip TLS for testing)
This is expected! GKE kubeconfigswith gke-gcloud-auth-plugin don't work in server environments. Use the token-based authentication instead (this is why we created these scripts).
-
Principle of Least Privilege: The example ClusterRole grants broad permissions for Velero resources. For production, consider creating a more restrictive role.
-
Token Rotation: Periodically rotate service account tokens:
kubectl delete secret ${SA_NAME}-token -n ${NAMESPACE} # Recreate the secret (Step 3)
-
Network Security:
- Use network policies to restrict access to the dashboard
- Consider using a VPN or bastion host for API server access
- Enable TLS verification in production (don't use Skip TLS)
-
Audit Logging: Enable Kubernetes audit logging to track dashboard activities
-
Multi-Tenancy: If managing multiple teams:
- Use separate namespaces for each team
- Create Role (not ClusterRole) with namespace-scoped permissions
- Use RoleBinding instead of ClusterRoleBinding
For a more secure setup with namespace-scoped access:
# Create role for single namespace
cat <<EOF | kubectl apply -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: velero-dashboard
namespace: ${NAMESPACE}
rules:
- apiGroups: ["velero.io"]
resources: ["backups", "restores", "schedules", "backupstoragelocations", "volumesnapshotlocations"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: velero-dashboard
namespace: ${NAMESPACE}
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: velero-dashboard
subjects:
- kind: ServiceAccount
name: ${SA_NAME}
namespace: ${NAMESPACE}
EOF