Skip to content

Create GCP IAM Resources

This guide explains how to create Workload Identity Federation (WIF) resources for GCP hosted clusters using the hypershift create iam gcp command.

Prerequisites

  • The hypershift CLI built from the repository
  • gcloud CLI authenticated with IAM permissions in the hosted cluster GCP project
  • An RSA keypair for OIDC service account token signing

Generate RSA Keypair

The hosted cluster's OIDC provider requires an RSA keypair for signing service account tokens:

# Generate 4096-bit RSA key in PKCS#1 format
openssl genrsa -traditional -out sa-signer.key 4096
openssl rsa -in sa-signer.key -pubout -out sa-signer.pub

Create a JWKS file from the public key:

# Extract modulus and compute key ID
HEX_MODULUS=$(openssl rsa -in sa-signer.key -pubout -outform DER 2>/dev/null | \
  openssl rsa -pubin -inform DER -text -noout 2>/dev/null | \
  grep -A 100 "^Modulus:" | grep -v "^Modulus:" | grep -v "^Exponent:" | \
  tr -d ' \n:' | sed 's/^00//')
MODULUS=$(printf '%b' "$(echo "$HEX_MODULUS" | sed 's/../\\x&/g')" | base64 -w0 | tr '+/' '-_' | tr -d '=')
KID=$(openssl rsa -in sa-signer.key -pubout -outform DER 2>/dev/null | \
  openssl dgst -sha256 -binary | base64 -w0 | tr '+/' '-_' | tr -d '=')

cat > jwks.json << EOF
{
  "keys": [
    {
      "kty": "RSA",
      "alg": "RS256",
      "use": "sig",
      "kid": "${KID}",
      "n": "${MODULUS}",
      "e": "AQAB"
    }
  ]
}
EOF

Create IAM Resources

The hypershift create iam gcp command creates WIF resources in the hosted cluster project:

  • Workload Identity Pool — Container for workload identity providers
  • OIDC Provider — Links the hosted cluster's Kubernetes OIDC issuer to GCP IAM
  • Service Accounts — GCP service accounts for hosted cluster components:
  • ctrlplane-op — Control Plane Operator (DNS admin, network admin, security admin, compute viewer). The roles/compute.securityAdmin role lets CPO reconcile the worker firewall rule (<infra-id>-internal-cluster).
  • nodepool — CAPG controller (compute instance admin, network admin)
  • cloud-controller — Cloud Controller Manager (load balancer admin, security admin, compute viewer)
  • storage — GCP PD CSI Driver (storage admin, instance admin, Tag User)
  • image-registry — Image Registry Operator (storage admin, Tag User)
  • cloud-network — Cloud Network Config Controller (instance admin, network user)
hypershift create iam gcp \
  --infra-id=<infra-id> \
  --project-id=<hosted-cluster-project-id> \
  --oidc-jwks-file=jwks.json

Reserved prefix

The --infra-id value must not start with gcp- — GCP reserves this prefix for Workload Identity Pool IDs.

Flags

Flag Required Description
--infra-id Yes Infrastructure ID (must match the value used for create infra gcp)
--project-id Yes GCP project ID where WIF resources will be created
--oidc-jwks-file Yes Path to JWKS JSON file containing the OIDC provider's public key
--oidc-issuer-url No Custom OIDC issuer URL (defaults to https://hypershift-<infra-id>-oidc)
--output-file No Path to save output JSON with WIF configuration

Example

hypershift create iam gcp \
  --infra-id=my-cluster \
  --project-id=my-hc-project \
  --oidc-jwks-file=jwks.json \
  > iam-output.json

Output

The command outputs JSON with the WIF configuration:

{
  "projectId": "my-hc-project",
  "projectNumber": "123456789",
  "infraId": "my-cluster",
  "workloadIdentityPool": {
    "poolId": "my-cluster-wi-pool",
    "providerId": "my-cluster-k8s-provider"
  },
  "serviceAccounts": {
    "ctrlplane-op": "my-cluster-ctrlplane-op@my-hc-project.iam.gserviceaccount.com",
    "nodepool-mgmt": "my-cluster-nodepool-mgmt@my-hc-project.iam.gserviceaccount.com",
    "cloud-controller": "my-cluster-cloud-controller@my-hc-project.iam.gserviceaccount.com",
    "gcp-pd-csi": "my-cluster-gcp-pd-csi@my-hc-project.iam.gserviceaccount.com",
    "image-registry": "my-cluster-image-registry@my-hc-project.iam.gserviceaccount.com",
    "cloud-network": "my-cluster-cloud-network@my-hc-project.iam.gserviceaccount.com"
  }
}

Save this output — you will need the project number, pool/provider IDs, and service account emails when creating the hosted cluster.

Resource tag permissions

When resourceTags is configured on a GCP HostedCluster, the guest GCP PD CSI driver uses serviceAccountsEmails.storage to tag new persistent disks, and the guest image registry operator uses serviceAccountsEmails.imageRegistry to tag its bucket. hypershift create iam gcp grants both Google service accounts roles/resourcemanager.tagUser on the hosted cluster project, in addition to their storage roles. The Cloud Resource Manager API must also be enabled in the project containing the resources to be tagged. See Google Cloud tag requirements.

The IAM template is applied only when hypershift create iam gcp runs. If the service accounts were created with an earlier version of the command, the image-registry service account does not have Tag User. Re-run the command with the same inputs, which adds missing role bindings to existing service accounts, or have an administrator add the project-level role binding.

For an organization-defined TagValue, a project-level grant alone is not enough. An organization administrator must also grant Tag User on each configured TagValue to both service accounts. For example, repeat this command with the storage and image-registry GSA emails:

gcloud resource-manager tags values add-iam-policy-binding <org-id>/<key>/<value> \
  --member="serviceAccount:<gsa-email>" \
  --role="roles/resourcemanager.tagUser"

HyperShift does not create TagKeys, TagValues, or organization-level IAM bindings. See the gcloud TagValue IAM reference.

Destroy IAM Resources

To clean up WIF resources:

hypershift destroy iam gcp \
  --infra-id=<infra-id> \
  --project-id=<hosted-cluster-project-id>

Next Steps