CertificateSigningRequest로 쿠버네티스 API 클라이언트용 인증서 발급하기

CertificateSigningRequest로 쿠버네티스 API 클라이언트용 인증서 발급하기 (Issue a Certificate for a Kubernetes API Client Using a CertificateSigningRequest)

쿠버네티스는 공개 키 인프라(PKI)를 사용해 클라이언트로 클러스터에 인증할 수 있게 해줘요.

일반 사용자가 인증하고 API를 호출할 수 있으려면 몇 단계가 필요해요. 먼저 그 사용자는 쿠버네티스 클러스터가 신뢰하는 기관이 발급한 X.509 인증서를 가져야 해요. 그런 다음 클라이언트가 그 인증서를 쿠버네티스 API에 제시해야 해요.

이 과정의 일부로 CertificateSigningRequest를 사용하며, 사용자나 다른 프린시펄이 요청을 승인해야 해요.

개인 키를 만들고, 인증서를 발급받고, 마지막으로 그 개인 키를 클라이언트에 구성하게 돼요.

출처: 문서

본문

시작하기 전에 (Before you begin)

이 페이지는 쿠버네티스 역할 기반 접근 제어 (RBAC)를 사용한다고 가정해요. 인가에 대한 대안적이거나 추가적인 보안 메커니즘이 있다면 그것들도 고려해야 해요.

개인 키 만들기

이 단계에서 개인 키를 만들어요. 이 개인 키를 비밀로 유지해야 해요. 그것을 가진 사람은 누구나 사용자를 사칭할 수 있어요.

# Create a private key
openssl genrsa -out myuser.key 3072

X.509 인증서 서명 요청 만들기

참고:

CSR의 CN과 O 속성을 설정하는 것이 중요해요. CN은 사용자의 이름이고 O는 이 사용자가 속할 그룹이에요. 표준 그룹은 RBAC를 참고할 수 있어요.

# Change the common name "myuser" to the actual username that you want to use
openssl req -new -key myuser.key -out myuser.csr -subj "/CN=myuser"

쿠버네티스 CertificateSigningRequest 만들기

이 명령으로 CSR 문서를 인코딩해요:

cat myuser.csr | base64 | tr -d "\n"

CertificateSigningRequest를 만들고 kubectl로 쿠버네티스 클러스터에 제출해요. 아래는 CertificateSigningRequest를 생성하는 데 사용할 수 있는 셸 스니펫이에요.

cat <<EOF | kubectl apply -f -
apiVersion: certificates.k8s.io/v1
kind: CertificateSigningRequest
metadata:
  name: myuser # example
spec:
  # This is an encoded CSR. Change this to the base64-encoded contents of myuser.csr
  request: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURSBSRVFVRVNULS0tLS0KTUlJQ1ZqQ0NBVDRDQVFBd0VURVBNQTBHQTFVRUF3d0dZVzVuWld4aE1JSUJJakFOQmdrcWhraUc5dzBCQVFFRgpBQU9DQVE4QU1JSUJDZ0tDQVFFQTByczhJTHRHdTYxakx2dHhWTTJSVlRWMDNHWlJTWWw0dWluVWo4RElaWjBOCnR2MUZtRVFSd3VoaUZsOFEzcWl0Qm0wMUFSMkNJVXBGd2ZzSjZ4MXF3ckJzVkhZbGlBNVhwRVpZM3ExcGswSDQKM3Z3aGJlK1o2MVNrVHF5SVBYUUwrTWM5T1Nsbm0xb0R2N0NtSkZNMUlMRVI3QTVGZnZKOEdFRjJ6dHBoaUlFMwpub1dtdHNZb3JuT2wzc2lHQ2ZGZzR4Zmd4eW8ybmlneFNVekl1bXNnVm9PM2ttT0x1RVF6cXpkakJ3TFJXbWlECklmMXBMWnoyalVnald4UkhCM1gyWnVVV1d1T09PZnpXM01LaE8ybHEvZi9DdS8wYk83c0x0MCt3U2ZMSU91TFcKcW90blZtRmxMMytqTy82WDNDKzBERHk5aUtwbXJjVDBnWGZLemE1dHJRSURBUUFCb0FBd0RRWUpLb1pJaHZjTgpBUUVMQlFBRGdnRUJBR05WdmVIOGR4ZzNvK21VeVRkbmFjVmQ1N24zSkExdnZEU1JWREkyQTZ1eXN3ZFp1L1BVCkkwZXpZWFV0RVNnSk1IRmQycVVNMjNuNVJsSXJ3R0xuUXFISUh5VStWWHhsdnZsRnpNOVpEWllSTmU3QlJvYXgKQVlEdUI5STZXT3FYbkFvczFqRmxNUG5NbFpqdU5kSGxpT1BjTU1oNndLaTZzZFhpVStHYTJ2RUVLY01jSVUyRgpvU2djUWdMYTk0aEpacGk3ZnNMdm1OQUxoT045UHdNMGM1dVJVejV4T0dGMUtCbWRSeEgvbUNOS2JKYjFRQm1HCkkwYitEUEdaTktXTU0xMzhIQXdoV0tkNjVoVHdYOWl4V3ZHMkh4TG1WQzg0L1BHT0tWQW9FNkpsYWFHdTlQVmkKdjlOSjVaZlZrcXdCd0hKbzZXdk9xVlA3SVFjZmg3d0drWm89Ci0tLS0tRU5EIENFUlRJRklDQVRFIFJFUVVFU1QtLS0tLQo=
  signerName: kubernetes.io/kube-apiserver-client
  expirationSeconds: 86400  # one day
  usages:
  - client auth
EOF

대안으로 YAML 매니페스트 파일을 만들고 kubectl 로 적용할 수도 있어요:

apiVersion: certificates.k8s.io/v1
kind: CertificateSigningRequest
metadata:
  name: myuser # example
spec:
  # This is an encoded CSR. Change this to the base64-encoded contents of myuser.csr
  request: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURSBSRVFVRVNULS0tLS0KTUlJQ1ZqQ0NBVDRDQVFBd0VURVBNQTBHQTFVRUF3d0dZVzVuWld4aE1JSUJJakFOQmdrcWhraUc5dzBCQVFFRgpBQU9DQVE4QU1JSUJDZ0tDQVFFQTByczhJTHRHdTYxakx2dHhWTTJSVlRWMDNHWlJTWWw0dWluVWo4RElaWjBOCnR2MUZtRVFSd3VoaUZsOFEzcWl0Qm0wMUFSMkNJVXBGd2ZzSjZ4MXF3ckJzVkhZbGlBNVhwRVpZM3ExcGswSDQKM3Z3aGJlK1o2MVNrVHF5SVBYUUwrTWM5T1Nsbm0xb0R2N0NtSkZNMUlMRVI3QTVGZnZKOEdFRjJ6dHBoaUlFMwpub1dtdHNZb3JuT2wzc2lHQ2ZGZzR4Zmd4eW8ybmlneFNVekl1bXNnVm9PM2ttT0x1RVF6cXpkakJ3TFJXbWlECklmMXBMWnoyalVnald4UkhCM1gyWnVVV1d1T09PZnpXM01LaE8ybHEvZi9DdS8wYk83c0x0MCt3U2ZMSU91TFcKcW90blZtRmxMMytqTy82WDNDKzBERHk5aUtwbXJjVDBnWGZLemE1dHJRSURBUUFCb0FBd0RRWUpLb1pJaHZjTgpBUUVMQlFBRGdnRUJBR05WdmVIOGR4ZzNvK21VeVRkbmFjVmQ1N24zSkExdnZEU1JWREkyQTZ1eXN3ZFp1L1BVCkkwZXpZWFV0RVNnSk1IRmQycVVNMjNuNVJsSXJ3R0xuUXFISUh5VStWWHhsdnZsRnpNOVpEWllSTmU3QlJvYXgKQVlEdUI5STZXT3FYbkFvczFqRmxNUG5NbFpqdU5kSGxpT1BjTU1oNndLaTZzZFhpVStHYTJ2RUVLY01jSVUyRgpvU2djUWdMYTk0aEpacGk3ZnNMdm1OQUxoT045UHdNMGM1dVJVejV4T0dGMUtCbWRSeEgvbUNOS2JKYjFRQm1HCkkwYitEUEdaTktXTU0xMzhIQXdoV0tkNjVoVHdYOWl4V3ZHMkh4TG1WQzg0L1BHT0tWQW9FNkpsYWFHdTlQVmkKdjlOSjVaZlZrcXdCd0hKbzZXdk9xVlA3SVFjZmg3d0drWm89Ci0tLS0tRU5EIENFUlRJRklDQVRFIFJFUVVFU1QtLS0tLQo=
  signerName: kubernetes.io/kube-apiserver-client
  expirationSeconds: 86400 # one day
  usages:
  - client auth

매니페스트를 적용해요:

kubectl apply -f myuser.yaml --server-side

주의할 몇 가지 점:

  • usagesclient auth 여야 해요
  • expirationSeconds 는 더 길게(10일의 경우 864000) 또는 더 짧게(1시간의 경우 3600) 설정할 수 있어요. 10분보다 짧은 기간은 요청할 수 없어요.
  • request 는 CSR 파일 내용의 base64 인코딩 값이에요.

CertificateSigningRequest 승인하기

kubectl로 만든 CSR을 찾아 수동으로 승인해요.

CSR 목록을 가져와요:

kubectl get csr

CSR을 승인해요:

kubectl certificate approve myuser

인증서 얻기

CSR에서 인증서를 검색해 괜찮아 보이는지 확인해요.

kubectl get csr/myuser -o yaml

인증서 값은 .status.certificate 아래 Base64 인코딩 형식이에요.

CertificateSigningRequest에서 발급된 인증서를 내보내요.

kubectl get csr myuser -o jsonpath='{.status.certificate}'| base64 -d > myuser.crt

인증서를 kubeconfig로 구성하기

다음 단계는 이 사용자를 kubeconfig 파일에 추가하는 것이에요.

먼저 새 자격 증명을 추가해야 해요:

kubectl config set-credentials myuser --client-key=myuser.key --client-certificate=myuser.crt --embed-certs=true

그런 다음 컨텍스트를 추가해요:

kubectl config set-context myuser --cluster=kubernetes --user=myuser

테스트하려면:

kubectl --context myuser auth whoami

자신이 "myuser"라는 것을 확인하는 출력이 보여야 해요.

Role과 RoleBinding 만들기

참고:

인증서가 생성됐으니 이제 이 사용자가 쿠버네티스 클러스터 리소스에 접근할 수 있도록 Role과 RoleBinding을 정의할 차례예요.

이 새 사용자를 위한 Role을 만드는 샘플 명령은 다음과 같아요:

kubectl create role developer --verb=create --verb=get --verb=list --verb=update --verb=delete --resource=pods

동등한 YAML:

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: developer
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["create", "get", "list", "update", "delete"]

이 새 사용자를 위한 RoleBinding을 만드는 샘플 명령은 다음과 같아요:

kubectl create rolebinding developer-binding-myuser --role=developer --user=myuser

동등한 YAML:

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: developer-binding-myuser
subjects:
- kind: User
  name: myuser
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: developer
  apiGroup: rbac.authorization.k8s.io

더 알아보기 (Learn more)