Manage GCP Cloud Endpoints IAM Policies

The gcp:endpoints/serviceIamPolicy:ServiceIamPolicy resource, part of the Pulumi GCP provider, manages IAM policies for Cloud Endpoints services. This guide focuses on three approaches: authoritative policy replacement, role-level member management, and incremental member addition.

The ServiceIamPolicy, ServiceIamBinding, and ServiceIamMember resources provide different levels of control. ServiceIamPolicy replaces the entire policy; ServiceIamBinding manages all members for a specific role; ServiceIamMember adds individual members. All three reference an existing Cloud Endpoints service. The examples are intentionally small. Combine them with your own service definitions and organizational access patterns.

Replace the entire IAM policy for a service

When you need complete control over service access, ServiceIamPolicy replaces the entire IAM policy with your configuration.

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.endpoints.ServiceIamPolicy("policy", {
    serviceName: endpointsService.serviceName,
    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.endpoints.ServiceIamPolicy("policy",
    service_name=endpoints_service["serviceName"],
    policy_data=admin.policy_data)
package main

import (
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/endpoints"
	"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 = endpoints.NewServiceIamPolicy(ctx, "policy", &endpoints.ServiceIamPolicyArgs{
			ServiceName: pulumi.Any(endpointsService.ServiceName),
			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.Endpoints.ServiceIamPolicy("policy", new()
    {
        ServiceName = endpointsService.ServiceName,
        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.endpoints.ServiceIamPolicy;
import com.pulumi.gcp.endpoints.ServiceIamPolicyArgs;
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 ServiceIamPolicy("policy", ServiceIamPolicyArgs.builder()
            .serviceName(endpointsService.serviceName())
            .policyData(admin.policyData())
            .build());

    }
}
resources:
  policy:
    type: gcp:endpoints:ServiceIamPolicy
    properties:
      serviceName: ${endpointsService.serviceName}
      policyData: ${admin.policyData}
variables:
  admin:
    fn::invoke:
      function: gcp:organizations:getIAMPolicy
      arguments:
        bindings:
          - role: roles/viewer
            members:
              - user:jane@example.com

The policyData property accepts output from getIAMPolicy, which defines bindings between roles and members. ServiceIamPolicy is authoritative: it removes any permissions not specified in your policy. The serviceName property identifies which Cloud Endpoints service to configure.

Grant a role to multiple members at once

Teams often grant the same role to several users while preserving other role assignments.

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

const binding = new gcp.endpoints.ServiceIamBinding("binding", {
    serviceName: endpointsService.serviceName,
    role: "roles/viewer",
    members: ["user:jane@example.com"],
});
import pulumi
import pulumi_gcp as gcp

binding = gcp.endpoints.ServiceIamBinding("binding",
    service_name=endpoints_service["serviceName"],
    role="roles/viewer",
    members=["user:jane@example.com"])
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := endpoints.NewServiceIamBinding(ctx, "binding", &endpoints.ServiceIamBindingArgs{
			ServiceName: pulumi.Any(endpointsService.ServiceName),
			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.Endpoints.ServiceIamBinding("binding", new()
    {
        ServiceName = endpointsService.ServiceName,
        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.endpoints.ServiceIamBinding;
import com.pulumi.gcp.endpoints.ServiceIamBindingArgs;
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 ServiceIamBinding("binding", ServiceIamBindingArgs.builder()
            .serviceName(endpointsService.serviceName())
            .role("roles/viewer")
            .members("user:jane@example.com")
            .build());

    }
}
resources:
  binding:
    type: gcp:endpoints:ServiceIamBinding
    properties:
      serviceName: ${endpointsService.serviceName}
      role: roles/viewer
      members:
        - user:jane@example.com

ServiceIamBinding manages all members for a specific role. The members array lists users, groups, or service accounts. This resource is authoritative for its role: it replaces the member list but leaves other roles unchanged. You can use multiple ServiceIamBinding resources for different roles on the same service.

Add a single member to a role incrementally

When multiple teams manage access independently, ServiceIamMember adds individual members without coordinating full member lists.

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

const member = new gcp.endpoints.ServiceIamMember("member", {
    serviceName: endpointsService.serviceName,
    role: "roles/viewer",
    member: "user:jane@example.com",
});
import pulumi
import pulumi_gcp as gcp

member = gcp.endpoints.ServiceIamMember("member",
    service_name=endpoints_service["serviceName"],
    role="roles/viewer",
    member="user:jane@example.com")
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := endpoints.NewServiceIamMember(ctx, "member", &endpoints.ServiceIamMemberArgs{
			ServiceName: pulumi.Any(endpointsService.ServiceName),
			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.Endpoints.ServiceIamMember("member", new()
    {
        ServiceName = endpointsService.ServiceName,
        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.endpoints.ServiceIamMember;
import com.pulumi.gcp.endpoints.ServiceIamMemberArgs;
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 ServiceIamMember("member", ServiceIamMemberArgs.builder()
            .serviceName(endpointsService.serviceName())
            .role("roles/viewer")
            .member("user:jane@example.com")
            .build());

    }
}
resources:
  member:
    type: gcp:endpoints:ServiceIamMember
    properties:
      serviceName: ${endpointsService.serviceName}
      role: roles/viewer
      member: user:jane@example.com

ServiceIamMember is non-authoritative: it adds one member to a role without affecting existing members. The member property uses GCP’s identity format (user:, serviceAccount:, group:, domain:). Multiple ServiceIamMember resources can grant the same role to different members.

Beyond these examples

These snippets focus on specific IAM management approaches: authoritative vs non-authoritative updates, and policy-level, role-level, and member-level control. They’re intentionally minimal rather than full access control systems.

The examples reference pre-existing infrastructure such as a Cloud Endpoints service (serviceName reference). They focus on IAM configuration rather than service provisioning.

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

  • IAM conditions for time-based or attribute-based access
  • Audit logging configuration (auditConfigs)
  • Custom role definitions
  • Service account creation and management

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 Cloud Endpoints ServiceIamPolicy resource reference for all available configuration options.

Let's manage GCP Cloud Endpoints IAM Policies

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

Try Pulumi Cloud for FREE

Frequently Asked Questions

Resource Conflicts & Compatibility
Can I use ServiceIamPolicy with ServiceIamBinding or ServiceIamMember?
No, gcp.endpoints.ServiceIamPolicy cannot be used with gcp.endpoints.ServiceIamBinding or gcp.endpoints.ServiceIamMember because they’ll conflict over policy state.
Can I use ServiceIamBinding and ServiceIamMember together?
Yes, but only if they don’t grant privileges to the same role. Using both for the same role causes conflicts.
Resource Selection & Configuration
Which IAM resource should I use for Cloud Endpoints?

Choose based on your needs:

  1. ServiceIamPolicy - Authoritative; replaces the entire IAM policy
  2. ServiceIamBinding - Authoritative for a specific role; preserves other roles
  3. ServiceIamMember - Non-authoritative; adds a single member while preserving others
How do I generate the policyData for ServiceIamPolicy?
Use the gcp.organizations.getIAMPolicy data source to generate policyData, as shown in the examples.
Can I change the serviceName after creating the resource?
No, serviceName is immutable and cannot be changed after creation.
Import & Custom Roles
How do I import an IAM resource with a custom role?
Use the full role name: projects/my-project/roles/my-custom-role or organizations/my-org/roles/my-custom-role.

Using a different cloud?

Explore iam guides for other cloud providers: