使用 IAM 进行访问权限控制

本页介绍了如何使用 Identity and Access Management (IAM) 控制对设备的访问权限。您可以在项目或注册表级别授予访问权限。单个设备层级没有访问权限控制机制。访问权限通常授予一人或一组用户,或服务器端服务帐号。(设备使用公钥/私钥身份验证;如需了解详情,请参阅设备安全性部分)。

例如,如果您将某个用户的 cloudiot.provisioner 角色分配给设备注册表 IAM 政策,则该用户可以添加或移除设备,但无法修改或删除注册表本身。也可以对云项目设置角色;然后,该角色适用于属于该云项目的所有注册表。

本部分重点介绍与 Cloud IoT Core 相关的 IAM 权限以及授予这些权限的 IAM 角色。如需详细了解 IAM 及其功能,请参阅 IAM 文档,尤其应参阅管理 IAM 政策部分。

角色

一个角色对应一组权限。例如,roles/cloudiot.viewer 包含 cloudiot.registries.getcloudiot.registries.listcloudiot.devices.getcloudiot.devices.list 权限。您可以为用户或群组分配角色,以允许他们对项目中的注册表执行操作。

下表列出了 Cloud IoT Core IAM 角色,包括与每个角色关联的权限:

角色 说明 权限
roles/cloudiot.viewer 拥有对所有 Cloud IoT 资源的只读权限
  • cloudiot.registries.get
  • cloudiot.registries.list
  • cloudiot.devices.get
  • cloudiot.devices.list
roles/cloudiot.deviceController 拥有更新设备配置的权限,但无权创建或删除设备 以上所有权限,以及以下权限:
  • cloudiot.devices.updateConfig
  • cloudiot.devices.sendCommand
roles/cloudiot.provisioner 拥有在注册表中创建和删除设备的权限,但无权修改注册表 以上所有权限,以及以下权限:
  • cloudiot.devices.create
  • cloudiot.devices.delete
  • cloudiot.devices.update
roles/cloudiot.editor 拥有对所有 Cloud IoT 资源的读写权限 以上所有权限,以及以下权限:
  • cloudiot.registries.create
  • cloudiot.registries.delete
  • cloudiot.registries.update
roles/cloudiot.admin 拥有所有 Cloud IoT 资源和权限的完全控制权 以上所有权限,以及以下权限:
  • cloudiot.registries.getIamPolicy
  • cloudiot.registries.setIamPolicy

其他角色 roles/cloudiot.serviceAgent 可向发布商授予相关 Cloud Pub/Sub 主题的权限。您在项目中启用 Google Cloud IoT Core API 时创建的服务帐号会自动分配此角色。在大多数情况下,您不需要设置或管理此角色。如果您遇到与 Cloud Pub/Sub 主题相关的权限错误,请参阅问题排查

如需详细了解角色,请参阅了解角色

权限

有了权限,用户便可对 Cloud IoT Core 中的注册表或设备执行特定操作。例如,拥有 cloudiot.registries.list 权限的用户可以列出您项目中的注册表。您不能直接授予用户权限;不过,您可以为他们分配角色(角色本身会具有一项或多项权限)。您还可以创建自定义角色

下表列出了与 Cloud IoT Core 关联的 IAM 权限:

设备注册表权限名称 说明
cloudiot.registries.create 在项目中创建一个新的注册表。
cloudiot.registries.delete 删除注册表。
cloudiot.registries.get 读取注册表详情(不包括 ACL)。
cloudiot.registries.getIAMPolicy 读取注册表 ACL。
cloudiot.registries.list 列出项目中的注册表。
cloudiot.registries.setIAMPolicy 更新注册表 ACL。
cloudiot.registries.update 更新注册表详细信息(不包括 ACL)。
cloudiot.devices.sendCommand (按注册表而不是设备)发送命令。
设备权限名称 说明
cloudiot.devices.create 将新设备添加到注册表。
cloudiot.devices.delete 删除设备。
cloudiot.devices.get 读取设备详细信息(不包括 ACL)。
cloudiot.devices.list 列出注册表中的设备。
cloudiot.devices.update 更新设备详细信息(不包括 ACL)。
cloudiot.devices.updateConfig 更新设备配置。
cloudiot.devices.bindGateway 将设备绑定到网关。
cloudiot.devices.unbindGateway 解除设备与网关的绑定。

如需详细了解哪些 IAM 权限允许用户在注册表和设备上运行方法,请参阅每个方法的特定 REST 参考文档

Cloud IoT Core IAM 管理

您可以使用 Google Cloud Console、IAM API 或 gcloud 工具获取和设置 IAM 政策。如需了解如何在项目级别执行此操作,请参阅授予、更改和撤消访问权限。本部分的其余内容包含有关设备注册表级别的 IAM 管理的信息。

购买保单

控制台

如需获取设备注册表的访问权限控制,请执行以下操作:

  1. 转到 Google Cloud Console 中的注册表页面。

    转到注册表页面

  2. 选中要为其设置权限的设备注册表旁边的复选框。如果信息面板未打开,请点击显示信息面板

  3. 点击权限。此时系统会打开一个“权限”窗格,其中包含用户及其权限的列表。

gcloud

如需获取设备注册表的政策,请运行 gcloud iot registries get-iam-policy 命令

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

API

如需通过 API 获取 IAM 权限,请使用 DeviceRegistry getIamPolicy 方法

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

设置政策

控制台

如需在设备注册表级别设置访问权限控制,请执行以下操作:

  1. 转到 Google Cloud Console 中的注册表页面。

    转到注册表页面

  2. 选中要为其设置权限的设备注册表旁边的复选框。如果信息面板未打开,请点击显示信息面板

  3. 点击权限。此时系统会打开一个“权限”窗格。

  4. 输入用户并从下拉菜单中选择一个角色,然后点击添加

gcloud

如需为设备注册表设置政策,请运行 gcloud iot registries set-iam-policy 命令

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

API

如需通过 API 设置 IAM 权限,请使用 DeviceRegistry setIamPolicy 方法

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