The gcp:endpoints/serviceIamMember:ServiceIamMember resource, part of the Pulumi GCP provider, grants IAM permissions to Cloud Endpoints services by adding individual members to roles without removing existing permissions. This guide focuses on three capabilities: non-authoritative member grants, authoritative role bindings, and complete policy replacement.
GCP provides three IAM resource types for Cloud Endpoints services, each with different authoritative behavior. ServiceIamMember adds members non-authoritatively, ServiceIamBinding manages all members for a role authoritatively, and ServiceIamPolicy replaces the entire policy. These resources cannot be mixed for the same service and role without causing conflicts. The examples are intentionally small. Choose the resource type that matches your permission management strategy.
Grant a role to a single member non-authoritatively
Most IAM configurations start by granting individual users or service accounts access without affecting existing permissions.
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
The member property specifies one identity using GCP’s identity format (user:, serviceAccount:, group:, etc.). The role property defines the permission level. This resource adds the member to the role without removing other members who already have that role on the service.
Grant a role to multiple members authoritatively
When you need to define the complete list of members for a role, binding resources replace all existing members.
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
The members property takes a list of identities. This resource is authoritative for the specified role: it replaces all existing members for that role with your list. Other roles on the service remain unchanged. Use this when you want to manage all members for a role in one place.
Replace the entire IAM policy authoritatively
Organizations managing IAM centrally often define the complete policy document in one place.
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 a complete IAM policy document, typically retrieved from getIAMPolicy. This resource replaces the entire IAM policy for the service, including all roles and members. It cannot coexist with ServiceIamBinding or ServiceIamMember resources on the same service, as they will conflict over policy ownership.
Beyond these examples
These snippets focus on specific IAM grant patterns: non-authoritative member grants, authoritative role bindings, and complete policy replacement. 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 granting permissions rather than provisioning the services themselves.
To keep things focused, common IAM patterns are omitted, including:
- Conditional IAM bindings (condition property)
- Custom role definitions and formatting
- Federated identity and workload identity pool configuration
- Policy conflict resolution between resource types
These omissions are intentional: the goal is to illustrate how each IAM resource type behaves, not provide drop-in access control modules. See the Cloud Endpoints ServiceIamMember resource reference for all available configuration options.
Let's manage GCP Endpoints Service IAM Permissions
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
gcp.endpoints.ServiceIamPolicy cannot be used with gcp.endpoints.ServiceIamBinding or gcp.endpoints.ServiceIamMember as they will conflict over policy control.Resource Selection & Use Cases
Choose based on your needs:
gcp.endpoints.ServiceIamPolicyfor full policy control (replaces entire policy)gcp.endpoints.ServiceIamBindingfor role-level control (manages all members for a role)gcp.endpoints.ServiceIamMemberfor adding individual members (preserves other members)
Configuration & Formats
[projects|organizations]/{parent-name}/roles/{role-name}. For example, projects/my-project/roles/my-custom-role.Supported formats include:
allUsersorallAuthenticatedUsersfor public/authenticated accessuser:{email},serviceAccount:{email},group:{email}for specific identitiesdomain:{domain}for G Suite domainsprojectOwner/Editor/Viewer:{projectid}for project-level roles- Federated identities (see Principal identifiers documentation)
Immutability & Lifecycle
member, role, and serviceName. Changing any of these requires recreating the resource.