The gcp:bigtable/tableIamPolicy:TableIamPolicy resource, part of the Pulumi GCP provider, controls IAM access to Bigtable tables through three distinct resources: TableIamPolicy (replaces entire policy), TableIamBinding (manages one role), and TableIamMember (adds individual members). This guide focuses on three capabilities: authoritative policy replacement, role-level binding management, and incremental member addition.
These resources reference existing Bigtable tables and instances. TableIamPolicy cannot be used with TableIamBinding or TableIamMember, as they will conflict over policy state. TableIamBinding and TableIamMember can coexist if they manage different roles. The examples are intentionally small. Combine them with your own table infrastructure and access requirements.
Replace the entire IAM policy for a table
When you need complete control over table access, you can set the entire IAM policy at once. This is useful for initial setup or when migrating from external access control systems.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const admin = gcp.organizations.getIAMPolicy({
bindings: [{
role: "roles/bigtable.user",
members: ["user:jane@example.com"],
}],
});
const editor = new gcp.bigtable.TableIamPolicy("editor", {
project: "your-project",
instanceName: "your-bigtable-instance",
table: "your-bigtable-table",
policyData: admin.then(admin => admin.policyData),
});
import pulumi
import pulumi_gcp as gcp
admin = gcp.organizations.get_iam_policy(bindings=[{
"role": "roles/bigtable.user",
"members": ["user:jane@example.com"],
}])
editor = gcp.bigtable.TableIamPolicy("editor",
project="your-project",
instance_name="your-bigtable-instance",
table="your-bigtable-table",
policy_data=admin.policy_data)
package main
import (
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/bigtable"
"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/bigtable.user",
Members: []string{
"user:jane@example.com",
},
},
},
}, nil)
if err != nil {
return err
}
_, err = bigtable.NewTableIamPolicy(ctx, "editor", &bigtable.TableIamPolicyArgs{
Project: pulumi.String("your-project"),
InstanceName: pulumi.String("your-bigtable-instance"),
Table: pulumi.String("your-bigtable-table"),
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/bigtable.user",
Members = new[]
{
"user:jane@example.com",
},
},
},
});
var editor = new Gcp.BigTable.TableIamPolicy("editor", new()
{
Project = "your-project",
InstanceName = "your-bigtable-instance",
Table = "your-bigtable-table",
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.bigtable.TableIamPolicy;
import com.pulumi.gcp.bigtable.TableIamPolicyArgs;
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/bigtable.user")
.members("user:jane@example.com")
.build())
.build());
var editor = new TableIamPolicy("editor", TableIamPolicyArgs.builder()
.project("your-project")
.instanceName("your-bigtable-instance")
.table("your-bigtable-table")
.policyData(admin.policyData())
.build());
}
}
resources:
editor:
type: gcp:bigtable:TableIamPolicy
properties:
project: your-project
instanceName: your-bigtable-instance
table: your-bigtable-table
policyData: ${admin.policyData}
variables:
admin:
fn::invoke:
function: gcp:organizations:getIAMPolicy
arguments:
bindings:
- role: roles/bigtable.user
members:
- user:jane@example.com
The policyData property accepts output from getIAMPolicy, which defines all role bindings in a single structure. TableIamPolicy replaces the existing policy entirely, so any roles not included in policyData are removed. This makes it authoritative: what you declare is exactly what exists.
Grant a role to multiple members at once
Teams often need to grant the same role to several users or service accounts without affecting other role assignments.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const editor = new gcp.bigtable.TableIamBinding("editor", {
table: "your-bigtable-table",
instanceName: "your-bigtable-instance",
role: "roles/bigtable.user",
members: ["user:jane@example.com"],
});
import pulumi
import pulumi_gcp as gcp
editor = gcp.bigtable.TableIamBinding("editor",
table="your-bigtable-table",
instance_name="your-bigtable-instance",
role="roles/bigtable.user",
members=["user:jane@example.com"])
package main
import (
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/bigtable"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := bigtable.NewTableIamBinding(ctx, "editor", &bigtable.TableIamBindingArgs{
Table: pulumi.String("your-bigtable-table"),
InstanceName: pulumi.String("your-bigtable-instance"),
Role: pulumi.String("roles/bigtable.user"),
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 editor = new Gcp.BigTable.TableIamBinding("editor", new()
{
Table = "your-bigtable-table",
InstanceName = "your-bigtable-instance",
Role = "roles/bigtable.user",
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.bigtable.TableIamBinding;
import com.pulumi.gcp.bigtable.TableIamBindingArgs;
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 editor = new TableIamBinding("editor", TableIamBindingArgs.builder()
.table("your-bigtable-table")
.instanceName("your-bigtable-instance")
.role("roles/bigtable.user")
.members("user:jane@example.com")
.build());
}
}
resources:
editor:
type: gcp:bigtable:TableIamBinding
properties:
table: your-bigtable-table
instanceName: your-bigtable-instance
role: roles/bigtable.user
members:
- user:jane@example.com
TableIamBinding manages one role at a time. The members array lists everyone who should have that role. Other roles on the table remain unchanged, making this safer than full policy replacement when you only need to manage specific roles.
Add a single member to a role incrementally
When onboarding individual users or service accounts, you can add them to a role without listing all existing members.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const editor = new gcp.bigtable.TableIamMember("editor", {
table: "your-bigtable-table",
instanceName: "your-bigtable-instance",
role: "roles/bigtable.user",
member: "user:jane@example.com",
});
import pulumi
import pulumi_gcp as gcp
editor = gcp.bigtable.TableIamMember("editor",
table="your-bigtable-table",
instance_name="your-bigtable-instance",
role="roles/bigtable.user",
member="user:jane@example.com")
package main
import (
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/bigtable"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := bigtable.NewTableIamMember(ctx, "editor", &bigtable.TableIamMemberArgs{
Table: pulumi.String("your-bigtable-table"),
InstanceName: pulumi.String("your-bigtable-instance"),
Role: pulumi.String("roles/bigtable.user"),
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 editor = new Gcp.BigTable.TableIamMember("editor", new()
{
Table = "your-bigtable-table",
InstanceName = "your-bigtable-instance",
Role = "roles/bigtable.user",
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.bigtable.TableIamMember;
import com.pulumi.gcp.bigtable.TableIamMemberArgs;
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 editor = new TableIamMember("editor", TableIamMemberArgs.builder()
.table("your-bigtable-table")
.instanceName("your-bigtable-instance")
.role("roles/bigtable.user")
.member("user:jane@example.com")
.build());
}
}
resources:
editor:
type: gcp:bigtable:TableIamMember
properties:
table: your-bigtable-table
instanceName: your-bigtable-instance
role: roles/bigtable.user
member: user:jane@example.com
TableIamMember adds one member to one role. This is the most granular approach and the safest for concurrent modifications, since multiple TableIamMember resources can add different members to the same role without conflict.
Beyond these examples
These snippets focus on specific IAM management approaches: authoritative policy replacement, role-level binding management, and incremental member addition. They’re intentionally minimal rather than full access control configurations.
The examples reference pre-existing infrastructure such as Bigtable tables and instances. They focus on IAM policy configuration rather than provisioning the tables themselves.
To keep things focused, common IAM patterns are omitted, including:
- Conditional IAM bindings (condition blocks)
- Service account impersonation
- Cross-project access grants
- Audit logging configuration
These omissions are intentional: the goal is to illustrate how each IAM resource type modifies policies, not provide drop-in access control modules. See the Bigtable TableIamPolicy resource reference for all available configuration options.
Let's manage GCP Bigtable 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 Conflicts & Compatibility
TableIamPolicy cannot be used with TableIamBinding or TableIamMember because they will conflict over the policy configuration.TableIamPolicy replaces the entire IAM policy, so you can accidentally remove existing permissions, including table ownership. Ensure all necessary permissions are included in your policy data.Resource Selection & Usage
Choose based on your needs:
TableIamPolicy: Authoritative, replaces the entire policyTableIamBinding: Authoritative for a specific role, preserves other rolesTableIamMember: Non-authoritative, adds a single member to a role while preserving other members
gcp.organizations.getIAMPolicy to generate policy data with role bindings, then pass the policyData to TableIamPolicy.TableIamBinding with the role property and a members array containing the member identifiers.TableIamMember with the role and member properties. This preserves existing members for that role.