Teleport Kubernetes 접근 제어
이 가이드는 Teleport Kubernetes 서비스가 Teleport 사용자가 Kubernetes 클러스터와 상호 작용할 때 역할 기반 접근 제어를 적용하는 방법을 설명합니다. 이 가이드에서는 Teleport에 연결한 Kubernetes 클러스터에 대한 접근을 관리하기 위해 Teleport 역할 내에서 사용 가능한 필드를 구성하는 방법을 보여드립니다.
이 가이드는 Teleport Kubernetes 서비스가 Teleport 사용자가 Kubernetes 클러스터와 상호 작용할 때 역할 기반 접근 제어를 적용하는 방법을 설명합니다. Kubernetes 서비스는 Kubernetes API 서버에 대한 요청을 가로채고 사용자의 Teleport 역할에 따라 각 요청을 수정합니다.
이 가이드에서는 Teleport에 연결한 Kubernetes 클러스터에 대한 접근을 관리하기 위해 Teleport 역할 내에서 사용 가능한 필드를 구성하는 방법을 보여드립니다.
로컬 minikube 클러스터를 사용하여 Kubernetes로 Teleport 역할을 사용하는 방법의 예시는
RBAC 방법 가이드를 참조하세요.
Kubernetes 접근 관리를 위한 역할 필드#
이 섹션에서는 Kubernetes 클러스터에 대한 접근을 구성하는 Teleport 역할 내의 필드를 설명합니다.
Kubernetes 클러스터에 대한 접근을 관리하려면 Teleport 역할의 spec.allow 섹션에 다음 필드가
포함되어야 합니다:
다음은 Kubernetes 클러스터에 대한 접근을 제한하는 Teleport 역할의 예시입니다:
kind: role
metadata:
name: kube-access
version: v8
spec:
allow:
kubernetes_labels:
region: '*'
platform: minikube
kubernetes_resources:
- kind: pods
namespace: production
name: '^webapp-[a-z0-9-]+$'
api_group: ''
- kind: pods
namespace: development
name: '*'
api_group: ''
- kind: deployments
namespace: development
name: '*'
api_group: apps
kubernetes_groups:
- developers
kubernetes_users:
- minikube
deny: {}
kubernetes_labels#
Teleport에 Kubernetes 클러스터를 등록할 때 레이블을 추가할 수 있습니다. 역할의 kubernetes_labels
필드를 사용하여 사용자의 다양한 레이블을 가진 Kubernetes 클러스터에 대한 접근을 제한할 수 있습니다.
kind: role
metadata:
name: kube-access
version: v8
spec:
allow:
kubernetes_labels:
region: '*'
environment: development
# ...
deny: {}
kubernetes_labels 필드의 값은 레이블 키에서 하나 이상의 레이블 값(즉, 문자열 또는 목록)으로
의 매핑입니다.
Kubernetes 서비스가 kubernetes_labels를 평가하는 방법#
레이블의 키와 값이 모두 와일드카드 *인 경우, Teleport Kubernetes 서비스는 사용자가 모든 태그를
가진 Kubernetes 클러스터에 접근할 수 있도록 허용합니다:
spec:
allow:
kubernetes_labels:
'*': '*'
# ...
그렇지 않으면, Kubernetes 서비스는 kubernetes_labels의 모든 키가 등록된 Kubernetes 클러스터의
해당 키와 일치하는지 확인합니다. 일치하지 않으면 일치하는 Kubernetes 클러스터가 없으며
Kubernetes 서비스는 요청을 거부합니다.
예를 들어, environment 키는 있지만 region 키가 없는 레이블을 가진 클러스터는 위의
kube-access 역할의 kubernetes_labels 필드와 일치하지 않습니다.
Kubernetes 서비스는 kubernetes_labels의 키를 가진 Kubernetes 클러스터 레이블의 값을 검색합니다.
kubernetes_labels의 각 키의 값은 Kubernetes 서비스가 사용자가 클러스터에 접근할 수 있게
하기 전에 Kubernetes 클러스터의 레이블 값과 일치해야 합니다.
예를 들어, 위의 kube-access 역할은 사용자가 region 키와 임의의 값을 가진 Kubernetes 클러스터에
접근할 수 있도록 합니다. environment 키와 development 값을 가진 Kubernetes 클러스터로 사용자를
제한합니다. 다음 섹션에서 kubernetes_labels 내 키의 유효한 값에 대해 설명합니다.
레이블 값#
kubernetes_labels의 레이블 키가 Kubernetes 클러스터의 키와 일치하려면 정확히 일치해야 합니다.
값의 경우, 유연성을 제공하기 위해 정규 표현식, 와일드카드 및 여러 값을 구성할 수 있습니다.
정규 표현식 및 와일드카드#
정규 표현식 또는 와일드카드 문자를 사용하여 문자열의 하위 집합이나 변형을 일치시킬 수 있습니다.
값이 ^로 시작하고 $로 끝나면, Kubernetes 서비스는 Go의 re2 구문을 사용하여 정규 표현식으로
처리합니다(re2 README 참조).
그렇지 않으면, Kubernetes 서비스는 값 내의 와일드카드를 평가하여 레이블의 임의 문자 시퀀스와 일치시킵니다.
예시:
spec:
allow:
kubernetes_labels:
region: 'us-east-*'
team: '^data-eng-[a-z-]+$'
# ...
이 allow 규칙은 region:us-east-1 및 region:us-east-2b 레이블을 가진 클러스터와 일치합니다.
또한 team:data-eng-analytics 및 team:data-eng-ml-training 레이블을 가진 클러스터와도 일치합니다.
여러 값#
kubernetes_labels의 키에 여러 값이 있는 경우, Kubernetes 서비스는 이러한 값 중 어떤 값이라도
Kubernetes 클러스터의 레이블과 일치하면 레이블 값이 일치한다고 간주합니다. 예를 들어, 이
kubernetes_labels 구성은 region:us-east-2 레이블과 development 또는 staging 환경 중 하나를
가진 클러스터와 일치합니다:
spec:
allow:
kubernetes_labels:
region: 'us-east-*'
environment: ['development', 'staging']
# ...
레이블 적용#
Teleport Kubernetes 서비스의 인스턴스에 레이블을 적용할 수 있습니다. 이를 수행하는 방법은 서비스를 시작한 방법에 따라 다릅니다:
teleport-kube-agent Helm 차트를 설치하거나 업그레이드할 때 레이블을 설정합니다. 예:
$ helm upgrade teleport-agent teleport-kube-agent --set kubeClusterName={CLUSTER?}\
--set proxyAddr=${PROXY?} --set authToken=${TOKEN?} --create-namespace --namespace=teleport-agent\
--set labels.env=prod --set labels.region=us-west-1
teleport 인스턴스의 구성 파일에서 Teleport Kubernetes 서비스를 활성화할 때 레이블을 설정합니다:
kubernetes_service:
enabled: true
kube_cluster_name: cookie
labels:
env: prod
region: us-west-1
kubernetes_groups 및 kubernetes_users#
Teleport Kubernetes 서비스는 kubectl을 통해 최종 사용자로부터 요청을 수신하고 Kubernetes API
서버로 전달합니다. Kubernetes 서비스는 impersonation 헤더를
사용하여 하나의 Kubernetes 사용자와 0개 이상의 Kubernetes 그룹으로 API 서버에 요청을 보냅니다.

kubernetes_users 및 kubernetes_groups 필드는 사용자가 Kubernetes API 서버에 요청을 보낼 때
가정할 수 있는 사용자와 그룹을 나타냅니다:
kind: role
metadata:
name: kube-access
version: v7
spec:
allow:
kubernetes_groups:
- developers
- viewers
kubernetes_users:
- myuser
- system:serviceaccount:someNamespace:saName # 서비스 계정 이름
# ...
deny: {}
kubernetes_groups 및 kubernetes_users의 값은 가장을 활성화할 그룹, 사용자 또는 서비스 계정
이름의 목록입니다.
Kubernetes 사용자 및 그룹#
Kubernetes 사용자 및 그룹은 Kubernetes 클러스터에 존재하고 ClusterRoleBinding 또는 RoleBinding
리소스를 통해 권한이 제어되는 엔티티입니다. 클러스터에 없으면 Kubernetes RBAC는 이를 무시합니다.
다음은 그룹 cluster-viewer-group과 사용자 cluster-viewer-user에 기본 제공 view ClusterRole을
할당하는 ClusterRoleBinding 리소스의 예시입니다:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: cluster-viewer
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: view
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: Group
name: cluster-viewer-group
- apiGroup: rbac.authorization.k8s.io
kind: User
name: cluster-viewer-user
이 시점에서, 사용자와 그룹은 Kubernetes 네임스페이스의 리소스를 볼 수 있는 동일한 권한을 가집니다. Kubernetes 사용자와 그룹에 동일한 권한을 할당하는 것이 필수적이지는 않습니다. Kubernetes는 요청에 사용된 가장 주체와 관련된 권한을 병합하기 때문입니다.
Kubernetes 서비스 계정#
Teleport는 kubernetes_users 필드에서 서비스 계정의 정규화된 이름을 사용하여 서비스 계정
가장을 지원합니다.
서비스 계정의 정규화된 이름은 다음 패턴으로 구성됩니다:
system:serviceaccount:<namespace>:<service_account_name>
FQN은 system:serviceaccount:로 시작해야 합니다. 그렇지 않으면 Kubernetes는 이를 일반 사용자로
평가합니다.
서비스 계정을 가장하는 역할의 예시는 다음과 같습니다.
kind: role
metadata:
name: kube-access-impersonate-sa
version: v7
spec:
allow:
kubernetes_users:
- system:serviceaccount:someNamespace:saName
# ...
deny: {}
Teleport 사용자가 Kubernetes 사용자, 그룹 및 서비스 계정을 가장하는 방법#
최종 사용자가 가장할 사용자나 서비스 계정 및 그룹을 지정하는 두 가지 방법이 있습니다:
수동으로#
사용자가 tsh kube login을 실행하여 Kubernetes 클러스터에 인증할 때, --as 및 --as-groups
플래그를 사용하여 인증할 사용자와 그룹을 수동으로 지정할 수 있습니다. Teleport Kubernetes 서비스는
사용자와 그룹이 사용자의 kubernetes_users 및 kubernetes_groups 구성에 속하는지 확인하고,
그렇지 않으면 사용자 접근을 거부합니다.
자동으로#
클러스터에 인증할 때 사용자가 Kubernetes 사용자와 Kubernetes 그룹을 명시적으로 결정하지 않은 경우,
Teleport Kubernetes 서비스는 사용자 역할의 kubernetes_users 및 kubernetes_groups 필드에서
이를 결정합니다.
사용자에게 kubernetes_users에 정확히 하나의 값이 있으면, Teleport Kubernetes 서비스는 해당
사용자를 가장합니다. kubernetes_users에 값이 없거나 와일드카드(*)가 있으면, Kubernetes 서비스는
사용자의 Teleport 사용자 이름을 사용합니다.
사용자에게 여러 kubernetes_users가 있고 클러스터에 인증할 때 하나를 지정하지 않은 경우
(즉, 이전 섹션에서 설명한 --as 플래그 사용), Kubernetes 서비스는 요청을 거부합니다.
사용자가 가장할 Kubernetes 그룹을 지정하지 않은 경우, Kubernetes 서비스는 kubernetes_groups
내의 모든 값을 사용합니다.
권한이 낮은 사용자를 가장할 때, --as-groups 플래그를 사용하여 특정 그룹을 수동으로
가장하지 않는 한, Kubernetes 서비스는 kubernetes_groups 내의 모든 그룹을 자동으로 가장한다는
점을 기억하세요.
이는 사용자와 자동으로 가장된 그룹의 권한이 결합되므로 혼란스러울 수 있습니다.
위의 kube-access 역할로, Teleport에 인증한 후 Kubernetes 서비스는 가장 헤더를 사용하여
developers 그룹과 myuser Kubernetes 사용자로 API 서버에 요청을 전달합니다.
가장 활성화#
Kubernetes 서비스가 가장 헤더로 사용자 요청을 전달할 수 있게 하려면, 서비스 계정이 클러스터 내의 Kubernetes RBAC 주체를 가장할 수 있는 권한이 있는지 확인해야 합니다. Kubernetes 서비스는 사용자가 접근할 수 없는 사용자 또는 그룹을 가장하려는 요청을 거부합니다.
다음은 가장을 활성화하기 위한 최소 권한 세트를 부여하는 Kubernetes ClusterRole과 서비스 계정에
이러한 권한을 부여하는 ClusterRoleBinding입니다.
일반적으로 이러한 리소스를 수동으로 정의할 필요가 없습니다. Teleport로 Kubernetes 클러스터를 등록하는 수동 방법 및 자동 방법에는 클러스터에 대한 접근을 허용하기 위해 Teleport에 필요한 Kubernetes RBAC 리소스를 설정하는 단계가 포함되어 있습니다.
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: teleport-impersonation
rules:
- apiGroups:
- ""
resources:
- users
- groups
- serviceaccounts
verbs:
- impersonate
- apiGroups:
- ""
resources:
- pods
verbs:
- get
- apiGroups:
- "authorization.k8s.io"
resources:
- selfsubjectaccessreviews
verbs:
- create
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: teleport
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: teleport-impersonation
subjects:
- kind: ServiceAccount
name: teleport-serviceaccount
namespace: default
사용자 트레이트를 기반으로 그룹 및 사용자 지정#
역할에 이 정보를 하드코딩하는 대신 각 Teleport 사용자에 대해 개별적으로 Kubernetes 그룹 및 사용자를 지정할 수 있습니다. 이를 위해 Teleport 역할에 템플릿 변수를 추가할 수 있으며, Teleport Auth 서비스는 각 인증 사용자의 정보로 이를 채웁니다.
Teleport 역할에서 템플릿 변수 확장이 작동하는 방법에 대한 자세한 내용은 접근 제어 참조를 참조하세요.
SSO(Single Sign-On) 공급자 트레이트#
Teleport의 역할은 템플릿 변수를 사용하여 OIDC 클레임 또는 SAML 속성을 매핑합니다.
Teleport Auth 서비스는 {{external.*}} 형식의 템플릿 변수를 해당 SAML 속성 또는 OIDC 클레임으로
대체합니다:
kind: role
version: v7
metadata:
name: group-member
spec:
allow:
kubernetes_groups: ["{{external.groups}}"]
kubernetes_users: ["{{external.kube_username}}"]
# ...
예를 들어, 사용자가 SAML 커넥터를 통해 Teleport에 인증하고, 사용자에게 값 myuser의
kube_username 속성과 값 developers 및 viewers의 groups 속성이 있는 경우,
위의 group-member 역할은 다음과 같이 평가됩니다:
kind: role
version: v7
metadata:
name: group-member
spec:
allow:
kubernetes_groups: ["developers", "viewers"]
kubernetes_users: ["myuser"]
# ...
로컬 사용자 트레이트#
로컬 사용자의 경우, user 리소스의 spec.traits 필드에 임의의 키-값 데이터를 지정한 다음,
역할의 {{external.*}} 템플릿 변수를 사용하여 해당 트레이트를 참조할 수 있습니다.
예를 들어, 이 역할은 내부 트레이트로 kubernetes_users 및 kubernetes_groups를 채웁니다:
kind: role
version: v7
metadata:
name: group-member
spec:
allow:
kubernetes_groups: ["{{external.groups}}"]
kubernetes_users: ["{{external.kube_username}}"]
# ...
그런 다음 로컬 사용자를 생성하거나 수정할 때 이러한 템플릿 변수의 값을 제공할 수 있습니다. 예를 들어, 이 사용자 정의는 Auth 서비스가 위의 역할 정의를 채우는 데 사용할 트레이트를 포함합니다:
kind: user
version: v2
metadata:
name: alice
spec:
roles:
- group-member
traits:
groups:
- developers
- viewers
kube_username:
- myuser
즉시 접근(Just-in-time) 구성#
특정 Kubernetes 리소스에 대한 즉시 접근을 활성화하기 위해 Teleport 역할을 설정하는 경우,
Kubernetes에 대한 접근 권한이 없는 주체를 가진 역할의 kubernetes_groups 및 kubernetes_users를
설정해야 합니다.
Teleport가 제한할 수 있는 Kubernetes 리소스 종류를 제외한 모든 Kubernetes 리소스에 접근할 수 있기 때문입니다.
이는 사용자가 Kubernetes Pod에 대한 접근을 요청하고 요청이 승인되면, Teleport Kubernetes 서비스가
역할의 kubernetes_groups 및 kubernetes_users 필드를 사용하여 사용자의 Kubernetes API 서버에
대한 요청에 가장 헤더를 추가하기 때문입니다. 이러한 조건에서, Teleport는 원하는 pod를 제외한
지원되는 모든 Kubernetes 리소스 종류에 대한 접근을 제한할 수 있습니다.
Teleport는 또한 네임스페이스 범위의 사용자 정의 리소스에 대한 접근을 제한할 수 있지만
클러스터 범위의 사용자 정의 리소스에는 제한할 수 없습니다. 클러스터 범위의 CRD 리소스는
kubernetes_users 및 kubernetes_groups 필드의 주체가 해당 리소스에 접근할 수 있으면
사용자가 접근할 수 있습니다.
Kubernetes 네임스페이스에 대한 접근 요청은 해당 네임스페이스의 모든 리소스에 접근할 수 있게 하지만 클러스터의 다른 지원 리소스에는 접근할 수 없습니다.
kubernetes_resources#
kubernetes_resources 필드를 통해 Teleport 역할이 Kubernetes 클러스터의 특정 리소스에 대한 접근을
구성할 수 있습니다.
이 필드의 값은 각 매핑이 다음과 같이 설명되는 매핑 목록입니다:
역할 V8#
역할 V8은 사용자 정의 리소스 정의(CRD)를 포함한 모든 Kubernetes 리소스 종류에 대한 접근 관리 지원을
추가했습니다. 이를 위해 이전 역할 버전과 비교하여 kubernetes_resources 섹션 처리 방식에 여러
변경 사항이 있습니다:
kind필드는 항상 리소스 종류의 복수형을 지정해야 합니다- 핵심 API 그룹에 없는 리소스에는
api_group필드를 설정해야 합니다 kind: namespaces는 이제 네임스페이스 리소스와 일치하며, 더 이상 네임스페이스 내 리소스와 일치하지 않습니다namespace필드를 설정하고*이외의 값으로 설정하면 클러스터 전체 리소스와 일치하지 않습니다.
이 동작은 이전 역할 버전과 다르므로, 이전 버전에서 역할을 V8로 마이그레이션하면 kubernetes_resources
섹션을 조정해야 할 수 있습니다.
kind: role
metadata:
name: kube-access
version: v8
spec:
allow:
kubernetes_labels:
"*": "*"
kubernetes_resources:
- kind: pods
api_group: ""
namespace: production
name: webapp
verbs: ["*"]
- kind: deployments
api_group: apps
namespace: development
name: "*"
# ...
kind: 접근을 활성화할 리소스 종류.*이거나 종류의 복수형(예:pods,deployments,cronjobs,mycustomresources)일 수 있습니다. 리소스에 그룹이 있는 경우,api_group필드에 지정해야 합니다. 예를 들어,pods는 그룹이 필요하지 않지만,deployments는api_group필드를apps로 설정해야 합니다.Tip다음 명령어를 실행하여 사용 가능한 리소스 및 API 그룹의 전체 목록을 찾을 수 있습니다:
kubectl api-resources --namespaced=true -o=name kubectl api-resources --namespaced=false -o=name- 줄에
.이 있으면, 종류는.앞의 첫 번째 요소이고 API 그룹은 첫 번째.이후의 모든 것입니다. - 줄에
.이 없으면, 종류는 전체 요소이고 API 그룹이 없습니다.
Warningnamespaces종류는 네임스페이스 내의 모든 리소스를 포함하지 않고, 네임스페이스 자체만 포함합니다. 이 동작은 네임스페이스 내의 리소스 자체와 모든 것을 포함했던 이전 역할 버전과 다르므로, 기존 역할을 이전 버전에서 V8로 마이그레이션하면kubernetes_resources섹션을 조정해야 할 수 있습니다.*를 포함한 종류는 이제namespace필드를 적용합니다. 클러스터 전체 리소스와 일치시키려면namespace필드가 비어 있거나*이어야 합니다. 이 동작은namespace필드에 관계없이 클러스터 전체 리소스를 포함했던 이전 역할 버전과 다릅니다.
-
api_group: 리소스의 API 그룹. 위의 예시kube-access에서,pods리소스는 핵심 리소스에 있으므로 api_group이""이고,deployments리소스 종류의 경우 값이apps로 설정됩니다. 와일드카드를 사용하여 임의의 API 그룹과 일치시킬 수 있습니다. -
namespace: 리소스에 대한 접근을 허용할 Kubernetes 네임스페이스. 클러스터 전체 리소스의 경우 비어 있거나*이어야 합니다.*이외의 모든 값(다른 와일드카드 포함)은 네임스페이스 리소스만 일치시킵니다.kube-access역할에서,production네임스페이스의 Pod에 대한 접근을 허용합니다.Tip와일드카드
*를 사용하면 클러스터 전체 리소스를 포함한 모든 리소스와 일치합니다(kind/api_group 기반). 빈 문자열""은 클러스터 전체 리소스만 일치시킵니다.^.+$와 같은 다른 값은 네임스페이스 리소스만 일치시키고 클러스터 전체 리소스는 제외합니다.-
name: 접근을 허용할 Pod의 이름.kube-access에서, 이는webappPod입니다. -
verbs: 리소스에 허용되는 작업. 현재 Teleport는 다음을 지원합니다:동사 접근 권한 *모든 작업 get리소스 읽기 list리소스 목록 조회 create리소스 생성 update리소스 업데이트 patch리소스 패치 delete리소스 삭제 deletecollection리소스 컬렉션 삭제 watch리소스 감시 portforwardPod에 대한 포트 포워드 요청 생성 execPod에서 명령어 실행
namespace,name및api_group필드의 경우, 와일드카드 문자(*)를 추가하여 임의 문자 시퀀스를 대체할 수 있습니다. 예를 들어,name: "pod-*-*"는pod-1-a및pod-2-c이름의 Pod와 일치합니다.kubernetes_labels와 마찬가지로, 값이^로 시작하고$로 끝나면, Kubernetes 서비스는 Go의re2구문을 사용하여 정규 표현식으로 처리합니다(re2README 참조).Tip사용자가 역할의
kubernetes_resources필드에 명명된 Pod에 접근하려면, 사용자에게kubernetes_groups또는kubernetes_users내에 최소 하나의 값을 포함하는 Teleport 역할이 할당되어야 합니다. Teleport는 접근을 허용하거나 거부하기 위해 Kubernetes 역할을 변경하지 않습니다. Kubernetes 서비스가 Teleport 역할을 평가하여 클러스터의 Pod에 대한 접근을 허용하거나 거부하는 방법에 대한 설명은 다음 섹션을 읽어보세요.역할 V7#
Tip역할 V7은 더 많은
kind값에 대한 지원을 추가했습니다. 이후 역할 버전에서 복수형을 사용하는 반면 단수 이름을 사용합니다.Warning와일드카드(
*)와namespace종류는 특별한 의미를 가지므로, 이를 사용할 때 의도와 이후 버전의 동작 차이에 각별히 주의하세요.kind: role metadata: name: kube-access version: v7 spec: allow: kubernetes_labels: "*": "*" kubernetes_resources: - kind: pod namespace: production name: webapp verbs: ["*"] # ...-
kind: 접근을 활성화할 리소스 종류. 현재 Teleport는 다음 종류를 지원합니다:Warning*종류 동작은 이후 버전과 약간 다릅니다. V7에서는namespace필드에 관계없이 클러스터 전체 리소스를 포함한 모든 리소스에 접근할 수 있습니다. 이후 역할 버전에서는namespace필드가 적용되므로, 업그레이드 시 특히 거부 측에서 리소스를 조정해야 할 수 있습니다.Warningnamespace종류는 네임스페이스 리소스와 그 안의 모든 리소스를 포함합니다. 이 동작은 리소스 자체만 포함하는 이후 역할 버전과 다르므로, 업그레이드 시 특히 거부 측에서 리소스를 조정해야 할 수 있습니다.종류 접근 권한 *namespace필드에 관계없이 클러스터 전체 리소스를 포함한 모든 리소스podPod secretSecrets configmapConfigMaps namespace네임스페이스 및 그 안의 모든 리소스. serviceServices serviceaccountServiceAccounts kube_nodeNodes persistentvolumePersistentVolumes persistentvolumeclaimPersistentVolumeClaims deploymentDeployments replicasetReplicaSets statefulsetStatefulSets daemonsetDaemonSets clusterroleClusterRoles kube_roleRoles clusterrolebindingClusterRoleBindings rolebindingRoleBindings cronjobCronJobs jobJobs certificatesigningrequestCertificateSigningRequests ingressIngresses -
namespace: 리소스에 대한 접근을 허용할 Kubernetes 네임스페이스.kube-access역할에서,production네임스페이스의 Pod에 대한 접근을 허용합니다.kind필드가*로 설정된 경우namespace필드는 무시됩니다. 이는namespace필드가 적용되는 이후 역할 버전과 다른 동작입니다. -
name: 접근을 허용할 Pod의 이름.kube-access에서, 이는webappPod입니다. -
verbs: 리소스에 허용되는 작업. 현재 Teleport는 다음을 지원합니다:동사 접근 권한 *모든 작업 get리소스 읽기 list리소스 목록 조회 create리소스 생성 update리소스 업데이트 patch리소스 패치 delete리소스 삭제 deletecollection리소스 컬렉션 삭제 watch리소스 감시 portforwardPod에 대한 포트 포워드 요청 생성 execPod에서 명령어 실행
namespace및name필드 모두에 와일드카드 문자(*)를 추가하여 임의 문자 시퀀스를 대체할 수 있습니다. 예를 들어,name: "pod-*-*"는pod-1-a및pod-2-c이름의 Pod와 일치합니다.kubernetes_labels와 마찬가지로, 값이^로 시작하고$로 끝나면, Kubernetes 서비스는 Go의re2구문을 사용하여 정규 표현식으로 처리합니다(re2README 참조).Tip사용자가 역할의
kubernetes_resources필드에 명명된 Pod에 접근하려면, 사용자에게kubernetes_groups또는kubernetes_users내에 최소 하나의 값을 포함하는 Teleport 역할이 할당되어야 합니다. Teleport는 접근을 허용하거나 거부하기 위해 Kubernetes 역할을 변경하지 않습니다. Kubernetes 서비스가 Teleport 역할을 평가하여 클러스터의 Pod에 대한 접근을 허용하거나 거부하는 방법에 대한 설명은 다음 섹션을 읽어보세요.역할 V6#
Tip역할 V6은
kubernetes_resources필드에 대한 지원을 도입했지만,pod종류의 Pod에만 접근을 허용하도록 제한되었습니다. 이후 역할 버전에서 추가 리소스에 대한 지원이 확장되었습니다.kind: role metadata: name: kube-access version: v6 spec: allow: kubernetes_labels: "*": "*" kubernetes_resources: - kind: pod namespace: production name: webapp # ...kind: 접근을 활성화할 리소스 종류. 유일하게 지원되는 값은pod입니다.namespace: 리소스에 대한 접근을 허용할 Kubernetes 네임스페이스.kube-access역할에서,production네임스페이스의 Pod에 대한 접근을 허용합니다.name: 접근을 허용할 Pod의 이름.kube-access에서, 이는webappPod입니다.
namespace및name필드 모두에 와일드카드 문자(*)를 추가하여 임의 문자 시퀀스를 대체할 수 있습니다. 예를 들어,name: "pod-*-*"는pod-1-a및pod-2-c이름의 Pod와 일치합니다.kubernetes_labels와 마찬가지로, 값이^로 시작하고$로 끝나면, Kubernetes 서비스는 Go의re2구문을 사용하여 정규 표현식으로 처리합니다(re2README 참조).Tip사용자가 역할의
kubernetes_resources필드에 명명된 Pod에 접근하려면, 사용자에게kubernetes_groups또는kubernetes_users내에 최소 하나의 값을 포함하는 Teleport 역할이 할당되어야 합니다. Teleport는 접근을 허용하거나 거부하기 위해 Kubernetes 역할을 변경하지 않습니다. Kubernetes 서비스가 Teleport 역할을 평가하여 클러스터의 Pod에 대한 접근을 허용하거나 거부하는 방법에 대한 설명은 다음 섹션을 읽어보세요.예시#
production을 제외한 네임스페이스 리소스에 대한 전체 접근#
다음 역할은
production네임스페이스를 제외한 모든 네임스페이스의 모든 네임스페이스 리소스에 대한 전체 접근을 허용하며,production에서는 리소스에 접근할 수 없습니다.kind: role metadata: name: kube-access version: v7 spec: allow: kubernetes_labels: "*": "*" kubernetes_resources: # v7에서 namespace는 네임스페이스 내의 모든 것을 의미합니다. - kind: namespace # v7은 단수형을 사용합니다. name: "*" verbs: ["*"] deny: kubernetes_resources: - kind: namespace # v7은 단수형을 사용합니다. name: production verbs: ["*"] # ...kind: role metadata: name: kube-access version: v8 spec: allow: kubernetes_labels: "*": "*" kubernetes_resources: # 모든 네임스페이스의 네임스페이스 리소스에 대한 접근 허용. - kind: "*" api_group: "*" name: "*" namespace: "^.+$" # 네임스페이스 리소스와 일치, 클러스터 전체 리소스는 일치하지 않음. verbs: ["*"] # 네임스페이스 리소스 자체에 대한 접근 허용. - kind: namespaces # v8에서 namespaces는 네임스페이스 자체를 의미합니다. 클러스터 전체 리소스로 간주되므로 별도로 추가해야 합니다. name: "*" verbs: ["*"] deny: kubernetes_resources: # production 네임스페이스의 네임스페이스 리소스 접근 거부. - kind: "*" api_group: "*" name: "*" namespace: production verbs: ["*"] # 네임스페이스 리소스 자체 접근 거부. - kind: namespaces # v8은 복수형을 사용합니다. name: production verbs: ["*"] # ...또는 다음과 같이도 사용할 수 있습니다:
kind: role metadata: name: kube-access version: v8 spec: allow: kubernetes_labels: "*": "*" kubernetes_resources: # 모든 것에 대한 전체 접근 허용. - kind: "*" api_group: "*" name: "*" namespace: "*" # v8에서 '*'는 네임스페이스 리소스와 클러스터 전체 리소스 모두와 일치합니다. verbs: ["*"] deny: kubernetes_resources: # 클러스터 전체 리소스 접근 거부. - kind: "*" api_group: "*" name: "*" namespace: "" # 빈 네임스페이스는 클러스터 전체 리소스만 일치합니다. verbs: ["*"] # production 네임스페이스의 네임스페이스 리소스 접근 거부. - kind: "*" api_group: "*" name: "*" namespace: production verbs: ["*"] # 네임스페이스 리소스 자체 접근 거부. - kind: namespaces # v8은 복수형을 사용합니다. name: production verbs: ["*"] # ...clusterroles를 제외한 dev 네임스페이스 및 모든 클러스터 전체 리소스에 대한 전체 접근#
다음 역할은
dev네임스페이스의 모든 리소스와clusterroles를 제외한 모든 클러스터 전체 리소스에 대한 접근을 허용합니다.kind: role metadata: name: kube-access version: v7 spec: allow: kubernetes_labels: "*": "*" kubernetes_resources: # v7에서 "*"는 namespace에 관계없이 클러스터 전체 리소스를 포함합니다. - kind: "*" name: "*" namespace: dev verbs: ["*"] deny: kubernetes_resources: - kind: clusterrole # v7은 단수형을 사용합니다. name: "*" verbs: ["*"] # ...kind: role metadata: name: kube-access version: v8 spec: allow: kubernetes_labels: "*": "*" kubernetes_resources: # dev 네임스페이스의 모든 리소스에 대한 접근 허용. # v8에서 "*"는 namespace가 설정된 경우 클러스터 전체 리소스를 포함하지 않습니다. - kind: "*" api_group: "*" name: "*" namespace: dev verbs: ["*"] # 모든 클러스터 전체 리소스에 대한 접근 허용. - kind: "*" api_group: "*" name: "*" namespace: "" # 빈 네임스페이스는 클러스터 전체 리소스만 일치합니다. verbs: ["*"] deny: kubernetes_resources: - kind: clusterroles # v8은 복수형을 사용합니다. api_group: "*" name: "*" # ...모든 것에 대한 전체 접근#
kind: role metadata: name: kube-access version: v7 spec: allow: kubernetes_labels: "*": "*" kubernetes_resources: - kind: "*" name: "*" namespace: "*" verbs: ["*"] # ...kind: role metadata: name: kube-access version: v8 spec: allow: kubernetes_labels: "*": "*" kubernetes_resources: - kind: "*" api_group: "*" name: "*" namespace: "*" # 와일드카드 '*'는 네임스페이스 리소스와 클러스터 전체 리소스 모두와 일치합니다. verbs: ["*"] # ...Kubernetes 서비스가 Teleport 역할을 평가하는 방법#
Teleport 사용자가 Kubernetes 클러스터의 API 서버에 요청하면, Teleport Kubernetes 서비스는 요청을 가로채고 사용자의 권한을 검사합니다. Kubernetes 서비스는 사용자가 특정 리소스를 볼 권한이 없는 경우 요청을 거부합니다. 사용자가 요청을 수행할 권한이 있으면, Kubernetes 서비스는 요청을 수정하고 적절한 API 서버로 전달합니다.
사용자 요청 승인#
Teleport Kubernetes 서비스가 요청을 수신하면, 사용자 역할 내의 두 필드를 평가합니다. 이러한 필드 중 어느 것이 사용자가 요청을 수행하는 것을 허용하지 않으면, Kubernetes 서비스는 사용자에게 오류를 반환합니다:
kubernetes_labels#Teleport Kubernetes 서비스는 Pod가 실행되는 클러스터에 사용자의
kubernetes_labels구성과 일치하는 레이블이 있는 경우에만 사용자의 Pod 접근을 허용합니다.kubernetes_resources#Kubernetes API 서버 내의 일부 리소스 URI는 특정 리소스의 이름을 포함합니다.
예를 들어, 사용자가
kubectl exec를 실행하여development네임스페이스의webappPod에 대해 명령어를 실행하면,kubectl은 다음 경로에서 대상 클러스터의 API 서버로 요청을 보냅니다:"/api/v1/namespaces/development/pods/webapp/exec"Kubernetes API 서버에 대한 요청의 URL 경로 내에 Kubernetes Pod가 있으면, Teleport Kubernetes 서비스는 사용자가 해당 Pod에 접근할 권한이 있는지 확인합니다.
위의 예에서, Kubernetes 서비스는 사용자가
development네임스페이스의webappPod에 접근할 권한이 있는지 확인하고, 그렇지 않으면 요청을 거부합니다.사용자 요청 전달#
Teleport Kubernetes 서비스가 사용자가 Kubernetes 클러스터와 (해당하는 경우) 특정 리소스에 대한 요청을 수행할 권한이 있음을 승인하면, 업스트림 API 서버에 대한 요청을 조합합니다. 사용자 역할의
kubernetes_groups및kubernetes_users필드를 기반으로 요청에 가장 헤더를 추가합니다 (이러한 필드에 대한 이전 토론 참조).Teleport Kubernetes 서비스는 Teleport 사용자의
kubernetes_groups및kubernetes_users필드에 나열된 RBAC 주체를 통해 업스트림 API 서버에 접근하므로, 이 필드에 지정하는 주체는 사용자의kubernetes_resources필드에 나열된 리소스에 접근할 수 있어야 합니다. 그렇지 않으면, Kubernetes 서비스는 부적절한 권한으로 업스트림 API 서버에 요청을 전달하고, API 서버는 요청을 거부합니다.여러 역할#
Kubernetes 서비스가 여러 역할을 평가하는 방법#
Kubernetes API 서버에 대한 사용자 요청을 평가하기 전에, Teleport Kubernetes 서비스는 사용자의 각 역할을 확인합니다. 하나의 역할의
spec.allow.kubernetes_labels또는spec.allow.kubernetes_resources조건이 사용자의 요청과 일치하지 않으면, Kubernetes 서비스는 다음 역할을 확인하는 식으로 진행합니다.Kubernetes 서비스가 클러스터의 레이블과 요청의 리소스 모두와 일치하는
spec.allow조건을 가진 역할을 찾으면, 역할의allow.kubernetes_groups및allow.kubernetes_users필드를 조회합니다. 이 값들을 나중에 가장 헤더를 작성하는 데 사용할 RBAC 주체 목록에 추가합니다.다음으로, Kubernetes 서비스는
spec.deny조건에 대해 사용자의 각 역할을 확인합니다. 하나의 역할의spec.deny.kubernetes_labels또는spec.deny.kubernetes_resources필드가 사용자의 요청과 일치하면, Kubernetes 서비스는 역할의spec.deny.kubernetes_groups및spec.deny.kubernetes_users필드를 조회합니다. 이러한 값들을 이전에 만든 사용자 및 그룹 목록에서 제거하여 사용자가 이러한 RBAC 주체에 접근하는 것을 거부합니다.예시#
사용자에게 다음 세 가지 역할이 할당되었다고 가정합니다:
kind: role metadata: name: allow-dev-us-east-2 version: v7 spec: allow: kubernetes_labels: "region": "us-east-2" kubernetes_resources: - kind: pod namespace: "development" name: "redis-*" - kind: pod namespace: "development" name: "nginx-*" kubernetes_groups: - dev-viewers # 사용자가 development 네임스페이스의 Pod를 볼 수 있도록 허용 --- kind: role metadata: name: allow-exec version: v7 spec: allow: kubernetes_labels: - "*": "*" kubernetes_resources: - kind: pod namespace: "*" name: "*" kubernetes_groups: - executors # 사용자가 모든 Pod에 대해 명령어를 실행할 수 있도록 허용 --- kind: role metadata: name: deny-redis-exec version: v7 spec: deny: kubernetes_resources: - kind: pod namespace: "*" name: "redis-*" kubernetes_groups: - executorsdev-viewersKubernetes 그룹은 사용자가development네임스페이스의 Pod를 볼 수 있게 합니다.executorsKubernetes 그룹은 사용자가 모든 네임스페이스의 모든 Pod에 대해 명령어를 실행할 수 있게 합니다.이러한 역할을 가진 사용자가
development네임스페이스에서kubectl get pods/redis-1을 실행하고 클러스터에region:us-east-2레이블이 있으면, Kubernetes 서비스는 요청을 수락합니다.deny-redis-exec역할이redis-*Pod에 대해executors그룹을 거부하므로, Kubernetes 서비스는dev-viewers그룹을 가장하지만executors그룹은 가장하지 않고 요청을 전달합니다.그러나 동일한 사용자가 동일한 클러스터의
development네임스페이스에서kubectl exec -it nginx /bin/bash를 실행하면,deny-redis-exec역할의deny조건이 요청과 일치하지 않으므로 Kubernetes 서비스는dev-viewers와executors그룹 모두로 가장 헤더를 사용하여 요청을 전달합니다.리소스에 대한 접근을 점진적으로 활성화#
Teleport와 Kubernetes RBAC를 설계하여 Kubernetes 리소스의 제한된 하위 집합에 대한 접근을 점진적으로 허용할 수 있습니다. 즉, 사용자는 Kubernetes 클러스터의 광범위한 리소스에 제한된 접근을 가집니다. 이러한 사용자의 하위 집합은 더 제한된 리소스 집합에 더 큰 접근 권한을 가집니다. 이러한 사용자의 하위 집합 중, 더 작은 그룹에 다른 리소스 집합에 대한 더 큰 접근 권한을 할당하는 식으로 계속됩니다.
이를 위해 다음과 같이 여러 Teleport 역할을 정의합니다:
- 일부 역할은 더 많은 Kubernetes 리소스에 대해 더 낮은 수준의 접근 권한을 활성화합니다
- 다른 역할은 더 적은 Kubernetes 리소스 집합에 대해 더 높은 수준의 접근 권한을 허용합니다
그런 다음 다른 사용자에게 역할의 조합을 할당할 수 있습니다.
예를 들어, 이 역할 조합은 사용자가 등록된 모든 Kubernetes 클러스터의 모든 Pod를 볼 수 있게 하지만
nginx-*Pod에서만kubectl exec또는kubectl logs를 실행할 수 있게 합니다:kind: role metadata: name: kube-viewer version: v7 spec: allow: kubernetes_labels: '*': '*' kubernetes_resources: - kind: pod namespace: "*" name: "*" kubernetes_groups: - viewer # Pod를 가져오고 목록을 조회할 수 있지만 명령어를 실행하거나 로그를 검색할 수 없음 --- kind: role metadata: name: nginx-exec version: v7 spec: allow: kubernetes_labels: '*': '*' kubernetes_resources: - kind: pod namespace: "*" name: "nginx-*" kubernetes_groups: - execAndLogs이 경우,
kube-viewer역할은 사용자를 Kubernetesviewer그룹에 매핑하여 사용자가 Pod를 가져오고 목록을 조회하지만 명령어를 실행하고 로그를 검색할 수 없게 합니다.nginx-exec역할을 통해, 사용자는execAndLogs그룹에 접근할 수 있어 명령어를 실행하고 로그를 검색할 수 있지만nginxPod에서만 가능합니다.이 설정에서, Teleport 사용자의 요구 사항에 따라 Pod 하위 집합에 대한 높은 수준의 접근 권한을 부여하는 다른 역할과
kube-viewer역할을 결합할 수도 있습니다.보안 고려 사항: 리소스 네임스페이스 제한#
Teleport 사용자가
kubectl get pods와 같이 Pod를 나열하는 요청을 보내면, Teleport Kubernetes 서비스는 다음을 수행합니다:- 사용자의 Teleport 역할에 기반하여 요청에 가장 헤더를 추가하면서 업스트림 Kubernetes API 서버에서 사용 가능한 Pod를 검색합니다. 여기에는 사용자가 요청을 보내는 Kubernetes 사용자와 그룹이 포함됩니다.
kubernetes_resources를 통해 사용자가 접근할 수 있는 Pod를 기반으로 사용 가능한 Pod 목록을 필터링합니다.- Pod 목록을 사용자에게 반환합니다.
리소스를 의도치 않게 노출하지 않으려면, Kubernetes RBAC의 네임스페이스 제한이 Teleport에서 설정한 것과 일치하는지 확인해야 합니다.
예를 들어, 사용자에게 모든 네임스페이스의 임의 Pod에 접근 권한을 부여하고 사용자를
default-pod-viewerKubernetes 그룹에 매핑하는 Teleport 역할이 있다고 가정합니다. 이 그룹은default네임스페이스의 Pod만 볼 수 있습니다:kind: role metadata: name: kube-access-1 version: v7 spec: allow: kubernetes_groups: - default-pod-viewer kubernetes_resources: - kind: pod namespace: "*" name: "*" # ...사용자에게는 사용자를
system:mastersKubernetes 그룹(모든 네임스페이스의 임의 Pod에 접근할 수 있음)에 매핑하고default네임스페이스의webappPod에만 접근 권한을 부여하는 두 번째 Teleport 역할이 있습니다:metadata: name: kube-access-2 version: v7 spec: allow: kubernetes_groups: - system:masters kubernetes_resources: - kind: pod namespace: "default" name: "webapp" # ...kube-access-2역할이 사용자를system:masters에 매핑하므로, Kubernetes 서비스가 이 사용자의 요청을 전달할 때 요청의 가장 헤더에system:masters그룹을 추가하여 Kubernetes 클러스터에서 모든 Pod를 가져옵니다.그러나 사용자에게 모든 네임스페이스의 모든 Pod에 접근 권한을 허용하는 역할(
kube-access-1)도 있으므로, Kubernetes 서비스는 첫 번째 API 서버 요청을 통해 검색된 Pod를 필터링하지 않습니다.즉, Kubernetes 서비스는
webappPod에만 접근 권한을 부여하기 위해 Teleport가 사용자를system:masters그룹에 매핑했다는 것을 알 방법이 없습니다.Teleport RBAC에 네임스페이스 제한이 있는 경우, 매핑된 Teleport 사용자의 Kubernetes RBAC 리소스에도 동일한 네임스페이스 제한이 있어야 합니다.
예를 들어, 사용자를
default네임스페이스의 Pod로 제한하기 위해 다음 권한을 가지도록kube-access-1역할을 다시 작성해야 합니다:kind: role metadata: name: kube-access-1 version: v7 spec: allow: kubernetes_groups: - default-pod-viewer kubernetes_resources: - kind: pod namespace: "default" name: "*" # ... -
-
- 줄에
