# You could update instead of creategcloud container node-pools create <nodepoolname> --cluster=<cluser_name> --workload-metadata=GKE_METADATA --region=us-central1
K8s에서 GCP 권한을 가진 GCP 서비스 계정을 위조합니다:
# Create SA called "gsa2ksa"gcloudiamservice-accountscreategsa2ksa--project=<project-id># Give "roles/iam.securityReviewer" role to the SAgcloudprojectsadd-iam-policy-binding<project-id> \--member "serviceAccount:gsa2ksa@<project-id>.iam.gserviceaccount.com" \--role "roles/iam.securityReviewer"
클러스터에 연결하고 사용할 서비스 계정을 생성합니다.
# Get k8s credsgcloudcontainerclustersget-credentials<cluster_name>--region=us-central1# Generate our testing namespacekubectlcreatenamespacetesting# Create the KSAkubectlcreateserviceaccountksa2gcp-ntesting
GSA와 KSA를 바인딩합니다.
# Allow the KSA to access the GSA in GCP IAMgcloudiamservice-accountsadd-iam-policy-bindinggsa2ksa@<project-id.iam.gserviceaccount.com \--role roles/iam.workloadIdentityUser \--member "serviceAccount:<project-id>.svc.id.goog[<namespace>/ksa2gcp]"# Indicate to K8s that the SA is able to impersonate the GSAkubectlannotateserviceaccountksa2gcp \--namespace testing \iam.gke.io/gcp-service-account=gsa2ksa@security-devbox.iam.gserviceaccount.com
KSA와 함께 pod를 실행하고 GSA에 대한 접근을 확인합니다:
# If using Autopilot remove the nodeSelector stuff!echo"apiVersion: v1kind: Podmetadata:name: workload-identity-testnamespace: <namespace>spec:containers:- image: google/cloud-sdk:slimname: workload-identity-testcommand: ['sleep','infinity']serviceAccountName: ksa2gcpnodeSelector:iam.gke.io/gke-metadata-server-enabled: 'true'"|kubectlapply-f-# Get inside the podkubectlexec-itworkload-identity-test \--namespace testing \-- /bin/bash# Check you can access the GSA from insie the pod withcurl-H"Metadata-Flavor: Google"http://169.254.169.254/computeMetadata/v1/instance/service-accounts/default/emailgcloudauthlist
K8s 내부의 공격자로서, GCP에서 무언가에 접근할 수 있는 것을 나타내는 iam.gke.io/gcp-service-account 주석을 가진 SAs를 찾아야 합니다. 또 다른 옵션은 클러스터 내의 각 KSA를 남용하고 접근할 수 있는지 확인하는 것입니다.
GCP에서는 항상 바인딩을 열거하고 Kubernetes 내부의 SAs에게 어떤 접근 권한을 부여하는지 알아내는 것이 흥미로울 것입니다.
다음은 이 주석을 찾기 위해 모든 pod 정의를 쉽게 반복하는 스크립트입니다:
for ns in`kubectlgetnamespaces-ocustom-columns=NAME:.metadata.name|grep-vNAME`; dofor pod in`kubectlgetpods-n "$ns" -ocustom-columns=NAME:.metadata.name|grep-vNAME`; doecho"Pod: $ns/$pod"kubectlgetpod"$pod"-n"$ns"-oyaml|grep"gcp-service-account"echo""echo""donedone|grep-B1"gcp-service-account"
AWS
Kiam & Kube2IAM (Pods용 IAM 역할)
Pods에 IAM 역할을 부여하는 (오래된) 방법은 Kiam 또는 Kube2IAM서버를 사용하는 것입니다. 기본적으로 클러스터 내에서 특권이 있는 IAM 역할을 가진 데몬셋을 실행해야 합니다. 이 데몬셋은 필요한 팟에 IAM 역할에 대한 액세스 권한을 부여할 것입니다.
먼저, 네임스페이스 내에서 액세스할 수 있는 역할을 구성해야 합니다. 이를 위해 네임스페이스 객체 내에 주석을 사용하여 구성합니다:
IAM 역할과 SA 간에 신뢰 관계를 생성합니다. 이때 IAM 역할과 SA의 이름(또는 역할에 액세스 권한을 부여하는 모든 네임스페이스)을 확인합니다. 신뢰 관계는 주로 OIDC 공급자 이름, 네임스페이스 이름 및 SA 이름을 확인합니다.
마지막으로, IAM 역할의 ARN을 나타내는 주석이 있는 SA를 생성하면 해당 SA로 실행되는 팟은 역할의 토큰에 액세스할 수 있습니다. 토큰은 파일에 기록되며 경로는 AWS_WEB_IDENTITY_TOKEN_FILE(기본값: /var/run/secrets/eks.amazonaws.com/serviceaccount/token)에 지정됩니다.
# Create a service account with a rolecat>my-service-account.yaml<<EOFapiVersion: v1kind: ServiceAccountmetadata:name: my-service-accountnamespace: defaultannotations:eks.amazonaws.com/role-arn: arn:aws:iam::318142138553:role/EKSOIDCTestingEOFkubectlapply-fmy-service-account.yaml# Add a role to an existent service accountkubectl annotate serviceaccount -n $namespace $service_account eks.amazonaws.com/role-arn=arn:aws:iam::$account_id:role/my-role
/var/run/secrets/eks.amazonaws.com/serviceaccount/token에서 토큰을 사용하여 aws를 얻으려면 다음을 실행하십시오:
for ns in`kubectlgetnamespaces-ocustom-columns=NAME:.metadata.name|grep-vNAME`; dofor pod in`kubectlgetpods-n "$ns" -ocustom-columns=NAME:.metadata.name|grep-vNAME`; doecho"Pod: $ns/$pod"kubectlgetpod"$pod"-n"$ns"-oyaml|grep"amazonaws.com"echo""echo""donefor sa in`kubectlgetserviceaccounts-n "$ns" -ocustom-columns=NAME:.metadata.name|grep-vNAME`; doecho"SA: $ns/$sa"kubectlgetserviceaccount"$sa"-n"$ns"-oyaml|grep"amazonaws.com"echo""echo""donedone|grep-B1"amazonaws.com"
노드 IAM 역할
이전 섹션에서는 팟을 사용하여 IAM 역할을 도용하는 방법에 대해 설명했습니다. 그러나 K8s 클러스터의 노드는 클라우드 내의 인스턴스가 될 것입니다. 이는 노드가 도난당할 수 있는 새로운 IAM 역할을 가지고 있을 가능성이 매우 높다는 것을 의미합니다 (일반적으로 K8s 클러스터의 모든 노드는 동일한 IAM 역할을 가지므로 각 노드를 확인하는 것은 가치가 없을 수도 있음을 유의하세요).
그러나 노드에서 메타데이터 엔드포인트에 액세스하기 위해서는 노드에 있어야 합니다 (ssh 세션?) 또는 적어도 동일한 네트워크에 있어야 합니다: