The gcp:iam/workforcePoolIamPolicy:WorkforcePoolIamPolicy resource, part of the Pulumi GCP provider, manages IAM policies for workforce pools, controlling who can administer and use workforce identity federation. This guide focuses on three approaches: authoritative policy replacement, role-level binding, and incremental member grants.
GCP provides three related resources for workforce pool IAM management. WorkforcePoolIamPolicy replaces the entire policy authoritatively. WorkforcePoolIamBinding manages all members for a specific role authoritatively. WorkforcePoolIamMember adds individual members non-authoritatively. These resources reference existing workforce pools and require a GCP location. The examples are intentionally small. Combine them with your own workforce pool infrastructure and organizational access patterns.
Replace the entire IAM policy authoritatively
When you need complete control over a workforce pool’s IAM policy, replacing the entire policy ensures no unexpected permissions remain.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const admin = gcp.organizations.getIAMPolicy({
bindings: [{
role: "roles/iam.workforcePoolAdmin",
members: ["user:jane@example.com"],
}],
});
const policy = new gcp.iam.WorkforcePoolIamPolicy("policy", {
location: example.location,
workforcePoolId: example.workforcePoolId,
policyData: admin.then(admin => admin.policyData),
});
import pulumi
import pulumi_gcp as gcp
admin = gcp.organizations.get_iam_policy(bindings=[{
"role": "roles/iam.workforcePoolAdmin",
"members": ["user:jane@example.com"],
}])
policy = gcp.iam.WorkforcePoolIamPolicy("policy",
location=example["location"],
workforce_pool_id=example["workforcePoolId"],
policy_data=admin.policy_data)
package main
import (
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/iam"
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/organizations"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
admin, err := organizations.LookupIAMPolicy(ctx, &organizations.LookupIAMPolicyArgs{
Bindings: []organizations.GetIAMPolicyBinding{
{
Role: "roles/iam.workforcePoolAdmin",
Members: []string{
"user:jane@example.com",
},
},
},
}, nil)
if err != nil {
return err
}
_, err = iam.NewWorkforcePoolIamPolicy(ctx, "policy", &iam.WorkforcePoolIamPolicyArgs{
Location: pulumi.Any(example.Location),
WorkforcePoolId: pulumi.Any(example.WorkforcePoolId),
PolicyData: pulumi.String(admin.PolicyData),
})
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 admin = Gcp.Organizations.GetIAMPolicy.Invoke(new()
{
Bindings = new[]
{
new Gcp.Organizations.Inputs.GetIAMPolicyBindingInputArgs
{
Role = "roles/iam.workforcePoolAdmin",
Members = new[]
{
"user:jane@example.com",
},
},
},
});
var policy = new Gcp.Iam.WorkforcePoolIamPolicy("policy", new()
{
Location = example.Location,
WorkforcePoolId = example.WorkforcePoolId,
PolicyData = admin.Apply(getIAMPolicyResult => getIAMPolicyResult.PolicyData),
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.organizations.OrganizationsFunctions;
import com.pulumi.gcp.organizations.inputs.GetIAMPolicyArgs;
import com.pulumi.gcp.iam.WorkforcePoolIamPolicy;
import com.pulumi.gcp.iam.WorkforcePoolIamPolicyArgs;
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) {
final var admin = OrganizationsFunctions.getIAMPolicy(GetIAMPolicyArgs.builder()
.bindings(GetIAMPolicyBindingArgs.builder()
.role("roles/iam.workforcePoolAdmin")
.members("user:jane@example.com")
.build())
.build());
var policy = new WorkforcePoolIamPolicy("policy", WorkforcePoolIamPolicyArgs.builder()
.location(example.location())
.workforcePoolId(example.workforcePoolId())
.policyData(admin.policyData())
.build());
}
}
resources:
policy:
type: gcp:iam:WorkforcePoolIamPolicy
properties:
location: ${example.location}
workforcePoolId: ${example.workforcePoolId}
policyData: ${admin.policyData}
variables:
admin:
fn::invoke:
function: gcp:organizations:getIAMPolicy
arguments:
bindings:
- role: roles/iam.workforcePoolAdmin
members:
- user:jane@example.com
The WorkforcePoolIamPolicy resource sets the complete IAM policy by consuming policyData from the getIAMPolicy data source. This approach is authoritative: it replaces any existing policy. The bindings array in getIAMPolicy defines roles and their members. Use this when you want to manage all workforce pool permissions in one place, but note that it cannot coexist with WorkforcePoolIamBinding or WorkforcePoolIamMember resources on the same pool.
Grant a role to multiple members at once
Teams often need to assign the same role to several users simultaneously, maintaining a single authoritative list for that role.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const binding = new gcp.iam.WorkforcePoolIamBinding("binding", {
location: example.location,
workforcePoolId: example.workforcePoolId,
role: "roles/iam.workforcePoolAdmin",
members: ["user:jane@example.com"],
});
import pulumi
import pulumi_gcp as gcp
binding = gcp.iam.WorkforcePoolIamBinding("binding",
location=example["location"],
workforce_pool_id=example["workforcePoolId"],
role="roles/iam.workforcePoolAdmin",
members=["user:jane@example.com"])
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.NewWorkforcePoolIamBinding(ctx, "binding", &iam.WorkforcePoolIamBindingArgs{
Location: pulumi.Any(example.Location),
WorkforcePoolId: pulumi.Any(example.WorkforcePoolId),
Role: pulumi.String("roles/iam.workforcePoolAdmin"),
Members: pulumi.StringArray{
pulumi.String("user:jane@example.com"),
},
})
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 binding = new Gcp.Iam.WorkforcePoolIamBinding("binding", new()
{
Location = example.Location,
WorkforcePoolId = example.WorkforcePoolId,
Role = "roles/iam.workforcePoolAdmin",
Members = new[]
{
"user:jane@example.com",
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.iam.WorkforcePoolIamBinding;
import com.pulumi.gcp.iam.WorkforcePoolIamBindingArgs;
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 binding = new WorkforcePoolIamBinding("binding", WorkforcePoolIamBindingArgs.builder()
.location(example.location())
.workforcePoolId(example.workforcePoolId())
.role("roles/iam.workforcePoolAdmin")
.members("user:jane@example.com")
.build());
}
}
resources:
binding:
type: gcp:iam:WorkforcePoolIamBinding
properties:
location: ${example.location}
workforcePoolId: ${example.workforcePoolId}
role: roles/iam.workforcePoolAdmin
members:
- user:jane@example.com
The WorkforcePoolIamBinding resource manages all members for a specific role. The members array lists user identities in the format “user:email@example.com”. This resource is authoritative for its role: it replaces any previous member list for that role while preserving other roles in the policy. You can use multiple WorkforcePoolIamBinding resources on the same pool as long as they manage different roles.
Add a single member to a role incrementally
When granting access to individual users without affecting other members, non-authoritative member resources let you add permissions incrementally.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const member = new gcp.iam.WorkforcePoolIamMember("member", {
location: example.location,
workforcePoolId: example.workforcePoolId,
role: "roles/iam.workforcePoolAdmin",
member: "user:jane@example.com",
});
import pulumi
import pulumi_gcp as gcp
member = gcp.iam.WorkforcePoolIamMember("member",
location=example["location"],
workforce_pool_id=example["workforcePoolId"],
role="roles/iam.workforcePoolAdmin",
member="user:jane@example.com")
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.NewWorkforcePoolIamMember(ctx, "member", &iam.WorkforcePoolIamMemberArgs{
Location: pulumi.Any(example.Location),
WorkforcePoolId: pulumi.Any(example.WorkforcePoolId),
Role: pulumi.String("roles/iam.workforcePoolAdmin"),
Member: pulumi.String("user:jane@example.com"),
})
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 member = new Gcp.Iam.WorkforcePoolIamMember("member", new()
{
Location = example.Location,
WorkforcePoolId = example.WorkforcePoolId,
Role = "roles/iam.workforcePoolAdmin",
Member = "user:jane@example.com",
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.iam.WorkforcePoolIamMember;
import com.pulumi.gcp.iam.WorkforcePoolIamMemberArgs;
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 member = new WorkforcePoolIamMember("member", WorkforcePoolIamMemberArgs.builder()
.location(example.location())
.workforcePoolId(example.workforcePoolId())
.role("roles/iam.workforcePoolAdmin")
.member("user:jane@example.com")
.build());
}
}
resources:
member:
type: gcp:iam:WorkforcePoolIamMember
properties:
location: ${example.location}
workforcePoolId: ${example.workforcePoolId}
role: roles/iam.workforcePoolAdmin
member: user:jane@example.com
The WorkforcePoolIamMember resource grants a role to one member without modifying other members of that role. The member property specifies a single identity. This is the only non-authoritative resource in the set: multiple WorkforcePoolIamMember resources can grant the same role to different members. Use this when you want to add access without coordinating with other team members managing the same role.
Beyond these examples
These snippets focus on specific IAM management approaches: authoritative vs non-authoritative management and policy-level, role-level, and member-level access control. They’re intentionally minimal rather than full identity federation deployments.
The examples reference pre-existing infrastructure such as workforce pools (workforcePoolId) and GCP locations for workforce pool resources. They focus on IAM policy configuration rather than provisioning the workforce pools themselves.
To keep things focused, common IAM patterns are omitted, including:
- Custom role definitions and naming conventions
- Conditional IAM bindings (IAM Conditions)
- Service account impersonation patterns
- Audit logging configuration for access changes
These omissions are intentional: the goal is to illustrate how each IAM resource type is wired, not provide drop-in access control modules. See the WorkforcePoolIamPolicy resource reference for all available configuration options.
Let's manage GCP Workforce Pool IAM Policies
Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.
Try Pulumi Cloud for FREEFrequently Asked Questions
Resource Selection & Conflicts
WorkforcePoolIamPolicy is authoritative and replaces the entire IAM policy. WorkforcePoolIamBinding is authoritative for a specific role, preserving other roles. WorkforcePoolIamMember is non-authoritative, adding a single member while preserving other members for that role.WorkforcePoolIamPolicy cannot be used with WorkforcePoolIamBinding or WorkforcePoolIamMember because they will conflict over policy control.Configuration & Setup
WorkforcePoolIamPolicy with policyData from gcp.organizations.getIAMPolicy, as shown in the policy example.WorkforcePoolIamBinding with the role and members array properties, as shown in the binding example.WorkforcePoolIamMember with the role and member properties, as shown in the member example.location and workforcePoolId are immutable and cannot be changed after the resource is created.Import & Custom Roles
[projects/my-project|organizations/my-org]/roles/my-custom-role when importing.