Run The Bridge
k8s 6일차 본문
0. 보안을 위한 인증과 인가 : ServiceAccount와 RBAC
인증 = login(Authentication)
인가 = login한 사용자가 가지는 권한(Authorized)
- 쿠버네티스는 다수의 사용자가 함께 사용하는 시스템이기 때문에 사용자의 접근과 사용자별로 사용할 수 있는 기능을 제어하는 등 보안 측면에서 다양한 기능을 제공
- 사용자 또는 애플리케이션에 해당하는 ServiceAccount
- 명령을 실행할 수 있는 권한을 부여하는 RBAC(Role Based Access Control)
kubectl은 k8s 설치 시 기본적으로 관리자 권한을 갖도록 설정되어 있다.
vi /etc/kubernetes/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
서비스 어카운트에 대한 정보를 자세히 보는 방법(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를 생성한다.
kubectl config use-context my-new-context # 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(인증요청서) 생성
이제 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
kubeconfig에 context 생성한다.
kubectl config set-context alicek106-x509-context --cluster kubernetes --user alicek106-x509-user
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
'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 |