Teleport gRPC API를 사용하여 GitHub 또는 AWS Identity와 같은 외부 역할 기반 액세스 제어(RBAC) 시스템에 따라 역할을 자동으로 생성할 수 있습니다.
이는 특히 유용합니다:
- 새로운 Teleport 클러스터를 설정할 때, 기존의 인증 수준이나 카테고리를 유지하면서 Teleport가 액세스 제어를 처리하게 할 수 있습니다.
- Teleport 클러스터가 관리하는 인프라의 RBAC 시스템과 항상 최신 상태를 유지하도록 보장합니다. 이렇게 하면 팀이 외부 RBAC 시스템을 재구성하더라도 Teleport 역할이 예기치 않게 권한을 얻거나 잃지 않습니다.
이 가이드에서는 Teleport의 API 클라이언트 라이브러리를 사용하여 Teleport 역할을 생성하는 방법을 보여주기 위해 작은 데모 애플리케이션을 구축할 것입니다.
이번 가이드에서 구축할 프로그램은 학습 도구로 의도된 것입니다. 이를 생산 Teleport 클러스터에 연결하지 마십시오. 대신 데모 클러스터를 사용하십시오.
필수 조건
-
실행 중인 Teleport 클러스터 버전 이상. Teleport를 시작하려면, 가입하기 위해 무료 평가판에 등록하거나 데모 환경 설정하기를 참조하세요.
-
tctl
관리 도구와tsh
클라이언트 도구.tctl
과tsh
다운로드에 대한 지침은 설치를 방문하세요.
- 작업 공간에 Go 버전 1.22 이상이 설치되어 있어야 합니다. Go 다운로드 페이지를 참조하십시오. 이 가이드를 완료하기 위해 Go에 익숙할 필요는 없지만, 생산 준비가 완료된 Teleport 클라이언트 애플리케이션을 구축하려면 Go 지식이 필요합니다.
생산 시나리오에서는 Teleport 역할을 생성하는 기반으로 사용할 서드파티 RBAC 솔루션이 이미 있을 것입니다. 이번 가이드에서는 로컬 Kubernetes 클러스터를 minikube
를 사용하여 배포하고 몇 가지 RBAC 리소스를 설정하여 이를 시뮬레이션할 것입니다. 그런 다음 이 Kubernetes 클러스터를 사용하여 Teleport 역할을 생성합니다.
로컬 데모 환경을 실행하려면 작업 공간에 다음 도구가 설치되어 있는지 확인하십시오:
도구 | 목적 | 설치 링크 |
---|---|---|
minikube | 로컬 Kubernetes 배포 도구 | minikube 설치하기 |
Helm | Kubernetes 패키지 관리자 | Helm 설치하기 |
kubectl | Kubernetes 관리 CLI | kubectl 설치하기 |
Docker | 필요한 minikube 드라이버 | Docker 시작하기 |
데모 프로젝트를 설정할 계획이 없더라도 이 가이드를 따라가면서 외부 RBAC 시스템에 기반하여 Teleport 역할을 자동으로 생성하는 데 사용 가능한 라이브러리, 유형 및 함수를 확인할 수 있습니다.
- 당신의 Teleport 클러스터에 연결할 수 있는지 확인하려면,
tsh login
으로 로그인한 다음 현재 자격 증명을 사용하여tctl
명령어를 실행할 수 있는지 확인하십시오. 예를 들어:클러스터에 연결하고tsh login --proxy=teleport.example.com --user=email@example.comtctl 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-contextminikube
데모 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.yamlnamespace/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.yamlclusterrole.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.yamlclusterrole.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.yamlrole '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 사용자에게 할당하려면 인증 제공자에 맞는 적절한 명령어를 실행하세요:
-
로컬 사용자의 역할을 콤마로 구분된 목록으로 가져옵니다:
ROLES=$(tsh status -f json | jq -r '.active.roles | join(",")') -
로컬 사용자를 편집하여 새로운 역할을 추가합니다:
tctl users update $(tsh status -f json | jq -r '.active.username') \ --set-roles "${ROLES?},sync-kubernetes-rbac-impersonator" -
Teleport 클러스터에서 로그아웃한 후 새로운 역할을 asum 하기 위해 다시 로그인합니다.
-
github
인증 커넥터를 가져옵니다:tctl get github/github --with-secrets > github.yaml--with-secrets
플래그는spec.signing_key_pair.private_key
의 값을github.yaml
파일에 추가합니다. 이 키는 민감한 값을 포함하고 있기 때문에, 리소스를 업데이트한 후 즉시github.yaml
파일을 제거해야 합니다. -
github.yaml
을 편집하고teams_to_roles
섹션에sync-kubernetes-rbac-impersonator
을 추가합니다.이 역할에 매핑할 팀은 귀하의 조직에서 어떻게 역할 기반 접근 제어(RBAC)를 설계했느냐에 따라 달라집니다. 하지만 팀에는 귀하의 사용자 계정이 포함되어야 하며, 조직 내에서 가능한 한 작은 팀이어야 합니다.
여기에 예시가 있습니다:
teams_to_roles: - organization: octocats team: admins roles: - access + - sync-kubernetes-rbac-impersonator
-
변경 사항을 적용합니다:
tctl create -f github.yaml -
Teleport 클러스터에서 로그아웃한 후 새로운 역할을 assum 하기 위해 다시 로그인합니다.
-
saml
구성 리소스를 가져옵니다:tctl get --with-secrets saml/mysaml > saml.yaml--with-secrets
플래그는spec.signing_key_pair.private_key
의 값을saml.yaml
파일에 추가합니다. 이 키는 민감한 값을 포함하고 있기 때문에, 리소스를 업데이트한 후 즉시saml.yaml
파일을 제거해야 합니다. -
saml.yaml
을 편집하고attributes_to_roles
섹션에sync-kubernetes-rbac-impersonator
을 추가합니다.이 역할에 매핑할 속성은 귀하의 조직에서 어떻게 역할 기반 접근 제어(RBAC)를 설계했느냐에 따라 달라집니다. 그러나 그룹에는 귀하의 사용자 계정이 포함되어야 하며, 조직 내에서 가능한 한 작은 그룹이어야 합니다.
여기에 예시가 있습니다:
attributes_to_roles: - name: "groups" value: "my-group" roles: - access + - sync-kubernetes-rbac-impersonator
-
변경 사항을 적용합니다:
tctl create -f saml.yaml -
Teleport 클러스터에서 로그아웃한 후 새로운 역할을 asum 하기 위해 다시 로그인합니다.
-
oidc
구성 리소스를 가져옵니다:tctl get oidc/myoidc --with-secrets > oidc.yaml--with-secrets
플래그는spec.signing_key_pair.private_key
의 값을oidc.yaml
파일에 추가합니다. 이 키는 민감한 값을 포함하고 있기 때문에, 리소스를 업데이트한 후 즉시oidc.yaml
파일을 제거해야 합니다. -
oidc.yaml
을 편집하고claims_to_roles
섹션에sync-kubernetes-rbac-impersonator
을 추가합니다.이 역할에 매핑할 클레임은 귀하의 조직에서 어떻게 역할 기반 접근 제어(RBAC)를 설계했느냐에 따라 달라집니다. 그러나 그룹에는 귀하의 사용자 계정이 포함되어야 하며, 조직 내에서 가능한 한 작은 그룹이어야 합니다.
여기에 예시가 있습니다:
claims_to_roles: - name: "groups" value: "my-group" roles: - access + - sync-kubernetes-rbac-impersonator
-
변경 사항을 적용합니다:
tctl create -f oidc.yaml -
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 minikubeSwitched 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 lsKube 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/v16cd 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/client | Auth 서비스의 gRPC API에 인증하고 요청을 수행하는 라이브러리로, teleport 라는 약어로 설정됩니다. |
github.com/gravitational/teleport/api/types | Auth 서비스 API에서 사용되는 유형, 예를 들어 애플리케이션 서비스 레코드입니다. |
github.com/gravitational/trace | 표준 라이브러리보다 더 유용한 세부정보로 오류를 표현합니다. |
google.golang.org/grpc | gRPC 클라이언트 및 서버 라이브러리입니다. |
k8s.io/api/rbac/v1 | Kubernetes RBAC API 클라이언트 라이브러리입니다. |
k8s.io/apimachinery/pkg/apis/meta/v1 | Kubernetes의 API 클라이언트 라이브러리에 공통된 코드입니다. |
k8s.io/client-go/kubernetes | 일반 목적의 Kubernetes 클라이언트를 설정합니다. |
k8s.io/client-go/kubernetes/typed/rbac/v1 | Kubernetes 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"
)
이 상수들은 나중에 프로그램에서 사용할 것입니다. 이 상수들은 나중에 변경하고 싶을 수도 있는 몇 가지 값을 정의합니다:
상수 | 설명 |
---|---|
proxyAddr | Teleport Proxy 서비스의 호스트와 포트, 예를 들어 mytenant.teleport.sh:443 , 이 값을 사용하여 클라이언트를 클러스터에 연결합니다. 이 값을 귀하의 Proxy 서비스의 호스트 및 포트로 설정하십시오: proxy-address |
initTimeout | Teleport 클러스터에 연결하기 위한 타임아웃입니다. 30초로 설정했습니다. |
identityFilePath | 이전에 생성한 Teleport 신원 파일의 경로입니다. |
clusterName | RBAC 리소스를 가져올 Kubernetes 클러스터의 이름입니다. 이 가이드에서는 클러스터 이름이 minikube 입니다. |
roleAnnotationKey | Kubernetes에서 주석은 리소스에 추가할 수 있는 임의의 키/값 쌍입니다. 이전에 생성한 역할 및 클러스터 역할 바인딩에는 클라이언트 애플리케이션이 이를 가져올 수 있도록 이 키가 포함되어 있습니다. |
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
}
getRBACClient
는 kubeconfigPath
에 있는 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_users 및 allow.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 서비스에 연결합니다.
이 프로그램은 자격 증명이나 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 문서를 확인하십시오.