Configure GCP Workload Identity Pools

The gcp:iam/workloadIdentityPool:WorkloadIdentityPool resource, part of the Pulumi GCP provider, defines a workload identity pool that groups external or Google Cloud workload identities and controls how they authenticate. This guide focuses on three capabilities: basic pool creation for external federation, metadata and state management, and TRUST_DOMAIN mode with mTLS certificate issuance.

Workload identity pools operate in two modes. FEDERATION_ONLY pools federate external identities (AWS, Azure, OIDC providers) and require separate WorkloadIdentityPoolProvider resources. TRUST_DOMAIN pools assign identities to Google Cloud workloads and require Certificate Authority pools plus trust anchor certificates. The examples are intentionally small. Combine them with your own identity providers, IAM bindings, and certificate infrastructure.

Create a minimal pool for external identity federation

Most deployments start with a basic pool that federates external identities into Google Cloud, acting as a container for identity providers you’ll configure separately.

import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";

const example = new gcp.iam.WorkloadIdentityPool("example", {workloadIdentityPoolId: "example-pool"});
import pulumi
import pulumi_gcp as gcp

example = gcp.iam.WorkloadIdentityPool("example", workload_identity_pool_id="example-pool")
package main

import (
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/iam"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := iam.NewWorkloadIdentityPool(ctx, "example", &iam.WorkloadIdentityPoolArgs{
			WorkloadIdentityPoolId: pulumi.String("example-pool"),
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;

return await Deployment.RunAsync(() => 
{
    var example = new Gcp.Iam.WorkloadIdentityPool("example", new()
    {
        WorkloadIdentityPoolId = "example-pool",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.iam.WorkloadIdentityPool;
import com.pulumi.gcp.iam.WorkloadIdentityPoolArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var example = new WorkloadIdentityPool("example", WorkloadIdentityPoolArgs.builder()
            .workloadIdentityPoolId("example-pool")
            .build());

    }
}
resources:
  example:
    type: gcp:iam:WorkloadIdentityPool
    properties:
      workloadIdentityPoolId: example-pool

The workloadIdentityPoolId sets the pool’s unique identifier within your project. Without specifying mode, the pool defaults to FEDERATION_ONLY, which accepts external workload identities. You’ll need to create WorkloadIdentityPoolProvider resources to define how external tokens map to Google Cloud identities.

Configure federation with display metadata and state control

Production pools often need human-readable names, descriptions, and the ability to disable token exchange without deleting the pool.

import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";

const example = new gcp.iam.WorkloadIdentityPool("example", {
    workloadIdentityPoolId: "example-pool",
    displayName: "Name of the pool",
    description: "Identity pool operates in FEDERATION_ONLY mode",
    disabled: true,
    mode: "FEDERATION_ONLY",
});
import pulumi
import pulumi_gcp as gcp

example = gcp.iam.WorkloadIdentityPool("example",
    workload_identity_pool_id="example-pool",
    display_name="Name of the pool",
    description="Identity pool operates in FEDERATION_ONLY mode",
    disabled=True,
    mode="FEDERATION_ONLY")
package main

import (
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/iam"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := iam.NewWorkloadIdentityPool(ctx, "example", &iam.WorkloadIdentityPoolArgs{
			WorkloadIdentityPoolId: pulumi.String("example-pool"),
			DisplayName:            pulumi.String("Name of the pool"),
			Description:            pulumi.String("Identity pool operates in FEDERATION_ONLY mode"),
			Disabled:               pulumi.Bool(true),
			Mode:                   pulumi.String("FEDERATION_ONLY"),
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;

return await Deployment.RunAsync(() => 
{
    var example = new Gcp.Iam.WorkloadIdentityPool("example", new()
    {
        WorkloadIdentityPoolId = "example-pool",
        DisplayName = "Name of the pool",
        Description = "Identity pool operates in FEDERATION_ONLY mode",
        Disabled = true,
        Mode = "FEDERATION_ONLY",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.iam.WorkloadIdentityPool;
import com.pulumi.gcp.iam.WorkloadIdentityPoolArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var example = new WorkloadIdentityPool("example", WorkloadIdentityPoolArgs.builder()
            .workloadIdentityPoolId("example-pool")
            .displayName("Name of the pool")
            .description("Identity pool operates in FEDERATION_ONLY mode")
            .disabled(true)
            .mode("FEDERATION_ONLY")
            .build());

    }
}
resources:
  example:
    type: gcp:iam:WorkloadIdentityPool
    properties:
      workloadIdentityPoolId: example-pool
      displayName: Name of the pool
      description: Identity pool operates in FEDERATION_ONLY mode
      disabled: true
      mode: FEDERATION_ONLY

The displayName and description properties add organizational metadata. Setting disabled to true prevents token exchange while preserving the pool configuration. The mode property explicitly declares FEDERATION_ONLY operation; this field is immutable after creation.

Issue mTLS certificates for Google Cloud workloads

TRUST_DOMAIN mode pools assign identities to Google Cloud workloads and issue mTLS certificates for mutual authentication.

import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
import * as std from "@pulumi/std";

const example = new gcp.iam.WorkloadIdentityPool("example", {
    workloadIdentityPoolId: "example-pool",
    displayName: "Name of the pool",
    description: "Identity pool operates in TRUST_DOMAIN mode",
    disabled: true,
    mode: "TRUST_DOMAIN",
    inlineCertificateIssuanceConfig: {
        caPools: {
            "us-central1": "projects/project-bar/locations/us-central1/caPools/ca-pool-bar",
            "asia-east2": "projects/project-foo/locations/asia-east2/caPools/ca-pool-foo",
        },
        lifetime: "86400s",
        rotationWindowPercentage: 50,
        keyAlgorithm: "ECDSA_P256",
    },
    inlineTrustConfig: {
        additionalTrustBundles: [
            {
                trustDomain: "example.com",
                trustAnchors: [
                    {
                        pemCertificate: std.file({
                            input: "test-fixtures/trust_anchor_1.pem",
                        }).then(invoke => invoke.result),
                    },
                    {
                        pemCertificate: std.file({
                            input: "test-fixtures/trust_anchor_2.pem",
                        }).then(invoke => invoke.result),
                    },
                ],
            },
            {
                trustDomain: "example.net",
                trustAnchors: [
                    {
                        pemCertificate: std.file({
                            input: "test-fixtures/trust_anchor_3.pem",
                        }).then(invoke => invoke.result),
                    },
                    {
                        pemCertificate: std.file({
                            input: "test-fixtures/trust_anchor_4.pem",
                        }).then(invoke => invoke.result),
                    },
                ],
            },
        ],
    },
});
import pulumi
import pulumi_gcp as gcp
import pulumi_std as std

example = gcp.iam.WorkloadIdentityPool("example",
    workload_identity_pool_id="example-pool",
    display_name="Name of the pool",
    description="Identity pool operates in TRUST_DOMAIN mode",
    disabled=True,
    mode="TRUST_DOMAIN",
    inline_certificate_issuance_config={
        "ca_pools": {
            "us-central1": "projects/project-bar/locations/us-central1/caPools/ca-pool-bar",
            "asia-east2": "projects/project-foo/locations/asia-east2/caPools/ca-pool-foo",
        },
        "lifetime": "86400s",
        "rotation_window_percentage": 50,
        "key_algorithm": "ECDSA_P256",
    },
    inline_trust_config={
        "additional_trust_bundles": [
            {
                "trust_domain": "example.com",
                "trust_anchors": [
                    {
                        "pem_certificate": std.file(input="test-fixtures/trust_anchor_1.pem").result,
                    },
                    {
                        "pem_certificate": std.file(input="test-fixtures/trust_anchor_2.pem").result,
                    },
                ],
            },
            {
                "trust_domain": "example.net",
                "trust_anchors": [
                    {
                        "pem_certificate": std.file(input="test-fixtures/trust_anchor_3.pem").result,
                    },
                    {
                        "pem_certificate": std.file(input="test-fixtures/trust_anchor_4.pem").result,
                    },
                ],
            },
        ],
    })
package main

import (
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/iam"
	"github.com/pulumi/pulumi-std/sdk/go/std"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		invokeFile, err := std.File(ctx, &std.FileArgs{
			Input: "test-fixtures/trust_anchor_1.pem",
		}, nil)
		if err != nil {
			return err
		}
		invokeFile1, err := std.File(ctx, &std.FileArgs{
			Input: "test-fixtures/trust_anchor_2.pem",
		}, nil)
		if err != nil {
			return err
		}
		invokeFile2, err := std.File(ctx, &std.FileArgs{
			Input: "test-fixtures/trust_anchor_3.pem",
		}, nil)
		if err != nil {
			return err
		}
		invokeFile3, err := std.File(ctx, &std.FileArgs{
			Input: "test-fixtures/trust_anchor_4.pem",
		}, nil)
		if err != nil {
			return err
		}
		_, err = iam.NewWorkloadIdentityPool(ctx, "example", &iam.WorkloadIdentityPoolArgs{
			WorkloadIdentityPoolId: pulumi.String("example-pool"),
			DisplayName:            pulumi.String("Name of the pool"),
			Description:            pulumi.String("Identity pool operates in TRUST_DOMAIN mode"),
			Disabled:               pulumi.Bool(true),
			Mode:                   pulumi.String("TRUST_DOMAIN"),
			InlineCertificateIssuanceConfig: &iam.WorkloadIdentityPoolInlineCertificateIssuanceConfigArgs{
				CaPools: pulumi.StringMap{
					"us-central1": pulumi.String("projects/project-bar/locations/us-central1/caPools/ca-pool-bar"),
					"asia-east2":  pulumi.String("projects/project-foo/locations/asia-east2/caPools/ca-pool-foo"),
				},
				Lifetime:                 pulumi.String("86400s"),
				RotationWindowPercentage: pulumi.Int(50),
				KeyAlgorithm:             pulumi.String("ECDSA_P256"),
			},
			InlineTrustConfig: &iam.WorkloadIdentityPoolInlineTrustConfigArgs{
				AdditionalTrustBundles: iam.WorkloadIdentityPoolInlineTrustConfigAdditionalTrustBundleArray{
					&iam.WorkloadIdentityPoolInlineTrustConfigAdditionalTrustBundleArgs{
						TrustDomain: pulumi.String("example.com"),
						TrustAnchors: iam.WorkloadIdentityPoolInlineTrustConfigAdditionalTrustBundleTrustAnchorArray{
							&iam.WorkloadIdentityPoolInlineTrustConfigAdditionalTrustBundleTrustAnchorArgs{
								PemCertificate: pulumi.String(invokeFile.Result),
							},
							&iam.WorkloadIdentityPoolInlineTrustConfigAdditionalTrustBundleTrustAnchorArgs{
								PemCertificate: pulumi.String(invokeFile1.Result),
							},
						},
					},
					&iam.WorkloadIdentityPoolInlineTrustConfigAdditionalTrustBundleArgs{
						TrustDomain: pulumi.String("example.net"),
						TrustAnchors: iam.WorkloadIdentityPoolInlineTrustConfigAdditionalTrustBundleTrustAnchorArray{
							&iam.WorkloadIdentityPoolInlineTrustConfigAdditionalTrustBundleTrustAnchorArgs{
								PemCertificate: pulumi.String(invokeFile2.Result),
							},
							&iam.WorkloadIdentityPoolInlineTrustConfigAdditionalTrustBundleTrustAnchorArgs{
								PemCertificate: pulumi.String(invokeFile3.Result),
							},
						},
					},
				},
			},
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;
using Std = Pulumi.Std;

return await Deployment.RunAsync(() => 
{
    var example = new Gcp.Iam.WorkloadIdentityPool("example", new()
    {
        WorkloadIdentityPoolId = "example-pool",
        DisplayName = "Name of the pool",
        Description = "Identity pool operates in TRUST_DOMAIN mode",
        Disabled = true,
        Mode = "TRUST_DOMAIN",
        InlineCertificateIssuanceConfig = new Gcp.Iam.Inputs.WorkloadIdentityPoolInlineCertificateIssuanceConfigArgs
        {
            CaPools = 
            {
                { "us-central1", "projects/project-bar/locations/us-central1/caPools/ca-pool-bar" },
                { "asia-east2", "projects/project-foo/locations/asia-east2/caPools/ca-pool-foo" },
            },
            Lifetime = "86400s",
            RotationWindowPercentage = 50,
            KeyAlgorithm = "ECDSA_P256",
        },
        InlineTrustConfig = new Gcp.Iam.Inputs.WorkloadIdentityPoolInlineTrustConfigArgs
        {
            AdditionalTrustBundles = new[]
            {
                new Gcp.Iam.Inputs.WorkloadIdentityPoolInlineTrustConfigAdditionalTrustBundleArgs
                {
                    TrustDomain = "example.com",
                    TrustAnchors = new[]
                    {
                        new Gcp.Iam.Inputs.WorkloadIdentityPoolInlineTrustConfigAdditionalTrustBundleTrustAnchorArgs
                        {
                            PemCertificate = Std.File.Invoke(new()
                            {
                                Input = "test-fixtures/trust_anchor_1.pem",
                            }).Apply(invoke => invoke.Result),
                        },
                        new Gcp.Iam.Inputs.WorkloadIdentityPoolInlineTrustConfigAdditionalTrustBundleTrustAnchorArgs
                        {
                            PemCertificate = Std.File.Invoke(new()
                            {
                                Input = "test-fixtures/trust_anchor_2.pem",
                            }).Apply(invoke => invoke.Result),
                        },
                    },
                },
                new Gcp.Iam.Inputs.WorkloadIdentityPoolInlineTrustConfigAdditionalTrustBundleArgs
                {
                    TrustDomain = "example.net",
                    TrustAnchors = new[]
                    {
                        new Gcp.Iam.Inputs.WorkloadIdentityPoolInlineTrustConfigAdditionalTrustBundleTrustAnchorArgs
                        {
                            PemCertificate = Std.File.Invoke(new()
                            {
                                Input = "test-fixtures/trust_anchor_3.pem",
                            }).Apply(invoke => invoke.Result),
                        },
                        new Gcp.Iam.Inputs.WorkloadIdentityPoolInlineTrustConfigAdditionalTrustBundleTrustAnchorArgs
                        {
                            PemCertificate = Std.File.Invoke(new()
                            {
                                Input = "test-fixtures/trust_anchor_4.pem",
                            }).Apply(invoke => invoke.Result),
                        },
                    },
                },
            },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.iam.WorkloadIdentityPool;
import com.pulumi.gcp.iam.WorkloadIdentityPoolArgs;
import com.pulumi.gcp.iam.inputs.WorkloadIdentityPoolInlineCertificateIssuanceConfigArgs;
import com.pulumi.gcp.iam.inputs.WorkloadIdentityPoolInlineTrustConfigArgs;
import com.pulumi.std.StdFunctions;
import com.pulumi.std.inputs.FileArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var example = new WorkloadIdentityPool("example", WorkloadIdentityPoolArgs.builder()
            .workloadIdentityPoolId("example-pool")
            .displayName("Name of the pool")
            .description("Identity pool operates in TRUST_DOMAIN mode")
            .disabled(true)
            .mode("TRUST_DOMAIN")
            .inlineCertificateIssuanceConfig(WorkloadIdentityPoolInlineCertificateIssuanceConfigArgs.builder()
                .caPools(Map.ofEntries(
                    Map.entry("us-central1", "projects/project-bar/locations/us-central1/caPools/ca-pool-bar"),
                    Map.entry("asia-east2", "projects/project-foo/locations/asia-east2/caPools/ca-pool-foo")
                ))
                .lifetime("86400s")
                .rotationWindowPercentage(50)
                .keyAlgorithm("ECDSA_P256")
                .build())
            .inlineTrustConfig(WorkloadIdentityPoolInlineTrustConfigArgs.builder()
                .additionalTrustBundles(                
                    WorkloadIdentityPoolInlineTrustConfigAdditionalTrustBundleArgs.builder()
                        .trustDomain("example.com")
                        .trustAnchors(                        
                            WorkloadIdentityPoolInlineTrustConfigAdditionalTrustBundleTrustAnchorArgs.builder()
                                .pemCertificate(StdFunctions.file(FileArgs.builder()
                                    .input("test-fixtures/trust_anchor_1.pem")
                                    .build()).result())
                                .build(),
                            WorkloadIdentityPoolInlineTrustConfigAdditionalTrustBundleTrustAnchorArgs.builder()
                                .pemCertificate(StdFunctions.file(FileArgs.builder()
                                    .input("test-fixtures/trust_anchor_2.pem")
                                    .build()).result())
                                .build())
                        .build(),
                    WorkloadIdentityPoolInlineTrustConfigAdditionalTrustBundleArgs.builder()
                        .trustDomain("example.net")
                        .trustAnchors(                        
                            WorkloadIdentityPoolInlineTrustConfigAdditionalTrustBundleTrustAnchorArgs.builder()
                                .pemCertificate(StdFunctions.file(FileArgs.builder()
                                    .input("test-fixtures/trust_anchor_3.pem")
                                    .build()).result())
                                .build(),
                            WorkloadIdentityPoolInlineTrustConfigAdditionalTrustBundleTrustAnchorArgs.builder()
                                .pemCertificate(StdFunctions.file(FileArgs.builder()
                                    .input("test-fixtures/trust_anchor_4.pem")
                                    .build()).result())
                                .build())
                        .build())
                .build())
            .build());

    }
}
resources:
  example:
    type: gcp:iam:WorkloadIdentityPool
    properties:
      workloadIdentityPoolId: example-pool
      displayName: Name of the pool
      description: Identity pool operates in TRUST_DOMAIN mode
      disabled: true
      mode: TRUST_DOMAIN
      inlineCertificateIssuanceConfig:
        caPools:
          us-central1: projects/project-bar/locations/us-central1/caPools/ca-pool-bar
          asia-east2: projects/project-foo/locations/asia-east2/caPools/ca-pool-foo
        lifetime: 86400s
        rotationWindowPercentage: 50
        keyAlgorithm: ECDSA_P256
      inlineTrustConfig:
        additionalTrustBundles:
          - trustDomain: example.com
            trustAnchors:
              - pemCertificate:
                  fn::invoke:
                    function: std:file
                    arguments:
                      input: test-fixtures/trust_anchor_1.pem
                    return: result
              - pemCertificate:
                  fn::invoke:
                    function: std:file
                    arguments:
                      input: test-fixtures/trust_anchor_2.pem
                    return: result
          - trustDomain: example.net
            trustAnchors:
              - pemCertificate:
                  fn::invoke:
                    function: std:file
                    arguments:
                      input: test-fixtures/trust_anchor_3.pem
                    return: result
              - pemCertificate:
                  fn::invoke:
                    function: std:file
                    arguments:
                      input: test-fixtures/trust_anchor_4.pem
                    return: result

In TRUST_DOMAIN mode, the pool issues certificates rather than federating external identities. The inlineCertificateIssuanceConfig defines Certificate Authority pools by region, certificate lifetime, and rotation behavior. The inlineTrustConfig establishes trust relationships by specifying trust domains and their PEM-encoded trust anchor certificates. All identities must follow the format ns/<namespace>/sa/<workload_identifier>.

Beyond these examples

These snippets focus on specific pool-level features: federation and trust domain modes, certificate issuance and trust configuration, and pool metadata and state management. They’re intentionally minimal rather than full identity federation solutions.

The examples may reference pre-existing infrastructure such as Certificate Authority pools (for TRUST_DOMAIN mode) and PEM certificate files for trust anchors. They focus on configuring the pool rather than provisioning the complete identity infrastructure.

To keep things focused, common pool patterns are omitted, including:

  • WorkloadIdentityPoolProvider configuration (required for FEDERATION_ONLY)
  • IAM policy bindings for granting pool access to resources
  • Subject identifier format constraints (ns//sa/<workload_identifier>)
  • Pool deletion and soft-delete recovery (UndeleteWorkloadIdentityPool)

These omissions are intentional: the goal is to illustrate how each pool feature is wired, not provide drop-in identity federation modules. See the Workload Identity Pool resource reference for all available configuration options.

Let's configure GCP Workload Identity Pools

Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.

Try Pulumi Cloud for FREE

Frequently Asked Questions

Mode Selection & Immutability
Why does my mode change fail even though preview succeeded?
The mode field is immutable after creation. While pulumi preview may show an update if you change this value, pulumi up will fail with an API error like “Error 400: Attempted to update an immutable field.” You must create a new Workload Identity Pool resource to use a different mode.
What's the difference between FEDERATION_ONLY and TRUST_DOMAIN modes?
FEDERATION_ONLY (the default) is for federating external workload identities into Google Cloud with no format constraints, and you can create providers within the pool. TRUST_DOMAIN is for assigning identities to Google Cloud workloads, requires a specific subject identifier format (ns/<namespace>/sa/<workload_identifier>), and does not allow creating gcp.iam.WorkloadIdentityPoolProviders.
Can I create providers in TRUST_DOMAIN mode?
No, gcp.iam.WorkloadIdentityPoolProviders cannot be created within TRUST_DOMAIN mode pools. Use FEDERATION_ONLY mode if you need providers.
What subject identifier format is required for TRUST_DOMAIN mode?
All identities within a TRUST_DOMAIN mode pool must conform to the format: ns/<namespace>/sa/<workload_identifier>.
Configuration & Constraints
Can I use 'gcp-' as a prefix for my pool ID?
No, the prefix gcp- is reserved for use by Google and cannot be specified in workloadIdentityPoolId.
What are the naming and length constraints for pool properties?
workloadIdentityPoolId must be 4-32 characters using only [a-z0-9-]. displayName cannot exceed 32 characters. description cannot exceed 256 characters.
What happens when I disable a workload identity pool?
You cannot use a disabled pool to exchange tokens, and existing tokens will no longer grant access to resources. If you re-enable the pool, existing tokens will grant access again.
Pool Lifecycle & State Management
What happens when I delete a workload identity pool?
Pools are soft-deleted and permanently deleted after approximately 30 days. You can restore a soft-deleted pool using UndeleteWorkloadIdentityPool. You cannot reuse the pool ID until it’s permanently deleted, and deleted pools cannot exchange tokens or grant access with existing tokens.
What properties can't I change after creating the pool?
The project, workloadIdentityPoolId, and mode fields are immutable after creation. Attempting to change mode will cause pulumi up to fail even if preview succeeds.

Using a different cloud?

Explore security guides for other cloud providers: