-
-
Save innovia/fbba8259042f71db98ea8d4ad19bd708 to your computer and use it in GitHub Desktop.
#!/bin/bash | |
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 | |
fi | |
SERVICE_ACCOUNT_NAME=$1 | |
NAMESPACE="$2" | |
KUBECFG_FILE_NAME="/tmp/kube/k8s-${SERVICE_ACCOUNT_NAME}-${NAMESPACE}-conf" | |
TARGET_FOLDER="/tmp/kube" | |
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[?(@.name == \"${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" \ | |
--embed-certs=true | |
echo -n "Setting token credentials entry in kubeconfig..." | |
kubectl config set-credentials \ | |
"${SERVICE_ACCOUNT_NAME}-${NAMESPACE}-${CLUSTER_NAME}" \ | |
--kubeconfig="${KUBECFG_FILE_NAME}" \ | |
--token="${USER_TOKEN}" | |
echo -n "Setting a context entry in kubeconfig..." | |
kubectl config set-context \ | |
"${SERVICE_ACCOUNT_NAME}-${NAMESPACE}-${CLUSTER_NAME}" \ | |
--kubeconfig="${KUBECFG_FILE_NAME}" \ | |
--cluster="${CLUSTER_NAME}" \ | |
--user="${SERVICE_ACCOUNT_NAME}-${NAMESPACE}-${CLUSTER_NAME}" \ | |
--namespace="${NAMESPACE}" | |
echo -n "Setting the current-context in the kubeconfig file..." | |
kubectl config use-context "${SERVICE_ACCOUNT_NAME}-${NAMESPACE}-${CLUSTER_NAME}" \ | |
--kubeconfig="${KUBECFG_FILE_NAME}" | |
} | |
create_target_folder | |
create_service_account | |
get_secret_name_from_service_account | |
extract_ca_crt_from_secret | |
get_user_token_from_secret | |
set_kube_config_values | |
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" | |
KUBECONFIG=${KUBECFG_FILE_NAME} kubectl get pods |
# permissions.yaml
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: deliverybot-clusterrolebinding
subjects:
- kind: ServiceAccount
name: deliverybot
namespace: default
roleRef:
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 setup.sh
./setup.sh deliverybot default
kubectl apply -f permissions.yaml
KUBECONFIG=/tmp/kube/k8s-deliverybot-default-conf kubectl get pods
Thanks! I've added new function for creating RBAC, not sure if "sed" will work on MacOS though.
apply_rbac() {
echo -e -n "\\nApplying RBAC permissions..."
sed -e "s|my_account|${SERVICE_ACCOUNT_NAME}|g" -e "s|my_namespace|${NAMESPACE}|g" \
permissions-template.yaml > permissions_${SERVICE_ACCOUNT_NAME}.yaml
kubectl apply -f permissions_${SERVICE_ACCOUNT_NAME}.yaml
printf "done"
}
apply_rbac
content of permissions-template.yaml
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: my_account-clusterrolebinding
subjects:
- kind: ServiceAccount
name: my_account
namespace: my_namespace
roleRef:
kind: ClusterRole
name: cluster-admin
apiGroup: ""
Full script with some other adjustemnts https://gist.github.com/xtavras/98c6a2625079a78054a907219c976e2b
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 https://godoc.org/k8s.io/apimachinery/pkg/util/wait useful in case anyone else references the above for creating a larger toolset in Go (e.g. with https://github.com/kubernetes/client-go/).
It is prompt me for Username & Password
brew install jq
and this is how to do it with openshift : https://gist.github.com/abdennour/fee44ca16e054c85d484e4cd9efa9f78
Hi, I create a complete project with a part of this wonderful script https://github.com/heralight/k8s-user-tools , don't hesitate to comment it!
Thank you
It takes too much time, is it expected?
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:
KUBECONFIG=${KUBECFG_FILE_NAME} kubectl get pods
# permissions.yaml --- kind: ClusterRoleBinding apiVersion: rbac.authorization.k8s.io/v1beta1 metadata: name: deliverybot-clusterrolebinding subjects: - kind: ServiceAccount name: deliverybot namespace: default roleRef: 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 setup.sh ./setup.sh deliverybot default kubectl apply -f permissions.yaml KUBECONFIG=/tmp/kube/k8s-deliverybot-default-conf kubectl get pods
Ah - this fixed it. Thanks!
Does this have an effect on the process?
From https://kubernetes.io/docs/concepts/security/service-accounts/
"""
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.
https://gist.github.com/sdarwin/ffc5fed82b6128a7549fd6d5696d98a8
What RBAC rules are needed? Doesn't feel like this is a complete example gist.