Google Cloud IoT Core is being retired on August 16, 2023. Contact your Google Cloud account team for more information.

Access control with IAM

Stay organized with collections Save and categorize content based on your preferences.

This page explains how to control access to devices using Identity and Access Management (IAM). Access can be granted at the project or registry level. There is no access control at the individual device level. Access is typically granted to a person or a group of users, or to server-side service accounts. (Devices use public/private key authentication; for more details, see the section on device security).

For example, if you assign a user the role of cloudiot.provisioner to a device registry IAM policy, that user will be able to add or remove devices but won't be able to modify or delete the registry itself. A role can also be set on a cloud project; it then applies to all registries belonging to that cloud project.

This section focuses on the IAM permissions relevant to Cloud IoT Core and the IAM roles that grant those permissions. For a detailed description of IAM and its features, see the IAM documentation. In particular, see the section on managing IAM policies.

Roles

A role is a bundle of permissions. For example, roles/cloudiot.viewer contains the permissions cloudiot.registries.get, cloudiot.registries.list, cloudiot.devices.get, and cloudiot.devices.list. You assign roles to users or groups in order to allow them to perform actions on the registries in your project.

The following table lists the Cloud IoT Core IAM roles, including the permissions associated with each role:

Role Description Permissions
roles/cloudiot.viewer Read-only access to all Cloud IoT resources
  • cloudiot.registries.get
  • cloudiot.registries.list
  • cloudiot.devices.get
  • cloudiot.devices.list
roles/cloudiot.deviceController Access to update the configuration of devices, but not to create or delete devices All of the above, and:
  • cloudiot.devices.updateConfig
  • cloudiot.devices.sendCommand
roles/cloudiot.provisioner Access to create and delete devices from registries, but not to modify the registries All of the above, and:
  • cloudiot.devices.create
  • cloudiot.devices.delete
  • cloudiot.devices.update
roles/cloudiot.editor Read-write access to all Cloud IoT resources All of the above, and:
  • cloudiot.registries.create
  • cloudiot.registries.delete
  • cloudiot.registries.update
roles/cloudiot.admin Full control of all Cloud IoT resources and permissions All of the above, and:
  • cloudiot.registries.getIamPolicy
  • cloudiot.registries.setIamPolicy

An additional role, roles/cloudiot.serviceAgent, grants Publisher permission for the relevant Cloud Pub/Sub topics. This role is automatically assigned to a service account that is created when you enable the Google Cloud IoT Core API in a project. In most cases, you won't need to set or manage this role. If you do encounter permission errors related to Cloud Pub/Sub topics, see Troubleshooting.

For more information about roles, see Understanding Roles.

Permissions

Permissions allow users to perform specific actions on registries or devices in Cloud IoT Core. For example, the cloudiot.registries.list permission allows a user to list the registries in your project. You don't directly give users permissions; instead, you assign them roles, which have one or more permissions bundled within them. You can also create custom roles.

The following tables list the IAM permissions that are associated with Cloud IoT Core:

Device registry permission name Description
cloudiot.registries.create Create a new registry in a project.
cloudiot.registries.delete Delete a registry.
cloudiot.registries.get Read registry details, excluding ACLs.
cloudiot.registries.getIAMPolicy Read registry ACLs.
cloudiot.registries.list List the registries in a project.
cloudiot.registries.setIAMPolicy Update registry ACLs.
cloudiot.registries.update Update registry details, excluding ACLs.
cloudiot.devices.sendCommand Send commands (per registry, not per device).
Device permission name Description
cloudiot.devices.create Add a new device to a registry.
cloudiot.devices.delete Delete a device.
cloudiot.devices.get Read device details, excluding ACLs.
cloudiot.devices.list List devices in a registry.
cloudiot.devices.update Update device details, excluding ACLs.
cloudiot.devices.updateConfig Update the device configuration.
cloudiot.devices.bindGateway Bind a device to a gateway.
cloudiot.devices.unbindGateway Unbind a device from a gateway.

For details on which IAM permissions allow users to run methods on registries and devices, see each method's specific REST reference.

Cloud IoT Core IAM management

You can get and set IAM policies using Google Cloud console, the IAM API, or the gcloud tool. For information on how to do so at the project level, see Granting, Changing, and Revoking Access. The rest of this section contains information on IAM management at the device registry level.

Get a policy

Console

To get access controls for a device registry:

  1. Go to the Registries page in Google Cloud console.

    Go to the Registries page

  2. Select the checkbox next to the device registry for which you want to set permissions. If the info panel isn't open, click Show Info Panel.

  3. Click Permissions. A Permissions pane opens containing a list of users and their permissions.

gcloud

To get a policy for a device registry, run the gcloud iot registries get-iam-policy command:

gcloud iot registries get-iam-policy REGISTRY_ID \
  --region=REGION \
  [--filter=EXPRESSION]
  [--limit=LIMIT]
  [--page-size=PAGE_SIZE]
  [--sort-by=[FIELD,...]]

API

To get IAM permissions via the API, use the DeviceRegistry getIamPolicy method:

C#

public static object GetIamPolicy(string projectId, string cloudRegion, string registryId)
{
    var cloudIot = CreateAuthorizedClient();
    // The resource name of the location associated with the key rings.
    var parent = $"projects/{projectId}/locations/{cloudRegion}/registries/{registryId}";
    try
    {
        var req = new GetIamPolicyRequest();
        var result = cloudIot.Projects.Locations.Registries.GetIamPolicy(req, parent).Execute();
        Console.WriteLine("Bindings: ");
        if (result.Bindings != null)
        {
            result.Bindings.ToList().ForEach(binding =>
            {
                Console.WriteLine($"Role: {binding.Role}");
                binding.Members.ToList().ForEach(member =>
                {
                    Console.WriteLine($"\tMember: {member}");
                });
            });
        }
        else
        {
            Console.WriteLine($"\tNo IAM bindings for {registryId}.");
        }
    }
    catch (Google.GoogleApiException e)
    {
        Console.WriteLine(e.Message);
        return e.Error.Code;
    }
    return 0;
}

Go


// getRegistryIAM gets the IAM policy for a device registry.
func getRegistryIAM(w io.Writer, projectID string, region string, registryID string) (*cloudiot.Policy, error) {
	// Authorize the client using Application Default Credentials.
	// See https://g.co/dv/identity/protocols/application-default-credentials
	ctx := context.Background()
	httpClient, err := google.DefaultClient(ctx, cloudiot.CloudPlatformScope)
	if err != nil {
		return nil, err
	}
	client, err := cloudiot.New(httpClient)
	if err != nil {
		return nil, err
	}

	var req cloudiot.GetIamPolicyRequest

	path := fmt.Sprintf("projects/%s/locations/%s/registries/%s", projectID, region, registryID)
	response, err := client.Projects.Locations.Registries.GetIamPolicy(path, &req).Do()
	if err != nil {
		return nil, err
	}

	fmt.Fprintln(w, "Policy:")
	for _, binding := range response.Bindings {
		fmt.Fprintf(w, "Role: %s\n", binding.Role)
		for _, member := range binding.Members {
			fmt.Fprintf(w, "\tMember: %s\n", member)
		}
	}

	return response, nil
}

Java

/** Retrieves IAM permissions for the given registry. */
protected static void getIamPermissions(String projectId, String cloudRegion, String registryName)
    throws GeneralSecurityException, IOException {
  GoogleCredentials credential =
      GoogleCredentials.getApplicationDefault().createScoped(CloudIotScopes.all());
  JsonFactory jsonFactory = JacksonFactory.getDefaultInstance();
  HttpRequestInitializer init = new HttpCredentialsAdapter(credential);
  final CloudIot service =
      new CloudIot.Builder(GoogleNetHttpTransport.newTrustedTransport(), jsonFactory, init)
          .setApplicationName(APP_NAME)
          .build();

  final String registryPath =
      String.format(
          "projects/%s/locations/%s/registries/%s", projectId, cloudRegion, registryName);

  com.google.api.services.cloudiot.v1.model.Policy policy =
      service
          .projects()
          .locations()
          .registries()
          .getIamPolicy(registryPath, new GetIamPolicyRequest())
          .execute();

  System.out.println("Policy ETAG: " + policy.getEtag());

  if (policy.getBindings() != null) {
    for (com.google.api.services.cloudiot.v1.model.Binding binding : policy.getBindings()) {
      System.out.println(String.format("Role: %s", binding.getRole()));
      System.out.println("Binding members: ");
      for (String member : binding.getMembers()) {
        System.out.println(String.format("\t%s", member));
      }
    }
  } else {
    System.out.println(String.format("No policy bindings for %s", registryName));
  }
}

Node.js

// const cloudRegion = 'us-central1';
// const projectId = 'adjective-noun-123';
// const registryId = 'my-registry';
const iot = require('@google-cloud/iot');

const iotClient = new iot.v1.DeviceManagerClient({
  // optional auth parameters.
});

async function getIamPolicy() {
  // Construct request
  const formattedResource = iotClient.registryPath(
    projectId,
    cloudRegion,
    registryId
  );

  let bindings;
  const [response] = await iotClient.getIamPolicy({
    resource: formattedResource,
  });

  bindings = response.bindings;
  const etag = response.etag;

  console.log('ETAG:', etag);
  bindings = bindings || [];

  bindings.forEach(_binding => {
    console.log(`Role: ${_binding.role}`);
    _binding.members || (_binding.members = []);
    _binding.members.forEach(_member => {
      console.log(`\t${_member}`);
    });
  });
}

getIamPolicy();

PHP

use Google\Cloud\Iot\V1\DeviceManagerClient;

/**
 * Retrieves IAM permissions for the given registry.
 *
 * @param string $registryId IOT Device Registry ID
 * @param string $projectId Google Cloud project ID
 * @param string $location (Optional) Google Cloud region
 */
function get_iam_policy(
    $registryId,
    $projectId,
    $location = 'us-central1'
) {
    print('Getting IAM Policy' . PHP_EOL);

    // Instantiate a client.
    $deviceManager = new DeviceManagerClient();

    // Format the full registry path
    $registryName = $deviceManager->registryName($projectId, $location, $registryId);

    $policy = $deviceManager->getIamPolicy($registryName);

    print($policy->serializeToJsonString() . PHP_EOL);
}

Python

# project_id = 'YOUR_PROJECT_ID'
# cloud_region = 'us-central1'
# registry_id = 'your-registry-id'
client = iot_v1.DeviceManagerClient()

registry_path = client.registry_path(project_id, cloud_region, registry_id)

policy = client.get_iam_policy(request={"resource": registry_path})

return policy

Ruby

# project_id  = "Your Google Cloud project ID"
# location_id = "The Cloud region the registry is located in"
# registry_id = "The registry to get an IAM policy for"

require "google/apis/cloudiot_v1"

# Initialize the client and authenticate with the specified scope
Cloudiot   = Google::Apis::CloudiotV1
iot_client = Cloudiot::CloudIotService.new
iot_client.authorization = Google::Auth.get_application_default(
  "https://www.googleapis.com/auth/cloud-platform"
)

# The resource name of the location associated with the project
parent   = "projects/#{project_id}/locations/#{location_id}"
resource = "#{parent}/registries/#{registry_id}"

# List the devices in the provided region
policy = iot_client.get_registry_iam_policy(
  resource
)

if policy.bindings
  policy.bindings.each do |binding|
    puts "Role: #{binding.role} Member: #{binding.members[0]}"
  end
else
  puts "No bindings"
end

Set a policy

Console

To set access controls at the device registry level:

  1. Go to the Registries page in Google Cloud console.

    Go to the Registries page

  2. Select the checkbox next to the device registry for which you want to set permissions. If the info panel isn't open, click Show Info Panel.

  3. Click Permissions. A Permissions pane opens.

  4. Enter a user or users, select a role from the drop-down menu, and click Add.

gcloud

To set a policy for a device registry, run the gcloud iot registries set-iam-policy command:

gcloud iot registries set-iam-policy REGISTRY_ID \
  --region=REGION \
  POLICY_FILE

API

To set IAM permissions via the API, use the DeviceRegistry setIamPolicy method:

C#

public static object SetIamPolicy(string projectId, string cloudRegion, string registryId,
                                 string role, string member)
{
    var cloudIot = CreateAuthorizedClient();
    // The resource name of the location associated with the key rings.
    var parent = $"projects/{projectId}/locations/{cloudRegion}/registries/{registryId}";
    try
    {
        var req = new SetIamPolicyRequest();
        Policy pol = new Policy();
        pol.Bindings = new List<Binding>();
        Binding bind = new Binding()
        {
            Role = role,
            Members = new List<string>()
        };
        bind.Members.Add(member);
        pol.Bindings.Add(bind);


        req.Policy = pol;
        var result = cloudIot.Projects.Locations.Registries.SetIamPolicy(req, parent).Execute();
    }
    catch (Google.GoogleApiException e)
    {
        Console.WriteLine(e.Message);
        return e.Error.Code;
    }
    return 0;
}

Go


// setRegistryIAM sets the IAM policy for a device registry
func setRegistryIAM(w io.Writer, projectID string, region string, registryID string, member string, role string) (*cloudiot.Policy, error) {
	// Authorize the client using Application Default Credentials.
	// See https://g.co/dv/identity/protocols/application-default-credentials
	ctx := context.Background()
	httpClient, err := google.DefaultClient(ctx, cloudiot.CloudPlatformScope)
	if err != nil {
		return nil, err
	}
	client, err := cloudiot.New(httpClient)
	if err != nil {
		return nil, err
	}

	req := cloudiot.SetIamPolicyRequest{
		Policy: &cloudiot.Policy{
			Bindings: []*cloudiot.Binding{
				{
					Members: []string{member},
					Role:    role,
				},
			},
		},
	}
	path := fmt.Sprintf("projects/%s/locations/%s/registries/%s", projectID, region, registryID)
	response, err := client.Projects.Locations.Registries.SetIamPolicy(path, &req).Do()
	if err != nil {
		return nil, err
	}

	fmt.Fprintf(w, "Successfully set IAM policy for registry: %s\n", registryID)

	return response, nil
}

Java

/** Sets IAM permissions for the given registry. */
protected static void setIamPermissions(
    String projectId, String cloudRegion, String registryName, String member, String role)
    throws GeneralSecurityException, IOException {
  GoogleCredentials credential =
      GoogleCredentials.getApplicationDefault().createScoped(CloudIotScopes.all());
  JsonFactory jsonFactory = JacksonFactory.getDefaultInstance();
  HttpRequestInitializer init = new HttpCredentialsAdapter(credential);
  final CloudIot service =
      new CloudIot.Builder(GoogleNetHttpTransport.newTrustedTransport(), jsonFactory, init)
          .setApplicationName(APP_NAME)
          .build();

  final String registryPath =
      String.format(
          "projects/%s/locations/%s/registries/%s", projectId, cloudRegion, registryName);

  com.google.api.services.cloudiot.v1.model.Policy policy =
      service
          .projects()
          .locations()
          .registries()
          .getIamPolicy(registryPath, new GetIamPolicyRequest())
          .execute();

  List<com.google.api.services.cloudiot.v1.model.Binding> bindings = policy.getBindings();

  boolean addNewRole = true;
  if (bindings != null) {
    for (com.google.api.services.cloudiot.v1.model.Binding binding : bindings) {
      if (binding.getRole().equals(role)) {
        List<String> members = binding.getMembers();
        members.add(member);
        binding.setMembers(members);
        addNewRole = false;
      }
    }
  } else {
    bindings = new ArrayList<>();
  }

  if (addNewRole) {
    com.google.api.services.cloudiot.v1.model.Binding bind =
        new com.google.api.services.cloudiot.v1.model.Binding();
    bind.setRole(role);
    List<String> members = new ArrayList<>();
    members.add(member);
    bind.setMembers(members);

    bindings.add(bind);
  }

  policy.setBindings(bindings);
  SetIamPolicyRequest req = new SetIamPolicyRequest().setPolicy(policy);

  policy = service.projects().locations().registries().setIamPolicy(registryPath, req).execute();

  System.out.println("Policy ETAG: " + policy.getEtag());
  for (com.google.api.services.cloudiot.v1.model.Binding binding : policy.getBindings()) {
    System.out.println(String.format("Role: %s", binding.getRole()));
    System.out.println("Binding members: ");
    for (String mem : binding.getMembers()) {
      System.out.println(String.format("\t%s", mem));
    }
  }
}

Node.js

// const cloudRegion = 'us-central1';
// const projectId = 'adjective-noun-123';
// const registryId = 'my-registry';

const iot = require('@google-cloud/iot');

const iotClient = new iot.v1.DeviceManagerClient({
  // optional auth parameters.
});

async function setIamPolicy() {
  // Construct request
  const resource = iotClient.registryPath(projectId, cloudRegion, registryId);

  const policy = {
    bindings: [
      {
        members: [member],
        role: role,
      },
    ],
  };

  const request = {
    resource: resource,
    policy: policy,
  };

  let bindings;

  const [response] = await iotClient.setIamPolicy(request);

  bindings = response.bindings;
  const etag = response.etag;

  console.log('ETAG:', etag);
  bindings = bindings || [];

  bindings.forEach(_binding => {
    console.log(`Role: ${_binding.role}`);
    _binding.members || (_binding.members = []);
    _binding.members.forEach(_member => {
      console.log(`\t${_member}`);
    });
  });
}

setIamPolicy();

PHP

use Google\Cloud\Iot\V1\DeviceManagerClient;
use Google\Cloud\Iam\V1\Policy;
use Google\Cloud\Iam\V1\Binding;

/**
 * Sets IAM permissions for the given registry to a single role/member.
 *
 * @param string $registryId IOT Device Registry ID
 * @param string $role Role used for IAM commands
 * @param string $member Member used for IAM commands
 * @param string $projectId Google Cloud project ID
 * @param string $location (Optional) Google Cloud region
 */
function set_iam_policy(
    $registryId,
    $role,
    $member,
    $projectId,
    $location = 'us-central1'
) {
    print('Setting IAM policy' . PHP_EOL);

    // Instantiate a client.
    $deviceManager = new DeviceManagerClient();
    $registryName = $deviceManager->registryName($projectId, $location, $registryId);

    $binding = (new Binding())
        ->setMembers([$member])
        ->setRole($role);

    $policy = (new Policy())
        ->setBindings([$binding]);

    $policy = $deviceManager->setIamPolicy($registryName, $policy);

    print($policy->serializeToJsonString() . PHP_EOL);
}

Python

# project_id = 'YOUR_PROJECT_ID'
# cloud_region = 'us-central1'
# registry_id = 'your-registry-id'
# role = 'viewer'
# member = 'group:dpebot@google.com'
client = iot_v1.DeviceManagerClient()
registry_path = client.registry_path(project_id, cloud_region, registry_id)

body = {"bindings": [{"members": [member], "role": role}]}

return client.set_iam_policy(request={"resource": registry_path, "policy": body})

Ruby

# project_id  = "Your Google Cloud project ID"
# location_id = "The Cloud region the registry is located in"
# registry_id = "The registry to set an IAM policy for"
# member      = "The member to add to the policy bindings"
# role        = "The role for the binding the policy is set to"

require "google/apis/cloudiot_v1"

# Initialize the client and authenticate with the specified scope
Cloudiot   = Google::Apis::CloudiotV1
iot_client = Cloudiot::CloudIotService.new
iot_client.authorization = Google::Auth.get_application_default(
  "https://www.googleapis.com/auth/cloud-platform"
)

# The resource name of the location associated with the project
parent   = "projects/#{project_id}/locations/#{location_id}"
resource = "#{parent}/registries/#{registry_id}"

request = Google::Apis::CloudiotV1::SetIamPolicyRequest.new
policy  = Google::Apis::CloudiotV1::Policy.new
binding = Google::Apis::CloudiotV1::Binding.new
binding.members = [member]
binding.role    = role
policy.bindings = [binding]
request.policy  = policy

# List the devices in the provided region
result = iot_client.set_registry_iam_policy(
  resource, request
)

if result.bindings
  puts "Binding set:"
  result.bindings.each do |binding|
    puts "\tRole: #{binding.role} Member: #{binding.members[0]}"
  end
else
  puts "No bindings"
end