Infograb logo
워크로드 인증
디자인 파트너십

우리는 Teleport Workload Identity의 미래를 함께 만들어 나갈 디자인 파트너를 적극적으로 찾고 있으며, 귀하의 피드백을 듣고 싶습니다.

워크로드 인증은 tbot 이 워크로드 API에 연결되고 인증서를 요청한 워크로드의 아이덴티티를 주장하기 위해 수행하는 과정입니다. 인증 중에 수집된 정보는 어떤 SPIFFE ID를 SVID에 인코딩하여 워크로드에 발급할지 결정하는 데 사용됩니다.

워크로드 인증자는 이 인증을 수행하는 개별 구성 요소입니다. 그들은 워크로드의 프로세스 ID를 사용하여 플랫폼 특정 API에서 워크로드에 대한 정보를 수집합니다. 예를 들어, Kubernetes 워크로드 인증자는 로컬 Kubelet API에 쿼리하여 해당 프로세스에 속한 Kubernetes 포드를 결정합니다.

인증 과정의 결과는 인증 메타데이터로 알려져 있습니다. 이 인증 메타데이터는 tbot 의 워크로드 API 서비스에 대해 구성한 규칙에서 참조됩니다. 예를 들어, 특정 Kubernetes 네임스페이스에서 실행되는 워크로드에만 특정 SPIFFE ID가 발급되어야 한다고 명시할 수 있습니다.

또한 이 메타데이터는 tbot 이 SVID를 발급할 때 출력하는 로그 메시지에 포함됩니다. 이를 통해 SVID 발급을 감사하고 특정 SPIFFE ID가 워크로드에 발급된 이유를 이해할 수 있습니다.

Unix

Unix 워크로드 인증자는 가장 기본적인 인증자로 특정 Unix 프로세스에 대해 발급되는 SVID를 제한할 수 있습니다.

인증 메타데이터

다음 메타데이터는 Unix 워크로드 인증자에 의해 생성되며, tbot 의 워크로드 API 서비스 규칙 구성 시 사용할 수 있습니다:

필드설명
unix.attested워크로드가 Unix 워크로드 인증자에 의해 인증되었음을 나타냅니다.
unix.pid인증된 워크로드의 프로세스 ID입니다.
unix.uid인증된 워크로드의 유효 사용자 ID입니다.
unix.gid인증된 워크로드의 유효 기본 그룹 ID입니다.

Kubernetes

Kubernetes 워크로드 인증자는 특정 Kubernetes 워크로드에 대해 SVID의 발급을 제한할 수 있습니다.

첫 번째로 주어진 프로세스 ID에 대한 포드 ID를 결정하고, 그런 다음 로컬 Kubelet API에 쿼리하여 해당 포드에 대한 세부정보를 문의합니다.

인증 메타데이터

다음 메타데이터는 Kubernetes 워크로드 인증자에 의해 생성되며, tbot 의 워크로드 API 서비스 규칙 구성 시 사용할 수 있습니다:

필드설명
kubernetes.attested워크로드가 Kubernetes 워크로드 인증자에 의해 인증되었음을 나타냅니다.
kubernetes.namespaceKubernetes 포드의 네임스페이스입니다.
kubernetes.service_accountKubernetes 포드의 서비스 계정입니다.
kubernetes.pod_nameKubernetes 포드의 이름입니다.

배포 안내

Kubernetes 워크로드 인증을 사용하기 위해 tbot 은 데몬셋으로 배포되어야 합니다. 이는 유닉스 도메인 소켓에 대해 에이전트와 동일한 노드에 있는 포드만 접근할 수 있기 때문입니다. 또한 데몬셋은 에이전트가 다른 컨테이너 내 프로세스에 대한 정보에 접근할 수 있도록 hostPID 속성이 true 로 설정되어야 합니다.

데몬셋에는 Kubelet API를 쿼리할 수 있는 서비스 계정이 할당되어야 합니다. 다음은 필요한 RBAC 예제 역할입니다:

kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: tbot
rules:
  - resources: ["pods", "nodes", "nodes/proxy"]
    apiGroups: [""]
    verbs: ["get"]

워크로드의 컨테이너에 워크로드 API 유닉스 도메인 소켓을 매핑하는 방법은 두 가지입니다:

  • tbot 데몬셋 및 연결해야 하는 워크로드에 대해 hostPath 볼륨을 직접 구성합니다.
  • spiffe-csi-driver를 사용합니다.

필수 Kubernetes 리소스에 대한 예제 매니페스트:

kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: tbot
rules:
  - resources: ["pods", "nodes", "nodes/proxy"]
    apiGroups: [""]
    verbs: ["get"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: tbot
subjects:
  - kind: ServiceAccount
    name: tbot
    namespace: default
roleRef:
  kind: ClusterRole
  name: tbot
  apiGroup: rbac.authorization.k8s.io
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: tbot
  namespace: default
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: tbot-config
  namespace: default
data:
  tbot.yaml: |
    version: v2
    onboarding:
      join_method: kubernetes
      # 생성한 조인 토큰의 이름으로 바꿉니다.
      token: example-token
    storage:
      type: memory
    # Teleport 프록시 서비스의 주소로 이 값을 설정하십시오.
    proxy_server: example.teleport.sh:443
    services:
      - type: spiffe-workload-api
        listen: unix:///run/tbot/sockets/workload.sock
        attestor:
          kubernetes:
            enabled: true
            kubelet:
              # 일반적으로 클러스터 CA에서 발급되지 않는 Kubelet API 인증서의
              # 검증을 건너뜁니다.
              skip_verify: true
        # 발급하려는 SPIFFE ID로 svid 항목을 바꾸고,
        # 규칙 블록을 사용하여 특정 Kubernetes 워크로드로 이를 제한합니다.
        svids:
          - path: /my-service
            rules:
              - kubernetes:
                  namespace: default
                  service_account: example-sa
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: tbot
spec:
  selector:
    matchLabels:
      app: tbot
  template:
    metadata:
      labels:
        app: tbot
    spec:
      securityContext:
        runAsUser: 0
        runAsGroup: 0
      hostPID: true
      containers:
        - name: tbot
          image: public.ecr.aws/gravitational/tbot-distroless:17.0.0-dev
          imagePullPolicy: IfNotPresent
          securityContext:
            privileged: true
          args:
            - start
            - -c
            - /config/tbot.yaml
            - --log-format
            - json
          volumeMounts:
            - mountPath: /config
              name: config
            - mountPath: /var/run/secrets/tokens
              name: join-sa-token
            - name: tbot-sockets
              mountPath: /run/tbot/sockets
              readOnly: false
          env:
            - name: TELEPORT_NODE_NAME
              valueFrom:
                fieldRef:
                  fieldPath: spec.nodeName
            - name: KUBERNETES_TOKEN_PATH
              value: /var/run/secrets/tokens/join-sa-token
      serviceAccountName: tbot
      volumes:
        - name: tbot-sockets
          hostPath:
            path: /run/tbot/sockets
            type: DirectoryOrCreate
        - name: config
          configMap:
            name: tbot-config
        - name: join-sa-token
          projected:
            sources:
              - serviceAccountToken:
                  path: join-sa-token
                  # Kubernetes가 지원하는 최소값은 600초입니다. 이 값을 사용하는 것이 좋습니다.
                  expirationSeconds: 600
                  # `example.teleport.sh` 는 Teleport 클러스터의 이름으로 바꿔야 합니다.
                  audience: example.teleport.sh

다음 단계

Teleport 원문 보기