Manage GCP Dataproc Metastore Database IAM Access

The gcp:dataproc/metastoreDatabaseIamMember:MetastoreDatabaseIamMember resource, part of the Pulumi GCP provider, manages IAM permissions for Dataproc Metastore databases by adding individual members to roles. This guide focuses on three approaches: adding individual members, managing complete member lists per role, and replacing entire IAM policies.

GCP provides three related resources for database IAM: MetastoreDatabaseIamMember (non-authoritative, adds one member), MetastoreDatabaseIamBinding (authoritative for a role, manages all members), and MetastoreDatabaseIamPolicy (authoritative, replaces the entire policy). The examples are intentionally small. Choose the resource that matches your access control requirements.

Grant a single user access to a database

Most IAM configurations add individual users or service accounts to databases without affecting other permissions.

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

const member = new gcp.dataproc.MetastoreDatabaseIamMember("member", {
    project: dpmsService.project,
    location: dpmsService.location,
    serviceId: dpmsService.serviceId,
    database: hive.hiveConfig[0].properties.database,
    role: "roles/viewer",
    member: "user:jane@example.com",
});
import pulumi
import pulumi_gcp as gcp

member = gcp.dataproc.MetastoreDatabaseIamMember("member",
    project=dpms_service["project"],
    location=dpms_service["location"],
    service_id=dpms_service["serviceId"],
    database=hive["hiveConfig"][0]["properties"]["database"],
    role="roles/viewer",
    member="user:jane@example.com")
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := dataproc.NewMetastoreDatabaseIamMember(ctx, "member", &dataproc.MetastoreDatabaseIamMemberArgs{
			Project:   pulumi.Any(dpmsService.Project),
			Location:  pulumi.Any(dpmsService.Location),
			ServiceId: pulumi.Any(dpmsService.ServiceId),
			Database:  pulumi.Any(hive.HiveConfig[0].Properties.Database),
			Role:      pulumi.String("roles/viewer"),
			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.Dataproc.MetastoreDatabaseIamMember("member", new()
    {
        Project = dpmsService.Project,
        Location = dpmsService.Location,
        ServiceId = dpmsService.ServiceId,
        Database = hive.HiveConfig[0].Properties.Database,
        Role = "roles/viewer",
        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.dataproc.MetastoreDatabaseIamMember;
import com.pulumi.gcp.dataproc.MetastoreDatabaseIamMemberArgs;
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 MetastoreDatabaseIamMember("member", MetastoreDatabaseIamMemberArgs.builder()
            .project(dpmsService.project())
            .location(dpmsService.location())
            .serviceId(dpmsService.serviceId())
            .database(hive.hiveConfig()[0].properties().database())
            .role("roles/viewer")
            .member("user:jane@example.com")
            .build());

    }
}
resources:
  member:
    type: gcp:dataproc:MetastoreDatabaseIamMember
    properties:
      project: ${dpmsService.project}
      location: ${dpmsService.location}
      serviceId: ${dpmsService.serviceId}
      database: ${hive.hiveConfig[0].properties.database}
      role: roles/viewer
      member: user:jane@example.com

The member property specifies who gets access (user, service account, group, or domain). The role property defines what they can do. This resource is non-authoritative: it adds the member without removing others who already have the same role. The database, serviceId, location, and project properties identify which Metastore database to modify.

Grant a role to multiple members at once

When multiple users need the same access level, MetastoreDatabaseIamBinding manages the complete member list for a role.

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

const binding = new gcp.dataproc.MetastoreDatabaseIamBinding("binding", {
    project: dpmsService.project,
    location: dpmsService.location,
    serviceId: dpmsService.serviceId,
    database: hive.hiveConfig[0].properties.database,
    role: "roles/viewer",
    members: ["user:jane@example.com"],
});
import pulumi
import pulumi_gcp as gcp

binding = gcp.dataproc.MetastoreDatabaseIamBinding("binding",
    project=dpms_service["project"],
    location=dpms_service["location"],
    service_id=dpms_service["serviceId"],
    database=hive["hiveConfig"][0]["properties"]["database"],
    role="roles/viewer",
    members=["user:jane@example.com"])
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := dataproc.NewMetastoreDatabaseIamBinding(ctx, "binding", &dataproc.MetastoreDatabaseIamBindingArgs{
			Project:   pulumi.Any(dpmsService.Project),
			Location:  pulumi.Any(dpmsService.Location),
			ServiceId: pulumi.Any(dpmsService.ServiceId),
			Database:  pulumi.Any(hive.HiveConfig[0].Properties.Database),
			Role:      pulumi.String("roles/viewer"),
			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.Dataproc.MetastoreDatabaseIamBinding("binding", new()
    {
        Project = dpmsService.Project,
        Location = dpmsService.Location,
        ServiceId = dpmsService.ServiceId,
        Database = hive.HiveConfig[0].Properties.Database,
        Role = "roles/viewer",
        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.dataproc.MetastoreDatabaseIamBinding;
import com.pulumi.gcp.dataproc.MetastoreDatabaseIamBindingArgs;
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 MetastoreDatabaseIamBinding("binding", MetastoreDatabaseIamBindingArgs.builder()
            .project(dpmsService.project())
            .location(dpmsService.location())
            .serviceId(dpmsService.serviceId())
            .database(hive.hiveConfig()[0].properties().database())
            .role("roles/viewer")
            .members("user:jane@example.com")
            .build());

    }
}
resources:
  binding:
    type: gcp:dataproc:MetastoreDatabaseIamBinding
    properties:
      project: ${dpmsService.project}
      location: ${dpmsService.location}
      serviceId: ${dpmsService.serviceId}
      database: ${hive.hiveConfig[0].properties.database}
      role: roles/viewer
      members:
        - user:jane@example.com

The members property lists all identities that should have this role. This resource is authoritative for the specified role: it sets the complete member list, removing anyone not in the array. Other roles on the database remain unchanged. You can combine MetastoreDatabaseIamBinding with MetastoreDatabaseIamMember only if they manage different roles.

Replace the entire IAM policy for a database

Organizations with strict access control sometimes define the complete IAM policy from scratch.

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

const admin = gcp.organizations.getIAMPolicy({
    bindings: [{
        role: "roles/viewer",
        members: ["user:jane@example.com"],
    }],
});
const policy = new gcp.dataproc.MetastoreDatabaseIamPolicy("policy", {
    project: dpmsService.project,
    location: dpmsService.location,
    serviceId: dpmsService.serviceId,
    database: hive.hiveConfig[0].properties.database,
    policyData: admin.then(admin => admin.policyData),
});
import pulumi
import pulumi_gcp as gcp

admin = gcp.organizations.get_iam_policy(bindings=[{
    "role": "roles/viewer",
    "members": ["user:jane@example.com"],
}])
policy = gcp.dataproc.MetastoreDatabaseIamPolicy("policy",
    project=dpms_service["project"],
    location=dpms_service["location"],
    service_id=dpms_service["serviceId"],
    database=hive["hiveConfig"][0]["properties"]["database"],
    policy_data=admin.policy_data)
package main

import (
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/dataproc"
	"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/viewer",
					Members: []string{
						"user:jane@example.com",
					},
				},
			},
		}, nil)
		if err != nil {
			return err
		}
		_, err = dataproc.NewMetastoreDatabaseIamPolicy(ctx, "policy", &dataproc.MetastoreDatabaseIamPolicyArgs{
			Project:    pulumi.Any(dpmsService.Project),
			Location:   pulumi.Any(dpmsService.Location),
			ServiceId:  pulumi.Any(dpmsService.ServiceId),
			Database:   pulumi.Any(hive.HiveConfig[0].Properties.Database),
			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/viewer",
                Members = new[]
                {
                    "user:jane@example.com",
                },
            },
        },
    });

    var policy = new Gcp.Dataproc.MetastoreDatabaseIamPolicy("policy", new()
    {
        Project = dpmsService.Project,
        Location = dpmsService.Location,
        ServiceId = dpmsService.ServiceId,
        Database = hive.HiveConfig[0].Properties.Database,
        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.dataproc.MetastoreDatabaseIamPolicy;
import com.pulumi.gcp.dataproc.MetastoreDatabaseIamPolicyArgs;
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/viewer")
                .members("user:jane@example.com")
                .build())
            .build());

        var policy = new MetastoreDatabaseIamPolicy("policy", MetastoreDatabaseIamPolicyArgs.builder()
            .project(dpmsService.project())
            .location(dpmsService.location())
            .serviceId(dpmsService.serviceId())
            .database(hive.hiveConfig()[0].properties().database())
            .policyData(admin.policyData())
            .build());

    }
}
resources:
  policy:
    type: gcp:dataproc:MetastoreDatabaseIamPolicy
    properties:
      project: ${dpmsService.project}
      location: ${dpmsService.location}
      serviceId: ${dpmsService.serviceId}
      database: ${hive.hiveConfig[0].properties.database}
      policyData: ${admin.policyData}
variables:
  admin:
    fn::invoke:
      function: gcp:organizations:getIAMPolicy
      arguments:
        bindings:
          - role: roles/viewer
            members:
              - user:jane@example.com

The policyData property contains the full IAM policy, typically retrieved from getIAMPolicy. This resource is fully authoritative: it replaces the entire policy, removing any bindings not specified. MetastoreDatabaseIamPolicy cannot be used with MetastoreDatabaseIamBinding or MetastoreDatabaseIamMember; they will conflict over policy state.

Beyond these examples

These snippets focus on specific IAM management approaches: single-member grants, role-level member lists, and complete policy replacement. They’re intentionally minimal rather than full access control configurations.

The examples reference pre-existing infrastructure such as Dataproc Metastore service (serviceId) and Metastore database (database name from hive configuration). They focus on IAM binding configuration rather than provisioning the Metastore service itself.

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

  • Conditional IAM bindings (condition property)
  • Custom role definitions
  • Federated identity configuration
  • Policy retrieval via data sources

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 Metastore Database IAM Member resource reference for all available configuration options.

Let's manage GCP Dataproc Metastore Database IAM Access

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

Try Pulumi Cloud for FREE

Frequently Asked Questions

Resource Selection & Conflicts
Which IAM resources can I use together?
You cannot use gcp.dataproc.MetastoreDatabaseIamPolicy with gcp.dataproc.MetastoreDatabaseIamBinding or gcp.dataproc.MetastoreDatabaseIamMember, as they will conflict over policy control. However, you can use MetastoreDatabaseIamBinding and MetastoreDatabaseIamMember together only if they grant different roles.
What's the difference between the three IAM resource types?

There are three options:

  1. MetastoreDatabaseIamPolicy - Authoritative, replaces the entire IAM policy
  2. MetastoreDatabaseIamBinding - Authoritative for a specific role, preserves other roles
  3. MetastoreDatabaseIamMember - Non-authoritative, adds a single member to a role while preserving other members
When should I use Member vs Binding vs Policy?
Use MetastoreDatabaseIamPolicy when you need complete control over all IAM permissions. Use MetastoreDatabaseIamBinding to manage all members for a specific role. Use MetastoreDatabaseIamMember to add individual members without affecting existing role assignments.
Configuration & Identity Formats
What identity formats can I use in the member property?

Valid formats include:

  • allUsers or allAuthenticatedUsers for public/authenticated access
  • user:{email} for specific Google accounts (e.g., user:alice@gmail.com)
  • serviceAccount:{email} for service accounts
  • group:{email} for Google groups
  • domain:{domain} for G Suite domains
  • projectOwner:, projectEditor:, or projectViewer: with project ID
  • Federated identities using principal:// format
How do I specify custom roles?
Custom roles must use the full path format: [projects|organizations]/{parent-name}/roles/{role-name}. For example, projects/my-project/roles/my-custom-role or organizations/my-org/roles/my-custom-role.
Operational Considerations
Can I modify IAM bindings after creation?
No, all main properties (database, location, member, project, role, serviceId) are immutable. You must recreate the resource to change these values.
How do I import existing IAM resources?

Import syntax varies by resource type:

  • Member: pulumi import gcp:dataproc/metastoreDatabaseIamMember:MetastoreDatabaseIamMember editor "resource-path roles/viewer user:jane@example.com"
  • Binding: pulumi import gcp:dataproc/metastoreDatabaseIamMember:MetastoreDatabaseIamMember editor "resource-path roles/viewer"
  • Policy: pulumi import gcp:dataproc/metastoreDatabaseIamMember:MetastoreDatabaseIamMember editor resource-path
What resource path formats are supported for import?

Four formats are supported (from most to least specific):

  1. projects/{{project}}/locations/{{location}}/services/{{serviceId}}/databases/{{name}}
  2. {{project}}/{{location}}/{{serviceId}}/{{name}}
  3. {{location}}/{{serviceId}}/{{name}}
  4. {{name}}

Missing values are taken from the provider configuration.

Using a different cloud?

Explore security guides for other cloud providers: