Infograb logo
텔레포트 Kubernetes 액세스 제어

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

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

로컬 minikube 클러스터와 함께 Kubernetes에 대한 액세스를 관리하기 위해 텔레포트 역할을 사용하는 방법에 대한 예는 RBAC 사용 방법 가이드를 참조하세요.

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

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

Kubernetes 클러스터에 대한 액세스를 관리하려면 텔레포트 역할은 다음 필드를 spec.allow 섹션에 포함해야 합니다:

Kubernetes 클러스터에 대한 액세스를 제한하는 텔레포트 역할의 예는 다음과 같습니다:

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 클러스터를 텔레포트에 등록할 때 레이블을 추가할 수 있습니다. 사용자의 액세스를 서로 다른 레이블이 있는 Kubernetes 클러스터로 제한할 수 있습니다 kubernetes_labels 필드를 사용하는 역할을 통해.

kind: role
metadata:
  name: kube-access
version: v7
spec:
  allow:
    kubernetes_labels:
      'region': '*'
      'environment': 'development'
      # ...
  deny: {}

kubernetes_labels 필드의 값은 레이블 와 하나 이상의 레이블 간의 매핑입니다(즉, 문자열 또는 목록).

Kubernetes 서비스가 kubernetes_labels를 평가하는 방법

레이블의 키와 값이 모두 와일드카드인 경우 *, 텔레포트 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']
    # ...

레이블 적용

텔레포트 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

텔레포트 인스턴스의 구성 파일에서 텔레포트 Kubernetes 서비스를 활성화할 때 레이블을 설정합니다:

kubernetes_service:
  enabled: true
  kube_cluster_name: cookie
  labels:
    env: prod
    region: us-west-1

kubernetes_groupskubernetes_users

텔레포트 Kubernetes 서비스는 최종 사용자로부터 요청을 받고(예: kubectl를 통해) 이를 Kubernetes API 서버에 전달합니다. Kubernetes 서비스는 임시 사용자 헤더를 사용하여 하나의 Kubernetes 사용자와 0개 이상의 Kubernetes 그룹으로 API 서버에 요청을 보냅니다.

Impersonation

kubernetes_userskubernetes_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_groupskubernetes_users의 값은 사용자가 수신하도록 허용할 그룹, 사용자 또는 서비스 계정의 이름 목록입니다.

Kubernetes 사용자 및 그룹

Kubernetes 사용자 및 그룹은 Kubernetes 클러스터 내에 존재하는 엔터티이며 ClusterRoleBinding 또는 RoleBinding 리소스를 통해 권한이 제어됩니다. 그들이 클러스터에 존재하지 않으면 Kubernetes RBAC는 이를 무시합니다.

다음은 사용자 cluster-viewer-user와 그룹 cluster-viewer-group에 내장된 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 서비스 계정

텔레포트는 서비스 계정의 전체 자격 이름을 사용하여 서비스 계정 임시화를 지원합니다.

서비스 계정의 전체 자격 이름은 다음 패턴으로 구성됩니다:

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: {}

텔레포트 사용자가 Kubernetes 사용자, 그룹 및 서비스 계정을 임시화하는 방법

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

수동으로

사용자가 Kubernetes 클러스터에 대해 인증하기 위해 tsh kube login을 사용할 때 --as--as-groups 플래그를 사용하여 수동으로 인증할 사용자 및 그룹을 지정할 수 있습니다. 텔레포트 Kubernetes 서비스는 사용자가 지정한 사용자 및 그룹이 사용자의 kubernetes_userskubernetes_groups 구성에 해당되는지 확인하고 그렇지 않은 경우 액세스를 거부합니다.

자동으로

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

사용자가 kubernetes_users에 정확히 하나의 값이 있는 경우 텔레포트 Kubernetes 서비스는 해당 사용자를 임시화합니다. kubernetes_users에 값이 없으면 Kubernetes 서비스는 사용자의 텔레포트 사용자 이름을 사용합니다.

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

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

위의 kube-access 역할을 통해 텔레포트에 인증한 후, Kubernetes 서비스는 사용자에게 developers 그룹과 myuser Kubernetes 사용자와 함께 API 서버에 요청을 전달하기 위해 임시화 헤더를 사용합니다.

임시화 활성화

Kubernetes 서비스는 사용자의 요청을 임시화 헤더로 전달할 수 있도록 하려면, 서비스 계정에 클러스터 내에서 Kubernetes RBAC 원칙을 임시화할 수 있는 권한이 필요합니다. Kubernetes 서비스는 사용자가 액세스할 수 없는 사용자 또는 그룹을 임시화 요청은 거부합니다.

아래는 임시화를 활성화하기 위해 필요한 최소 권한 집합을 부여하는 Kubernetes ClusterRole과 이러한 권한을 서비스 계정에 부여하는 ClusterRoleBinding입니다.

일반적으로 이러한 리소스를 수동으로 정의할 필요는 없습니다. 텔레포트에 Kubernetes 클러스터를 등록하기 위한 수동 방법자동 방법에는 텔레포트가 클러스터에 대한 액세스를 허용하는 데 필요한 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

사용자 특성에 따라 그룹 및 사용자 지정

각 텔레포트 사용자별로 Kubernetes 그룹 및 사용자를 지정할 수 있으며, 이러한 정보가 텔레포트 역할에 하드 코딩되지 않도록 할 수 있습니다. 이렇게 하려면 텔레포트 역할에 템플릿 변수를 추가할 수 있으며, 텔레포트 인증 서비스가 각 인증 사용자의 정보로 이를 채웁니다.

템플릿 변수 확장이 텔레포트 역할에서 작동하는 방법에 대한 자세한 내용은 텔레포트 액세스 제어 참조를 참조하십시오.

SSO 공급자 특성

텔레포트의 역할은 템플릿 변수를 사용하여 OIDC 클레임이나 SAML 속성을 매핑합니다. 텔레포트 인증 서비스는 {{external.*}} 형식의 템플릿 변수를 해당하는 SAML 속성 또는 OIDC 클레임으로 대체합니다:

kind: role
version: v7
metadata:
  name: group-member
spec:
  allow:
    kubernetes_groups: ["{{external.groups}}"]
    kubernetes_users: ["{{external.kube_username}}"]
    # ...

예를 들어, 사용자가 SAML 커넥터를 통해 텔레포트에 인증하고, 사용자에게 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}}"]
    # ...

다음은 이러한 템플릿 변수를 채우기 위해 로컬 사용자 생성 또는 수정 시 값을 제공하는 사용자 정의 정의의 예입니다:

kind: user
version: v2
metadata:
  name: alice
spec:
  roles:
    - group-member
  traits:
    groups:
      - developers
      - viewers
    kube_username:
      - myuser

kubernetes_resources

kubernetes_resources 필드는 텔레포트 역할이 Kubernetes 클러스터 내의 특정 리소스에 대한 액세스를 구성할 수 있게 해줍니다:

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

이 필드의 값은 각 매핑이 네 개의 필드를 가진 목록입니다:

  • kind: 액세스를 허용할 리소스의 종류. 현재, 텔레포트는 다음 종류를 지원합니다:

    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: 리소스에 대해 허용할 작업. 현재 텔레포트가 지원하는 작업은 다음과 같습니다:

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

네임스페이스 및 이름 필드 모두에 와일드카드 문자(*)를 추가하여 임의의 문자 시퀀스를 대체할 수 있습니다. 예를 들어, name: "pod-*-*"pod-1-apod-2-c로 명명된 포드와 일치합니다. kubernetes_labels와 마찬가지로 값이 ^로 시작하고 $로 끝나는 경우 Kubernetes 서비스는 이를 Go의 re2 구문을 사용하는 정규 표현식으로 처리합니다(참고로 re2 README).

사용자가 역할의 kubernetes_resources 필드에 명시된 포드에 접근하기 위해서는 사용자가 최소한 kubernetes_groups 또는 kubernetes_users에 하나의 값을 포함하는 텔레포트 역할을 할당받아야 합니다. 텔레포트는 액세스를 허용하거나 거부하도록 Kubernetes 역할을 변경하지 않습니다. 사용자가 클러스터에서 포드에 대한 액세스를 허용하거나 거부하도록 텔레포트 역할을 평가하는 방법에 대한 설명은 다음 섹션을 참조하세요.

Kubernetes 서비스가 텔레포트 역할을 평가하는 방법

텔레포트 사용자가 Kubernetes 클러스터의 API 서버에 요청을 보낼 때, 텔레포트 Kubernetes 서비스는 요청을 가로채고 사용자의 권한을 검사합니다. 사용자가 특정 리소스를 볼 수 있는 권한이 없으면 Kubernetes 서비스는 요청을 거부합니다. 사용자가 요청을 수행할 수 있는 권한이 있는 경우, Kubernetes 서비스는 요청을 수정하고 적절한 API 서버로 전달합니다.

사용자 요청 승인

텔레포트 Kubernetes 서비스는 요청을 수신하면 사용자 역할 내의 두 필드를 평가합니다. 이 필드 중 하나라도 사용자가 요청을 수행하도록 허용하지 않으면 Kubernetes 서비스는 사용자에게 오류를 반환합니다:

kubernetes_labels

텔레포트 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 포드가 있는 경우, 텔레포트 Kubernetes 서비스는 사용자가 해당 포드에 액세스할 수 있는 권한이 있는지 확인합니다.

예를 들어, 위의 예에서 Kubernetes 서비스는 사용자가 development 네임스페이스에 있는 webapp 포드에 접근할 수 있는 권한이 있는지 확인하고, 없으면 요청을 거부합니다.

사용자 요청 전달

텔레포트 Kubernetes 서비스가 사용자가 Kubernetes 클러스터에 대한 요청을 수행할 수 있는지 검사하고 특정 리소스(해당되는 경우)에 대해 권한을 부여하면, 요청을 상위 API 서버로 조립합니다. 사용자 역할의 kubernetes_groupskubernetes_users 필드에 따라 임시화 헤더를 요청에 추가합니다 (이 필드에 대한 논의 참조).

텔레포트 Kubernetes 서비스는 위에서 생성된 임시화 헤더에서 지정된 RBAC 원칙을 사용하여 상위 API 서버에 접근하므로, 이러한 필드에 지정한 원칙은 사용자가 kubernetes_resources 필드의 리소스에 접근해야 합니다. 그렇지 않으면 Kubernetes 서비스는 올바르지 않은 권한으로 상위 API 서버에 대한 요청을 전달하고 API 서버는 요청을 거부합니다.

여러 역할

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

텔레포트 Kubernetes 서비스는 사용자의 요청을 Kubernetes API 서버에 평가하기 전에 사용자의 역할을 확인합니다. 하나의 역할의 spec.allow.kubernetes_labels 또는 spec.allow.kubernetes_resources 조건이 사용자의 요청과 일치하지 않으면 Kubernetes 서비스는 다음 역할을 확인합니다.

Kubernetes 서비스가 클러스터의 레이블 및 요청의 리소스와 모두 일치하는 spec.allow 조건을 가진 역할을 발견하면, 해당 역할의 allow.kubernetes_groupsallow.kubernetes_users 필드를 조회합니다. 이 값을 나중에 임시화 헤더를 작성하는 데 사용할 RBAC 원칙 목록에 추가합니다.

그 다음, Kubernetes 서비스는 사용자의 역할에서 spec.deny 조건을 확인합니다. 하나의 역할의 spec.deny.kubernetes_labels 또는 spec.deny.kubernetes_resources 필드가 사용자의 요청과 일치하는 경우, Kubernetes 서비스는 해당 역할의 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 # 개발 네임스페이스에서 포드를 볼 수 있도록 사용자를 허용합니다.
---
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 그룹은 사용자가 어떤 네임스페이스의 모든 포드에 대해서도 명령을 실행할 수 있도록 허용합니다.

사용자가 kubectl get pods/redis-1development 네임스페이스에서 실행하고 클러스터에 레이블 region:us-east-2가 있다면, Kubernetes 서비스는 요청을 수락합니다. deny-redis-exec 역할이 redis-* 포드에 대해 executors 그룹을 거부하므로, Kubernetes 서비스는 dev-viewers 그룹을 임시화하면서 요청을 전달하지만 executors 그룹은 임시화하지 않습니다.

그러나 동일한 사용자가 development 네임스페이스에서 kubectl exec -it nginx /bin/bash를 실행하면 Kubernetes 서비스는 요청을 dev-viewersexecutors 그룹 모두를 임시화하여 전달합니다. 요청에 대한 deny-redis-exec 역할의 deny 조건이 일치하지 않기 때문입니다.

리소스에 대한 점진적 액세스 활성화

텔레포트 및 Kubernetes RBAC를 설계하여 사용자에게 Kubernetes 리소스의 제한된 하위 집합에 대한 액세스를 점진적으로 허용할 수 있습니다. 즉, 사용자는 Kubernetes 클러스터의 광범위한 리소스에 대한 제한된 액세스가 가능하며, 더 제한된 리소스에 대한 더 높은 액세스를 갖는 여러 사용자 그룹을 생성할 수 있습니다.

이렇게 하려면 여러 텔레포트 역할을 정의하십시오:

  • 일부 역할은 더 많은 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 역할을 다른 역할과 결합하여 사용자의 요구 사항에 따라 포드의 하위 집합에 대한 높은 권한을 부여할 수 있습니다.

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

텔레포트 사용자가 포드 목록을 가져오기 위해 요청을 보낼 때, 예를 들어 kubectl get pods, 텔레포트 Kubernetes 서비스는 다음을 수행합니다:

  • 사용자 텔레포트 역할의 임시화 헤더를 추가하여 상위 Kubernetes API 서버에서 사용 가능한 포드를 검색합니다. 이는 사용자가 보낸 요청의 임시화 헤더에 Kubernetes 사용자 및 그룹이 포함됩니다.
  • 사용자가 kubernetes_resources를 통해 액세스할 수 있는 포드로 목록을 필터링합니다.
  • 사용자가 지정한 포드 목록을 반환합니다.

리소스가 우발적으로 노출되지 않도록 하려면, Kubernetes RBAC에 설정한 네임스페이스 제한이 텔레포트에 설정한 제한과 일치하는지 확인해야 합니다.

예를 들어, 사용자가 모든 네임스페이스의 모든 포드에 대한 액세스를 허용하는 텔레포트 역할을 가지고 있으며 이 사용자가 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: "*"
    # ...

이 사용자에게 두 번째 텔레포트 역할이 있으며, 이 사용자를 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"
    # ...

그 사용자에게 system:masters에 매핑된 역할(kube-access-2)이 있으므로, Kubernetes 서비스는 이 사용자의 요청을 처리하면서 모든 포드 목록을 가져올 수 있습니다. 그러나 사용자가 kube-access-1 역할을 가지고 있다면 모든 네임스페이스의 포드 목록이 노출됩니다.

리소스에 대한 접근이 노출되지 않도록 하려면 Kubernetes에서 자체적으로 지정한 권한과 텔레포트가 특정 사용자에게 지정한 권한 간에 제한을 설정해야 합니다.

Teleport 원문 보기