|
| 1 | +#!/bin/bash |
| 2 | +set -o errexit |
| 3 | +set -o nounset |
| 4 | +set -o pipefail |
| 5 | + |
| 6 | +INFRA_NAME=${NAMESPACE}-${UNIQUE_HASH} |
| 7 | + |
| 8 | +# logger function prints standard logs |
| 9 | +logger() { |
| 10 | + local level="$1" |
| 11 | + local message="$2" |
| 12 | + local timestamp |
| 13 | + |
| 14 | + # Generate a timestamp for the log entry |
| 15 | + timestamp=$(date +"%Y-%m-%d %H:%M:%S") |
| 16 | + |
| 17 | + # Print the log message with the level and timestamp |
| 18 | + echo "[$timestamp] [$level] $message" |
| 19 | +} |
| 20 | + |
| 21 | +function run_command() { |
| 22 | + local CMD="$1" |
| 23 | + echo "Running Command: ${CMD}" >&2 |
| 24 | + eval "${CMD}" |
| 25 | +} |
| 26 | + |
| 27 | +logger "INFO" "Starting GCP Filestore Workload Identity Federation configuration" |
| 28 | + |
| 29 | +# For disconnected or otherwise unreachable environments, we want to |
| 30 | +# have steps use an HTTP(S) proxy to reach the API server. This proxy |
| 31 | +# configuration file should export HTTP_PROXY, HTTPS_PROXY, and NO_PROXY |
| 32 | +# environment variables, as well as their lowercase equivalents (note |
| 33 | +# that libcurl doesn't recognize the uppercase variables). |
| 34 | +if test -f "${SHARED_DIR}/proxy-conf.sh" |
| 35 | +then |
| 36 | + # shellcheck disable=SC1091 |
| 37 | + source "${SHARED_DIR}/proxy-conf.sh" |
| 38 | + logger "INFO" "Loaded proxy configuration from ${SHARED_DIR}/proxy-conf.sh" |
| 39 | +fi |
| 40 | + |
| 41 | +GOOGLE_PROJECT_ID="$(<${CLUSTER_PROFILE_DIR}/openshift_gcp_project)" |
| 42 | +export GCP_SHARED_CREDENTIALS_FILE="${CLUSTER_PROFILE_DIR}/gce.json" |
| 43 | +GCP_SERVICE_ACCOUNT=$(jq -r .client_email ${GCP_SHARED_CREDENTIALS_FILE}) |
| 44 | +SA_SUFFIX=${GCP_SERVICE_ACCOUNT#*@} |
| 45 | +SA_EMAIL=$(jq -r .client_email ${GCP_SHARED_CREDENTIALS_FILE}) |
| 46 | + |
| 47 | +if ! gcloud auth list | grep -E "\*\s+${SA_EMAIL}" |
| 48 | +then |
| 49 | + logger "INFO" "Authenticating with GCP service account" |
| 50 | + CMD="gcloud auth activate-service-account --key-file=\"${GCP_SHARED_CREDENTIALS_FILE}\"" |
| 51 | + run_command "${CMD}" |
| 52 | + CMD="gcloud config set project \"${GOOGLE_PROJECT_ID}\"" |
| 53 | + run_command "${CMD}" |
| 54 | + logger "INFO" "Successfully authenticated with GCP service account" |
| 55 | +fi |
| 56 | + |
| 57 | +# Ref: TBD (no Red Hat docs available yet). Google doc: https://cloud.google.com/iam/docs/workload-identity-federation-with-kubernetes#create_the_workload_identity_pool_and_provider |
| 58 | +logger "INFO" "Create GCP Filestore cloud infrastructure for Workload Identity Federation" |
| 59 | + |
| 60 | +## TODO: replace steps to manually create the service account and bindings with ccoctl automation if this ever gets implemented |
| 61 | +## TODO: alternatively, this could be documented later in the docs, make sure the code below is aligned with the official procedure |
| 62 | + |
| 63 | +# Create Google cloud service account for GCP Filestore Operator (name length must be between 6 and 30) |
| 64 | +SERVICE_ACCOUNT_NAME="gcp-filestore-sa-${UNIQUE_HASH}"-`echo $RANDOM` |
| 65 | +SERVICE_ACCOUNT_EMAIL="${SERVICE_ACCOUNT_NAME}@${SA_SUFFIX}" |
| 66 | + |
| 67 | +logger "INFO" "Creating GCP IAM service account: ${SERVICE_ACCOUNT_EMAIL}" |
| 68 | +CMD="gcloud iam service-accounts create \"$SERVICE_ACCOUNT_NAME\" --display-name=\"$SERVICE_ACCOUNT_NAME\"" |
| 69 | +run_command "$CMD" |
| 70 | + |
| 71 | +# Obtain project number, pool ID, and provider ID |
| 72 | +# We assume the pool ID is the same as the infrastructure name and reuse it. If this won't work well in the future we can create a new pool for the operator. |
| 73 | +logger "INFO" "Obtaining project details and identity pool information" |
| 74 | +CMD="gcloud projects describe \"$GOOGLE_PROJECT_ID\" --format=\"value(projectNumber)\"" |
| 75 | +PROJECT_NUMBER=$(run_command "${CMD}") |
| 76 | +POOL_ID=${INFRA_NAME} |
| 77 | +PROVIDER_ID=${INFRA_NAME} |
| 78 | +logger "INFO" "Project number: ${PROJECT_NUMBER}, Pool ID: ${POOL_ID}, Provider ID: ${PROVIDER_ID}" |
| 79 | + |
| 80 | +# Set roles for the service account - this should match roles CredentialsRequest of Filestore Operator |
| 81 | +logger "INFO" "Setting IAM roles for the service account" |
| 82 | +CMD="gcloud projects add-iam-policy-binding \"$GOOGLE_PROJECT_ID\" --member=\"serviceAccount:$SERVICE_ACCOUNT_EMAIL\" --role=\"roles/file.editor\" --condition=None" |
| 83 | +run_command "${CMD}" |
| 84 | +CMD="gcloud projects add-iam-policy-binding \"$GOOGLE_PROJECT_ID\" --member=\"serviceAccount:$SERVICE_ACCOUNT_EMAIL\" --role=\"roles/resourcemanager.tagUser\" --condition=None" |
| 85 | +run_command "${CMD}" |
| 86 | +logger "INFO" "IAM roles set successfully" |
| 87 | + |
| 88 | +# Allow OpenShift service accounts to impersonate Google cloud service account |
| 89 | +logger "INFO" "Configuring Workload Identity Federation for OpenShift service accounts" |
| 90 | +CMD="gcloud iam service-accounts add-iam-policy-binding \"$SERVICE_ACCOUNT_EMAIL\" --member=\"principal://iam.googleapis.com/projects/$PROJECT_NUMBER/locations/global/workloadIdentityPools/$POOL_ID/subject/system:serviceaccount:openshift-cluster-csi-drivers:gcp-filestore-csi-driver-controller-sa\" --role=roles/iam.workloadIdentityUser" |
| 91 | +run_command "${CMD}" |
| 92 | +CMD="gcloud iam service-accounts add-iam-policy-binding \"$SERVICE_ACCOUNT_EMAIL\" --member=\"principal://iam.googleapis.com/projects/$PROJECT_NUMBER/locations/global/workloadIdentityPools/$POOL_ID/subject/system:serviceaccount:openshift-cluster-csi-drivers:gcp-filestore-csi-driver-operator\" --role=roles/iam.workloadIdentityUser" |
| 93 | +run_command "${CMD}" |
| 94 | +logger "INFO" "Workload Identity Federation configured successfully" |
| 95 | + |
| 96 | +# Store GCP WIF variables to a known location to be used later in chain as OO_CONFIG_ENVVARS used by `optional-operators-subscribe` step |
| 97 | +logger "INFO" "Storing GCP Workload Identity Federation variables" |
| 98 | +echo "$POOL_ID" > "${SHARED_DIR}"/gcp-filestore-pool-id |
| 99 | +echo "$PROVIDER_ID" > "${SHARED_DIR}"/gcp-filestore-provider-id |
| 100 | +echo "$SERVICE_ACCOUNT_EMAIL" > "${SHARED_DIR}"/gcp-filestore-service-account-email |
| 101 | +printf '"%s"' "$PROJECT_NUMBER" > "${SHARED_DIR}"/gcp-filestore-project-number |
| 102 | + |
| 103 | +logger "INFO" "GCP Workload Identity Federation variables stored successfully in ${SHARED_DIR}:" |
| 104 | +logger "INFO" " Pool ID: $(cat ${SHARED_DIR}/gcp-filestore-pool-id)" |
| 105 | +logger "INFO" " Provider ID: $(cat ${SHARED_DIR}/gcp-filestore-provider-id)" |
| 106 | +logger "INFO" " Service Account Email: $(cat ${SHARED_DIR}/gcp-filestore-service-account-email)" |
| 107 | +logger "INFO" " Project Number: $(cat ${SHARED_DIR}/gcp-filestore-project-number)" |
| 108 | + |
| 109 | +logger "INFO" "GCP Filestore Workload Identity Federation configuration completed" |
| 110 | + |
0 commit comments