Thursday, February 11, 2021

Kubernetes - context, role, rolebinding, IAM - Day 17

Day17- Kubernetes - context, role, rolebinding, IAM -  2/10/2021


IAM - Identity and access management.
- Who can access your service?
  - you have to set up authentication part (identity)
    - User with key
    - user with cert
    - User with password
    - User with one time password

How do you prove you are who you are
- username/pw


After login
what can you do?
  - What authority you have
    - based on that authority, you can access

managing identity and access part is called IAM.

- what power or role assigned to you
- Based on that role, you can perform the tasks and this is called rolebinding.

Auth
- Username/pw (LDAP)
- User/token/key
- User/cert
- user/sso (single sign on)

based on use case, you may use any or more of the above auth methods


user (PC-VM) ------> connects to  k8s cluster
 -anywhere in the world


cluster can be any of the following
- k8s cluster - aws
- Minikube
- EKS --GCP, Azure

you have to create user on these cluster to authenticate.
- you can use tocken, keys, cert, pw

how kubectl command knows where to create pod on the cluster?

when you use your local machine,
create a config file which contains user info of the cluster.
using this file, connect to the node where you will be deploying your pods.
# cd /kubews
# vi john.kubeconfig
apiVersion: v1
clusters:
- cluster:
    certificate-authority: ca.crt
    server: https://53.56.34.654:6443
  name: awskubecluster
contexts: null
currect-context: ""
kind: Config
preferences: {}
users:
- name: john
  user:
    client-certificate: john.crt
    client-key: john.key

This file tells us that where is our cluster
username/pw or certificate used.

# kc get pods --kubeconfig john.kubeconfig

go to this file and connect
but you get error
localhost:8080 was refused...

john.kubeconfig is a local config file for user.

In this file, we don't only write one cluster detail.

We can add more cluster info as well.

# vi john.kubeconfig
apiVersion: v1
clusters:
- cluster:
    certificate-authority: ca.crt
    server: https://53.56.34.654:6443
  name: awskubecluster
#
- cluster:
    certificate-authority: ca.crt
    server: https://192.168.10.20:6443
  name: minikubelocal
# you can add other cluster here as well

contexts: null
currect-context: ""
kind: Config
preferences: {}
users:
- name: john
  user:
    client-certificate: john.crt
    client-key: john.key
# add more users info
- name: johnlocal
  user:
    client-certificate: johnlocal.crt
    client-key: johnlocal.key


This way you can define other cluster and user information on your local config file.

> kc config get-users --kubeconfig john.kubeconfig

now, still we get error, but the confising part here is what cluster to use?

for cluster1 what user to use, 2nd what user to use, it gets confuse.

For this, we use local config file called kubeconfig file...


here we define, for cluster1, use this use and cluster2, use this user.

This kind of combination is called context.
context mean - what combination to use...

now, we have to set the context


How to set a context?
lets get help
# kc config -h

set-cluster, set-context

# kc config get-cluster
no result

specify the config file
# kubectl config get-cluster --kubeconfig john.kubeconfig

get all the users on this file
# kc config get-users --kubeconfig john.kubeconfig

# get all the context on this file
# kc config get-contexts --kubeconfig john.kubeconfig
We haven't get set up context, so no result is displayed.

lets get more help, how to use, whats the method to use.
get the example from help
# kc config set-config -h
# kc config set-context awskubecluster --user=john

so, now, we created a context.

now, check how many contexts you have,
# kc config get-contexts --kubeconfig john.kubeconfig
no result

when using the set-context command, we didn't speficy what file to update.
it updates the default file by default. but we have to update john.kubeconfig file.

Lets run the command and get the context from the same file,
# kc config set-context awskubecluster --user=john --kubeconfig
this time, you see the output..

for this cluster, this is the authentication information..

this is the way, you can do it.

here, we didn't specify the cluster information.
you can do it through cmd or you can edit the config file,
let update it
on last command, we forgot to specify cluster name
# kc config set-context john@awskubecluster --user=john --cluster awskubecluster  --kubeconfig john.kubeconfig
# kc config set-context user@clustername --user-john --cluster awskubecluster --kubeconfig john.kubeconfig

anyone who wants to use this cluster, will use user called john.

lets get the context
# kc config get-contexts --kubeconfig john.kubeconfig

now, you will seee entry under CLUSTER

now, let see the config file,

# cat john.kubeconfig
apiVersion: v1
clusters:
- cluster:
    certificate-authority: ca.crt
    server: https://53.56.34.654:6443
  name: awskubecluster
#
- cluster:
    certificate-authority: ca.crt
    server: https://192.168.10.20:6443
  name: minikubelocal
# you can add other cluster here as well

contexts:
- context:
    cluster: awskubecluster
    user: john
  name: john@awskubecluster
currect-context: ""
kind: Config
preferences: {}
users:
- name: john
  user:
    client-certificate: john.crt
    client-key: john.key
# add more users info
- name: johnlocal
  user:
    client-certificate: johnlocal.crt
    client-key: johnlocal.key


Note: for each cluster, you have to give unique name.


Now, lets set up another context
# kc config set-context johnlocal@minikubelocal --user=johnlocal --cluster minikubelocal --kubeconfig john.kubeconfig

Lets get the context
# kc config get-contexts --kubeconfig john.kubeconfig

now two different cluster is listed.


now, you can decide what context do you want to launch your pod.

# kc get pods --kubeconfig john.kubeconfig
it failed again..

there are two context, which one to use?

so, technically you have to set one default context.


by editing the john.kubeconfig file, you can specify any context that you want to
make it default, by speficying at the current-context.
Let try using command line,
# kc config --help
current-context
# kc config current-context --kubeconfig john.kubeconfig
# kc config user-context -h

# kc config get-contexts --kubeconfig john.kubeconfig
# kc config use-context john@awskubecluster --kubeconfig john.kubeconfig

# kc config current-context --kubeconfig john.kubeconfig

Now open the file and see the value on current-context


# cat john.kubeconfig
apiVersion: v1
clusters:
- cluster:
    certificate-authority: ca.crt
    server: https://53.56.34.654:6443
  name: awskubecluster
#
- cluster:
    certificate-authority: ca.crt
    server: https://192.168.10.20:6443
  name: minikubelocal
# you can add other cluster here as well

contexts:
- context:
    cluster: awskubecluster
    user: john
  name: john@awskubecluster
currect-context: john@awskubecluster
kind: Config
preferences: {}
users:
- name: john
  user:
    client-certificate: john.crt
    client-key: john.key
# add more users info
- name: johnlocal
  user:
    client-certificate: johnlocal.crt
    client-key: johnlocal.key


-----------------------------

# kc config -h
look for current confext
$ kc config current-context --kubeconfig john.kubeconfig

# vi john.kubeconfig

# kc config -h
# kc config use-context john@awskubecluster
error no contest
# kc config use-context john@awskubecluster --kubeconfig john.kubeconfig
# kc config current-context --kubeconfig john.kubeconfig
# vi john.kubeconfig


Lets work on minukube

Lets start minikube

 > minikube start
automatically configures single master node, worker mode, updates kubeconfig file


Now, run to get the context
# kc config get-context --kubeconfig john.kubeconfig

you have two contexts.
# kc get pods
never know what context to use...

# kc get pods --kubeconfig john.kubeconfig
new error come up..
something different came up..

it says, unable to connect to the server: x509: certificate is valid for this this ip but not this

since our cluster server is on remove location.

so, we have master node
- api-server

when a user/client connects, they always connect to api-server.
that is why, we specify ip and port of master node on kubeconfig file.
Lets consider, the api-server is a kind of webserver, and running on a port
say ip:port or ip:6443

when user connects to the web server, it goes to http but we want to
encript the connection (https). which gives us more secure (in terms of encription)..

so, what we need for encription?
- private key
- certificate crt

crt signed by authority.

master node is CA is automatically configured
when you launch kubeadm init command on master node,
master is configured as CA - certificate authority
ca signed it and send it to CRT)
- csr is configured
- Key is already configured
- CRT is also created.

(all process happened automatically)

login to you aws master node (AWS)
[ - get the ip and paste it to putty
  - expand connection -> ssh -> click on Auth
  - click on browse and select the privatekey file ]

# cd /etc/kubernetes/pki
# ls

you see key, CA and certificates...
- key for apiserver, etcd, proxy and of course our certificates that we created ....


Why you need certificate?

- because of security, all of our custeomer connect using https, if you want to connect to app
  server or web server, your server need private key, and crt certificate.
  that means signed certificate by some CA.


In the same process, user also needed CA certificate,
in term of neagotiation, user ca and server CA may not recognize.

if you open and look at the config file, you will see certificate ahd
server UTL:port

# cat john.kubeconfig
same CA which signed api-server.
If this is not the case, it does not work.


In case of minikube, you have to same CA which signed api-server.
otherwise it wont work.

minikube has its won api-server and need to get their own certificate.
or find minikube certificate.


Login to your local master minikube server.

You have two IP on your master server.

In a  cryptographic world,
whenever you create a certificate,

When api-server is created, it creates a private key
- Then from this private key, they create their own certificate called CSR (signing certificate)
- And they send the certificate to CA, verifies this and sign it.
- and finally becomes CRT.

Private key -> CSR -> CA -> CRT

What CSR certificate contains?
it contains lots of information
country, locatity, org name, email and more ....
- we can add some extra info for security.


lets say, we have webserver (192.168.10.20) and use connects to the site.
it is connected using certificate.

say, hacker copy all the contents and created a duplicate same site.
and user think that is legitimate site. enters username/pw and info is stole...

for security reason, we put a restriction of IP addresses..

we have a certificate and that can only be useful to one IP address or
can use multiple IP but we define.
Our certificate is restricted to certain IPs not all available on the web.


on apiserver.crt has entry, which allows only specified IP addresses.

This file is encoded, you have to decode it.
# vi apiserver.crt

it has some fields, and it only allows two ips
so they try to connect to only these two. if they connect anyother will
be deny access.


in case of cloud, you will have public and private IP.
and virtual machine will never know the public IP.


convert into text
# openssl x509 -in apiserver.crt  -text

x509 is a standard they follow.

certificate is decoded.

Review the output, you will see
SAM - Subject alternative Name


How to decript the certificate
# decode certificate
# openssl x509 -in apiserver

subject alternative name:
you see two ip addresses..

this certificate can only be used by listed IP addresses...


Now, to resolve unable to connect issue,
remove certificate, key and create again.

Remove certificate/private key of apiserver
# rm /etc/kubernetes/pki/apiserver.*

You have to create certificate for all apiserver. Here you can add SANIP
# kc init phase certs all --apiserver-advertise-address=0.0.0.0 --apiserver-cert-extra-sans=<your_public_ip_of_masternode-AWS>
# kc init phase certs all --apiserver-advertise-address=0.0.0.0 --apiserver-cert-extra-san=54.56.32.243

it will re-create certificate on private key and add three IP addresses... You can see and review the command output.
so, IP is added where client will connect.

Now, go ahead and decode the key
# openssl x509 -in apiserver.crt -text

Note: API-server runs inside POD and pod is a kind of container (docker).
# docker ps | grep api

You can see it is running inside api-server.

From the output, we can see that it is running on older cert, now, we will delete this and crete a new one certificate
What we have to do, is to delete this container.
# docker rm -f `docker ps -q -f 'name=k8s_kube-apiserver*'`
it will create automatically. Now start kubelet to update..
# kubectl restart kubelet


Now, go back to your workstation (PC) and run,
# kc get pods --kubeconfig john.kubeconfig

we got different error this time. something to do with forbidden
This means, workstation is successfully connected /authenticated.

What happened here is that, we tried to connect (login) to the master server (IP:port) using the config file.
Out username pw (cert) was good and authenticated.
after authentication, we tried to access some resources and one of the resource is POD. What happened is
we want to get some resources.. (other options, create,delete but want to get it)

if you want to do some action on some of the resources, you need to have proper access.
We haven't yet provided enough access to user john. (with action call get)

kubernetes works on least priviledge concept. you keep on adding the access to the user based on requirement.

This user does not have the get/view the result
So, we have to configure the role.

When you create a user, in your cluster, create a namespace. user logins to namespace and use the namespace.

Cluster is like a hotel and
namespace is like a room
The default namespace(ns) is default.

# kc get ns

create a new room
# kc create ns tech
# kc get ns

on your workstation

# kc config -h

Lets initiate a connection, go to cluster using tech namespace.
# kc get pods --kubeconfig john.kubeconfig --namespace tech

namespace is allocated to user john


now, we have to define, what facility (resources) user can access..

Resources/facilities user can use.

Resources ->     Actions
POD        - Get, delete
Deployment    


You have to create role, and

Go to master( aws) and check how many roles we have
# kc get roles
nno resources found in default ns

# kc get roles -n tech
get the name space tech to check if role is created for tech namespace

Now, what we have to do is to create. Grant access, pod what action can do?
# kc create role john-tech --resource=pods --verb=get,list -n tech

one role has been created. we gave power/access to user based on role (RBAC)
Here user created based on RBAC concept for authentication


now, go to your workstation and try
# kc get pods --kubeconfig john.kubeconfig --namespace tech

again got error,
because the admin created user for the role. we have to give this power to the user @ workstation. this process is called roll binding.

go to the server and run
# kubectl get rolebinding -n tech

no role binding set up yet
now, lets set up

I am allocating role to a user in the room called tech
# kc create rolebinding john-tech-rb --role john-tech --user john -n tech
# kc get rolebinding -n tech

# kc describe rolebinding john-tech-rb -n tech
from the output you see john user is assign to role john-tech.

get the description of role...
# kc describe role john-tech -n tech

anyone who has this role, they can list pod. they can get and list
this profile is what is given to the user

go back to local workstation
# kc get pods --kubeconfig john.kubeconfig --namespace tech
now, its working..

# kc create deploy myd --image=httpd --kubeconfig john.kubeconfig --namespace tech
# kc get deployment --kubeconfig john.kubeconfig --namespace tech

can't do it because of the access
to get access, we have to give access to the role - john-tech

for that you have to go to master and edit the role
# kc edit role john-tech -n tech


go to the section roles ..
and go the namespace: tech
go down to rules:
and add resources.

add entry under roles and add under resources

rules:
- apiGroups:
  - ""
  resources:
  - pods
  - deployments

  verb
  - get
  - list


now run,
# kc describe role john.tech -n tech

go to workstation and run
# kc get deployment --kubeconfig john.kubeconfig --namespace tech

got error

# kc create deploy myd --image=httpd --keyconfig john,kubeconfig
can not create..

reason is some resources are depend of another resource.

for eg, deployment resource is dependednt to some other resources.
say service.. or replica set ..

rules:
- apiGroups:
  - ""
  resources:
  - pods
  - deployments
  - services

  verb
  - get
  - list

still failed. Lets use * - all the power..

rules:
- apiGroups:
  - ""
  resources:
  - pods
  - deployments


  verb
  - '*' # give all the power on three resources.


# kc describe role john-tech -n tech

now, john user has power to perform the task.


Lets try to create deployment
# kc create deploy myd --image=httpd --kubeconfig john.kubeconfig

failed..


# kc get services --kubeconfig john.kubeconfig
# kc get rs --kubeconfig john.kubeconfig

Now, edit the role and add extra resources.
# kc edit role john-tech -n tech
rules:
- apiGroups:
  - ""
  resources:
  - pods
  - deployments
  - rs
  verb
  - '*'
rs=replicaset..

or
all resource, all verbs

rules:
- apiGroups:
  - ""
  resources:
  - '*'
  verb
  - '*'
rs=replicaset..


# kc describe role vomal-tech -n tech

we can control resources this way ...


now issue is resolved.

---------------------------------

# kc edit role john.tech -n team
# kc describe role john-tech -n tech

# kc edit
# kc edit rolebinding john

kc describe role john-tech -n tech
kc edit role john-tech -n tech

kc describe rolebinding johntech-rb -n tech
kc edit rolebinding john-tech-rb -n tech
kc edit role john-tech -n tech
# kc edit tol

kc describe

we can control resources with verbs....



No comments:

Post a Comment

Git branch show detached HEAD

  Git branch show detached HEAD 1. List your branch $ git branch * (HEAD detached at f219e03)   00 2. Run re-set hard $ git reset --hard 3. ...