Run The Bridge

k8s 6일차 본문

Cloud/k8s

k8s 6일차

anfrhrl5555 2021. 8. 17. 17:20
728x90

0. 보안을 위한 인증과 인가 : ServiceAccount와 RBAC

인증 = login(Authentication)
인가 = login한 사용자가 가지는 권한(Authorized)

 

  • 쿠버네티스는 다수의 사용자가 함께 사용하는 시스템이기 때문에 사용자의 접근과 사용자별로 사용할 수 있는 기능을 제어하는 등 보안 측면에서 다양한 기능을 제공
  • 사용자 또는 애플리케이션에 해당하는 ServiceAccount
  • 명령을 실행할 수 있는 권한을 부여하는 RBAC(Role Based Access Control)

 

 

kubectl은 k8s 설치 시 기본적으로 관리자 권한을 갖도록 설정되어 있다.

vi /etc/kubernetes/admin.conf

admin.conf

user는 kubernetes-admin 밖에없다.

kubernetes-admin은 k8s에서 최고권한을 갖는다.

쿠버네티스는 설치하면 기본으로 6443 port가 열린다.(쿠버네티스 API 주소)

 

 

ServiceAccount으로 인증을 한다.

권한에 대한 정의를 Role & ClusterRole로 정의를 한다.

  • Role - 하나의 namespace내에서 적용되는 권한
  • ClusterRole - 클러스터 전체에 적용되는 권한

 

(실습) 서비스 어카운트 생성 및 권한 생성

kubectl get serviceaccount  # 서비스 어카운트 확인

k create ns test

k get sa -n test  # default로 잡혀있다.

 

우리만의 서비스 어카운트를 생성해본다.

k create sa alicek106  # 생성

# 에러가 나온다.
# 이제 막 생성한 서비스 어카운트에 권한이 없다.
kubectl get svc --as system:serviceaccount:default:alicek106

 

yaml 파일을 만들어 실습을 해본다.

# vi service-reader-role.yaml

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: default
  name: service-reader
rules:
- apiGroups: [""]  # 1. 대상이 될 오브젝트의 API 그룹
  resources: ["services"]  # 2. 대상이 될 오브젝트의 이름
  verbs: ["get", "list"]  # 3. 어떠한 동작을 허용할 것인지 명시
  
apiGroups, resources: 어떤 리소스가 어떤 API 그룹에 속하는지는 kubectl api-resources 명령어로 확인
verbs: 대상 리소스에 대한 동작. 'get은 하나 가져오고', 'list는 모든 것을 가져온다'

 

서비스 어카운트와 권한만 있다고 해서 권한이 부여되지 않는다. binding이 필요하다.

# vi rolebinding-service-reader.yaml

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: service-reader-rolebinding
  namespace: default

subjects:
- kind: ServiceAccount
  name: alicek106  # 권한을 부여할 주체
  namespace: default

roleRef:
  kind: Role
  name: service-reader  # 앞에 정의한 role-name
  apiGroup: rbac.authorization.k8s.io

 

(실습) ClusterRole

# vi ndes-reader-cluster-role.yaml

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: nodes-reader
  namespace: default
  
rules:
- apiGroups: [""]
  resources: ["nodes"]
  verbs: ["get", "list"]

 

이제 binding도 쌍으로 만들어줘야 한다.

# vi clusterrolebinding-nodes-reader.yaml

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: nodes-reader-clusterrolebinding
  namespace: default

subjects:
- kind: ServiceAccount
  name: alicek106
  namespace: default

roleRef:
  kind: ClusterRole
  name: nodes-reader
  apiGroup: rbac.authorization.k8s.io

nodes-reader-clusterrolebinding 가 생성된 것을 볼 수 있다.

 

서비스 어카운트에 대한 정보를 자세히 보는 방법(describe, -o yaml)

secret 으로 만들어진 token이 존재한다.

serviceaccount가 생성되면 자동으로 token이 만들어진다.

이 정보에 인증이 관련된 정보가 담겨있다.

root@kube-master1 ~/practice_10 # k get secret alicek106-token-44h8q -o yaml
apiVersion: v1
data:
  ca.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUN5RENDQWJDZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFWTVJNd0VRWURWUVFERXdwcmRXSmwKY201bGRHVnpNQjRYRFRJeE1EZ3dOVEF5TWpBeE5Gb1hEVE14TURnd016QXlNakF4TkZvd0ZURVRNQkVHQTFVRQpBeE1LYTNWaVpYSnVaWFJsY3pDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBTDJzCjRKMERmV1NsNzVYT2hCWjJCTXEyMmpiWDlROUJQMHRMaElIcHhldzdQL1BaZGpqQ0pvcVFBaHBVcDhLMXBmRm4KNkN6SnFNRGtJNWlyWjdmY2p0eE1rUGl5K2E5ZTZaOTZjTlRyemNjbzNzbENhbDBidHczak1xcTR1NGxDZkVtWApLdnhCSkFWN2tIWHZMZnlPbCs5U3RTS1VIOUw5b0NvaGk4ZnhrZmNKYlRxV1hSS3cwUnpyOTNCdUdEZFp4MHBqCm9mM1RjV25KVUNMOERwYlN4STIxUDFlZ2VRZWdpZS9yOENDQ215VDhia29PVndpbGozTDNTTlBPeE9KVVpwQ2sKYlVyYUIwVEtDVnh3WGRQZlEySDhlVll1MkR0MEdiWlN5UXdzTjlrNWJMeDBtLy9KOHVWWG55UlAzcDFRZHRxcwp1aE9ZbVBuRzZNbFNTVzlWeTJVQ0F3RUFBYU1qTUNFd0RnWURWUjBQQVFIL0JBUURBZ0trTUE4R0ExVWRFd0VCCi93UUZNQU1CQWY4d0RRWUpLb1pJaHZjTkFRRUxCUUFEZ2dFQkFJU2VMQ2JJajVVL01va2pmdXA0K282ZVE2TUEKYVlxeU50QjBLbGphaE9QdDBXeDRsYVVxUnJ5anYvQ3M1K1IyUGZ5aDB0cnFqQll5YXhUcVpLYUJ4UjJOanBUbgowa3N0RFQwd2tIUURFRm9TM0NRdURHT1VEY0FPUERlV3BZM1NrM2RIdTMyTWRaZlFuVWlDR3p3WWpGN0V1N09XCnlkWUIrQTBNa3pCY3JxS0JrZ1VRRURoRGp1NklkSnpFUVZBRUh0bHNWUFlBcnVGMnA2TUlRR2R4RXJxNldLR0gKU1pQajI4NUhsM3R0QTFPVHJqVEMwdVpBVjFTeU5KZHhCS1dsN094NHhHUEw2bW5CbGVidzFRWkdOOStqUFVYNgpVWUhIS3RDckRBUWZJaFB4Uld4d3JNcTM4OHlRa1E3Qlo3UHQvU0ovQnhHUmZCcnppalhnaC96b2hITT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=
  namespace: ZGVmYXVsdA==
  token: ZXlKaGJHY2lPaUpTVXpJMU5pSXNJbXRwWkNJNklrZGFXa3RCUTNZd1pIaFhTMlppVWs0MlNEYzVRMjFoZDFSaU1rUjVZMkpMTW1kRGVESktSVVZMYm1zaWZRLmV5SnBjM01pT2lKcmRXSmxjbTVsZEdWekwzTmxjblpwWTJWaFkyTnZkVzUwSWl3aWEzVmlaWEp1WlhSbGN5NXBieTl6WlhKMmFXTmxZV05qYjNWdWRDOXVZVzFsYzNCaFkyVWlPaUprWldaaGRXeDBJaXdpYTNWaVpYSnVaWFJsY3k1cGJ5OXpaWEoyYVdObFlXTmpiM1Z1ZEM5elpXTnlaWFF1Ym1GdFpTSTZJbUZzYVdObGF6RXdOaTEwYjJ0bGJpMDBOR2c0Y1NJc0ltdDFZbVZ5Ym1WMFpYTXVhVzh2YzJWeWRtbGpaV0ZqWTI5MWJuUXZjMlZ5ZG1salpTMWhZMk52ZFc1MExtNWhiV1VpT2lKaGJHbGpaV3N4TURZaUxDSnJkV0psY201bGRHVnpMbWx2TDNObGNuWnBZMlZoWTJOdmRXNTBMM05sY25acFkyVXRZV05qYjNWdWRDNTFhV1FpT2lKbVpqTm1ZekJoTmkweU5tTXhMVFE1T0RZdFlURTFOUzB3TVdFek1qRmxOek5rWXpnaUxDSnpkV0lpT2lKemVYTjBaVzA2YzJWeWRtbGpaV0ZqWTI5MWJuUTZaR1ZtWVhWc2REcGhiR2xqWldzeE1EWWlmUS5wbUJ2Ym9PLWdzcjZLdE56Q0FKbXVfQk5hY1g5QjA3MnMxdVBZVGl5a2ZEZDNOcmVHdEJucHdESVl3Z2lwMXo2c3N0THBGN2JpbllnZWI3WDZpb0FkaWRneDBjUGhrYjFzZWUxVllQS29lS085R1RSUkszMXVTUU1IZF9tVmxnQWhlOHdaU0pLOEVlQUVQam5iSVJsU3JNcFluX3c1aWJiOGU3ajd2Y20xSTNsVGI4bjV2RDV5aEs4bTAxemxOZHJvbmR6MDlSd1VmZlZDcGpwVWl5SW9yMEhWZURfelFNRE1oX25iZ1FsX3IxUEZ4T3MtSlI1UWNmRFppYmlfeVFRcmlOcGFmNU9MQlNPdkszeEFMUmt0WTNQemM2R0V4bHlxWERSUkZic0JJRWQ0ZU15ZU51ZFR3ZG1ValpxWFppLWJaZDJJODdsMWJDSGY2R2ZGSFpUZ3c=
kind: Secret
metadata:
  annotations:
    kubernetes.io/service-account.name: alicek106
    kubernetes.io/service-account.uid: ff3fc0a6-26c1-4986-a155-01a321e73dc8
  creationTimestamp: "2021-08-17T06:43:30Z"
  managedFields:
  - apiVersion: v1
    fieldsType: FieldsV1
    fieldsV1:
      f:data:
        .: {}
        f:ca.crt: {}
        f:namespace: {}
        f:token: {}
      f:metadata:
        f:annotations:
          .: {}
          f:kubernetes.io/service-account.name: {}
          f:kubernetes.io/service-account.uid: {}
      f:type: {}
    manager: kube-controller-manager
    operation: Update
    time: "2021-08-17T06:43:30Z"
  name: alicek106-token-44h8q
  namespace: default
  resourceVersion: "674167"
  selfLink: /api/v1/namespaces/default/secrets/alicek106-token-44h8q
  uid: c99cf5b1-0dba-424c-bd0b-f3984b05c0fb
type: kubernetes.io/service-account-token

 

(실습)서비스 어카운트의 시크릿을 이용해 쿠버네티스 API 서버에 접근

k get secert 
 alicek106-token-44h8q

export secret_name=alicek106-token-44h8q

kubectl get secret $secret_name -o jsonpath='{.data.token}'

kubectl get secret $secret_name -o jsonpath='{.data.token}' | base64 -d  # decording 볼 수 있따.

 

echo $decoded_token

이 디코딩된 토큰은 헤더의 요청에 싣어서 보내야한다.

 

curl https://localhost:6443/apis -k --header "Authorization: Bearer $decoded_token"

 

curl https://localhost:6443/api/v1/namespaces/default/services -k --header "Authorization: Bearer $decoded_token"

kubectl get svc --as system:serviceaccount:default:alicek106 를 실행했을 때와 동일한 결과

 

클러스터 내부에서 'kubernetes' 서비스를 통해 API 서버에 접근

  • 클러스터 내부에서 실행되고 있는 애플리케이션에서 API 서버에 접근
  • default 네임스페이스에 있는 kubernetes 서비스와 default 서비스 어카운트 사용

 

kubeconfig 파일에 서비스 어카운트 인증 정보 설정

cd ./kube && cp config config.bak  # kube 디렉토리로 이동 후 config 파일 백업

export secret_name=alicek106-token-t24hm  # 본인의 secret 이름으로 해야한다.

export decoded_token=$(kubectl get secret $secret_name -o jsonpath='{.data.token}' | base64 -d)

 

kubectl config set-credentials alicek106-user --token=$decoded_token  # config를 바꿔주는 명령어

set-credentials: alicek106  # alicek106이라는 유저 생성

 

 

kubectl config get-clusters  # config안에 setting된 cluster를 조회한다.

 

kubectl config set-context my-new-context --cluster=kubernetes --user=alicek106-user  # context를 생성한다.

 

 

context가 생성되었다.

 

kubectl config use-context my-new-context  # context 활성화 방법

current-context가 바뀌었다.

 

kubectl get pod  # 오류가 뜬다.

권한이 없어서 pod들을 볼 수 없다. 어제 부여한 service밖에 볼 수 없다.

 

다시 되돌리는 방법 master에서 다음 명령을 입력한다.

kubectl config use-context kubernetes-admin@kubernetes

or 백업해두었던 config.bak 파일을 원복시켜준다.

 

유저(User)와 그룹(Group)의 개념

  • 서비스 어카운트도 개념상 '유저'의 한 종류이지만 '사람'을 표현하는 것이라기 보다는 쿠버네티스의 서비스를 사용할 수 있는 주체를 의미한다
  • 쿠버네티스에서 '유저'는 '사람'을 표현하는 개념이며, '그룹'은 '유저의 집합'이다
  • 유저와 그룹은 오브젝트로 존재하지는 않는다(kubectl get user, kubectl get group 불가능)
system:serviceaccount:default:alicek106  # k8s에서 유저명과 serviceAccount를 나타내는 표현

system:serviceaccount:<네임스페이스 이름>:<서비스 어카운트 이름>

 

예시

# cat rolebinding-service-reader.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: service-reader-rolebinding
  namespace: default
subjects:
- kind: User
  name: system:serviceaccount:default:alicek106
  namespace: default
roleRef:
  kind: Role
  name: service-reader
  apiGroup: rbac.authorization.k8s.io

 

 

x509 인증서를 이용한 사용자 인증

  • X.509는 공개키 인증서와 인증 알고리즘을 사용하기 위한 PKI(공개키 기반 구조) 표준이다
  • 쿠버네티스에서는 공개키 인증서 방식의 인증도 지원한다
  • 쿠버네티스 설치 시 최상위 인증서(CA)가 생성되고 이를 기반으로 사용자 인증서를 생성한다
     → CA로부터 인증을 하기 때문에 자체 인증(self-singed)이라고 한다

 

(실습) X.509인증서 생성

openssl genrsa -out alicek106.key 2048  # key 생성

openssl req -new -key alicek106.key -out alicek106.csr -subj "/O=alicek106-org/CN=alicek106-cert"  # CSR(인증요청서) 생성

파일 2개

이제 ROOT 인증서와 엮는다.

openssl x509 -req -in alicek106.csr -days 365 -sha1 -CAcreateserial -CA /etc/kubernetes/pki/ca.crt -CAkey /etc/kubernetes/pki/ca.key -out alicek106.crt  # 인증서 생성

 

kubeconfig에 유저 생성한다.

kubectl config set-credentials alicek106-x509-user --client-certificate=alicek106.crt --client-key=alicek106.key

~/.kube/config 파일에 alicek106-x509-user가 만들어졌다.

 

kubeconfig에 context 생성한다.

kubectl config set-context alicek106-x509-context --cluster kubernetes --user alicek106-x509-user

context 추가완료

 

kubeconfig의 current-context 변경

kubectl config use-context alicek106-x509-context

 

이제 kubectl get pod 같은 명령을 날리면 오류가난다. rolebinding을 해주어야 한다.

# vi rolebinding-service-reader.yaml

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: service-reader-rolebinding
  namespace: default

subjects:
- kind: ServiceAccount
  name: alicek106
  namespace: default

roleRef:
  kind: Role
  name: service-reader
  apiGroup: rbac.authorization.k8s.io

하지만 rolebinding을 해도 error가 난다.

 

user-context를 바꾸어야 한다.

root@kube-master1 ~/practice_10 # kubectl config use-context kubernetes-admin@kubernetes
Switched to context "kubernetes-admin@kubernetes".

root@kube-master1 ~/practice_10 # k apply -f x509-cert-rolebinding-user.yaml
rolebinding.rbac.authorization.k8s.io/service-reader-rolebinding configured

service가 불러진다.

 
728x90

'Cloud > k8s' 카테고리의 다른 글

k8s 8일차  (0) 2021.08.19
k8s 7일차  (0) 2021.08.18
docker-registry를 이용해 toyproject k8s에 deployment로 올리기  (0) 2021.08.16
k8s 5일차  (0) 2021.08.13
Secert과 tls 타입의 시크릿 생성 후 mysql, wordpress, nginx 적용  (0) 2021.08.11
Comments