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 with ServiceIamPolicy, role-level member management with ServiceIamBinding, and individual member grants with ServiceIamMember.

These three resources reference existing Cloud Endpoints services and cannot be mixed. ServiceIamPolicy conflicts with ServiceIamBinding and ServiceIamMember because they manage permissions at different levels. The examples are intentionally small. Choose the resource that matches your management style: full policy control, role-level lists, or incremental member additions.

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

ServiceIamPolicy is authoritative: it removes any existing bindings not included in your policy. The policyData comes from the getIAMPolicy data source, which constructs the policy JSON from your bindings. The serviceName identifies which Cloud Endpoints service to update.

Grant a role to multiple members at once

When several users need the same role, ServiceIamBinding manages all members for that role as a unit.

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 is authoritative for the specified role: it removes any members not in your list. The members array accepts user accounts, service accounts, groups, and domains. Other roles on the service remain unchanged.

Add a single member to a role incrementally

When you need to grant access to one user without managing the full member list, ServiceIamMember adds a single member non-authoritatively.

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 preserves other members for the role. The member property accepts a single identity (user, service account, group, or domain). You can create multiple ServiceIamMember resources for the same role without conflicts.

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 configurations.

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

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

  • IAM conditions for time-based or attribute-based access
  • Custom roles (require full path like projects/my-project/roles/my-role)
  • Service account impersonation
  • Audit logging configuration

These omissions are intentional: the goal is to illustrate how each IAM resource manages permissions, 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 Compatibility & Conflicts
Why are my IAM resources conflicting with each other?
ServiceIamPolicy cannot be used with ServiceIamBinding or ServiceIamMember because they’ll fight over policy control. Additionally, ServiceIamBinding and ServiceIamMember will conflict if they grant privileges to the same role.
Can I use ServiceIamPolicy with ServiceIamBinding or ServiceIamMember?
No, ServiceIamPolicy is authoritative and will conflict with ServiceIamBinding or ServiceIamMember. Use ServiceIamPolicy alone, or use ServiceIamBinding and ServiceIamMember together.
Can I use ServiceIamBinding and ServiceIamMember together?
Yes, but only if they target different roles. If both resources grant privileges to the same role, they’ll conflict.
Resource Selection
What's the difference between ServiceIamPolicy, ServiceIamBinding, and ServiceIamMember?
ServiceIamPolicy is authoritative and replaces the entire IAM policy. ServiceIamBinding is authoritative for a specific role, preserving other roles in the policy. ServiceIamMember is non-authoritative, adding a single member to a role while preserving other members.
Which IAM resource should I use for Cloud Endpoints?
Use ServiceIamPolicy for full policy control, ServiceIamBinding to manage all members for specific roles, or ServiceIamMember to add individual members without affecting others. Choose based on whether you need authoritative or additive behavior.
Import & Custom Roles
How do I import an IAM resource with a custom role?
Use the full custom role name in the format [projects/my-project|organizations/my-org]/roles/my-custom-role rather than just the role name.

Using a different cloud?

Explore iam guides for other cloud providers: