[kubernetes-실습] Security - Authentication, Authorization, Admission

Kubernetes 클러스터는 사용자의 유형으로 service accoount와 normal users 가 있지만 normal users는 외부 서비스에 의해 관리된다. normal users를 나타낼 개체가 없고, 또한 API 호출을 통해 추가할 수도 없다. 하지만 service account를 추가할 수 있다. RBAC을 사용하여 개발자 devJang을 위한 네임스페이스 내의 행동에 대한 접근을 테스트해 본다.

# Authentication, Authorization 

- 두개의 테스트용 dev, prod namespace를 생성한다.

# dev, prod의 두개 namespace를 생성한다.
ps0107@k8smaster1:~$ kubectl create ns dev
namespace/dev created

ps0107@k8smaster1:~$ kubectl create ns prod
namespace/prod created

 

- 사용가능한 현재 클러스터와 context 를 확인한다

# 사용가능한 현재 클러스터와 context 를 확인한다.
# context 를 사용하면 클러스터가 쉽고 일관된 방식으로 kubectl 명령에 사용할 클러스터, 네임스페이스 및 사용자를 구성할 수 있다.
ps0107@k8smaster1:~$ kubectl config get-contexts
CURRENT   NAME                          CLUSTER      AUTHINFO           NAMESPACE
*         kubernetes-admin@kubernetes   kubernetes   kubernetes-admin   

 

- 사용자 계정을 추가 및 key 생성

# 사용자 계정을 추가한다.
ps0107@k8smaster1:~$ sudo useradd -s /bin/bash devJang                                                                                ps0107@k8smaster1:~$ sudo passwd devJang 
Enter new UNIX password: 
Retype new UNIX password: 
passwd: password updated successfully

# devJang 계정을 위한 CSR(Certificate Signing Request) private key를 생성한다.
ps0107@k8smaster1:~$ openssl genrsa -out devJang.key 2048
Generating RSA private key, 2048 bit long modulus
............................+++
....................................................................+++
e is 65537 (0x10001)

ps0107@k8smaster1:~$ openssl req -new -key devJang.key -out devJang.csr -subj "/CN=devJang/O=dev"                                     

# x509 프로토콜을 사용하는 self-signed certificate를 생성 요청하여 새롭게 생성된 것을 사용한다.
# kubernetes 클러스터를 위한 CA key를 사용한다. 그리고 45일 만료로 세팅해 준다.
ps0107@k8smaster1:~$ sudo openssl x509 -req -in devJang.csr \
> -CA /etc/kubernetes/pki/ca.crt \
> -CAkey /etc/kubernetes/pki/ca.key \                                                                                                 
> -CAcreateserial \
> -out devJang.crt -days 45                                                                                                           

Signature ok
subject=/CN=devJang/O=dev
Getting CA Private Key

# 새로운 key와 certificate를 참조하기 위해 config file 접근을 업데이트한다.
# 보통 root가 아닌 사용자의 home 에 이동시켜 두는게 좋다.
ps0107@k8smaster1:~$ kubectl config set-credentials devJang \
> --client-certificate=/home/ps0107/devJang.crt \                                                                                    
> --client-key=/home/ps0107/devJang.key                                                                                               
User "devJang" set.

# credentials file 업데이트를 확인 해본다. diff 로 비교해본다.
ps0107@k8smaster1:~$ diff cluster-api-config .kube/config                                                                             
15a16,19
> - name: devJang
>   user:
>     client-certificate: /home/ps0107/devJang.crt
>     client-key: /home/ps0107/devJang.key

 

- context 생성 및 확인 (dev)

# context를 생성한다.
ps0107@k8smaster1:~$ kubectl config set-context devJang-context \
> --cluster=kubernetes \
> --namespace=dev \                                                                                                                   
> --user=devJang

Context "devJang-context" created.

# devJang-context로 pod를 보려고 시도해보자.
# 권한이 없어 에러가 발생한다.
ps0107@k8smaster1:~$ kubectl --context=devJang-context get pods
Error from server (Forbidden): pods is forbidden: User "devJang" cannot list resource "pods" in API group "" in the namespace "dev"

# context 확인 해본다.
ps0107@k8smaster1:~$ kubectl config get-contexts 
CURRENT   NAME                          CLUSTER      AUTHINFO           NAMESPACE
          devJang-context               kubernetes   devJang            dev
*         kubernetes-admin@kubernetes   kubernetes   kubernetes-admin   

# 다시 한번 변경된 cluster access config file을 확인해본다.
ps0107@k8smaster1:~$ diff cluster-api-config .kube/config
9a10,14
>     namespace: dev
>     user: devJang
>   name: devJang-context
> - context:
>     cluster: kubernetes
15a21,24
> - name: devJang
>   user:
>     client-certificate: /home/ps0107/devJang.crt
>     client-key: /home/ps0107/devJang.key

 

- 권한을 주기위해 Role 생성 및 RoleBinding을 해준후 테스트 한다. (개발자에게 개발 관련 권한 전체 부여)

# RBAC 을 할당하기 위해 yaml 파일을 만들어 준다.
ps0107@k8smaster1:~$ vi role-dev.yaml 
kind: Role
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  namespace: dev
  name: developer
rules:
- apiGroups: ["", "extensions", "apps"]
  resources: ["deployments", "replicasets", "pods"]
  verbs: ["list", "get", "watch", "create", "update", "patch", "delete"]
# You can use ["*"] for all verbs

# RBAC object를 생성한다.
ps0107@k8smaster1:~$ kubectl create -f role-dev.yaml 
role.rbac.authorization.k8s.io/developer created

# user에 Role을 할당하기 위해 RollBinding을 생성한다.
ps0107@k8smaster1:~$ vi rolebind.yaml
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: developer-role-binding
  namespace: dev
subjects:
- kind: User
  name: devJang
  apiGroup: ""
roleRef:
  kind: Role
  name: developer
  apiGroup: ""

ps0107@k8smaster1:~$ kubectl apply -f rolebind.yaml                                                                                   rolebinding.rbac.authorization.k8s.io/developer-role-binding created

# context를 다시 테스트 해본다.
# 이번엔 정상적으로 수행된다.
ps0107@k8smaster1:~$ kubectl --context=devJang-context get pods
No resources found.

# deployment도 한번 만들어서 조회해 보자.
ps0107@k8smaster1:~$ kubectl --context=devJang-context create deployment nginx --image=nginx                                          deployment.apps/nginx created

# 역시 조회가 잘되는것을 확인할 수 있다.
ps0107@k8smaster1:~$ kubectl --context=devJang-context get pods
NAME                     READY   STATUS    RESTARTS   AGE
nginx-554b9c67f9-pnwl5   1/1     Running   0          10s

# 확인 했으니 deployment를 삭제해주자.
ps0107@k8smaster1:~$ kubectl --context=devJang-context delete deploy nginx
deployment.extensions "nginx" deleted

 

- 이번엔 devJang에서 prod에 대한 일부 권한을 부여해 보자. (개발자이므로 운영모든 권한 부여는 필요없음)

# 이번엔 devJang에 prod namespace의 권한을 설정해 본다.
ps0107@k8smaster1:~$ vi role-prd.yaml
kind: Role
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  namespace: prod
  name: dev-prod
rules:
- apiGroups: ["", "extensions", "apps"]
  resources: ["deployments", "replicasets", "pods"]
  verbs: ["list", "get", "watch"]
# You can use ["*"] for all verbs

# RollBinding도 설정하기 위해 yaml파일을 만든다ㅏ.
ps0107@k8smaster1:~$ vi rolebindprod.yaml
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: prod-role-binding
  namespace: prod
subjects:
- kind: User
  name: devJang
  apiGroup: ""
roleRef:
  kind: Role
  name: dev-prod
  apiGroup: ""

# role 객체를 생성해 준다.
ps0107@k8smaster1:~$ kubectl apply -f role-prd.yaml 
role.rbac.authorization.k8s.io/dev-prod created

# rolebinding 객체를 생성해 준다.
ps0107@k8smaster1:~$ kubectl apply -f rolebindprod.yaml                                                                               rolebinding.rbac.authorization.k8s.io/prod-role-binding created

# prod context를 만들어준다.
ps0107@k8smaster1:~$ kubectl config set-context prodJang-context \
> --cluster=kubernetes \
> --namespace=prod \
> --user=devJang

Context "prodJang-context" created.

# 생성된 context로 pod를 조회해 본다.
# 정상적으로 조회가 된다.
ps0107@k8smaster1:~$ kubectl --context=prodJang-context get pods
No resources found.

# 설정된 role을 확인해볼수 있다.
ps0107@k8smaster1:~$ kubectl -n prod describe role dev-prod 
Name:         dev-prod
Labels:       <none>
Annotations:  kubectl.kubernetes.io/last-applied-configuration:
                {"apiVersion":"rbac.authorization.k8s.io/v1beta1","kind":"Role","metadata":{"annotations":{},"name":"dev-prod","namespace":"prod"},"rules"...
PolicyRule:
  Resources               Non-Resource URLs  Resource Names  Verbs
  ---------               -----------------  --------------  -----
  deployments             []                 []              [list get watch]
  pods                    []                 []              [list get watch]
  replicasets             []                 []              [list get watch]
  deployments.apps        []                 []              [list get watch]
  pods.apps               []                 []              [list get watch]
  replicasets.apps        []                 []              [list get watch]
  deployments.extensions  []                 []              [list get watch]
  pods.extensions         []                 []              [list get watch]
  replicasets.extensions  []                 []              [list get watch]

 

# Admission

ps0107@k8smaster1:~$ sudo grep admission /etc/kubernetes/manifests/kube-apiserver.yaml 
    - --enable-admission-plugins=NodeRestriction