Manage GCP Container Analysis Note IAM Members

The gcp:containeranalysis/noteIamMember:NoteIamMember resource, part of the Pulumi GCP provider, manages IAM permissions for Container Analysis notes. Container Analysis notes store vulnerability and compliance metadata for container images. This guide focuses on two capabilities: choosing between three IAM management approaches (policy, binding, member) and understanding authoritative vs non-authoritative permission grants.

These resources reference existing Container Analysis notes and require the Container Analysis API enabled in your project. The examples are intentionally small. Combine them with your own note resources and identity management.

Replace the entire IAM policy for a note

When you need complete control over all permissions, you can define the entire IAM policy from scratch.

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

const admin = gcp.organizations.getIAMPolicy({
    bindings: [{
        role: "roles/containeranalysis.notes.occurrences.viewer",
        members: ["user:jane@example.com"],
    }],
});
const policy = new gcp.containeranalysis.NoteIamPolicy("policy", {
    project: note.project,
    note: note.name,
    policyData: admin.then(admin => admin.policyData),
});
import pulumi
import pulumi_gcp as gcp

admin = gcp.organizations.get_iam_policy(bindings=[{
    "role": "roles/containeranalysis.notes.occurrences.viewer",
    "members": ["user:jane@example.com"],
}])
policy = gcp.containeranalysis.NoteIamPolicy("policy",
    project=note["project"],
    note=note["name"],
    policy_data=admin.policy_data)
package main

import (
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/containeranalysis"
	"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/containeranalysis.notes.occurrences.viewer",
					Members: []string{
						"user:jane@example.com",
					},
				},
			},
		}, nil)
		if err != nil {
			return err
		}
		_, err = containeranalysis.NewNoteIamPolicy(ctx, "policy", &containeranalysis.NoteIamPolicyArgs{
			Project:    pulumi.Any(note.Project),
			Note:       pulumi.Any(note.Name),
			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/containeranalysis.notes.occurrences.viewer",
                Members = new[]
                {
                    "user:jane@example.com",
                },
            },
        },
    });

    var policy = new Gcp.ContainerAnalysis.NoteIamPolicy("policy", new()
    {
        Project = note.Project,
        Note = note.Name,
        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.containeranalysis.NoteIamPolicy;
import com.pulumi.gcp.containeranalysis.NoteIamPolicyArgs;
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/containeranalysis.notes.occurrences.viewer")
                .members("user:jane@example.com")
                .build())
            .build());

        var policy = new NoteIamPolicy("policy", NoteIamPolicyArgs.builder()
            .project(note.project())
            .note(note.name())
            .policyData(admin.policyData())
            .build());

    }
}
resources:
  policy:
    type: gcp:containeranalysis:NoteIamPolicy
    properties:
      project: ${note.project}
      note: ${note.name}
      policyData: ${admin.policyData}
variables:
  admin:
    fn::invoke:
      function: gcp:organizations:getIAMPolicy
      arguments:
        bindings:
          - role: roles/containeranalysis.notes.occurrences.viewer
            members:
              - user:jane@example.com

The NoteIamPolicy resource replaces the entire IAM policy for the note. The getIAMPolicy data source constructs the policy document with bindings that map roles to members. This approach is authoritative: it removes any permissions not explicitly listed. Use this when you want to ensure no unexpected access exists.

Grant a role to multiple members at once

When several users or service accounts need the same access level, you can bind them all to a role together.

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

const binding = new gcp.containeranalysis.NoteIamBinding("binding", {
    project: note.project,
    note: note.name,
    role: "roles/containeranalysis.notes.occurrences.viewer",
    members: ["user:jane@example.com"],
});
import pulumi
import pulumi_gcp as gcp

binding = gcp.containeranalysis.NoteIamBinding("binding",
    project=note["project"],
    note=note["name"],
    role="roles/containeranalysis.notes.occurrences.viewer",
    members=["user:jane@example.com"])
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := containeranalysis.NewNoteIamBinding(ctx, "binding", &containeranalysis.NoteIamBindingArgs{
			Project: pulumi.Any(note.Project),
			Note:    pulumi.Any(note.Name),
			Role:    pulumi.String("roles/containeranalysis.notes.occurrences.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.ContainerAnalysis.NoteIamBinding("binding", new()
    {
        Project = note.Project,
        Note = note.Name,
        Role = "roles/containeranalysis.notes.occurrences.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.containeranalysis.NoteIamBinding;
import com.pulumi.gcp.containeranalysis.NoteIamBindingArgs;
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 NoteIamBinding("binding", NoteIamBindingArgs.builder()
            .project(note.project())
            .note(note.name())
            .role("roles/containeranalysis.notes.occurrences.viewer")
            .members("user:jane@example.com")
            .build());

    }
}
resources:
  binding:
    type: gcp:containeranalysis:NoteIamBinding
    properties:
      project: ${note.project}
      note: ${note.name}
      role: roles/containeranalysis.notes.occurrences.viewer
      members:
        - user:jane@example.com

The NoteIamBinding resource manages all members for a specific role. The members property takes a list of identities. This approach is authoritative for the specified role but preserves other roles in the policy. Multiple NoteIamBinding resources can coexist as long as they manage different roles.

Add a single member to a role incrementally

When you need to grant access to one identity without managing the full member list, you can add members one at a time.

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

const member = new gcp.containeranalysis.NoteIamMember("member", {
    project: note.project,
    note: note.name,
    role: "roles/containeranalysis.notes.occurrences.viewer",
    member: "user:jane@example.com",
});
import pulumi
import pulumi_gcp as gcp

member = gcp.containeranalysis.NoteIamMember("member",
    project=note["project"],
    note=note["name"],
    role="roles/containeranalysis.notes.occurrences.viewer",
    member="user:jane@example.com")
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := containeranalysis.NewNoteIamMember(ctx, "member", &containeranalysis.NoteIamMemberArgs{
			Project: pulumi.Any(note.Project),
			Note:    pulumi.Any(note.Name),
			Role:    pulumi.String("roles/containeranalysis.notes.occurrences.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.ContainerAnalysis.NoteIamMember("member", new()
    {
        Project = note.Project,
        Note = note.Name,
        Role = "roles/containeranalysis.notes.occurrences.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.containeranalysis.NoteIamMember;
import com.pulumi.gcp.containeranalysis.NoteIamMemberArgs;
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 NoteIamMember("member", NoteIamMemberArgs.builder()
            .project(note.project())
            .note(note.name())
            .role("roles/containeranalysis.notes.occurrences.viewer")
            .member("user:jane@example.com")
            .build());

    }
}
resources:
  member:
    type: gcp:containeranalysis:NoteIamMember
    properties:
      project: ${note.project}
      note: ${note.name}
      role: roles/containeranalysis.notes.occurrences.viewer
      member: user:jane@example.com

The NoteIamMember resource adds a single member to a role without affecting other members. This is non-authoritative: existing members for the role are preserved. Use this when you want to grant access incrementally or when multiple teams manage permissions independently. You can combine NoteIamMember with NoteIamBinding as long as they don’t grant the same role.

Beyond these examples

These snippets focus on specific IAM management features: policy, binding, and member resources for authoritative vs incremental permission grants. They’re intentionally minimal rather than full access control configurations.

The examples reference pre-existing infrastructure such as Container Analysis notes and a GCP project with the Container Analysis API enabled. They focus on configuring IAM permissions rather than provisioning the underlying notes.

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

  • Conditional IAM bindings (condition property)
  • Custom role definitions
  • Service account creation and management
  • Note creation and configuration

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 Container Analysis NoteIamMember resource reference for all available configuration options.

Let's manage GCP Container Analysis Note IAM Members

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 & Compatibility
What's the difference between NoteIamPolicy, NoteIamBinding, and NoteIamMember?
NoteIamPolicy is authoritative and replaces the entire IAM policy. NoteIamBinding is authoritative for a specific role, preserving other roles in the policy. NoteIamMember is non-authoritative, adding a single member to a role while preserving other members.
Can I use these IAM resources together?
NoteIamPolicy cannot be used with NoteIamBinding or NoteIamMember as they will conflict. However, NoteIamBinding and NoteIamMember can be used together if they don’t grant privileges to the same role.
IAM Configuration
What member identity formats are supported?

You can use:

  • allUsers or allAuthenticatedUsers for public/authenticated access
  • user:{email}, serviceAccount:{email}, or group:{email} for specific identities
  • domain:{domain} for G Suite domains
  • projectOwner:{projectid}, projectEditor:{projectid}, or projectViewer:{projectid} for project roles
  • Federated identities like principal://iam.googleapis.com/locations/global/workforcePools/...
What format do custom roles need?
Custom roles must use the format [projects|organizations]/{parent-name}/roles/{role-name}, for example projects/my-project/roles/my-custom-role.
Resource Properties
What properties can't be changed after creation?
All input properties are immutable: member, role, note, project, and condition. You must recreate the resource to change any of these.
How is the project determined if I don't specify it?
If project isn’t provided, it’s parsed from the parent note resource identifier. If the parent doesn’t include a project, the provider’s default project is used.

Using a different cloud?

Explore security guides for other cloud providers: