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

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

이는 특히 유용합니다:

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

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

이번 가이드에서 구축할 프로그램은 학습 도구로 의도된 것입니다. 이를 생산 Teleport 클러스터에 연결하지 마십시오. 대신 데모 클러스터를 사용하십시오.

필수 조건

  • 실행 중인 Teleport 클러스터 버전 이상. Teleport를 시작하려면, 가입하기 위해 무료 평가판에 등록하거나 데모 환경 설정하기를 참조하세요.

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

    tctltsh 다운로드에 대한 지침은 설치를 방문하세요.

  • 작업 공간에 Go 버전 1.22 이상이 설치되어 있어야 합니다. Go 다운로드 페이지를 참조하십시오. 이 가이드를 완료하기 위해 Go에 익숙할 필요는 없지만, 생산 준비가 완료된 Teleport 클라이언트 애플리케이션을 구축하려면 Go 지식이 필요합니다.

생산 시나리오에서는 Teleport 역할을 생성하는 기반으로 사용할 서드파티 RBAC 솔루션이 이미 있을 것입니다. 이번 가이드에서는 로컬 Kubernetes 클러스터를 minikube를 사용하여 배포하고 몇 가지 RBAC 리소스를 설정하여 이를 시뮬레이션할 것입니다. 그런 다음 이 Kubernetes 클러스터를 사용하여 Teleport 역할을 생성합니다.

로컬 데모 환경을 실행하려면 작업 공간에 다음 도구가 설치되어 있는지 확인하십시오:

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

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

  • 당신의 Teleport 클러스터에 연결할 수 있는지 확인하려면, tsh login으로 로그인한 다음 현재 자격 증명을 사용하여 tctl 명령어를 실행할 수 있는지 확인하십시오. 예를 들어:
    tsh login --proxy=teleport.example.com --user=email@example.com
    tctl status

    클러스터 teleport.example.com

    버전 16.2.0

    CA 핀 sha256:abdc1245efgh5678abdc1245efgh5678abdc1245efgh5678abdc1245efgh5678

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

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

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

minikube 시작하기

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

minikube start --driver=docker

이 명령은 로컬 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' has been createduser "sync-kubernetes-rbac" has been created

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

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

자체 호스팅된 Teleport Enterprise 배포를 실행하고 Auth 서비스 호스트에서 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 클러스터에서 로그아웃한 후 새로운 역할을 asum 하기 위해 다시 로그인합니다.

  1. github 인증 커넥터를 가져옵니다:

    tctl get github/github --with-secrets > github.yaml

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

  2. github.yaml을 편집하고 teams_to_roles 섹션에 sync-kubernetes-rbac-impersonator을 추가합니다.

    이 역할에 매핑할 팀은 귀하의 조직에서 어떻게 역할 기반 접근 제어(RBAC)를 설계했느냐에 따라 달라집니다. 하지만 팀에는 귀하의 사용자 계정이 포함되어야 하며, 조직 내에서 가능한 한 작은 팀이어야 합니다.

    여기에 예시가 있습니다:

      teams_to_roles:
        - organization: octocats
          team: admins
          roles:
            - access
    +       - sync-kubernetes-rbac-impersonator
    
  3. 변경 사항을 적용합니다:

    tctl create -f github.yaml
  4. Teleport 클러스터에서 로그아웃한 후 새로운 역할을 assum 하기 위해 다시 로그인합니다.

  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 클러스터에서 로그아웃한 후 새로운 역할을 asum 하기 위해 다시 로그인합니다.

  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 클러스터에서 로그아웃한 후 새로운 역할을 asum 하기 위해 다시 로그인합니다.

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

Teleport Kubernetes 서비스 설치

클라이언트 애플리케이션이 Kubernetes 클러스터와 통신할 수 있도록 Teleport Kubernetes 서비스를 활성화할 것입니다. 이 서비스는 요청을 인증한 후 포워딩하여 클러스터와의 통신을 가능하게 합니다. 이 단계는 로컬 minikube 클러스터에서는 꼭 필요하지 않지만, Teleport를 사용하여 외부 RBAC 시스템의 API에 안전하게 접근하는 방법을 시연합니다.

Teleport Helm 리포지토리를 설정하세요. Teleport Helm 리포지토리에 호스팅된 차트를 설치하도록 Helm을 허용하세요:

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

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

helm repo update

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 서비스의 호스트 및 포트(예: 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 16.2.0

몇 초 후, 다음 명령을 실행하여 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/v16
cd teleport/examples/api-sync-roles

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

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

sync-kubernetes-rbac 사용자는 Teleport 클러스터 및 Kubernetes 클러스터에 연결하기 위해 서명된 자격 증명이 필요합니다. 이러한 자격 증명을 요청하기 위해 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 서비스에 연결하고, 이는 Auth 서비스로의 역 터널 연결을 설정합니다. 클라이언트 애플리케이션은 이 역 터널과 TLS 자격 증명을 사용하여 Auth 서비스의 gRPC 엔드포인트에 연결합니다.

Kubernetes 클러스터에 연결하기

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

다음 명령을 실행하여 proxy-address에 Proxy 서비스의 호스트와 포트를 포함시키십시오:

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

가져오기

api-sync-roles 디렉터리에서 main.go를 열면 이 가이드에서 시연할 API 클라이언트 프로그램이 포함되어 있습니다.

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

패키지설명
context긴 실행 루틴(외부 서비스와의 연결 등)을 제어하기 위한 추상화입니다.
fmt데이터 형식을 지정하여 출력, 문자열 및 오류를 처리합니다.
io파일 읽기 또는 네트워크 소켓과 같은 입출력 작업을 처리합니다.
os운영 체제와 상호작용하며, 예를 들어 파일을 엽니다.
time시간을 처리합니다. Auth 서비스에 연결하는 데 타임아웃을 정의하고, 반복적으로 검색 로직을 실행하는 타이커를 사용하는 데 사용됩니다.

클라이언트는 다음과 같은 제3자 코드를 가져옵니다:

패키지설명
github.com/gravitational/teleport/api/clientAuth 서비스의 gRPC API에 인증하고 요청을 수행하는 라이브러리로, teleport라는 약어로 설정됩니다.
github.com/gravitational/teleport/api/typesAuth 서비스 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 서비스의 호스트와 포트, 예를 들어 mytenant.teleport.sh:443, 이 값을 사용하여 클라이언트를 클러스터에 연결합니다. 이 값을 귀하의 Proxy 서비스의 호스트 및 포트로 설정하십시오: proxy-address
initTimeoutTeleport 클러스터에 연결하기 위한 타임아웃입니다. 30초로 설정했습니다.
identityFilePath이전에 생성한 Teleport 신원 파일의 경로입니다.
clusterNameRBAC 리소스를 가져올 Kubernetes 클러스터의 이름입니다. 이 가이드에서는 클러스터 이름이 minikube입니다.
roleAnnotationKeyKubernetes에서 주석은 리소스에 추가할 수 있는 임의의 키/값 쌍입니다. 이전에 생성한 역할 및 클러스터 역할 바인딩에는 클라이언트 애플리케이션이 이를 가져올 수 있도록 이 키가 포함되어 있습니다.

Kubernetes RBAC 클라이언트 초기화

Kubernetes API에 연락하기 위해 HTTP 클라이언트를 설정해야 합니다. 클라이언트는 상호 TLS를 통해 API에 인증되며, kubeconfigPath에 있는 파일에서 클라이언트 인증서, 인증 기관 및 비밀 키를 로드합니다. 이전에 Teleport Auth 서비스로부터 이를 요청했습니다.

프로그램은 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("Upserted Teleport role:", role.GetName())
	return nil
}

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

우리는 이 프로그램을 사용하여 생성한 역할을 신속하게 식별할 수 있기를 원하기 때문에, 이 함수는 모든 역할의 이름을 다음 속성을 기반으로 정의합니다:

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

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

이 함수는 types.RoleV6, Teleport API 클라이언트의 역할 유형에 필드를 할당합니다.

역할 필드목적할당 방법
allow.kubernetes_labels이 역할을 가진 사용자가 액세스할 수 있도록 하는 Teleport에 등록된 Kubernetes 클러스터의 레이블입니다.클러스터 역할 바인딩에 포함된 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("Connected to Teleport")

	ks, err := teleport.GetKubernetesServers(context.Background())
	if err != nil {
		panic(err)
	}
	for _, k := range ks {
		if k.GetCluster().GetName() != clusterName {
			continue
		}
		fmt.Println("Retrieved Kubernetes cluster", clusterName)

		if err := createTeleportRolesForKubeCluster(teleport, k.GetCluster()); err != nil {
			panic(err)
		}
		fmt.Println("Created roles for Kubernetes cluster", clusterName)
		return
	}
	panic("Unable to locate a Kubernetes Service instance for " + clusterName)
}

client는 Teleport API 클라이언트를 설정하기 위한 라이브러리입니다. 우리의 프로그램은 client.LoadIdentityFile을 호출하여 client.Credentials를 가져오고, 그 후 client.New를 사용하여 제공된 신원 파일로 지정된 Teleport Proxy 서비스에 연결합니다.

Warning

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

  • 이전에 내보낸 신원 파일의 TTL이 만료되지 않았습니다.
  • teleport.Config에서 Addrs 필드에 제공한 값은 Teleport Proxy 서비스의 호스트 웹 포트를 모두 포함해야 합니다, 예: mytenant.teleport.sh:443.

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

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

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

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

go run main.go

다음과 같은 출력이 보여야 합니다:

Connected to Teleport
Retrieved Kubernetes cluster minikube
Upserted Teleport role: minikube-pod-ops-cluster
Upserted Teleport role: minikube-pod-reader-app
Created roles for Kubernetes cluster 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 역할을 생성하는 클라이언트 애플리케이션을 효과적으로 작성하기 위해서는 관리할 인프라 리소스의 역할 필드에 대한 이해가 필요합니다.

다음 링크에서 다양한 인프라 리소스와 관련된 필드에 대한 가이드를 확인하십시오:

일반 지침은 Access Controls Reference를 읽으십시오.

클라우드 공급자를 Teleport에 등록하기

클라우드 공급자 API를 Teleport로 보호하고 API 클라이언트 애플리케이션이 이러한 API에 Teleport Application 서비스를 통해 연결하도록 지시할 수 있습니다. Teleport로 보호된 클라우드 공급자 API를 사용하여 클라우드 공급자의 RBAC 솔루션에 따라 Teleport 역할을 생성할 수 있습니다.

클라우드 공급자 API에 대한 Teleport Application 서비스를 설정하는 방법에 대한 가이드를 참조하십시오:

예제 참고

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

클라이언트 애플리케이션에 짧은 수명의 자격 증명 프로비저닝하기

이번 예제에서는 tctl auth sign 명령을 사용하여 작성한 프로그램의 자격 증명을 가져왔습니다. 프로덕션 사용을 위해서는 기계 ID를 통해 짧은 수명의 자격 증명을 프로비저닝할 것을 권장합니다. 기계 ID에 대한 더 많은 정보를 보려면 기계 ID 문서를 확인하십시오.

Teleport 원문 보기