Infograb logo
Teleport Kubernetes 액세스 제어

이 가이드는 Teleport 사용자가 Kubernetes 클러스터와 상호 작용할 때 Teleport Kubernetes 서비스가 역할 기반 액세스 제어를 적용하는 방식을 설명합니다. Kubernetes 서비스는 Kubernetes API 서버에 대한 요청을 가로채고 각 요청을 사용자의 Teleport 역할에 따라 수정합니다.

이 가이드에서는 Teleport 역할에서 사용할 수 있는 필드를 구성하여 Teleport에 연결된 Kubernetes 클러스터에 대한 액세스를 관리하는 방법을 보여줍니다.

로컬 minikube 클러스터와 함께 Teleport 역할을 사용하여 Kubernetes에 대한 액세스를 관리하는 방법에 대한 예는 RBAC 사용 방법 가이드를 참조하십시오.

Kubernetes 액세스를 관리하기 위한 역할 필드

이 섹션에서는 Kubernetes 클러스터에 대한 액세스를 구성하는 Teleport 역할 내의 필드를 설명합니다.

Kubernetes 클러스터에 대한 액세스를 관리하려면 Teleport 역할에 spec.allow 섹션에 다음 필드가 포함되어야 합니다:

다음은 Kubernetes 클러스터에 대한 액세스를 제한하는 Teleport 역할의 예입니다:

kind: role
metadata:
  name: kube-access
version: v7
spec:
  allow:
    kubernetes_labels:
      "region": "*"
      "platform": "minikube"
    kubernetes_resources:
      - kind: pod
        namespace: "production"
        name: "^webapp-[a-z0-9-]+$"
      - kind: pod
        namespace: "development"
        name: "*"
    kubernetes_groups:
      - developers
    kubernetes_users:
      - minikube
  deny: {}

kubernetes_labels

Kubernetes 클러스터를 Teleport에 등록할 때 레이블을 추가할 수 있습니다. 역할의 kubernetes_labels 필드를 사용하여 서로 다른 레이블을 가진 Kubernetes 클러스터에 대한 사용자의 액세스를 제한할 수 있습니다.

kind: role
metadata:
  name: kube-access
version: v7
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 클러스터의 레이블 값과 일치해야 사용자가 클러스터에 액세스할 수 있습니다.

예를 들어, 위의 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-1region:us-east-2b 가 있는 클러스터와 일치합니다. 또한 레이블 team:data-eng-analyticsteam: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_groupskubernetes_users

Teleport Kubernetes 서비스는 최종 사용자로부터 요청을 받고, 예를 들어 kubectl 을 통해 Kubernetes API 서버로 전달합니다. Kubernetes 서비스는 임포스네이션 헤더를 사용하여 하나의 Kubernetes 사용자와 0개 이상의 Kubernetes 그룹으로 API 서버에 요청을 보냅니다.

임포스네이션

kubernetes_userskubernetes_groups 필드는 사용자가 Kubernetes API 서버에 요청을 보낼 때 어떤 사용자와 그룹을 허용할지를 나타냅니다:

kind: role
metadata:
  name: kube-access
version: v7
spec:
  allow:
    kubernetes_groups:
      - 개발자
      - 조회자
    kubernetes_users:
      - myuser
      - system:serviceaccount:someNamespace:saName # 서비스 계정 이름
    # ...
  deny: {}

kubernetes_groupskubernetes_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는 요청에 사용된 임Personation 주체와 관련된 권한을 병합합니다.

Kubernetes 서비스 계정

Teleport는 kubernetes_users 필드에서 서비스 계정의 완전한 이름을 사용하여 서비스 계정 임Personaation을 지원합니다.

서비스 계정의 완전한 이름(FQN)은 다음 패턴으로 구성됩니다:

system:serviceaccount:<namespace>:<service_account_name>

FQN은 system:serviceaccount:로 접두사가 붙어야 하며, 그렇지 않으면 Kubernetes는 이를 일반 사용자로 평가합니다.

서비스 계정을 임Personaation하는 역할의 예는 아래와 같습니다.

kind: role
metadata:
  name: kube-access-impersonate-sa
version: v7
spec:
  allow:
    kubernetes_users:
      - system:serviceaccount:someNamespace:saName
    # ...
  deny: {}

Teleport 사용자가 Kubernetes 사용자, 그룹 및 서비스 계정을 임Personaate하는 방법

최종 사용자가 어떤 사용자 또는 서비스 계정과 그룹을 임Personaate할지를 지정하는 방법은 두 가지가 있습니다:

수동

사용자가 tsh kube login 을 실행하여 Kubernetes 클러스터에 인증할 때, --as--as-groups 플래그를 사용하여 인증할 사용자와 그룹을 수동으로 지정할 수 있습니다. Teleport Kubernetes 서비스는 사용자가 사용하는 kubernetes_userskubernetes_groups 구성에 사용자 및 그룹이 속하는지 여부를 판단하고, 그렇지 않을 경우 사용자의 접근을 거부합니다.

자동

사용자가 클러스터에 인증할 때 Kubernetes 사용자와 Kubernetes 그룹을 명시적으로 결정하지 않은 경우, Teleport Kubernetes 서비스는 사용자의 역할 내 kubernetes_userskubernetes_groups 필드에서 이를 결정합니다.

사용자가 kubernetes_users 에 정확히 하나의 값이 있는 경우, Teleport Kubernetes 서비스는 해당 사용자를 임Personaate합니다. kubernetes_users 에 값이 없으면 Kubernetes 서비스는 사용자의 Teleport 사용자 이름을 사용합니다.

사용자가 여러 kubernetes_users 를 가지고 있고 클러스터에 인증할 때 하나를 지정하지 않은 경우, Kubernetes 서비스는 요청을 거부합니다 (즉, 이전 섹션에서 설명한 --as 플래그를 사용하는 경우).

사용자가 임Personaate할 Kubernetes 그룹을 지정하지 않은 경우, Kubernetes 서비스는 kubernetes_groups 내의 모든 값을 사용합니다.

위의 kube-access 역할을 사용하여 Teleport에 인증한 후, Kubernetes 서비스는 임Personaation 헤더를 사용하여 요청을 API 서버에 developers 그룹과 myuser Kubernetes 사용자로 전달합니다.

위임 활성화

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 역할에서 작동하는 방법에 대한 자세한 내용은 Teleport 액세스 제어 참조를 참조하십시오.

싱글 사인온 제공자 특성

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에 인증하면, 사용자의 kube_username 속성이 myuser 값과 함께 있고 groups 속성이 developersviewers 값을 가지고 있는 경우, 위의 group-member 역할은 다음과 같이 평가됩니다:

kind: role
version: v7
metadata:
  name: group-member
spec:
  allow:
    kubernetes_groups: ["developers", "viewers"]
    kubernetes_users: ["myuser"]
    # ...
로컬 사용자 특성

로컬 사용자에 대해 user 리소스의 spec.traits 필드에 임의의 키-값 데이터를 지정한 후, 역할에서 이러한 특성을 참조하기 위해 {{external.*}} 템플릿 변수를 사용할 수 있습니다.

예를 들어, 이 역할은 내부 특성으로 kubernetes_userskubernetes_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

kubernetes_resources

kubernetes_resources 필드는 Teleport 역할이 Kubernetes 클러스터의 특정 리소스에 대한 액세스를 구성할 수 있도록 합니다:

kind: role
metadata:
  name: kube-access
version: v7
spec:
  allow:
    kubernetes_labels:
      '*':'*'
    kubernetes_resources:
      - kind: pod
        namespace: "production"
        name: "webapp"
        verbs: ['*']
    # ...

이 필드의 값은 네 개의 필드를 가진 매핑의 리스트입니다:

  • kind : 액세스를 허용할 리소스의 종류입니다. 현재 Teleport는 다음 종류를 지원합니다:

    KindGrants access to
    *모든 리소스
    pod파드
    secret비밀
    configmap구성 맵
    namespace네임스페이스 및 그 안의 모든 리소스
    service서비스
    serviceaccount서비스 계정
    kube_node노드
    persistentvolume영구 볼륨
    persistentvolumeclaim영구 볼륨 청구
    deployment배포
    replicaset복제 세트
    statefulset상태 설정 세트
    daemonset데몬 세트
    clusterrole클러스터 역할
    kube_role역할
    clusterrolebinding클러스터 역할 바인딩
    rolebinding역할 바인딩
    cronjob크론잡
    job
    certificatesigningrequest인증서 서명 요청
    ingress인그레스
  • namespace : 리소스에 대한 액세스를 허용할 Kubernetes 네임스페이스입니다. kube-access 역할에서는 production 네임스페이스의 파드에 대한 액세스를 허용하고 있습니다.

  • name : 액세스를 허용할 파드의 이름입니다. kube-access 에서 이는 webapp 파드입니다.

  • verbs : 리소스에서 허용할 작업입니다. 현재 Teleport는 다음을 지원합니다:

    VerbGrants access to
    *모든 작업
    get리소스 읽기
    list리소스 나열
    create리소스 생성
    update리소스 업데이트
    patch리소스 패치
    delete리소스 삭제
    deletecollection리소스 모음 삭제
    watch리소스 감시
    portforward파드에 대한 포트포워드 요청 생성
    exec파드에서 명령 실행

namespacename 필드의 경우, 임의의 문자 시퀀스를 대체하기 위해 와일드카드 문자(*)를 추가할 수 있습니다. 예를 들어, name: "pod-*-*"pod-1-apod-2-c 라는 이름의 파드를 일치시킵니다. kubernetes_labels 와 마찬가지로, 값이 ^로 시작하고 $로 끝나면 Kubernetes 서비스는 이를 Go의 re2 구문을 사용하는 정규 표현식으로 처리합니다 (자세한 내용은 re2 README를 참조하십시오).

사용자가 역할의 kubernetes_resources 필드에서 지정된 파드에 액세스하려면, 사용자는 kubernetes_groups 또는 kubernetes_users 중 적어도 하나의 값을 포함하는 Teleport 역할이 할당되어야 합니다. Teleport는 Kubernetes 역할을 변경하여 액세스를 허용하거나 거부하지 않습니다. 클러스터의 파드에 대한 접근을 허용하거나 거부하기 위해 Kubernetes 서비스가 Teleport 역할을 평가하는 방법에 대한 설명은 다음 섹션을 참조하십시오.

Kubernetes 서비스가 Teleport 역할을 평가하는 방법

Teleport 사용자가 Kubernetes 클러스터의 API 서버에 요청을 하면,
Teleport Kubernetes Service는 요청을 가로채고 사용자의 인증을 검사합니다.
사용자가 특정 리소스를 볼 수 있는 권한이 없는 경우, Kubernetes Service는 요청을 거부합니다.
사용자가 요청을 수행할 수 있는 권한이 있는 경우, Kubernetes Service는 요청을 수정하고
적절한 API 서버로 전달합니다.

사용자 요청 승인

Teleport Kubernetes Service가 요청을 받을 때, 사용자의 역할 내 두 개 필드를 평가합니다.
이 필드 중 하나라도 사용자가 요청을 수행할 수 있도록 허용하지 않으면,
Kubernetes Service는 사용자에게 오류를 반환합니다:

kubernetes_labels

Teleport Kubernetes Service는 사용자가 접근할 수 있는 포드가
포드가 실행 중인 클러스터에 사용자의 kubernetes_labels 구성과 일치하는 레이블이 있는 경우에만 허용합니다.

kubernetes_resources

Kubernetes API 서버 내 일부 리소스 URI에는 특정 리소스의 이름이 포함됩니다.

예를 들어 사용자가 development 네임스페이스의 webapp 포드에서
명령을 실행하기 위해 kubectl exec 를 실행하면, kubectl 은 다음 경로에서
대상 클러스터의 API 서버에 요청을 보냅니다:

"/api/v1/namespaces/development/pods/webapp/exec"

Kubernetes API 서버에 대한 요청의 URL 경로에 Kubernetes 포드가 있는 경우,
Teleport Kubernetes Service는 사용자가 해당 포드에 접근할 수 있는 권한이 있는지 확인합니다.

위 예제에서 Kubernetes Service는 사용자가 development 네임스페이스의
webapp 포드에 접근할 수 있는 권한이 있는지 확인하고, 그렇지 않은 경우
요청을 거부합니다.

사용자 요청 전달

Teleport Kubernetes Service가 사용자가 Kubernetes 클러스터에 대한 요청을 수행할 수 있도록 승인하고
(해당되는 경우) 특정 리소스에 대한 요청을 승인하면, 상위 API 서버에 요청을 구성합니다.
사용자의 역할 내 kubernetes_groupskubernetes_users 필드를 기반으로
인격화 헤더를 요청에 추가합니다 (이 필드에 대한 논의를 참조).

Teleport Kubernetes Service는 사용자 kubernetes_groups
kubernetes_users 필드에 나열된 RBAC 주체를 통해 상위 API 서버에 접근하므로,
이 필드에 지정한 주체는 사용자의 kubernetes_resources 필드에 나열된 리소스에
접근할 수 있어야 합니다. 그렇지 않으면, Kubernetes Service는 잘못된 인증으로
상위 API 서버에 요청을 전달하고, API 서버는 요청을 거부합니다.

여러 역할

Kubernetes Service가 여러 역할을 평가하는 방법

사용자의 Kubernetes API 서버에 대한 요청을 평가하기 전에,
Teleport Kubernetes Service는 사용자의 각 역할을 확인합니다.
어느 역할의 spec.allow.kubernetes_labels 또는 spec.allow.kubernetes_resources 조건이
사용자의 요청과 일치하지 않으면, Kubernetes Service는 다음 역할을 확인하고 계속 진행합니다.

Kubernetes Service가 클러스터의 모든 레이블과 요청의 리소스에
일치하는 spec.allow 조건이 있는 역할을 찾으면,
해당 역할의 allow.kubernetes_groupsallow.kubernetes_users 필드를 조회합니다.
이 값을 인격화 헤더를 작성하는 데 사용할 RBAC 주체 목록에 추가합니다.

다음으로, Kubernetes Service는 사용자의 각 역할에서 spec.deny 조건을 확인합니다.
어느 역할의 spec.deny.kubernetes_labels 또는 spec.deny.kubernetes_resources 필드가
사용자의 요청과 일치하면, Kubernetes Service는 해당 역할의
spec.deny.kubernetes_groupsspec.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:
      - executors

dev-viewers Kubernetes 그룹은 사용자가 development 네임스페이스의 포드를 볼 수 있도록 허용합니다. executors Kubernetes 그룹은 사용자가 모든 네임스페이스의 모든 포드에서 명령을 실행할 수 있도록 허용합니다.

해당 역할을 가진 사용자가 development 네임스페이스에서 kubectl get pods/redis-1 을 실행하면, 클러스터에 region:us-east-2 레이블이 있을 경우 Kubernetes 서비스는 요청을 수락합니다. deny-redis-exec 역할이 redis-* 포드에 대해 executors 그룹을 거부하므로 Kubernetes 서비스는 executors 그룹이 아니라 dev-viewers 그룹으로 가장하여 요청을 전달합니다.

그러나 같은 사용자가 development 네임스페이스에서 동일한 클러스터에 대해 kubectl exec -it nginx /bin/bash 를 실행하면, 요청은 dev-viewersexecutors 그룹용 가장자리를 포함하여 전달됩니다. 이는 deny-redis-exec 역할의 deny 조건이 요청과 일치하지 않기 때문입니다.

리소스에 대한 점진적인 접근 허용

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 역할은 사용자를 Kubernetes viewer 그룹에 매핑하여, 사용자가 포드를 얻고 나열할 수 있지만 명령을 실행하거나 로그를 가져올 수 없습니다. nginx-exec 역할을 사용하면 사용자는 execAndLogs 그룹에 접근할 수 있으며, 이 그룹은 nginx 포드에서만 명령을 실행하고 로그를 가져올 수 있습니다.

이 설정에서는 요구 사항에 따라 포드의 하위 집합에 대한 높은 접근 권한을 부여하는 다른 역할과 함께 kube-viewer 역할을 결합할 수도 있습니다.

보안 고려 사항: 리소스 네임스페이스 제한

Teleport 사용자가 kubectl get pods 와 같은 요청을 보내면, Teleport Kubernetes 서비스는 다음을 수행합니다:

  • 사용자의 Teleport 역할에 기반하여 요청에 임시 헤더를 추가하면서 상위 Kubernetes API 서버에서 사용 가능한 팟을 가져옵니다. 여기에는 사용자가 요청하는 Kubernetes 사용자 및 그룹이 포함됩니다.
  • 사용자가 kubernetes_resources 를 통해 접근할 수 있는 팟을 기반으로 사용 가능한 팟 목록을 필터링합니다.
  • 사용자가 요청한 팟 목록을 반환합니다.

리소스가 의도치 않게 유출되지 않도록 하려면, Kubernetes RBAC에서 설정한 네임스페이스 제한이 Teleport에서 설정한 것과 일치하는지 확인해야 합니다.

예를 들어, 사용자가 모든 네임스페이스의 모든 팟에 대한 접근 권한을 부여하는 Teleport 역할을 가지고 있고, 해당 사용자를 default-pod-viewer Kubernetes 그룹에 매핑한다고 가정해봅시다. 이 그룹은 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:masters Kubernetes 그룹에 매핑합니다 (이 그룹은 모든 네임스페이스의 모든 팟에 접근할 수 있습니다), 그리고 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: "*"
    # ...
Teleport 원문 보기