Teleport Kubernetes 접근 제어
Teleport v18.9이 가이드는 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#
Kubernetes 클러스터를 Teleport에 등록할 때 라벨을 추가할 수 있습니다.
역할의 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/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 서비스는 임퍼소네이션
헤더를
사용하여 하나의 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은
이를 무시합니다.
다음은 내장된 view ClusterRole을 cluster-viewer-group 그룹과 cluster-viewer-user
사용자에게 할당하는 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 사용자, 그룹, 서비스 계정을 임퍼소네이트하는 방법#
최종 사용자가 임퍼소네이트할 사용자 또는 서비스 계정과 그룹을 지정하는 방법에는 두 가지가 있습니다:
수동으로#
사용자가 Kubernetes 클러스터에 인증하기 위해 tsh kube login을 실행할 때, --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입니다.
일반적으로 이러한 리소스를 수동으로 정의할 필요는 없습니다. Kubernetes 클러스터를 Teleport에 등록하는 수동 방법과 자동 방법에는 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 역할에 이 정보를 하드코딩하는 대신, 각 Teleport 사용자별로 개별적으로 Kubernetes 그룹과 사용자를 지정할 수 있습니다. 이를 위해 Teleport 역할에 템플릿 변수를 추가할 수 있으며, Teleport Auth 서비스가 인증하는 각 사용자의 정보로 이를 채웁니다.
Teleport 역할에서 템플릿 변수 확장이 작동하는 방식에 대한 자세한 내용은 Access Controls Reference를 참조하세요.
싱글 사인온 제공업체 트레이트#
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 access) 구성#
특정 Kubernetes 리소스에 대한 적시 접근을 활성화하기 위해 Teleport 역할을 설정하는 경우,
Teleport가 접근을 제한할 수 있는 Kubernetes 리소스 외에는 Kubernetes 리소스에 대한 접근
권한이 없는 프린시펄로 역할의 kubernetes_groups와 kubernetes_users를 설정해야 합니다.
이는 사용자가 Kubernetes 파드에 대한 접근을 요청하고 요청이 승인되면, 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네임스페이스의 파드에 대한 접근을 허용하고 있습니다.Tip와일드카드
*를 사용하면 클러스터 범위 리소스를 포함하여(종류/api_group 기준) 모든 리소스와 일치한다는 점에 유의하세요. 빈 문자열""을 사용하면 클러스터 범위 리소스와만 일치합니다.^.+$와 같은 다른 값은 네임스페이스가 지정된 리소스와만 일치하고 클러스터 범위 리소스는 제외합니다.-
name: 접근을 허용할 파드의 이름입니다.kube-access에서는webapp파드입니다. -
verbs: 리소스에 허용할 작업입니다. 현재 Teleport는 다음을 지원합니다:Verb 부여하는 접근 권한 *모든 작업 get리소스 읽기 list리소스 목록 조회 create리소스 생성 update리소스 업데이트 patch리소스 패치 delete리소스 삭제 deletecollection리소스 컬렉션 삭제 watch리소스 감시 portforward파드에 대한 포트포워드 요청 생성 exec파드 내 명령 실행
namespace,name,api_group필드에는 와일드카드 문자(*)를 추가하여 임의의 문자 시퀀스를 대체할 수 있습니다. 예를 들어,name: "pod-*-*"는pod-1-a와pod-2-c라는 이름의 파드와 일치합니다.kubernetes_labels와 마찬가지로, 값이^로 시작하고$로 끝나면 Kubernetes 서비스는 이를 Go의re2구문을 사용하는 정규 표현식으로 처리합니다 (re2README 참조).Tip역할의
kubernetes_resources필드에 이름이 지정된 파드에 사용자가 접근하려면, 사용자는kubernetes_groups또는kubernetes_users내에 적어도 하나의 값을 포함하는 Teleport 역할이 할당되어 있어야 합니다. Teleport는 접근을 허용하거나 거부하기 위해 Kubernetes 역할을 변경하지 않습니다. Kubernetes 서비스가 클러스터 내 파드에 대한 접근을 허용하거나 거부하기 위해 Teleport 역할을 평가하는 방식에 대한 설명은 다음 섹션을 참조하세요.역할 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필드가 강제되므로, 업그레이드할 때 특히 deny 쪽에서 리소스를 조정해야 할 수 있습니다.Warningnamespace종류는namespace리소스 자체는 물론 그 안의 모든 리소스도 다룹니다. 이는 이후 역할 버전에서 리소스 자체만 다루는 것과 다른 동작이므로, 업그레이드할 때 특히 deny 쪽에서 리소스를 조정해야 할 수 있습니다.Kind 부여하는 접근 권한 *namespace필드와 관계없이 클러스터 범위 리소스를 포함한 모든 리소스pod파드 secret시크릿 configmapConfigMap namespace네임스페이스 및 그 안의 모든 리소스 service서비스 serviceaccount서비스 계정 kube_node노드 persistentvolumePersistentVolume persistentvolumeclaimPersistentVolumeClaim deployment디플로이먼트 replicasetReplicaSet statefulsetStatefulSet daemonsetDaemonSet clusterroleClusterRole kube_roleRole clusterrolebindingClusterRoleBinding rolebindingRoleBinding cronjobCronJob jobJob certificatesigningrequestCertificateSigningRequest ingressIngress -
namespace: 리소스에 대한 접근을 허용할 Kubernetes 네임스페이스입니다.kube-access역할에서는production네임스페이스의 파드에 대한 접근을 허용하고 있습니다.kind필드가*로 설정된 경우namespace필드는 무시되며, 이는namespace필드가 강제되는 이후 역할 버전과 다른 동작이라는 점에 유의하세요. -
name: 접근을 허용할 파드의 이름입니다.kube-access에서는webapp파드입니다. -
verbs: 리소스에 허용할 작업입니다. 현재 Teleport는 다음을 지원합니다:Verb 부여하는 접근 권한 *모든 작업 get리소스 읽기 list리소스 목록 조회 create리소스 생성 update리소스 업데이트 patch리소스 패치 delete리소스 삭제 deletecollection리소스 컬렉션 삭제 watch리소스 감시 portforward파드에 대한 포트포워드 요청 생성 exec파드 내 명령 실행
namespace와name필드 모두에 와일드카드 문자(*)를 추가하여 임의의 문자 시퀀스를 대체할 수 있습니다. 예를 들어,name: "pod-*-*"는pod-1-a와pod-2-c라는 이름의 파드와 일치합니다.kubernetes_labels와 마찬가지로, 값이^로 시작하고$로 끝나면 Kubernetes 서비스는 이를 Go의re2구문을 사용하는 정규 표현식으로 처리합니다(re2README 참조).Tip역할의
kubernetes_resources필드에 이름이 지정된 파드에 사용자가 접근하려면, 사용자는kubernetes_groups또는kubernetes_users내에 적어도 하나의 값을 포함하는 Teleport 역할이 할당되어 있어야 합니다. Teleport는 접근을 허용하거나 거부하기 위해 Kubernetes 역할을 변경하지 않습니다. Kubernetes 서비스가 클러스터 내 파드에 대한 접근을 허용하거나 거부하기 위해 Teleport 역할을 평가하는 방식에 대한 설명은 다음 섹션을 참조하세요.역할 V6#
Tip역할 V6은
kubernetes_resources필드에 대한 지원을 도입했지만, 종류가 '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네임스페이스의 파드에 대한 접근을 허용하고 있습니다.name: 접근을 허용할 파드의 이름입니다.kube-access에서는webapp파드입니다.
namespace와name필드 모두에 와일드카드 문자(*)를 추가하여 임의의 문자 시퀀스를 대체할 수 있습니다. 예를 들어,name: "pod-*-*"는pod-1-a와pod-2-c라는 이름의 파드와 일치합니다.kubernetes_labels와 마찬가지로, 값이^로 시작하고$로 끝나면 Kubernetes 서비스는 이를 Go의re2구문을 사용하는 정규 표현식으로 처리합니다(re2README 참조).Tip역할의
kubernetes_resources필드에 이름이 지정된 파드에 사용자가 접근하려면, 사용자는kubernetes_groups또는kubernetes_users내에 적어도 하나의 값을 포함하는 Teleport 역할이 할당되어 있어야 합니다. Teleport는 접근을 허용하거나 거부하기 위해 Kubernetes 역할을 변경하지 않습니다. Kubernetes 서비스가 클러스터 내 파드에 대한 접근을 허용하거나 거부하기 위해 Teleport 역할을 평가하는 방식에 대한 설명은 다음 섹션을 참조하세요.예시#
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: ["*"] # ...dev 네임스페이스와 clusterroles를 제외한 모든 클러스터 범위 리소스에 대한 전체 접근#
다음 역할은
dev네임스페이스의 모든 리소스와clusterroles를 제외한 모든 클러스터 범위 리소스에 대한 접근을 부여합니다.kind: role metadata: name: kube-access version: v7 spec: allow: kubernetes_labels: "*": "*" kubernetes_resources: # v7에서 "*"는 네임스페이스와 관계없이 클러스터 범위 리소스를 포함합니다. - 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에서는 네임스페이스가 설정된 경우 "*"에 클러스터 범위 리소스가 포함되지 않습니다. - 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 서비스는 파드가 실행 중인 클러스터에 사용자의
kubernetes_labels구성과 일치하는 라벨이 있는 경우에만 파드에 대한 접근을 허용합니다.kubernetes_resources#Kubernetes API 서버 내의 일부 리소스 URI에는 특정 리소스의 이름이 포함됩니다.
예를 들어, 사용자가
kubectl exec를 실행하여development네임스페이스의webapp파드에 대해 명령을 실행하면,kubectl은 대상 클러스터의 API 서버에 다음 경로로 요청을 보냅니다:"/api/v1/namespaces/development/pods/webapp/exec"Kubernetes API 서버에 대한 요청의 URL 경로 내에 Kubernetes 파드가 있는 경우, Teleport Kubernetes 서비스는 사용자가 해당 파드에 접근할 권한이 있는지 확인합니다.
위 예시에서 Kubernetes 서비스는 사용자가
development네임스페이스의webapp파드에 접근할 권한이 있는지 확인하고, 없으면 요청을 거부합니다.사용자 요청 전달#
Teleport Kubernetes 서비스가 사용자가 Kubernetes 클러스터와 (해당하는 경우) 특정 리소스에 대해 요청을 수행할 권한이 있다고 인가하면, 상위 API 서버에 대한 요청을 조립합니다. 사용자 역할의
kubernetes_groups와kubernetes_users필드(앞서 설명한 이 필드에 대한 설명 참조)를 기반으로 요청에 임퍼소네이션 헤더를 추가합니다.Teleport Kubernetes 서비스는 Teleport 사용자의
kubernetes_groups와kubernetes_users필드에 나열된 RBAC 프린시펄을 통해 상위 API 서버에 접근하므로, 이러한 필드에 지정하는 프린시펄은 사용자의kubernetes_resources필드에 나열된 리소스에 대한 접근 권한을 가지고 있어야 합니다. 그렇지 않으면 Kubernetes 서비스는 부적절한 인가로 요청을 상위 API 서버에 전달하게 되고, API 서버는 요청을 거부합니다.여러 역할#
Kubernetes 서비스가 여러 역할을 평가하는 방식#
Teleport Kubernetes 서비스는 사용자의 Kubernetes API 서버에 대한 요청을 평가하기 전에 사용자의 각 역할을 확인합니다. 한 역할의
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 네임스페이스에서 파드를 볼 수 있도록 허용합니다 --- kind: role metadata: name: allow-exec version: v7 spec: allow: kubernetes_labels: "*": "*" kubernetes_resources: - kind: pod namespace: "*" name: "*" kubernetes_groups: - executors # 사용자가 모든 파드에 대해 명령을 실행할 수 있도록 허용합니다 --- kind: role metadata: name: deny-redis-exec version: v7 spec: deny: kubernetes_resources: - kind: pod namespace: "*" name: "redis-*" kubernetes_groups: - executorsdev-viewersKubernetes 그룹은 사용자가development네임스페이스의 파드를 볼 수 있도록 허용합니다.executorsKubernetes 그룹은 사용자가 모든 네임스페이스의 모든 파드에 대해 명령을 실행할 수 있도록 허용합니다.이러한 역할을 가진 사용자가
development네임스페이스에서kubectl get pods/redis-1을 실행하고 클러스터에region:us-east-2라벨이 있는 경우, Kubernetes 서비스는 요청을 수락합니다.deny-redis-exec역할이redis-*파드에 대해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 클러스터에서 모든 파드를 볼 수 있도록 허용하지만,
nginx-*파드에서만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 # 파드를 가져오고 목록을 조회할 수 있지만 명령 실행이나 로그 검색은 할 수 없습니다 --- 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그룹에 매핑하여, 사용자가 파드를 가져오고 목록을 조회할 수 있지만 명령을 실행하거나 로그를 검색할 수는 없도록 합니다.nginx-exec역할을 사용하면, 사용자는 명령을 실행하고 로그를 검색할 수 있는execAndLogs그룹에 접근할 수 있지만,nginx파드에서만 가능합니다.이 설정에서는 Teleport 사용자의 요구 사항에 따라
kube-viewer역할을 파드의 부분 집합에 대한 상승된 접근 권한을 부여하는 다른 역할과 결합할 수도 있습니다.보안 고려 사항: 리소스 네임스페이스 제한#
Teleport 사용자가 예를 들어
kubectl get pods로 파드 목록 조회 요청을 보내면, Teleport Kubernetes 서비스는 다음을 수행합니다:- 사용자의 Teleport 역할을 기반으로 임퍼소네이션 헤더를 요청에 추가하여 상위 Kubernetes API 서버에서 사용 가능한 파드를 가져옵니다. 여기에는 사용자가 요청을 보낼 때 사용하는 Kubernetes 사용자와 그룹이 포함됩니다.
kubernetes_resources를 통해 사용자가 접근할 권한이 있는 파드를 기준으로 사용 가능한 파드 목록을 필터링합니다.- 파드 목록을 사용자에게 반환합니다.
의도치 않게 리소스가 유출되는 것을 방지하려면, Kubernetes RBAC의 네임스페이스 제한이 Teleport에 설정한 제한과 일치하는지 확인해야 합니다.
예를 들어, 사용자가 어떤 네임스페이스의 어떤 파드에도 접근을 허용하는 Teleport 역할을 가지고 있고, 해당 사용자를
default-pod-viewerKubernetes 그룹에 매핑한다고 가정해 보겠습니다. 이 그룹은default네임스페이스의 파드만 볼 수 있습니다:kind: role metadata: name: kube-access-1 version: v7 spec: allow: kubernetes_groups: - default-pod-viewer kubernetes_resources: - kind: pod namespace: "*" name: "*" # ...사용자는 두 번째 Teleport 역할을 가지고 있으며, 이는 사용자를
system:mastersKubernetes 그룹(모든 네임스페이스의 모든 파드에 접근 가능)에 매핑하고,default네임스페이스의webapp파드에만 접근 권한을 부여합니다: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 클러스터에서 모든 파드를 가져옵니다.그러나 사용자는 모든 네임스페이스의 모든 파드에 대한 접근을 허용하는 역할(
kube-access-1)도 가지고 있으므로, Kubernetes 서비스는 API 서버에 대한 첫 번째 요청을 통해 가져온 파드를 필터링하지 않습니다.즉, Kubernetes 서비스는 Teleport가
default네임스페이스의webapp파드에만 접근을 허용하기 위해 사용자를system:masters그룹에 매핑했다는 것을 알 방법이 없습니다.Teleport RBAC에 네임스페이스 제한이 있는 경우, Teleport 사용자에게 매핑하는 Kubernetes RBAC 리소스에도 동일한 네임스페이스 제한이 있는지 확인해야 합니다.
예를 들어, 다음과 같은 권한을 갖도록
kube-access-1역할을 다시 작성하여 사용자를default네임스페이스의 파드로 제한해야 합니다:kind: role metadata: name: kube-access-1 version: v7 spec: allow: kubernetes_groups: - default-pod-viewer kubernetes_resources: - kind: pod namespace: "default" name: "*" # ... -
-
- 해당 줄에