Infograb logo
외부 RBAC 시스템에서 Teleport 역할 생성

Teleport gRPC API를 사용하여 GitHub 또는 AWS Identity and Access Management와 같은 외부 역할 기반 액세스 제어(RBAC) 시스템을 기반으로 역할을 자동으로 생성할 수 있습니다.

이는 특히 다음과 같은 경우에 유용합니다:

  • 새로운 Teleport 클러스터를 설정할 때, 기존의 권한 수준이나 범주를 유지하면서 Teleport가 액세스 제어를 처리하도록 할 수 있습니다.
  • 관리하는 인프라의 RBAC 시스템과 함께 Teleport 클러스터가 최신 상태를 유지하도록 보장합니다. 이렇게 하면 팀이 외부 RBAC 시스템을 재구성할 경우 Teleport 역할이 예상치 않게 권한을 얻거나 잃지 않습니다.

이 가이드에서는 Teleport의 API 클라이언트 라이브러리를 사용하여 Teleport 역할을 생성하는 방법을 보여주는 작은 데모 애플리케이션을 만들 것입니다.

이 가이드에서 우리는 학습 도구로 사용할 프로그램을 구축할 것입니다. 프로덕션 Teleport 클러스터에 연결하지 마십시오. 대신 데모 클러스터를 사용하십시오.

필수 조건

  • 실행 중인 Teleport 클러스터 버전 17.0.0-dev 이상. Teleport를 시작하려면 가입하여 무료 평가판을 이용하거나 데모 환경 설정 방법을 확인하십시오.

  • tctl 관리자 도구와 tsh 클라이언트 도구.

    tctltsh 다운로드 방법에 대한 지침은 설치를 방문하십시오.

  • 워크스테이션에 설치된 Go 버전 1.22 이상. Go 다운로드 페이지를 참조하십시오. 이 가이드를 완수하는 데 Go에 익숙할 필요는 없지만 프로덕션 준비가 완료된 Teleport 클라이언트 애플리케이션을 구축하려면 Go 지식이 필요합니다.

프로덕션 시나리오에서는 이미 Teleport 역할 생성을 위한 기반으로 사용할 타사 RBAC 솔루션이 있어야 합니다. 이 가이드에서는 minikube 를 사용하여 로컬 Kubernetes 클러스터를 배포하고 일부 RBAC 리소스를 설정하여 이를 시뮬레이션할 것입니다. 그런 다음 이 Kubernetes 클러스터를 사용하여 Teleport 역할을 생성합니다.

로컬 데모 환경을 실행하려면 워크스테이션에 다음 도구가 설치되어 있는지 확인하십시오:

도구목적설치 링크
minikube로컬 Kubernetes 배포 도구minikube 설치
HelmKubernetes 패키지 관리자Helm 설치
kubectlKubernetes 관리 CLIkubectl 설치
Docker필요한 minikube 드라이버Docker 시작하기
Tip

데모 프로젝트를 설정할 계획이 없다 하더라도, 이 가이드를 따라 외부 RBAC 시스템을 기반으로 Teleport 역할을 자동으로 생성하는 데 사용할 수 있는 라이브러리, 유형 및 기능을 확인할 수 있습니다.

  • 연결이 가능한지 확인하기 위해 tsh login 으로 로그인한 다음, 현재 자격 증명을 사용하여 tctl 명령어를 실행할 수 있는지 확인하십시오. 예를 들어:
    tsh login --proxy=teleport.example.com --user=email@example.com
    tctl status

    클러스터 teleport.example.com

    버전 17.0.0-dev

    CA 핀 sha256:abdc1245efgh5678abdc1245efgh5678abdc1245efgh5678abdc1245efgh5678

    클러스터에 연결할 수 있고 tctl status 명령어를 실행할 수 있다면, 현재 자격 증명을 사용하여 워크스테이션에서 후속 tctl 명령어를 실행할 수 있습니다.
    자신의 Teleport 클러스터를 호스팅하는 경우, Teleport Auth Service를 호스팅하는 컴퓨터에서 전체 권한으로 tctl 명령어를 실행할 수도 있습니다.

1/4단계. Kubernetes 클러스터 설정

이 단계에서는 로컬 Kubernetes 클러스터를 시작하고 클러스터 내에서 역할 기반 액세스 제어를 설정합니다. 그런 다음 이 Kubernetes 클러스터를 Teleport 역할 생성을 위한 기반으로 사용할 것입니다.

minikube 시작하기

Docker 드라이버로 minikube를 시작하여 단일 Docker 컨테이너에서 로컬 Kubernetes 클러스터를 부팅합니다:

minikube start --driver=docker

이 명령은 로컬 Kubernetes 클러스터를 시작하고 현재 상호작용 중인 Kubernetes 클러스터의 컨텍스트(즉, 현재 상호작용하고 있는 Kubernetes 클러스터)를 minikube 로 설정해야 합니다. 이를 확인하려면 다음 명령을 실행하십시오:

kubectl config current-context
minikube

데모 Kubernetes RBAC 리소스 정의

다음으로, Teleport 역할을 생성하는 기초로 사용할 수 있도록 로컬 minikube 클러스터에서 RBAC 리소스를 설정합니다.

Kubernetes에서는 클러스터를 논리적으로 격리된 네임스페이스로 나눌 수 있습니다. 역할은 특정 네임스페이스에서 리소스를 조작하기 위한 권한 집합을 정의합니다. 클러스터 역할은 클러스터의 모든 네임스페이스에 적용되는 역할입니다. 역할 바인딩 또는 클러스터 역할 바인딩을 사용하여 Kubernetes 사용자 및 그룹에 역할 또는 클러스터 역할을 연결할 수 있습니다.

app-developer 그룹의 사용자가 app 네임스페이스에서 포드를 읽고 나열할 수 있는 Kubernetes 역할 및 역할 바인딩을 정의합니다. 아래 내용을 pod-reader.yaml 이라는 파일에 추가하세요:

apiVersion: v1
kind: Namespace
metadata:
  name: app
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: app
  name: pod-reader
rules:
  - apiGroups: [""]
    resources: ["pods"]
    verbs: ["get", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: read-pods
  namespace: app
  annotations:
    "create-teleport-role": "true"
subjects:
  - kind: Group
    name: app-developer
    apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: pod-reader
  apiGroup: rbac.authorization.k8s.io

리소스를 생성합니다:

kubectl apply -f pod-reader.yaml
namespace/app createdrole.rbac.authorization.k8s.io/pod-reader createdrolebinding.rbac.authorization.k8s.io/read-pods created

다음으로, ops 그룹의 사용자가 모든 네임스페이스에서 포드를 읽고 생성하며 명령을 실행할 수 있는 클러스터 역할 및 클러스터 역할 바인딩을 정의합니다. 아래 내용을 pod-ops.yaml 이라는 파일에 추가하세요:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: pod-ops
rules:
  - apiGroups: [""]
    resources: ["pods"]
    verbs: ["get", "watch", "list", "create", "exec", "logs"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: pod-ops
  annotations:
    "create-teleport-role": "true"
subjects:
  - kind: Group
    name: ops
    apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: pod-ops
  apiGroup: rbac.authorization.k8s.io

리소스를 생성합니다:

kubectl apply -f pod-ops.yaml
clusterrole.rbac.authorization.k8s.io/pod-ops createdclusterrolebinding.rbac.authorization.k8s.io/pod-ops created

이 가이드의 후반부에서는 작성한 Kubernetes RBAC 리소스를 기반으로 Teleport 역할을 자동으로 생성하는 방법을 보여드리겠습니다.

클라이언트 애플리케이션을 위한 RBAC 리소스 정의

다음으로, API 클라이언트가 생성한 RBAC 리소스를 읽을 수 있도록 합니다. 아래 내용을 rbac-sync.yaml 이라는 파일에 추가하세요:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: rbac-sync
rules:
  - apiGroups: ["rbac.authorization.k8s.io"]
    resources: ["roles", "clusterroles", "rolebindings", "clusterrolebindings"]
    verbs: ["get", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: rbac-sync
subjects:
  - kind: User
    name: sync-kubernetes-rbac
    apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: rbac-sync
  apiGroup: rbac.authorization.k8s.io

변경 사항을 적용합니다:

kubectl apply -f rbac-sync.yaml
clusterrole.rbac.authorization.k8s.io/rbac-sync createdclusterrolebinding.rbac.authorization.k8s.io/rbac-sync created

2/4단계. Teleport 설정

이 단계에서는 API 클라이언트 애플리케이션이 Kubernetes 클러스터와 상호작용할 수 있도록 Teleport를 구성합니다.

클라이언트 애플리케이션을 위한 사용자 및 역할 생성

클라이언트 애플리케이션에 Teleport 사용자 및 역할을 부여하여 Teleport에 등록된 Kubernetes 클러스터에 대한 정보를 검색하고, 클러스터에 인증하며, Teleport 역할을 생성하거나 업데이트할 수 있도록 합니다.

다음 내용을 포함하는 sync-kubernetes-rbac.yaml 라는 파일을 만듭니다:

kind: role
version: v7
metadata:
  name: sync-kubernetes-rbac
spec:
  allow:
    kubernetes_labels:
      "*": "*"
    kubernetes_users:
      - sync-kubernetes-rbac
    kubernetes_resources:
      - kind: pod
        name: "*"
        namespace: "*"
    rules:
      - resources: ["kubernetes_cluster"]
        verbs: ["read"]
      - resources: ["role"]
        verbs: ["create", "update"]
---
kind: user
metadata:
  name: sync-kubernetes-rbac
spec:
  roles: ["sync-kubernetes-rbac"]
version: v2

사용자와 역할을 생성합니다:

tctl create -f sync-kubernetes-rbac.yaml
role 'sync-kubernetes-rbac' 가 생성되었습니다user "sync-kubernetes-rbac" 가 생성되었습니다

클라이언트 애플리케이션의 위임 활성화

모든 Teleport 사용자와 마찬가지로, Teleport Auth 서비스는 sync-kubernetes-rbac 사용자를 단기 TLS 자격 증명을 발행하여 인증합니다. 이 경우, sync-kubernetes-rbac 역할과 사용자를 위임하여 자격 증명을 수동으로 요청합니다.

셀프 호스팅된 Teleport Enterprise 배포에서 Auth Service 호스트의 tctl 을 사용 중이라면, 이미 위임 권한이 있습니다.

sync-kubernetes-rbac 에 대한 위임 권한을 사용자에게 부여하려면, sync-kubernetes-rbac-impersonator 라는 역할을 정의하고 다음 YAML 문서를 sync-kubernetes-rbac-impersonator.yaml 라는 파일에 붙여넣습니다:

kind: role
version: v5
metadata:
  name: sync-kubernetes-rbac-impersonator
spec:
  allow:
    impersonate:
      roles:
        - sync-kubernetes-rbac
      users:
        - sync-kubernetes-rbac

sync-kubernetes-rbac-impersonator 역할을 생성합니다:

tctl create -f sync-kubernetes-rbac-impersonator.yaml

sync-kubernetes-rbac-impersonator 역할을 Teleport 사용자에게 할당하려면, 인증 제공자에 맞는 적절한 명령어를 실행하십시오:

  1. 로컬 사용자의 역할을 쉼표로 구분된 목록으로 가져옵니다:

    ROLES=$(tsh status -f json | jq -r '.active.roles | join(",")')
  2. 새로운 역할을 추가하기 위해 로컬 사용자를 수정합니다:

    tctl users update $(tsh status -f json | jq -r '.active.username') \ --set-roles "${ROLES?},sync-kubernetes-rbac-impersonator"
  3. Teleport 클러스터에서 로그아웃한 후 다시 로그인하여 새로운 역할을 가집니다.

  1. 텍스트 편집기에서 github 인증 커넥터를 엽니다:

    tctl edit github/github
  2. github 커넥터를 수정하여 teams_to_roles 섹션에 sync-kubernetes-rbac-impersonator 을 추가합니다.

    이 역할에 매핑해야 하는 팀은 조직의 역할 기반 액세스 제어(RBAC) 설계에 따라 다릅니다. 그러나 팀은 귀하의 사용자 계정을 포함해야 하며, 조직 내에서 가장 작은 팀이어야 합니다.

    예시는 다음과 같습니다:

      teams_to_roles:
        - organization: octocats
          team: admins
          roles:
            - access
    +       - sync-kubernetes-rbac-impersonator
    
  3. 파일을 편집하고 저장하여 변경 사항을 적용합니다.

  4. Teleport 클러스터에서 로그아웃한 후 다시 로그인하여 새로운 역할을 가집니다.

  1. saml 구성 리소스를 가져옵니다:

    tctl get --with-secrets saml/mysaml > saml.yaml

    --with-secrets 플래그는 spec.signing_key_pair.private_key 의 값을 saml.yaml 파일에 추가합니다. 이 키는 민감한 값을 포함하므로, 리소스를 업데이트한 후 즉시 saml.yaml 파일을 삭제해야 합니다.

  2. saml.yaml 을 수정하여 attributes_to_roles 섹션에 sync-kubernetes-rbac-impersonator 을 추가합니다.

    이 역할에 매핑해야 하는 속성은 조직의 역할 기반 액세스 제어(RBAC) 설계에 따라 다릅니다. 그러나 그룹은 귀하의 사용자 계정을 포함해야 하며, 조직 내에서 가장 작은 그룹이어야 합니다.

    예시는 다음과 같습니다:

      attributes_to_roles:
        - name: "groups"
          value: "my-group"
          roles:
            - access
    +       - sync-kubernetes-rbac-impersonator
    
  3. 변경 사항을 적용합니다:

    tctl create -f saml.yaml
  4. Teleport 클러스터에서 로그아웃한 후 다시 로그인하여 새로운 역할을 가집니다.

  1. oidc 구성 리소스를 가져옵니다:

    tctl get oidc/myoidc --with-secrets > oidc.yaml

    --with-secrets 플래그는 spec.signing_key_pair.private_key 의 값을 oidc.yaml 파일에 추가합니다. 이 키는 민감한 값을 포함하므로, 리소스를 업데이트한 후 즉시 oidc.yaml 파일을 삭제해야 합니다.

  2. oidc.yaml 을 수정하여 claims_to_roles 섹션에 sync-kubernetes-rbac-impersonator 을 추가합니다.

    이 역할에 매핑해야 하는 클레임은 조직의 역할 기반 액세스 제어(RBAC) 설계에 따라 다릅니다. 그러나 그룹은 귀하의 사용자 계정을 포함해야 하며, 조직 내에서 가장 작은 그룹이어야 합니다.

    예시는 다음과 같습니다:

      claims_to_roles:
        - name: "groups"
          value: "my-group"
          roles:
            - access
    +       - sync-kubernetes-rbac-impersonator
    
  3. 변경 사항을 적용합니다:

    tctl create -f oidc.yaml
  4. Teleport 클러스터에서 로그아웃한 후 다시 로그인하여 새로운 역할을 가집니다.

이제 sync-kubernetes-rbac 역할과 사용자를 위한 서명된 인증서를 생성할 수 있습니다.

Teleport Kubernetes 서비스 설치

클라이언트 애플리케이션이 Teleport Kubernetes 서비스를 통해 Kubernetes 클러스터와 통신할 수 있도록 하며, 이 서비스는 요청을 승인한 후 전달합니다. 이 단계는 로컬 minikube 클러스터와는 엄밀히 필요하지 않지만, 외부 RBAC 시스템의 API에 안전하게 접근하기 위해 Teleport를 사용하는 한 가지 방법을 보여줍니다.

Teleport Helm 저장소를 설정합니다.

Helm이 Teleport Helm 저장소에서 호스팅되는 차트를 설치할 수 있도록 허용합니다:

helm repo add teleport https://charts.releases.teleport.dev

원격 저장소의 차트 캐시를 업데이트하여 모든 사용 가능한 릴리스로 업그레이드할 수 있습니다:

helm repo update

Kubernetes 서비스가 Teleport 클러스터에 조인하는 데 사용할 토큰을 요청합니다:

tctl tokens add --type=kube,app,discovery --ttl=10000h --format=json

토큰을 복사하여 Teleport Kubernetes 서비스를 실행할 때 사용할 수 있도록 합니다.

올바른 Kubernetes 클러스터에 연결되어 있는지 확인합니다 (이전의 Teleport 로그인으로 Kubernetes 컨텍스트가 변경됩니다):

kubectl config use-context minikube
Switched to context "minikube".

Teleport Kubernetes 서비스를 클러스터에 설치하며, proxy-address를 Teleport Proxy Service의 호스트와 포트 (예: mytenant.teleport.sh:443 )로, token을 이전에 요청한 토큰으로 설정합니다:

helm install teleport-agent teleport/teleport-kube-agent \ --set kubeClusterName=minikube \ --set roles="kube\,app\,discovery" \ --set proxyAddr=proxy-address \ --set authToken=token \ --create-namespace \ --namespace=teleport-agent \ --set labels.environment=demo \ --version 17.0.0-dev

몇 초 후, 다음 명령을 실행하여 Teleport Kubernetes 서비스가 배포되었는지 확인합니다:

kubectl -n teleport-agent get pods

이 명령은 Kubernetes 서비스가 실행 중임을 보여야 합니다:

NAME               READY   STATUS    RESTARTS   AGE
teleport-agent-0   1/1     Running   0          22s

tsh 는 클러스터가 Teleport에 등록되었음을 나타내야 합니다:

tsh kube ls
Kube Cluster Name Labels Selected----------------- ---------------- --------minikube environment=demo

3/4 단계. 클라이언트 애플리케이션 작성

이 시점에서 우리는 Teleport 역할을 생성하기 위해 사용할 외부 RBAC 시스템을 설정했으며, API 클라이언트가 Kubernetes 클러스터 및 Teleport 클러스터와 상호 작용할 수 있도록 Teleport를 구성했습니다. 이 단계에서는 클라이언트 애플리케이션을 작성합니다.

Go 프로젝트 설정

API 클라이언트 애플리케이션의 소스 코드를 다운로드합니다:

git clone --depth=1 https://github.com/gravitational/teleport -b branch/v17
cd teleport/examples/api-sync-roles

이 가이드의 나머지 부분에서는 클라이언트 애플리케이션을 설정하는 방법과 Teleport의 API를 사용하여 Teleport 역할을 자동으로 생성하는 방법을 보여줍니다.

클라이언트 애플리케이션을 위한 신원 파일 내보내기

sync-kubernetes-rbac 사용자는 Teleport 클러스터와 Kubernetes 클러스터에 연결하기 위해 서명된 자격 증명이 필요합니다. API 클라이언트를 위해 이러한 자격 증명을 요청하기 위해 tctl auth sign 명령을 사용합니다.

Teleport 클러스터에 연결하기

다음 tctl auth sign 명령은 sync-kubernetes-rbac 사용자로 가장하여 서명된 자격 증명을 생성하고 신원 파일을 로컬 디렉토리에 작성합니다:

tctl auth sign --user=sync-kubernetes-rbac --out=auth.pem

신원 파일인 auth.pem 에는 TLS 및 SSH 자격 증명이 모두 포함됩니다. 클라이언트 애플리케이션은 SSH 자격 증명을 사용하여 Proxy Service에 연결하고, 이 연결은 Auth Service에 대한 역 터널 연결을 설정합니다. 클라이언트 애플리케이션은 이 역 터널과 TLS 자격 증명을 사용하여 Auth Service의 gRPC 엔드포인트에 연결합니다.

Kubernetes 클러스터에 연결하기

클라이언트 애플리케이션이 Kubernetes 클러스터에 인증할 수 있는 방법도 제공해야 합니다. 이를 위해 Teleport의 인증 기관을 사용하여 sync-kubernetes-rbac 사용자를 위한 자격 증명을 서명합니다. API 클라이언트는 이 자격 증명을 제시하여 Teleport Kubernetes Service에 인증하고, 이를 통해 Kubernetes 클러스터에 대한 요청을 프록시합니다.

다음 명령을 실행하며, proxy-address에 Proxy Service의 호스트와 포트를 포함해야 합니다:

tctl auth sign --user=sync-kubernetes-rbac \ --kube-cluster-name=minikube \ --format=kubernetes \ --proxy=https://proxy-address \ --out=kubeconfig

임포트

api-sync-roles 디렉토리에서 이 가이드에서 시연하는 API 클라이언트 프로그램이 포함된 main.go 파일을 엽니다.

다음은 클라이언트 애플리케이션이 Go의 표준 라이브러리에서 가져오는 패키지입니다:

패키지설명
contextcontext.Context 타입을 포함합니다. context.Context 는 실패하거나 시간 초과될 수 있는 외부 서비스에 대한 연결과 같은 장기 실행 루틴을 제어하기 위한 추상화입니다. 프로그램은 컨텍스트를 취소하거나 타임아웃 및 메타데이터를 할당할 수 있습니다.
fmt데이터를 출력, 문자열 또는 오류 형식 지정.
io파일이나 네트워크 소켓을 읽는 등의 I/O 작업 처리.
os파일을 열기 위한 운영 체제와 상호 작용.
time시간을 다룰 때 사용합니다. 우리는 Auth Service에 연결하기 위해 타임아웃을 정의하고, 발견 논리를 루프에서 실행하기 위한 틱커를 정의하는 데 이 기능을 사용할 것입니다.

클라이언트는 다음과 같은 서드파티 코드를 가져옵니다:

패키지설명
github.com/gravitational/teleport/api/clientAuth Service의 gRPC API에 인증하고 요청을 만들기 위한 라이브러리, teleport 로 별칭 처리됨.
github.com/gravitational/teleport/api/typesAuth Service API에서 사용되는 타입, 예: 애플리케이션 서비스 레코드.
github.com/gravitational/trace표준 라이브러리에서 제공하는 것보다 더 유용한 세부 정보로 오류를 제시.
google.golang.org/grpcgRPC 클라이언트 및 서버 라이브러리.
k8s.io/api/rbac/v1Kubernetes RBAC API 클라이언트 라이브러리.
k8s.io/apimachinery/pkg/apis/meta/v1Kubernetes API 클라이언트 라이브러리에 일반적으로 사용되는 코드.
k8s.io/client-go/kubernetes일반 목적의 Kubernetes 클라이언트 설정.
k8s.io/client-go/kubernetes/typed/rbac/v1Kubernetes RBAC API를 위한 타입.
k8s.io/client-go/tools/clientcmd또 다른 일반 목적의 Kubernetes 클라이언트 라이브러리.

상수

프로그램은 나중에 외부에서 구성하기 쉽게 보이는 위치에 상수를 정의합니다:

const (
	proxyAddr         string = ""
	initTimeout              = time.Duration(30) * time.Second
	identityFilePath  string = "auth.pem"
	kubeconfigPath    string = "kubeconfig"
	clusterName       string = "minikube"
	roleAnnotationKey string = "create-teleport-role"
)

우리는 나중에 프로그램에서 이러한 상수를 사용할 것입니다. 이들은 나중에 변경할 수 있는 몇 가지 값을 정의합니다:

상수설명
proxyAddrTeleport Proxy Service의 호스트 및 포트, 예: mytenant.teleport.sh:443 , 이는 클라이언트를 클러스터에 연결하는 데 사용됩니다. 자신의 Proxy Service의 호스트와 포트에 할당하십시오: proxy-address
initTimeoutTeleport 클러스터에 연결하는 타임아웃. 우리는 이것을 30초로 정의했습니다.
identityFilePath이전에 생성한 Teleport 신원 파일의 경로입니다.
clusterNameRBAC 리소스를 가져올 Kubernetes 클러스터의 이름입니다. 이 가이드에서 클러스터 이름은 minikube 입니다.
roleAnnotationKeyKubernetes에서 주석은 리소스에 추가할 수 있는 임의의 키/값 쌍입니다. 우리가 이전에 생성한 역할 및 클러스터 역할 바인딩에는 여기에 지정한 주석 키가 포함되어 있어, 클라이언트 애플리케이션이 이들을 가져올 수 있습니다.

Kubernetes RBAC 클라이언트 초기화

Kubernetes API에 연락하기 위해 HTTP 클라이언트를 설정해야 합니다. 클라이언트는 상호 TLS를 사용하여 API에 인증하며, kubeconfigPath 의 파일에서 클라이언트 인증서, 인증 기관 및 개인 키를 로드합니다. 이전 가이드에서 이를 Teleport Auth Service에 요청했습니다.

프로그램은 getRBACClient 함수로 Kubernetes API 클라이언트를 설정합니다:

func getRBACClient() (v1.RbacV1Interface, error) {
	f, err := os.Open(kubeconfigPath)
	if err != nil {
		return nil, trace.Wrap(err)
	}

	kc, err := io.ReadAll(f)
	if err != nil {
		return nil, trace.Wrap(err)
	}
	n, err := clientcmd.RESTConfigFromKubeConfig(kc)
	if err != nil {
		return nil, trace.Wrap(err)
	}

	c, err := kubernetes.NewForConfig(n)
	if err != nil {
		return nil, trace.Wrap(err)
	}

	return c.RbacV1(), nil
}

getRBACClientkubeconfigPath 의 Kubernetes 자격 증명 파일을 열고 읽은 다음, 이 파일을 사용하여 Kubernetes API 클라이언트 구성을 설정합니다(clientcmd.RESTConfigFromKubeConfig(kc)) 그리고 이를 통해 HTTP 클라이언트(kubernetes.NewForConfig(n))를 생성합니다.

마지막으로, 이 함수는 역할 기반 액세스 제어 전용 Kubernetes API에 대한 인터페이스를 반환하며, 프로그램의 나머지 부분에서 Kubernetes 클러스터와 상호작용하는 데 사용됩니다.

Kubernetes 클러스터 역할 바인딩에서 Teleport 역할 만들기

createTeleportRoleFromClusterRoleBinding 함수는 Kubernetes 클러스터 역할 바인딩에서 Teleport 역할을 생성합니다. 이는 후자를 기반으로 한 필드를 채워서 이루어집니다:

func createTeleportRoleFromClusterRoleBinding(teleport *client.Client, k types.KubeCluster, r rbacv1.ClusterRoleBinding) error {
	if e, ok := r.Annotations[roleAnnotationKey]; !ok || e != "true" {
		return nil
	}

	role := types.RoleV6{}
	role.SetMetadata(types.Metadata{
		Name: k.GetName() + "-" + r.RoleRef.Name + "-" + "cluster",
	})

	b := k.GetStaticLabels()
	labels := make(types.Labels)
	for k, v := range b {
		labels[k] = []string{v}
	}
	role.SetKubernetesLabels(types.Allow, labels)
	role.SetKubeResources(types.Allow, []types.KubernetesResource{
		types.KubernetesResource{
			Kind:      "pod",
			Namespace: "*",
			Name:      "*",
		},
	})

	var g []string
	var u []string
	for _, s := range r.Subjects {
		if s.Kind == "User" || s.Kind == "ServiceAccount" {
			u = append(u, s.Name)
			continue
		}
		if s.Kind == "Group" {
			g = append(g, s.Name)
			continue
		}
	}
	role.SetKubeGroups(types.Allow, g)
	role.SetKubeUsers(types.Allow, u)
	if err := teleport.UpsertRole(
		context.Background(),
		&role,
	); err != nil {
		return trace.Wrap(err)
	}
	fmt.Println("업서트된 Teleport 역할:", role.GetName())
	return nil
}

예상치 못한 동작을 피하기 위해, 이 함수는 Kubernetes 관리 역할과 Teleport Kubernetes Service와 같은 내부 시스템의 역할을 무시합니다. 이 함수는 클러스터 역할 바인딩의 메타데이터에서 특정 키인 roleAnnotationKey 가 설정된 주석을 체크하며, 이 키가 "true"로 설정되지 않은 리소스는 무시합니다.

또한, 이 프로그램으로 생성한 역할을 식별하기 위한 빠른 방법을 원합니다. 이를 위해, 이 함수는 클러스터 역할 바인딩에 따라 생성하는 모든 역할의 이름을 다음 속성에 따라 설정합니다:

  • Kubernetes 클러스터 이름
  • Kubernetes 역할 이름
  • 접미사 -cluster .

우리의 데모 애플리케이션에서는 이 함수가 minikube-pod-ops-cluster 라는 Teleport 역할을 생성할 것입니다.

함수의 나머지 부분은 클러스터 역할 바인딩에 따라 types.RoleV6 라는 Teleport API 클라이언트의 역할 유형에 필드를 할당합니다:

역할 필드목적할당 방법
allow.kubernetes_labels이 역할을 가진 사용자가 접근할 수 있는 Teleport 등록 Kubernetes 클러스터의 레이블.Kubernetes 클러스터 역할 바인딩에 속하는 Teleport 등록 Kubernetes 클러스터를 기반으로 합니다.
allow.kubernetes_resources이 역할을 가진 사용자가 접근할 수 있는 특정 네임스페이스의 Kubernetes 포드.클러스터 역할 바인딩이 네임스페이스에 의해 제한되지 않기 때문에 모든 네임스페이스에 대한 접근을 허용합니다.
allow.kubernetes_usersallow.kubernetes_groups이 역할을 가진 Teleport 사용자가 Kubernetes 클러스터와 상호작용할 때 가정하는 Kubernetes 그룹 및 사용자.클러스터 역할 바인딩에 연결된 사용자 또는 그룹의 이름을 제공합니다.

Kubernetes 역할 바인딩으로부터 Teleport 역할 생성하기

클러스터 역할 바인딩과 마찬가지로, 이 프로그램은 Kubernetes 역할 바인딩을 기반으로 Teleport 역할을 생성합니다:

func createTeleportRoleFromRoleBinding(teleport *client.Client, k types.KubeCluster, r rbacv1.RoleBinding) error {
	if e, ok := r.Annotations[roleAnnotationKey]; !ok || e != "true" {
		return nil
	}

	role := types.RoleV6{}
	role.SetMetadata(types.Metadata{
		Name: k.GetName() + "-" + r.RoleRef.Name + "-" + r.Namespace,
	})

	b := k.GetStaticLabels()
	labels := make(types.Labels)
	for k, v := range b {
		labels[k] = []string{v}
	}
	role.SetKubernetesLabels(types.Allow, labels)
	role.SetKubeResources(types.Allow, []types.KubernetesResource{
		types.KubernetesResource{
			Kind:      "pod",
			Namespace: r.Namespace,
			Name:      "*",
		},
	})
	var g []string
	var u []string
	for _, s := range r.Subjects {
		if s.Kind == "User" || s.Kind == "ServiceAccount" {
			u = append(u, s.Name)
			continue
		}
		if s.Kind == "Group" {
			g = append(g, s.Name)
			continue
		}
	}
	role.SetKubeGroups(types.Allow, g)
	role.SetKubeUsers(types.Allow, u)

	if err := teleport.UpsertRole(
		context.Background(),
		&role,
	); err != nil {
		return trace.Wrap(err)
	}
	fmt.Println("Upserted Teleport role:", role.GetName())
	return nil
}

이 함수의 전반적인 동작 방식은 createTeleportRoleFromClusterRoleBinding 와 동일하지만, Kubernetes 역할 바인딩에 따라 Teleport 역할에 필드를 할당하는 방법에서 일부 차이가 있습니다:

  • 역할의 이름을 설정할 때, -cluster 대신 역할 바인딩의 네임스페이스를 접미사로 사용하여 이 역할이 적용되는 네임스페이스를 표시합니다.
  • 역할의 kubernetes_resources 필드에서는 역할 바인딩과 동일한 네임스페이스를 사용하여 적용됩니다.

Kubernetes 리소스를 기반으로 Teleport 역할 생성하기

이제 개별 Kubernetes RBAC 리소스를 기반으로 Teleport 역할을 생성하는 함수를 만든 상태이므로, Kubernetes 클러스터에서 모든 RBAC 리소스를 가져오고 이러한 함수를 호출할 수 있습니다:

func createTeleportRolesForKubeCluster(teleport *client.Client, k types.KubeCluster) error {
	rbac, err := getRBACClient()
	if err != nil {
		return trace.Wrap(err)
	}

	crb, err := rbac.ClusterRoleBindings().List(
		context.Background(),
		metav1.ListOptions{},
	)
	if err != nil {
		return trace.Wrap(err)
	}

	for _, i := range crb.Items {
		if err := createTeleportRoleFromClusterRoleBinding(teleport, k, i); err != nil {
			return trace.Wrap(err)
		}
	}

	rb, err := rbac.RoleBindings("").List(
		context.Background(),
		metav1.ListOptions{},
	)
	if err != nil {
		return trace.Wrap(err)
	}

	for _, i := range rb.Items {
		if err := createTeleportRoleFromRoleBinding(teleport, k, i); err != nil {
			return trace.Wrap(err)
		}
	}
	return nil
}

createTeleportRolesForKubeCluster 는 Teleport 클라이언트와 Teleport에 등록된 Kubernetes 클러스터를 인수로 받습니다. 앞서 정의한 getRBACClient 함수를 호출하여 Kubernetes 클러스터용 클라이언트를 설정합니다. 그런 다음:

  • Kubernetes 클러스터 역할 바인딩 목록을 가져오고 각 역할에 대해 Teleport 역할을 생성합니다.
  • Kubernetes 역할 바인딩 목록을 가져오고 각 역할에 대해 Teleport 역할을 생성합니다.

클라이언트 초기화 및 애플리케이션 시작

우리가 이전에 선언한 함수들은 Teleport API 클라이언트와 Teleport에 등록된 Kubernetes 클러스터가 필요하며, 우리는 이러한 것들을 프로그램의 진입점인 main 함수에서 초기화합니다:

func main() {
	ctx, cancel := context.WithTimeout(context.Background(), initTimeout)
	defer cancel()
	creds := client.LoadIdentityFile(identityFilePath)

	teleport, err := client.New(ctx, client.Config{
		Addrs:       []string{proxyAddr},
		Credentials: []client.Credentials{creds},
	})
	if err != nil {
		panic(err)
	}
	fmt.Println("테레포트에 연결되었습니다.")

	ks, err := teleport.GetKubernetesServers(context.Background())
	if err != nil {
		panic(err)
	}
	for _, k := range ks {
		if k.GetCluster().GetName() != clusterName {
			continue
		}
		fmt.Println("Kubernetes 클러스터를 가져옴", clusterName)

		if err := createTeleportRolesForKubeCluster(teleport, k.GetCluster()); err != nil {
			panic(err)
		}
		fmt.Println("Kubernetes 클러스터를 위한 역할 생성 완료", clusterName)
		return
	}
	panic("Kubernetes 서비스 인스턴스를 찾을 수 없습니다: " + clusterName)
}

client 는 API 클라이언트를 설정하기 위한 Teleport의 라이브러리입니다. 우리의 프로그램은 client.LoadIdentityFile 을 호출하여 client.Credentials 를 얻고, 이를 통해 client.New 를 호출하여 Addrs 필드에 명시된 Teleport 프록시 서비스에 연결합니다.

Warning

이 프로그램은 자격 증명이나 Teleport 클러스터 주소를 검증하지 않습니다. 다음 사항을 확인하십시오:

  • 이전에 내보낸 식별 파일이 만료된 TTL이 없음을 확인합니다.
  • teleport.ConfigAddrs 필드에 제공한 값에는 Teleport 프록시 서비스의 호스트 웹 포트가 포함되어야 합니다 (예: mytenant.teleport.sh:443 ).

Teleport 클라이언트를 초기화한 후, main 함수는 Teleport에 등록된 모든 Kubernetes 서버를 가져오고 (teleport.GetKubernetesServers ), 지정한 클러스터와 일치하는 등록된 Kubernetes 클러스터가 있는지 확인합니다.

일치하는 Kubernetes 클러스터가 존재하면, 코드는 우리가 이전에 정의한 createTeleportRolesForKubeClusters 함수를 호출합니다. 그렇지 않으면, 프로그램은 오류 메시지와 스택 트레이스를 출력하며 Go의 내장 panic 함수를 호출합니다.

4/4단계. 클라이언트 애플리케이션 테스트

클라이언트 애플리케이션을 테스트하려면 프로젝트 디렉터리 내에서 실행하십시오:

go run main.go

다음과 같은 출력이 표시되어야 합니다:

테레포트에 연결되었습니다.
Kubernetes 클러스터를 가져옴 minikube
업서트 Teleport 역할: minikube-pod-ops-cluster
업서트 Teleport 역할: minikube-pod-reader-app
Kubernetes 클러스터를 위한 역할 생성 완료 minikube

아래 명령을 실행하여 새로 생성된 minikube-pod-ops-cluster 역할을 검사합니다:

tctl get roles/minikube-pod-ops-cluster

다음과 유사한 출력을 볼 수 있습니다:

kind: role
metadata:
  id: 1678732494974032643
  name: minikube-pod-ops-cluster
spec:
  allow:
    kubernetes_groups:
      - ops
    kubernetes_labels:
      environment: demo
    kubernetes_resources:
      - kind: pod
        name: "*"
        namespace: "*"
  deny: {}
  options:
    cert_format: standard
    create_host_user: false
    desktop_clipboard: true
    desktop_directory_sharing: true
    enhanced_recording:
      - command
      - network
    forward_agent: false
    idp:
      saml:
        enabled: true
    max_session_ttl: 30h0m0s
    pin_source_ip: false
    port_forwarding: true
    record_session:
      default: best_effort
      desktop: true
    ssh_file_copy: true
version: v7

다음 명령을 사용하여 minikube-pod-reader-app 역할과 비교합니다:

tctl get roles/minikube-pod-reader-app

다음은 우리가 생성한 역할입니다:

kind: role
metadata:
  id: 1678732495284493075
  name: minikube-pod-reader-app
spec:
  allow:
    kubernetes_groups:
      - app-developer
    kubernetes_labels:
      environment: demo
    kubernetes_resources:
      - kind: pod
        name: "*"
        namespace: app
  deny: {}
  options:
    cert_format: standard
    create_host_user: false
    desktop_clipboard: true
    desktop_directory_sharing: true
    enhanced_recording:
      - command
      - network
    forward_agent: false
    idp:
      saml:
        enabled: true
    max_session_ttl: 30h0m0s
    pin_source_ip: false
    port_forwarding: true
    record_session:
      default: best_effort
      desktop: true
    ssh_file_copy: true
version: v7

역할 바인딩은 네임스페이스에 속하므로, 이 역할은 해당 역할 바인딩이 적용된 app 네임스페이스의 포드에만 접근할 수 있도록 허용합니다. Kubernetes 서비스는 이 역할을 가진 사용자로부터의 트래픽을 app-developer Kubernetes 그룹을 통해 전달합니다.

다음 단계

우리는 Kubernetes RBAC 시스템을 기반으로 Teleport 역할을 생성하는 Teleport API 클라이언트를 구현했습니다. Teleport의 API를 사용하여 GitHub 팀이나 데이터베이스 관리 시스템 내의 그룹과 같은 다른 RBAC 시스템과 상호 작용하는 유사한 애플리케이션을 구축할 수 있습니다.

클라이언트 애플리케이션을 구축하기 위한 시작점은 다음과 같습니다.

Teleport 역할에 대해 더 알아보기

외부 RBAC 솔루션에서 Teleport 역할을 생성하는 효과적인 클라이언트 애플리케이션을 작성하려면 액세스를 관리하려는 인프라 리소스에 적용되는 역할 필드를 이해해야 합니다.

다양한 인프라 리소스와 관련된 필드에 대한 가이드를 보려면 아래 링크를 참조하세요:

일반적인 안내를 원하시면 액세스 제어 참조 를 읽어보세요.

클라우드 제공업체를 Teleport에 등록하기

Teleport로 클라우드 제공업체 API를 보호하고 API 클라이언트 애플리케이션이 Teleport 애플리케이션 서비스에 연결하도록 지시할 수 있습니다. Teleport로 보호된 클라우드 제공업체 API를 사용하면 클라우드 제공업체의 RBAC 솔루션을 기반으로 Teleport 역할을 생성할 수 있습니다.

클라우드 제공업체 API용 Teleport 애플리케이션 서비스를 설정하는 방법에 대한 가이드는 다음과 같습니다:

예제 참조

Teleport 코드 저장소에는 생산 준비가 완료된 Teleport API 클라이언트의 예제가 포함되어 있습니다. 현재 Teleport 역할을 생성하는 플러그인은 유지 관리되지 않지만, 이러한 예제를 사용하여 구성 파싱, 재시도 및 기타 작업을 구현하는 방법을 확인할 수 있습니다.

단기 자격 증명으로 클라이언트 애플리케이션 프로비저닝하기

이 예제에서는 작성한 프로그램의 자격 증명을 가져오기 위해 tctl auth sign 명령을 사용했습니다. 생산 사용을 위해 우리는 이러한 자격 증명이 도난될 위험을 줄이기 위해 머신 ID를 통해 단기 자격 증명을 프로비저닝하는 것을 권장합니다. 더 자세한 내용은 Machine ID 문서를 참조하세요.

Teleport 원문 보기