From 9fb836b8d4e6012e7af6563a04b9f293d13a4f9d Mon Sep 17 00:00:00 2001 From: marcel-dempers Date: Mon, 13 Sep 2021 13:28:23 +1000 Subject: [PATCH] wip --- kubernetes/rbac/README.md | 186 ++++++++++++++++++ kubernetes/rbac/pod.yaml | 9 + kubernetes/rbac/role.yaml | 12 ++ kubernetes/rbac/rolebinding.yaml | 13 ++ kubernetes/rbac/serviceaccount-role.yaml | 9 + .../rbac/serviceaccount-rolebinding.yaml | 12 ++ kubernetes/rbac/serviceaccount.yaml | 4 + 7 files changed, 245 insertions(+) create mode 100644 kubernetes/rbac/README.md create mode 100644 kubernetes/rbac/pod.yaml create mode 100644 kubernetes/rbac/role.yaml create mode 100644 kubernetes/rbac/rolebinding.yaml create mode 100644 kubernetes/rbac/serviceaccount-role.yaml create mode 100644 kubernetes/rbac/serviceaccount-rolebinding.yaml create mode 100644 kubernetes/rbac/serviceaccount.yaml diff --git a/kubernetes/rbac/README.md b/kubernetes/rbac/README.md new file mode 100644 index 0000000..f3262c4 --- /dev/null +++ b/kubernetes/rbac/README.md @@ -0,0 +1,186 @@ +# Introduction to Kubernetes: RBAC + +## Create Kubernetes cluster + + +``` +kind create cluster --name rbac --image kindest/node:v1.20.2 +``` + +## Kubernetes CA Certificate + +Kubernetes does not have a concept of users, instead it relies on certificates and would only +trust certificates signed by its own CA.
+ +To get the CA certificates for our cluster, easiest way is to access the master node.
+Because we run on `kind`, our master node is a docker container.
+The CA certificates exists in the `/etc/kubernetes/pki` folder by default.
+If you are using `minikube` you may find it under `~/.minikube/.` + +Access the master node: + +``` +docker exec -it rbac-control-plane bash + +ls -l /etc/kubernetes/pki +total 60 +-rw-r--r-- 1 root root 1135 Sep 10 01:38 apiserver-etcd-client.crt +-rw------- 1 root root 1675 Sep 10 01:38 apiserver-etcd-client.key +-rw-r--r-- 1 root root 1143 Sep 10 01:38 apiserver-kubelet-client.crt +-rw------- 1 root root 1679 Sep 10 01:38 apiserver-kubelet-client.key +-rw-r--r-- 1 root root 1306 Sep 10 01:38 apiserver.crt +-rw------- 1 root root 1675 Sep 10 01:38 apiserver.key +-rw-r--r-- 1 root root 1066 Sep 10 01:38 ca.crt +-rw------- 1 root root 1675 Sep 10 01:38 ca.key +drwxr-xr-x 2 root root 4096 Sep 10 01:38 etcd +-rw-r--r-- 1 root root 1078 Sep 10 01:38 front-proxy-ca.crt +-rw------- 1 root root 1679 Sep 10 01:38 front-proxy-ca.key +-rw-r--r-- 1 root root 1103 Sep 10 01:38 front-proxy-client.crt +-rw------- 1 root root 1675 Sep 10 01:38 front-proxy-client.key +-rw------- 1 root root 1679 Sep 10 01:38 sa.key +-rw------- 1 root root 451 Sep 10 01:38 sa.pub + +exit the container +``` + +Copy the certs out of our master node: + +``` +cd kubernetes/rbac +docker cp rbac-control-plane:/etc/kubernetes/pki/ca.crt ca.crt +docker cp rbac-control-plane:/etc/kubernetes/pki/ca.key ca.key +``` + +# Kubernetes Users + +As mentioned before, Kubernetes has no concept of users, it trusts certificates that is signed by its CA.
+This allows a lot of flexibility as Kubernetes lets you bring your own auth mechanisms, such as [OpenID Connect](https://kubernetes.io/docs/reference/access-authn-authz/authentication/#openid-connect-tokens) or OAuth.
+ +

This allows managed Kubernetes offerings to use their cloud logins to authenticate.

+ + So on Azure, I can use my Microsoft account, GKE my Google account and AWS EKS my Amazon account.
+ + You will need to consult your cloud provider to setup authentication.
+ Example [Azure AKS](https://docs.microsoft.com/en-us/azure/aks/azure-ad-integration-cli) + +## User Certificates + +First thing we need to do is create a certificate signed by our Kubernetes CA.
+We have the CA, let's make a certificate.
+ +Easy way to create a cert is use `openssl` and the easiest way to get `openssl` is to simply run a container: + +``` +docker run -it -v ${PWD}:/work -w /work -v ${HOME}:/root/ --net host alpine sh + +apk add openssl +``` + +Let's create a certificate for Bob Smith: + + +``` +#start with a private key +openssl genrsa -out bob.key 2048 + +``` + +Now we have a key, we need a certificate signing request (CSR).
+We also need to specify the groups that Bob belongs to.
+Let's pretend Bob is part of the `Shopping` team and will be developing +applications for the `Shopping` + +``` +openssl req -new -key bob.key -out bob.csr -subj "/CN=Bob Smith/O=Shopping" +``` + +Use the CA to generate our certificate by signing our CSR.
+We may set an expiry on our certificate as well + +``` +openssl x509 -req -in bob.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out bob.crt -days 1 +``` + +## Building a kube config + +Let's install `kubectl` in our container to make things easier: + +``` +apk add curl nano +curl -LO https://storage.googleapis.com/kubernetes-release/release/`curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt`/bin/linux/amd64/kubectl +chmod +x ./kubectl +mv ./kubectl /usr/local/bin/kubectl +``` + +We'll be trying to avoid messing with our current kubernetes config.
+So lets tell `kubectl` to look at a new config that does not yet exists + +``` +export KUBECONFIG=~/.kube/new-config +``` + +Create a cluster entry which points to the cluster and contains the details of the CA certificate: + +``` +kubectl config set-cluster dev-cluster --server=https://127.0.0.1:51972 \ +--certificate-authority=ca.crt \ +--embed-certs=true + +#see changes +nano ~/.kube/new-config +``` + + +kubectl config set-credentials bob --client-certificate=bob.crt --client-key=bob.key + +kubectl config set-context dev --cluster=dev-cluster --namespace=shopping --user=bob + +kubectl config use-context dev + +kubectl get pods +Error from server (Forbidden): pods is forbidden: User "Bob Smith" cannot list resource "pods" in API group "" in the namespace "shopping" + + +## Give Bob Smith Access + +``` +kubectl create ns shopping + +kubectl -n shopping apply -f .\role.yaml +kubectl -n shopping apply -f .\rolebinding.yaml +``` + +## Test Access as Bob + +kubectl get pods +No resources found in shopping namespace. + +# Kubernetes Service Accounts + +So we've covered users, but what about applications or services running in our cluster ?
+Most business apps will not need to connect to the kubernetes API unless you are building something that integrates with your cluster, like a CI/CD tool, an autoscaler or a custom webhook.
+ +Generally applications will use a service account to connect.
+You can read more about [Kubernetes Service Accounts](https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/). + + + +``` +# Point to the internal API server hostname +APISERVER=https://kubernetes.default.svc + +# Path to ServiceAccount token +SERVICEACCOUNT=/var/run/secrets/kubernetes.io/serviceaccount + +# Read this Pod's namespace +NAMESPACE=$(cat ${SERVICEACCOUNT}/namespace) + +# Read the ServiceAccount bearer token +TOKEN=$(cat ${SERVICEACCOUNT}/token) + +# Reference the internal certificate authority (CA) +CACERT=${SERVICEACCOUNT}/ca.crt + +# List pods through the API +curl --cacert ${CACERT} --header "Authorization: Bearer $TOKEN" -s ${APISERVER}/api/v1/namespaces/shopping/pods/ +``` \ No newline at end of file diff --git a/kubernetes/rbac/pod.yaml b/kubernetes/rbac/pod.yaml new file mode 100644 index 0000000..1b7d69e --- /dev/null +++ b/kubernetes/rbac/pod.yaml @@ -0,0 +1,9 @@ +apiVersion: v1 +kind: Pod +metadata: + name: nginx +spec: + containers: + - image: nginx + name: nginx + serviceAccountName: shopping-api diff --git a/kubernetes/rbac/role.yaml b/kubernetes/rbac/role.yaml new file mode 100644 index 0000000..b42e20f --- /dev/null +++ b/kubernetes/rbac/role.yaml @@ -0,0 +1,12 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + namespace: shopping + name: pod-reader +rules: +- apiGroups: [""] + resources: ["pods", "pods/exec"] + verbs: ["get", "watch", "list", "create", "delete"] +- apiGroups: [""] + resources: ["deployments"] + verbs: ["get", "watch", "list", "delete", "create"] \ No newline at end of file diff --git a/kubernetes/rbac/rolebinding.yaml b/kubernetes/rbac/rolebinding.yaml new file mode 100644 index 0000000..5ecf3b3 --- /dev/null +++ b/kubernetes/rbac/rolebinding.yaml @@ -0,0 +1,13 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: read-pods + namespace: shopping +subjects: +- kind: User + name: "Bob Smith" + apiGroup: rbac.authorization.k8s.io +roleRef: + kind: Role + name: pod-reader + apiGroup: rbac.authorization.k8s.io \ No newline at end of file diff --git a/kubernetes/rbac/serviceaccount-role.yaml b/kubernetes/rbac/serviceaccount-role.yaml new file mode 100644 index 0000000..88d8b8b --- /dev/null +++ b/kubernetes/rbac/serviceaccount-role.yaml @@ -0,0 +1,9 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + namespace: shopping + name: shopping-api +rules: +- apiGroups: [""] + resources: ["pods"] + verbs: ["get", "watch", "list"] \ No newline at end of file diff --git a/kubernetes/rbac/serviceaccount-rolebinding.yaml b/kubernetes/rbac/serviceaccount-rolebinding.yaml new file mode 100644 index 0000000..856d424 --- /dev/null +++ b/kubernetes/rbac/serviceaccount-rolebinding.yaml @@ -0,0 +1,12 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: shopping-api + namespace: shopping +subjects: +- kind: ServiceAccount + name: shopping-api +roleRef: + kind: Role + name: shopping-api + apiGroup: rbac.authorization.k8s.io \ No newline at end of file diff --git a/kubernetes/rbac/serviceaccount.yaml b/kubernetes/rbac/serviceaccount.yaml new file mode 100644 index 0000000..3073199 --- /dev/null +++ b/kubernetes/rbac/serviceaccount.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: shopping-api \ No newline at end of file