--- title: RBAC permissions for Helm url: https://devopstales.github.io/kubernetes/k8s-helm-rbac/ date: 2019-04-14 keywords: kubernetes deployment --- I this post I will demonstrate the basic mechanism of helm and Role-based access control (RBAC). <!--more--> {{< content "/filedir/kubernetes.html" >}} I whant to use helm on Openshift but firt I startid with the basics of helm and Role-based access control (RBAC) on a simple Kubernestes cluster. Most people seem to be running Helm with their own credentials or a dedicated service account with cluster-admin permissions. This isn’t very good from a security perspective, especially so if it’s being run within CI/CD. ### Helm Helm is a package manager and teplating engine for Kubernetes. It based on tree main components: * the helm cli client * the helm server called tiller * the template pcakage called halm chart ### Helm with cluster-admin permissions ``` nano helm-cluster-admin.yaml apiVersion: v1 kind: ServiceAccount metadata: name: tiller-admin namespace: kube-system --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: tiller-admin roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: cluster-admin subjects: - kind: ServiceAccount name: tiller-admin namespace: kube-system ``` ### Helm with namespace permissions We are granting permissions on only the API groups and resources that Tiller needs to deploy and manage releases in its namespace. ``` nano helm-dev-namespace.yaml kind: Namespace apiVersion: v1 metadata: name: dev --- kind: ServiceAccount apiVersion: v1 metadata: name: tiller namespace: dev --- kind: Role apiVersion: rbac.authorization.k8s.io/v1 metadata: name: tiller-manager namespace: dev rules: - apiGroups: ["", "batch", "extensions", "apps"] resources: ["*"] verbs: ["*"] --- kind: RoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: tiller-binding namespace: dev subjects: - kind: ServiceAccount name: tiller namespace: dev roleRef: kind: Role name: tiller-manager apiGroup: rbac.authorization.k8s.io ``` ``` nano helm-prod-namespace.yaml kind: Namespace apiVersion: v1 metadata: name: prod --- kind: ServiceAccount apiVersion: v1 metadata: name: tiller namespace: prod --- kind: Role apiVersion: rbac.authorization.k8s.io/v1 metadata: name: tiller-manager namespace: prod rules: - apiGroups: ["", "batch", "extensions", "apps"] resources: ["*"] verbs: ["*"] --- kind: RoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: tiller-binding namespace: prod subjects: - kind: ServiceAccount name: tiller namespace: prod roleRef: kind: Role name: tiller-manager apiGroup: rbac.authorization.k8s.io ``` ``` kubectl create -f helm-dev-namespace.yaml kubectl create -f helm-prod-namespace.yaml kubectl -n dev get sa kubectl -n prod get sa helm init --service-account tiller --tiller-namespace dev helm init --service-account tiller --tiller-namespace prod ``` ### Helm with minimal cluster permissions ``` nano helm-cluster-role.yml kind: Namespace apiVersion: v1 metadata: name: helm --- kind: ServiceAccount apiVersion: v1 metadata: name: helm namespace: helm --- kind: ClusterRole apiVersion: rbac.authorization.k8s.io/v1 metadata: name: helm-clusterrole rules: - apiGroups: [""] resources: ["pods/portforward"] verbs: ["create"] - apiGroups: [""] resources: ["pods"] verbs: ["list", "get"] --- kind: ClusterRoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: helm-clusterrolebinding roleRef: kind: ClusterRole apiGroup: rbac.authorization.k8s.io name: helm-clusterrole subjects: - kind: ServiceAccount name: helm namespace: helm ``` ### Generate a Kubeconfig file from the Helm Service Account Credit to Ami Mahloof for this script. ``` NAMESPACE=helm # Find the secret associated with the Service Account SECRET=$(kubectl -n $NAMESPACE get sa helm -o jsonpath='{.secrets[].name}') # Get the token from the secret TOKEN=$(kubectl get secrets -n $NAMESPACE $SECRET -o jsonpath='{.data.token}' | base64 -D) # Get the CA from the secret kubectl get secrets -n $NAMESPACE $SECRET -o jsonpath='{.data.ca\.crt}' | base64 -D > ca.crt CONTEXT=$(kubectl config current-context) CLUSTER_NAME=$(kubectl config get-contexts $CONTEXT --no-headers=true | awk '{print $3}') SERVER=$(kubectl config view -o jsonpath="{.clusters[?(@.name == \"${CLUSTER_NAME}\")].cluster.server}") KUBECONFIG_FILE=config USER=helm CA=ca.crt # Set up config kubectl config set-cluster $CLUSTER_NAME \ --kubeconfig=$KUBECONFIG_FILE \ --server=$SERVER \ --certificate-authority=$CA \ --embed-certs=true kubectl config set-credentials $USER \ --kubeconfig=$KUBECONFIG_FILE \ --token=$TOKEN kubectl config set-context $USER \ --kubeconfig=$KUBECONFIG_FILE \ --cluster=$CLUSTER_NAME \ --user=$USER kubectl config use-context $USER \ --kubeconfig=$KUBECONFIG_FILE ```