k8s.io/test-infra@v0.0.0-20240520184403-27c6b4c223d8/workload-identity/bind-service-accounts.sh (about) 1 #!/usr/bin/env bash 2 # Copyright 2020 The Kubernetes Authors. 3 # 4 # Licensed under the Apache License, Version 2.0 (the "License"); 5 # you may not use this file except in compliance with the License. 6 # You may obtain a copy of the License at 7 # 8 # http://www.apache.org/licenses/LICENSE-2.0 9 # 10 # Unless required by applicable law or agreed to in writing, software 11 # distributed under the License is distributed on an "AS IS" BASIS, 12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 # See the License for the specific language governing permissions and 14 # limitations under the License. 15 16 17 set -o errexit 18 set -o nounset 19 set -o pipefail 20 21 if [[ $# != 6 ]]; then 22 echo "Usage: $(basename "$0") <project> <zone_or_region> <cluster> <namespace> <name> <gcp-service-account>" >&2 23 exit 1 24 fi 25 26 # Require bash version >= 4.4 27 if ((${BASH_VERSINFO[0]}<4)) || ( ((${BASH_VERSINFO[0]}==4)) && ((${BASH_VERSINFO[1]}<4)) ); then 28 echo "ERROR: This script requires a minimum bash version of 4.4, but got version of ${BASH_VERSINFO[0]}.${BASH_VERSINFO[1]}" 29 if [ "$(uname)" = 'Darwin' ]; then 30 echo "On macOS with homebrew 'brew install bash' is sufficient." 31 fi 32 exit 1 33 fi 34 35 project=$1 36 zone=$2 37 cluster=$3 38 context="gke_${project}_${zone}_${cluster}" 39 namespace=$4 40 name=$5 41 gcp_service_account=$6 42 43 current-annotation() { 44 kubectl get serviceaccounts \ 45 "--context=$context" "--namespace=$namespace" "$name" \ 46 -o jsonpath="{.metadata.annotations.iam\.gke\.io/gcp-service-account}" 47 } 48 49 current=$(current-annotation || echo MISSING) 50 51 if [[ "$current" != "$gcp_service_account" ]]; then 52 echo "Service account has wrong/missing annotation, please declare the following to $namespace/$name in $context:" >&2 53 echo '"{"metadata": {"annotations": "iam.gke.io/gcp-service-account": '"\"$gcp_service_account\"}}" 54 exit 1 55 fi 56 57 # Extract GOAL from someone@GOAL.iam.gserviceaccount.com 58 gcp_sa_project=${gcp_service_account##*@} 59 gcp_sa_project=${gcp_sa_project%%.*} 60 61 # Default compute engine service accounts have a different format that makes them 62 # appear to belong to a 'developer' project: <project-number>-compute@developer.gserviceaccount.com 63 # We assume the default compute SA belongs to the project containing the cluster in this case. 64 if [[ "${gcp_sa_project}" == "developer" ]]; then 65 gcp_sa_project="${project}" 66 fi 67 68 role=roles/iam.workloadIdentityUser 69 members=($( 70 gcloud iam service-accounts get-iam-policy \ 71 "--project=$gcp_sa_project" "$gcp_service_account" \ 72 --filter="bindings.role=$role" \ 73 --flatten=bindings --format='value[delimiter=" "](bindings.members)' 74 )) 75 76 want="serviceAccount:$project.svc.id.goog[$namespace/$name]" 77 fix_policy=yes 78 for member in "${members[@]}"; do 79 if [[ "$want" == "$member" ]]; then 80 fix_policy= 81 break 82 fi 83 done 84 85 86 if [[ -z "${fix_policy}" ]]; then 87 echo "ALREADY MEMBER: $want has $role for $gcp_service_account." 88 else 89 ( 90 set -o xtrace 91 gcloud iam service-accounts add-iam-policy-binding \ 92 "--project=$gcp_sa_project" \ 93 --role=roles/iam.workloadIdentityUser \ 94 "--member=$want" \ 95 $gcp_service_account 96 ) > /dev/null 97 echo "Sleeping 2m to allow credentials to propagate.." >&2 98 sleep 2m 99 fi 100 101 102 pod-identity() { 103 head -n 1 <( 104 entropy=$(date +%S) 105 set -o xtrace 106 kubectl run --rm=true -i \ 107 "--context=$context" "--namespace=$namespace" \ 108 "--overrides={\"spec\": {\"serviceAccount\": \"$name\"}}" \ 109 --image=google/cloud-sdk:slim "workload-identity-test-$entropy" \ 110 <<< "gcloud config get-value core/account" 111 ) 112 } 113 114 # Filter out the the "try pressing enter" message from stderr 115 got=$((pod-identity 3>&1 1>&2 2>&3 | grep -v "try pressing enter") 3>&1 1>&2 2>&3) 116 if [[ "$got" != "$gcp_service_account" ]]; then 117 echo "Bad identity, got $got, want $gcp_service_account" >&2 118 exit 1 119 fi 120 121 echo "DONE: --context=$context --namespace=$namespace serviceaccounts/$name acts as $gcp_service_account"