Authorization
앞선 내용들이 Authentication(인증)에 대한 내용이었다면, 여기서부터는 Authorization(인가, 권한 부여)에 관한 내용이다.
여러 팀 또는 조직간에 클러스터를 공유할 때 네임스페이스를 통해 논리적으로 분할함으로써 사용자의 액세스를 자신이 속한 네임스페이스에만 가능하도록 제한할 수 있다.
Authorization Mechanisms
- Kube API 서버에 Authorization mode 옵션을 따로 명시하지 않으면 AlwaysAllow가 기본값이다.
- `/etc/kubernetes/manifests/kube-apiserver.yaml` 파일의 `spec.containers[*].command[*].authorization-mode` 필드값으로 다수의 메커니즘을 명시할 수 있다. (, 로 구분) - 복수의 메커니즘을 명시했다면 명시한 순서대로 동작한다. 앞서 동작한 메커니즘에서 요청을 허가할 경우 그대로 authorization은 끝이나지만 만약 요청이 거부된 경우 체인의 다음 순서의(다음 순서로 명시한) 메커니즘으로 넘어가게 된다.
쿠버네티스가 제공하는 Authorization 메커니즘들은 아래와 같다.
Node Authorization
- kubelet에 의해 생성된 API 요청을 허가하는 특수 목적의 authorization
- Cf. kubelet은 시스템 노드 그룹의 일부이며 이름 앞에 system node 를 붙여야 한다. 🤔
- 클러스터 내의 액세스에 한정
ABAC(Attribute-Based Access Control)
- 사용자 또는 사용자 그룹을 일련의 권한(a set of permissions)과 연결하는 방식
- 정책 목록(a set of policies)으로 구성된 JSON 파일 포맷의 policy file을 생성하여 적용할 수 있다.
{
"kind": "Policy",
"spec":
{
"user": "dev-user", # user 또는 group
"namespace": "*",
"resource": "pods",
"apiGroup": "*"
}
}
- 만약 security에 추가 또는 수정 사항이 생기면, 항상 사용자 또는 사용자 그룹에 대한 정책 파일을 직접 수정해주고 Kube API 서버를 재가동시켜야 한다. → 관리하기 힘듦(↔ RBAC)
RBAC(Roll-Based Access Control)
- 사용자 또는 사용자 그룹과 직접 정책을 연결하지 않고, Role을 생성하여 이를 사용자(또는 그룹)와 연결하면 즉시 사용자(또는 그룹)의 권한이 변경된다.
Webhook
- 내장 메커니즘이 아닌 외부에서 권한을 관리하고자 할 때 사용
- 예를 들어 어떤 Open Policy Agent가 admission control과 authorization을 돕는 서드 파티 도구일 때, 쿠버네티스가 해당 Open Policy Agent에 유저 및 유저의 접근에 필요한 정보를 가지고 API 요청을 하면 Open Policy Agent는 사용자에 대한 허가 여부를 결정한다. → the user is granted access.
AlwaysAllow(Default)
Authorization check 없이 항상 허가
AlwaysDeny
항상 거부
RBAC
Create Role object
`developer-role.yaml`
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: developer
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["list", "get", "create", "update", "delete"]
# resourceNames: ["blue", "orange"]
# 위와 같이 작성하면 blue, orange 파드에만 해당 동작들에 대해 권한을 가짐
- apiGroups: [""]
resources: ["ConfigMap"]
verbs: ["create"]
kubectl create -f developer-role.yaml
core group(`/api`)에 해당하는 경우 `apiGroup` 을 빈 값으로 남겨둘 수 있다. 이 외의 그룹들은 모두 그룹명을 명시해야한다.
link user to the role(Create RoleBinding object)
` devuser-developer-binding.yaml`
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: devuser-developer-binding
# namespace: default가 아닌 경우 명시
subjects:
- kind: User
name: dev-user
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: developer
apiGroup: rbac.authorization.k8s.io
kubectl create -f devuser-developer-binding.yaml
⚠️ Role, RoleBinding은 모두 네임스페이스의 범위에 속한다. `devuser` 와 같이 `namespace` 를 명시하지 않으면 default 네임스페이스 내에 있는 파드, ConfigMap에 대한 접근이 허가하는 것을 의미한다.
View RBAC
kubectl get roles
kubectl get rolebindings
kubectl describe role developer
kubectl describe rolebinding devuser-developer-binding
Check Access
사용자가 특정 리소스에 대해 자신이 접근할 수 있는 권한이 있는지 확인하고자 할 때 사용(관리자의 경우 다른 이를 사칭해서 확인하는 것도 가능)
# kubectl auth can-i(result : yes | no)
kubectl auth can-i [verb] [resources]
# example
kubectl auth can-i create deployments
# if you are admin, you can specify user with 'as' option
kubectl auth can-i create deployments --as dev-user
# you can also specify the namespace in the command
kubectl auth can-i get developments --namespace dev
Cf. `--namespace`는 `--n`와 같이 줄일 수 없다.
Cluster Role
일반적인 Role, RoleBinding이 namespaced(namespace의 범위 내에서의 권한을 생성 및 부여하는 것)이라면, Cluster Role은 cluster-scope인 오브젝트들에 대한 권한을 다룬다.
⚠️ ClusterRole이나 ClusterRoleBinding을 namespacescoped인 오브젝트들을 리소스로 사용하게끔 만들 수도 있다. 예를 들어 ClusterRole을 생성하면서 리소스로 pods를 명시하는 경우, 클러스터 내의 모든 파드에 대해 특정 동작을 수행할 수 있게 된다.
⚠️ 특정 ClusterRole에 바인딩된 유저 또는 그룹을 찾기 위해 ClusterRoleBinding 을 찾을 경우 보통은 같은 이름을 가진다. 따라서 ClusterRole명으로된 ClusterRoleBinding을 찾으면 된다.
Service Account
RBAC 메커니즘에 따라 알맞은 권한을 승인한 Service account를 생성하여 해당 Service account의 token을 내보내서드파티 애플리케이션이 쿠버네티스 API에 인증하는 데에 사용할 수 있다.
⚠️ 만약 커스텀 쿠버네티스 대시보드 애플리케이션 또는 프로메테우스 등이 클러스터에 호스팅되어있다면, 아래의 Service account를 생성하고 token을 내보내는 일련의 과정은 token을 지닌 Secret object가 해당 써드파티 애플리케이션이 호스팅되어있는 파드 내부에 볼륨으로 자동으로 마운팅됨으로써 훨씬 간단해질 수 있다. - 아마 서드파티 애플리케이션이 자동으로 해당 Secret object를 볼륨으로 마운팅하는 것으로 해석됨(이 경우 수동으로 토큰을 제공할 필요 X)
특징
모든 네임스페이스마다 자동으로 default Service account가 생성된다. (1.22 version 이전)
- 이 default Service account는 기본적인 쿠버네티스 API 쿼리를 위한 권한만 존재하기 때문에 매우 제한적이다.
파드가 생성될 때마다 이 Service account와 그것의 token은 볼륨으로 해당 파드에 마운트된다.
- kubectl describe pod [pod-name] 결과를 조회해보면 Volumes 하위에 default-token-[random character + number] 이름의 요소가 존재하는 것을 확인할 수 있다.
토큰
TokenRequest API 도입(1.22 버전) 이후
- TokenRequest API(by Service account admission controller)를 통해 생성된 토큰은 만료일 정보를 가진다.
- Secret object 가 볼륨으로 마운트되던 것과 달리 projected 볼륨으로 토큰 정보가 마운트 된다.
참고(pod 정보를 yaml 형태로 조회한 결과의 일부)
1.24 버전 이후
Service account 생성시 더이상 Secret object는 자동으로 생성되지 않으며, 토큰이 필요하다면 생성하는 과정을 거쳐야 한다.
⚠️ 이전과 같이 특정 Service account와 연결되고, 만료일이 없는 토큰을 지니는 Secret object를 생성하고자 한다면, Secret 생성시 manifest 파일에 아래와 같이 작성해야 한다.(metadata.annotations.kubernetes.io/service-account.name)
⚠️ 비 만료 토큰(만료일이 지정되지 않고 Service account와 연결되는 Secret object를 통해 얻어지는 토큰)을 생성하는 것 보다 TokenRequest API를 통해 토큰을 생성하는 것을 권장한다. 때문에, 비 만료 토큰 생성 방식은 TokenRequest API를 통해 토큰을 얻을 수 없는 경우에만 행해져야 하며, 보안상 취약점이 허용될 때만 생성할 수 있다.
토큰 생성
kubectl create [name of service account]
생성된 토큰을 디코딩해보면 만료일(`exp`)가 존재하는 것을 확인할 수 있다. 만료일을 명시적으로 지정하지 않는다면, 보통은 커맨드 실행 후 1시간 동안 유효하다.
⚠️ Secret 생성 전에 Service account를 생성하는 것이 선행되어야 한다.
apiVersion: v1
kind: Secret
type: kubernetes.io/service-account-token
metadata:
name: [secret-name]
annotations:
kubernetes.io/service-account.name: [service account name]
유형
User account(for human)
Service account(for machine)
- ex. 프로메테우스(모니터링 프로그램)은 서비스 계정을 이용해 쿠버네티스 API를 퍼포먼스 메트릭으로 뽑아내며, 젠킨스와 같은 자동화된 빌드 툴의 경우 서비스 계정을 이용해 애플리케이션을 배포한다.
Create Service account
kubectl create serviceaccount [name]
View Service accounts
kubectl get serviceaccount
Pod 생성시 Service account 지정하기
- `.yaml`(.yml) 파일에 `spec.serviceAccountName` 필드 작성하기
- ⚠️ Deployment의 경우 `spec.template.spec.serviceAccountName` 필드 작성
- Pod나 Deployment는 명시적으로 지정하지 않는 경우 자동으로 자신이 속한 namespace의 `default` Service account를 마운트하게 된다.
- 자동으로 Service account를 마운트하는 것이 싫다면, `automountServiceAccountToken: false` 와 같이 설정 가능하다.
- 이미 생성된 Pod의 Service account는 수정할 수 없으므로 삭제 후 생성하는 수 밖에 없다.
- Deployment는 Pod와 달리 정의 파일(`.yaml`)에서 수정할 수 있다. 이 경우 자동으로 Pod를 삭제 후 새로이 지정된 namespace에 재생성한다.
'Kubernetes' 카테고리의 다른 글
k8s) Security - 5. Network Policy(Ingress & Egress) (0) | 2024.03.10 |
---|---|
k8s) Security - 4. Image Security, Security Contexts, (0) | 2024.03.10 |
k8s) Security - 2. KubeConfig, API Groups (0) | 2024.03.10 |
k8s) Security - 1. Kubernetes의 Authentication, TLS 구조 (0) | 2024.03.10 |
k8s) Cluster Maintenance (0) | 2023.11.17 |