티어 정책을 위한 RBAC 구성하기
멀티 팀 클러스터에서 티어(tier) 정책에 세밀한 사용자 접근 제어(RBAC)를 설정하는 방법을 다뤄요. 표준 Kubernetes RBAC Authorization API를 그대로 활용하면서 Calico 정책과 티어별로 누가 무엇을 볼 수 있고 수정할 수 있는지 제어할 수 있어요. john이라는 비(非)관리자 사용자를 예로 여덟 가지 권한 시나리오를 차례로 살펴봐요.
출처: 문서
본문
큰 그림
티어 정책을 위해 세밀한 사용자 접근 제어를 구성해요.
가치
셀프 서비스는 컨테이너화와 마이크로서비스를 위한 CI/CD 프로세스에서 중요한 부분이에요. Calico는 다음에 대해 세밀한 접근 제어(RBAC)를 제공해요:
- Calico 정책과 티어
- Kubernetes 네트워크 정책
개념
표준 Kubernetes RBAC
Calico는 Role과 ClusterRole 타입으로 표준 Kubernetes RBAC Authorization API를 구현해요. 기본 설치에서는 Calico API 서버가 익스텐션 API 서버(extension API server)로 Kubernetes RBAC Authorization API와 통합돼요. 네이티브 v3 CRD를 사용할 때는 대신 어드미션 웹훅(admission webhook)으로 티어 RBAC가 강제돼요.
SECONDARY: 네이티브
projectcalico.org/v3CRD를 사용할 때는 티어 RBAC가 어드미션 웹훅으로 create, update, delete 연산에 강제돼요. 하지만 어드미션 웹훅은 읽기 요청을 가로챌 수 없기 때문에 티어 정책에 대한 GET, LIST, WATCH 연산은 강제되지 않아요. 이건 알려진 제한 사항이에요.
정책과 티어를 위한 RBAC
Calico에서 글로벌 네트워크 정책과 네트워크 정책 리소스는 특정 티어와 연결돼요. 관리자는 표준 Kubernetes Role과 ClusterRole 리소스 타입으로 이런 Calico 정책에 대한 접근 제어를 구성할 수 있어요. 덕분에 Kubernetes 네트워크 정책과 Calico 티어 정책 양쪽의 RBAC를 손쉽게 관리할 수 있어요. RBAC 권한에는 Calico 웹 콘솔과 kubectl을 사용한 리소스 관리가 포함돼요.
Calico 네트워크 정책을 위한 RBAC 정의
Calico 네트워크 정책과 Calico 글로벌 네트워크 정책에 티어별 RBAC를 지정하려면 Role과 ClusterRole 정의에서 의사(pseudo) 리소스 종류와 이름을 사용해요. 예를 들면 다음과 같아요.
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: tier-default-reader
rules:
- apiGroups: ['projectcalico.org']
resources: ['tiers']
resourceNames: ['default']
verbs: ['get']
- apiGroups: ['projectcalico.org']
resources: ['tier.networkpolicies']
resourceNames: ['default.*']
verbs: ['get', 'list']
각 필드의 의미는 다음과 같아요:
-
resources:
tier.globalnetworkpolicies와tier.networkpolicies -
resourceNames:
- 비워 두기 - 모든 티어에서 지정한 종류의 모든 정책.
<tiername>.*- 지정한 티어 안에서 지정한 종류의 모든 정책.<tiername.policyname>- 지정한 종류의 특정 정책. 정책 이름 앞에 티어 이름이 붙기 때문에 티어도 함께 지정돼요.
시작하기 전에...
필수
리소스를 만들고 수정할 수 있는 전체 권한을 가진 cluster-admin 역할.
권장
티어 정책 워크플로가 대략 어떻게 흘러가는지, 누가 무엇에 접근해야 하는지에 대한 감각. 티어 정책 구성을 참고하세요.
방법
SECONDARY:
kubectl auth can-i는 티어 정책에 대한 RBAC를 확인하는 데 사용할 수 없어요.
전체 권한을 가진 관리자 사용자 만들기
다음 명령으로 Calico 웹 콘솔(그리고 클러스터의 나머지 전부)에 대한 전체 접근 권한을 가진 관리자 사용자를 만들어요. 선택한 인증 방식에 따라 사용자를 식별하는 방법과 RBAC 리소스 사용법은 Kubernetes 문서를 참고하세요.
kubectl create clusterrolebinding permissive-binding \
--clusterrole=cluster-admin \
--user=<USER\>
튜토리얼
이 튜토리얼은 RBAC를 사용해 관리자가 아닌 사용자 john(사용자 이름 john)의 리소스 접근과 CRUD 작업을 제어하는 방법을 보여줘요.
소개되는 RBAC 예시는 다음과 같아요:
- 사용자가 어떤 티어에서도 정책을 읽을 수 없음
- 사용자가 모든 정책을 볼 수 있고, 기본 네임스페이스와 티어의 정책은 수정 가능
- 사용자가 기본 티어와 기본 네임스페이스 양쪽에서만 정책을 읽을 수 있음
- 사용자가 특정 티어와 기본 네임스페이스 양쪽에서만 정책을 읽을 수 있음
- 사용자가 특정 티어만 볼 수 있음
- 사용자가 모든 티어와 네임스페이스의 모든 정책을 읽을 수 있음
- 사용자가 특정 티어와 기본 네임스페이스 양쪽의 정책만 완전히 제어 가능
사용자가 어떤 티어에서도 정책을 읽을 수 없음
사용자 'john'은 어떤 티어에서도(default 티어와 net-sec 티어) 정책을 읽는 것이 금지돼 있어요.
John이 다음 명령을 내리면:
kubectl get networkpolicies.p
다음을 반환해요:
Error from server (Forbidden): networkpolicies.projectcalico.org is forbidden: User "john" cannot list networkpolicies.projectcalico.org in tier "default" and namespace "default" (user cannot get tier)
마찬가지로 John이 이 명령을 내리면:
kubectl get networkpolicies.p -l projectcalico.org/tier==net-sec
다음을 반환해요:
Error from server (Forbidden): networkpolicies.projectcalico.org is forbidden: User "john" cannot list networkpolicies.projectcalico.org in tier "net-sec" and namespace "default" (user cannot get tier)
SECONDARY:
.p확장자(networkpolicies.p)는 "networkpolicies.projectcalico.org"의 줄임말로, Kubernetes NetworkPolicy 리소스와 그 아래 CRD(Kubernetes Datastore Driver를 사용하는 경우)와 구별하기 위해 사용해요.
SECONDARY: 티어를 선택하는 레이블은
projectcalico.org/tier예요. 레이블 셀렉터를 지정하지 않으면 서버는 선택을default티어로 기본 설정해요. 대신 필드 셀렉터(spec.tier)로 티어를 선택할 수도 있어요.kubectl get networkpolicies.p --field-selector spec.tier=net-sec
사용자가 모든 정책을 볼 수 있고, 기본 네임스페이스와 티어의 정책은 수정 가능
-
다음 명령으로
<USER\>를 권한을 부여하려는 사용자의name or email로 바꿔요:sed -i -e 's/<USER\>/<name or email>/g' read-all-crud-default-rbac.yaml -
다음 명령으로 바인딩을 설치해요:
kubectl apply -f read-all-crud-default-rbac.yaml
이 파일의 역할과 바인딩은 모든 티어의 모든 정책을 읽을 수 있는 권한과, default 티어와 default 네임스페이스의 정책을 완전히 관리할 수 있는 권한을 제공해요. 이 파일에는 모든 UI 사용자를 위해 필요한 최소한의 ClusterRole과 ClusterRoleBinding 정의가 포함되어 있어요(위의 min-ui-user-rbac.yaml 참고).
사용자가 기본 티어와 기본 네임스페이스 양쪽에서만 정책을 읽을 수 있음
이 예시에서는 사용자 'john'에게 default 티어와 네임스페이스 양쪽에서만 정책을 읽을 수 있는 권한을 줘요.
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: tigera-example-get-default-tier
rules:
# To access Calico policy in a tier, the user requires "get" access to that tier.
- apiGroups: ["projectcalico.org"]
resources: ["tiers"]
resourceNames: ["default"]
verbs: ["get"]
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: tigera-example-read-policies-in-default-tier
rules:
# This allows "get" and "list" of the Calico NetworkPolicy resources in the default tier.
- apiGroups: ["projectcalico.org"]
resources: ["tier.networkpolicies"]
resourceNames: ["default.*"]
verbs: ["get", "list"]
---
# tigera-example-get-default-tier is applied globally
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: john-can-get-default-tier
subjects:
- kind: User
name: john
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: tigera-example-get-default-tier
apiGroup: rbac.authorization.k8s.io
---
# tigera-example-read-policies-in-default-tier is applied per-namespace
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: john-can-read-policies-in-default-tier-and-namespace
subjects:
- kind: User
name: john
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: tigera-example-read-policies-in-default-tier
apiGroup: rbac.authorization.k8s.io
위 설정으로 사용자 john은 default 티어의 모든 NetworkPolicy 리소스를 나열할 수 있어요:
kubectl get networkpolicies.p --all-namespaces
클러스터에 예시 정책이 몇 개 있다면 다음을 반환해요:
NAMESPACE NAME CREATED AT
blue default.calico-np-blue-ns-default-tier 2021-07-26T09:05:11Z
default default.calico-np-default-ns-default-tier 2021-07-26T09:05:11Z
green default.calico-np-green-ns-default-tier 2021-07-26T09:05:13Z
red default.calico-np-red-ns-default-tier 2021-07-26T09:05:12Z
yellow default.calico-np-yellow-ns-default-tier 2021-07-26T09:05:13Z
의도한 대로 john은 default 네임스페이스 안의 것만 살펴볼 수 있어요:
kubectl get networkpolicies.p default.calico-np-green-ns-default-tier -o yaml -n=green
올바르게 다음을 반환해요:
Error from server (Forbidden): networkpolicies.projectcalico.org "default.calico-np-green-ns-default-tier" is forbidden: User "john" cannot get networkpolicies.projectcalico.org in tier "default" and namespace "green"
John은 여전히 의도한 대로 net-sec 티어에 접근할 수 없어요:
kubectl get networkpolicies.p -l projectcalico.org/tier==net-sec
다음을 반환해요:
Error from server (Forbidden): networkpolicies.projectcalico.org is forbidden: User "john" cannot list networkpolicies.projectcalico.org in tier "net-sec" and namespace "default" (user cannot get tier)
사용자가 특정 티어와 기본 네임스페이스 양쪽에서만 정책을 읽을 수 있음
kubernetes-admin이 사용자 'john'에게 net-sec 티어의 정책을 나열할 권한을 주되, 정책 상세는 default 네임스페이스에 있는 것만 살펴볼 수 있게 한다고 가정해 볼게요. 사용자 'john'에게 이 권한들을 주려면 다음 ClusterRole, ClusterRoleBinding, RoleBinding을 사용해요.
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: tigera-example-get-net-sec-tier
rules:
# To access Calico policy in a tier, the user requires "get" access to that tier.
- apiGroups: ["projectcalico.org"]
resources: ["tiers"]
resourceNames: ["net-sec"]
verbs: ["get"]
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: tigera-example-read-policies-in-net-sec-tier
rules:
# This allows "get" and "list" of the Calico NetworkPolicy resources in the net-sec tier.
- apiGroups: ["projectcalico.org"]
resources: ["tier.networkpolicies"]
resourceNames: ["net-sec.*"]
verbs: ["get", "list"]
---
# tigera-example-get-net-sec-tier is applied globally
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: john-can-get-net-sec-tier
subjects:
- kind: User
name: john
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: tigera-example-get-net-sec-tier
apiGroup: rbac.authorization.k8s.io
---
# tigera-example-read-policies-in-net-sec-tier is applied per-namespace
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: john-can-read-policies-in-net-sec-tier-and-namespace
subjects:
- kind: User
name: john
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: tigera-example-read-policies-in-net-sec-tier
apiGroup: rbac.authorization.k8s.io
사용자가 특정 티어만 볼 수 있음
이 예시에서는 다음 ClusterRole과 ClusterRoleBinding으로 net-sec 티어에 대한 'get' 접근 권한을 줄 수 있어요. 이렇게 하면 Calico 웹 콘솔에서 net-sec 티어가 보이게 돼요(그 티어에 담긴 정책 이름 목록까지 포함해서요).
다만 net-sec 티어 안의 정책을 수정하거나 상세를 보려면 추가 RBAC 권한이 필요해요.
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: tigera-example-make-net-sec-tier-visible
rules:
# To access Calico policy in a tier, the user requires "get" access to that tier.
- apiGroups: ["projectcalico.org"]
resources: ["tiers"]
resourceNames: ["net-sec"]
verbs: ["get"]
---
# tigera-example-make-net-sec-tier-visible is applied globally
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: john-can-view-the-net-sec-tier
subjects:
- kind: User
name: john
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: tigera-example-make-net-sec-tier-visible
apiGroup: rbac.authorization.k8s.io
사용자가 모든 티어와 네임스페이스의 모든 정책을 읽을 수 있음
이 예시에서는 단일 ClusterRole로 모든 티어의 모든 정책 리소스 타입에 대한 읽기 접근을 제공해요. 이 경우 클러스터의 현재와 미래의 모든 네임스페이스에 적용하려는 것이므로 ClusterRoleBinding과 RoleBinding을 둘 다 쓸 필요 없이 ClusterRoleBinding 하나가 원하는 범위를 제공해요.
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: tigera-example-all-tiers-and-namespaces-policy-reader
rules:
# To access Calico policy in a tier, the user requires "get" access to that tier.
# Not specifying any specific "resourceNames" provides access to all tiers.
- apiGroups: ["projectcalico.org"]
resources: ["tiers"]
verbs: ["get"]
# This allows read access to the Kubernetes NetworkPolicy resources (these are always in the default tier).
- apiGroups: ["networking.k8s.io", "extensions"]
resources: ["networkpolicies"]
verbs: ["get","watch","list"]
# This allows read access to the Calico NetworkPolicy and GlobalNetworkPolicies.
# Not specifying any specific "resourceNames" provides access to them in all tiers.
- apiGroups: ["projectcalico.org"]
resources: ["tier.networkpolicies","tier.globalnetworkpolicies"]
verbs: ["get","watch","list"]
---
# tigera-example-all-tiers-and-namespaces-policy-reader is applied globally, with a single ClusterRoleBinding,
# since all the rules it contains apply to all current and future namespaces on the cluster.
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: read-all-tier
subjects:
- kind: User
name: john
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: tigera-example-all-tiers-and-namespaces-policy-reader
apiGroup: rbac.authorization.k8s.io
사용자가 특정 티어와 기본 네임스페이스 양쪽의 정책만 완전히 제어 가능
이 예시에서는 두 개의 ClusterRole 객체로 net-sec 티어의 Calico NetworkPolicy 리소스 타입에 대한 완전한 접근 제어를 제공해요:
tiers리소스는 글로벌 리소스이기 때문에ClusterRoleBinding으로 사용자에게 묶여요. 이 결과 사용자는 모든 네임스페이스에서 티어 내용을 읽을 수 있게 돼요.networkpolicies리소스는 이 경우 CRUD가 기본 네임스페이스에서만 가능하도록 하는 것이 목적이었기 때문에RoleBinding으로 사용자에게 묶여요. 이ClusterRole은 하나만 정의하면 되고, 추가RoleBinding객체로 다른 네임스페이스에 적용할 수 있어요. 현재와 미래의 모든 네임스페이스에 적용하려는 의도라면ClusterRoleBinding을 사용할 수도 있어요.
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: tigera-example-get-net-sec-tier
rules:
# To access Calico policy in a tier, the user requires "get" access to that tier.
- apiGroups: ["projectcalico.org"]
resources: ["tiers"]
resourceNames: ["net-sec"]
verbs: ["get"]
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: tigera-example-crud-policies-in-net-sec-tier
rules:
# This allows full CRUD access to the Calico NetworkPolicy resources in the net-sec tier.
- apiGroups: ["projectcalico.org"]
resources: ["tier.networkpolicies"]
resourceNames: ["net-sec.*"]
verbs: ["*"]
---
# tigera-example-get-net-sec-tier is applied globally
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: john-can-get-net-sec-tier
subjects:
- kind: User
name: john
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: tigera-example-get-net-sec-tier
apiGroup: rbac.authorization.k8s.io
---
# tigera-example-crud-policies-in-net-sec-tier is applied per-namespace
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: john-can-crud-policies-in-net-sec-tier-and-namespace
subjects:
- kind: User
name: john
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: tigera-example-crud-policies-in-net-sec-tier
apiGroup: rbac.authorization.k8s.io
더 알아보기 (Learn more)
핵심은 티어 자체에 대한 'get' 권한이 있어야 그 티어의 정책에 접근할 수 있다는 점이에요. 리소스 이름 앞의 tier. 접두사와 <tiername>.* 패턴이 티어별·정책별 권한을 가르는 역할을 하죠. 네임스페이스 단위 제어가 필요하면 RoleBinding, 클러스터 전체 제어가 필요하면 ClusterRoleBinding을 선택하세요.