授予服务之间的访问权

使用 IBM Cloud® Identity and Access Management (IAM) 可创建或除去授权,授权用于授予一个服务对另一个服务的访问权。 使用授权委派可自动创建访问策略来授予对相依服务的访问权。

IAM 的许多功能都侧重于管理和执行用户和应用程序对 IBM Cloud 资源的访问。 但是,您可能会遇到其他情况,需要让一个服务访问另一个服务中的用户资源。 此类型访问权称为授权。

在授权中,源服务是获准访问目标服务的服务。 您选择的角色定义了源服务的访问级别。 目标服务是您根据分配的角色授予源服务访问权限的服务。 源服务可以在创建授权的同一账户中,也可以在其他账户中。 目标服务始终位于创建授权的账户中。 通过查看 IBM Cloud® 控制台“授权”页面上特定授权的“源账户”列,可以查看源服务是位于当前账户还是其他账户。

授权受抚养人服务

在某些情况下,除了源服务外,还可以对相依服务授权。 被允许访问目标服务的源服务依赖于另一个服务。 相依服务必须分配有访问权才可完成工作流程。 下图说明了在源服务、目标服务和从属服务之间委托访问的过程:

S2S 从属服务的授权。
S2S 授权如何与家属服务一起使用

有关角色的更多信息,请参阅 服务访问角色。

下面的示例解释了源服务、目标服务和从属服务之间的关系。 假设您有一个 IBM Watson® 服务,它依赖 IBM Cloud Object Storage 的一个实例来存储数据。 在 IBM Watson 服务和 IBM® Key Protect 服务之间启用授权时,可能需要 Object Storage 实例访问用户 Key Protect 实例中的密钥。 因此,虽然是 IBM Watson 服务与 Key Protect 服务之间的授权,也会同时将 Object Storage 服务作为 IBM Watson 服务的相依服务授予访问权。 通过选择启用对相依服务的授权的选项,您无需执行任何其他操作,因为系统会自动为相依服务创建策略。

源服务的相依服务可能位于源服务的帐户中,这意味着这些服务不会显示在您的帐户中。 但是,源服务为其相依服务创建的任何访问策略都会始终显示。 您可以通过查看“授权”页面上针对特定授权的“类型”列,判断授权是用户创建的还是源服务创建的。

在控制台中创建授权

您必须有权访问目标服务,才能在服务之间创建授权。 作为目标服务的用户,您只能授予自己拥有的访问级别。 例如,如果您对目标服务具有查看者访问权,那么只能为授权分配查看者角色。

  1. 在 IBM Cloud 控制台中,单击管理 > 访问 (IAM),然后选择授权。

  2. 单击创建。

  3. 选择一个源账户。

    • 如果需要访问目标的源在此账户中,请选择此账户。
    • 如果需要访问目标的源处于不同的账户中,请选择 另一个账户。 然后,输入源账户的账户 ID。
  4. 选择需要访问的一项或多项服务。

    • 您可以选择单个服务,并指定是否希望源包括所有资源、仅包括特定资源组中的实例或仅包括账户中的特定实例。
    • 新 您也可以选择所有启用身份和访问的服务,然后选择或输入资源组 ID。

    新 将资源组作为源输入后,资源组中的服务实例就可以访问账户中的目标资源。 如果不想让用户直接访问资源,可能需要设置这种访问级别。

  5. 选择目标。

  6. 指定您希望目标包括所有资源还是特定资源。 如果选择特定资源作为目标,可以添加属性来进一步确定访问范围。 属性类型取决于您选择的目标服务。

  7. (可选)选择 允许源服务和从属服务授权,允许源服务将其访问权委托给任何从属服务。 仅当源服务具有相依服务时,才会显示此选项。 通过选择此选项,源服务会自动为相依服务创建策略。

  8. 选择角色以向源服务分配访问目标服务的访问权。

  9. 单击授权。

如果在其他账户的服务和当前账户的目标服务之间创建授权,则只需访问目标资源。 对于源账户,只需输入账号即可。

使用 CLI 创建授权

要授权源服务访问目标服务,请运行 ibmcloud iam authorization-policy-create 命令。

下面的示例使用模拟数据创建了一个策略,授权 IBM Cloud Object Storage 的特定源服务实例访问 IBM Key Protect 的特定目标服务实例:

ibmcloud iam authorization-policy-create cloud-object-storage kms Reader --source-service-instance-id 123123 --target-service-instance-id 456456

有关此命令可用参数的更多信息,请参阅 ibmcloud iam authorization-policy-create。

使用 Terraform 创建授权

您必须有权访问目标服务,才能在服务之间创建授权。 作为目标服务的用户,您只能授予自己拥有的访问级别。 例如,如果您对目标服务具有查看者访问权,那么只能为授权分配查看者角色。

在使用 Terraform 创建授权之前,请确保已完成以下步骤:

  • 安装 Terraform CLI 并为 Terraform 配置 IBM Cloud Provider 插件。 更多信息,请参见 IBM Cloud® 上的 Terraform 入门 教程。 该插件抽象了用于完成这项任务的 IBM Cloud API。
  • 创建名为 main.tf 的 Terraform 配置文件。 在该文件中,您可以使用 HashiCorp 配置语言定义资源。 更多信息,请参阅 Terraform 文档。

使用以下步骤通过 Terraform 创建授权:

  1. 在 main.tf 文件中使用 ibm_iam_authorization_policy 资源参数,在服务之间创建授权策略。

    下面的示例创建了服务之间的授权:

    resource "ibm_iam_authorization_policy" "policy" {
    source_service_name = "cloud-object-storage"
    target_service_name = "kms"
    roles               = ["Reader"]
    description         = "Authorization Policy"
    transaction_id     = "terraformAuthorizationPolicy"
    }
    

    ibm_iam_authorization_policy 资源需要源服务、目标服务和角色。 源服务被授予对目标服务的访问权限,角色是访问权限的级别。 可选择添加授权说明和交易 ID。

    有关更多示例,请参阅 Terraform 授权资源文档。

  2. 完成构建配置文件后,初始化 Terraform CLI。 更多信息,请参阅 初始化工作目录。

    terraform init
    
  3. 从 main.tf 文件调配资源。 如需了解更多信息,请参阅 使用 Terraform 配置基础架构。

    1. 运行 terraform plan 生成 Terraform 执行计划,以预览建议的操作。

      terraform plan
      
    2. 运行 terraform apply 以创建计划中定义的资源。

      terraform apply
      

使用应用程序接口创建授权

要授权源服务访问目标服务,请使用 IAM 策略管理 API。 请参阅以下 API 示例,了解如何使用 type=authorization 创建策略方法。

创建授权策略所支持的属性取决于每个服务所支持的属性。 有关每种服务支持的属性的更多信息,请参阅所用服务的文档。

curl --request POST \
  --url https://iam.cloud.ibm.com/v1/policies \
  --header 'Authorization: Bearer <token>' \
  --header 'Content-Type: application/json' \
  --data '{
    "type": "authorization",
    "subjects": [
        {
            "attributes": [
                {
                    "name": "accountId",
                    "value": "<account-id>"
                },
                {
                    "name": "serviceName",
                    "value": "<service-name>"
                },
                {
                    "name": "serviceInstance",
                    "value": "<instance-id>"
                }
            ]
        }
    ],
    "roles": [
        {
            "role_id": "crn:v1:bluemix:public:iam::::serviceRole:Reader"
        }
    ],
    "resources": [
        {
            "attributes": [
                {
                    "name": "accountId",
                    "value": "<account-id>"
                },
                {
                    "name": "serviceName",
                    "value": "<service-name>"
                },
                {
                    "name": "serviceInstance",
                    "value": "<instance-id>"
                },
                {
                    "name": "resourceType",
                    "value": "<resource-type>"
                },
                {
                    "name": "resource",
                    "value": "<id>"
                }
            ]
        }
    ]
}'
SubjectAttribute accountSubjectAttribute = new SubjectAttribute.Builder()
      .name("accountId")
      .value(exampleAccountId)
      .build();

SubjectAttribute serviceNameSubjectAttribute = new SubjectAttribute.Builder()
      .name("serviceName")
      .value(exampleSourceServiceName)
      .build();

SubjectAttribute serviceInstanceSubjectAttribute = new SubjectAttribute.Builder()
      .name("serviceInstance")
      .value(exampleSourceServiceInstanceId)
      .build();

PolicySubject policySubjects = new PolicySubject.Builder()
      .addAttributes(accountSubjectAttribute)
      .addAttributes(serviceNameSubjectAttribute)
      .addAttributes(serviceInstanceSubjectAttribute)
      .build();

PolicyRole policyRoles = new PolicyRole.Builder()
      .roleId("crn:v1:bluemix:public:iam::::serviceRole:Reader")
      .build();

ResourceAttribute accountIdResourceAttribute = new ResourceAttribute.Builder()
      .name("accountId")
      .value(exampleAccountId)
      .operator("stringEquals")
      .build();

ResourceAttribute serviceNameResourceAttribute = new ResourceAttribute.Builder()
      .name("serviceName")
      .value(exampleTargetServiceName)
      .operator("stringEquals")
      .build();

ResourceAttribute serviceInstanceResourceAttribute = new ResourceAttribute.Builder()
      .name("serviceInstance")
      .value(exampleTargetInstanceId)
      .operator("stringEquals")
      .build();

ResourceAttribute resourceTypeResourceAttribute = new ResourceAttribute.Builder()
      .name("resourceType")
      .value(exampleResourceType)
      .operator("stringEquals")
      .build();

ResourceAttribute resourceResourceAttribute = new ResourceAttribute.Builder()
      .name("resource")
      .value(exampleResourceId)
      .operator("stringEquals")
      .build();

PolicyResource policyResources = new PolicyResource.Builder()
      .addAttributes(accountIdResourceAttribute)
      .addAttributes(serviceNameResourceAttribute)
      .addAttributes(serviceInstanceResourceAttribute)
      .addAttributes(resourceTypeResourceAttribute)
      .addAttributes(resourceResourceAttribute)
      .build();

CreatePolicyOptions options = new CreatePolicyOptions.Builder()
      .type("authorization")
      .subjects(Arrays.asList(policySubjects))
      .roles(Arrays.asList(policyRoles))
      .resources(Arrays.asList(policyResources))
      .build();

Response<Policy> response = service.createPolicy(options).execute();
Policy policy = response.getResult();

System.out.println(policy);
const policySubjects = [
  {
    attributes: [
      {
        name: 'accountId',
        value: exampleAccounId,
      },
      {
        name: 'serviceName',
        value: exampleSourceServiceName,
      },
      {
        name: 'serviceInstance',
        value: exampleSourceServiceInstaceId,
      },
    ],
  },
];
const policyRoles = [
  {
    role_id: 'crn:v1:bluemix:public:iam::::serviceRole:Reader',
  },
];
const accountIdResourceAttribute = {
  name: 'accountId',
  value: exampleAccountId,
  operator: 'stringEquals',
};
const serviceNameResourceAttribute = {
  name: 'serviceName',
  value: exampleTargetServiceName,
  operator: 'stringEquals',
};
const serviceInstanceResourceAttribute = {
  name: 'serviceInstance',
  value: exampleTargetServiceInstanceId,
  operator: 'stringEquals',
};
const resourceTypeResourceAttribute = {
  name: 'resourceType',
  value: exampleResourceType,
  operator: 'stringEquals',
};
const resourceResourceAttribute = {
  name: 'resource',
  value: exampleResourceId,
  operator: 'stringEquals',
};

const policyResources = [
  {
    attributes: [
      accountIdResourceAttribute,
      serviceNameResourceAttribute,
      serviceInstanceResourceAttribute,
      resourceTypeResourceAttribute,
      resourceResourceAttribute,
    ],
  },
];
const params = {
  type: 'authorization',
  subjects: policySubjects,
  roles: policyRoles,
  resources: policyResources,
};

iamPolicyManagementService.createPolicy(params)
  .then(res => {
    examplePolicyId = res.result.id;
    console.log(JSON.stringify(res.result, null, 2));
  })
  .catch(err => {
    console.warn(err)
  });
policy_subjects = PolicySubject(
    attributes=[SubjectAttribute(name='accountId', value=example_account_id),
                SubjectAttribute(name='serviceName', value=example_source_service_name),
                SubjectAttribute(name='serviceInstance', value=example_source_service_instance_id)])
policy_roles = PolicyRole(
    role_id='crn:v1:bluemix:public:iam::::serviceRole:Reader')
account_id_resource_attribute = ResourceAttribute(
    name='accountId', value=example_account_id)
service_name_resource_attribute = ResourceAttribute(
    name='serviceName', value=example_target_service_name)
service_instance_resource_attribute = ResourceAttribute(
    name='serviceInstance', value=example_target_service_instance_id)
resource_type_resource_attribute = ResourceAttribute(
    name='resourceType', value=example_resource_type)
resource_resource_attribute = ResourceAttribute(
    name='resource', value=example_resource_id)
policy_resources = PolicyResource(
    attributes=[account_id_resource_attribute,
                service_name_resource_attribute,
                service_instance_resource_attribute,
                resource_type_resource_attribute,
                resource_resource_attribute])

policy = iam_policy_management_service.create_policy(
    type='authorization',
    subjects=[policy_subjects],
    roles=[policy_roles],
    resources=[policy_resources]
).get_result()

print(json.dumps(policy, indent=2))
accountSubjectAttribute := &iampolicymanagementv1.SubjectAttribute{
    Name:  core.StringPtr("accountId"),
    Value: &exampleAccountID,
}
serviceNameSubjectAttribute := &iampolicymanagementv1.SubjectAttribute{
    Name:  core.StringPtr("serviceName"),
    Value: &exampleSourceServiceName,
}
serviceInstanceSubjectAttribute := &iampolicymanagementv1.SubjectAttribute{
    Name:  core.StringPtr("serviceInstance"),
    Value: &exampleSourceServiceInstanceId,
}
policySubjects := &iampolicymanagementv1.PolicySubject{
    Attributes: []iampolicymanagementv1.SubjectAttribute{*accountSubjectAttribute,
        *serviceNameSubjectAttribute, *serviceInstanceSubjectAttribute},
}
policyRoles := &iampolicymanagementv1.PolicyRole{
    RoleID: core.StringPtr("crn:v1:bluemix:public:iam::::serviceRole:Reader"),
}
accountIDResourceAttribute := &iampolicymanagementv1.ResourceAttribute{
    Name:     core.StringPtr("accountId"),
    Value:    core.StringPtr(exampleAccountID),
    Operator: core.StringPtr("stringEquals"),
}
serviceNameResourceAttribute := &iampolicymanagementv1.ResourceAttribute{
    Name:     core.StringPtr("serviceName"),
    Value:    core.StringPtr(exampleTargetServiceName),
    Operator: core.StringPtr("stringEquals"),
}
serviceInstanceResourceAttribute := &iampolicymanagementv1.ResourceAttribute{
    Name:     core.StringPtr("serviceInstance"),
    Value:    core.StringPtr(exampleTargetServiceInstanceId),
    Operator: core.StringPtr("stringEquals"),
}
resourceTypeResourceAttribute := &iampolicymanagementv1.ResourceAttribute{
    Name:     core.StringPtr("resourceType"),
    Value:    core.StringPtr(exampleResourceType),
    Operator: core.StringPtr("stringEquals"),
}
resourceResourceAttribute := &iampolicymanagementv1.ResourceAttribute{
    Name:     core.StringPtr("resource"),
    Value:    core.StringPtr(exampleResourceId),
    Operator: core.StringPtr("stringEquals"),
}
policyResources := &iampolicymanagementv1.PolicyResource{
    Attributes: []iampolicymanagementv1.ResourceAttribute{
        *accountIDResourceAttribute, *serviceNameResourceAttribute,
        *serviceInstanceResourceAttribute, *resourceTypeResourceAttribute,
        *resourceResourceAttribute},
}

options := iamPolicyManagementService.NewCreatePolicyOptions(
    "authorization",
    []iampolicymanagementv1.PolicySubject{*policySubjects},
    []iampolicymanagementv1.PolicyRole{*policyRoles},
    []iampolicymanagementv1.PolicyResource{*policyResources},
)

policy, response, err := iamPolicyManagementService.CreatePolicy(options)
if err != nil {
    panic(err)
}
b, _ := json.MarshalIndent(policy, "", "  ")
fmt.Println(string(b))

并非所有服务都支持 resourceType 和个人 resource 级别的政策。 支持这些属性的服务示例有 IBM Cloud Object Storage 和 IBM Key Protect,其中桶和键是资源类型,ID 则用于指定特定资源。

创建使用 resource-group 作为 resourceType

要创建使用 resource-group 作为源或目标的授权,请使用 IAM 策略管理 API。

resource-group 作为源头

请参阅以下 API 示例,了解如何创建将 resource-group 指定为源的策略方法。

{
 "type": "authorization",
    "subjects": [
        {
            "attributes": [
                {
                    "name": "resourceGroupId",
                    "value": "<rgId>"
                },
                {
                    "name": "accountId",
                    "value": "<sourceAccountId>"
                }
            ]
        }
    ],
    "roles": [
        {
            "role_id": "crn:v1:bluemix:public:iam::::role:Viewer"
        }
    ],
    "resources": [
        {
            "attributes": [
                {
                    "name": "accountId",
                    "value": "<targetAccountId>"
                },
                {
                    "name": "serviceName",
                    "value": "<targetService>"
                },
                {
                    "name": "serviceInstance",
                    "value": "<targetServiceInstance>"
                }
            ]
        }
    ]
}

resource-group 为目标

请参阅以下 API 示例,了解如何创建将 resource-group 指定为目标的策略方法。

{
 "type": "authorization",
    "subjects": [
        {
            "attributes": [
                {
                    "name": "accountId",
                    "value": "<sourceAccountId>"
                },
                {
                    "name": "serviceName",
                    "value": "<sourceService>"
                },
                {
                    "name": "serviceInstance",
                    "value": "<sourceServiceInstance>"
                }
            ]
        }
    ],
    "roles": [
        {
            "role_id": "crn:v1:bluemix:public:iam::::role:Viewer"
        }
    ],
    "resources": [
        {
            "attributes": [
                {
                    "name": "accountId",
                    "value": "<targetAccountId>"
                },
                {
                    "name": "resourceType",
                    "value": "resource-group"
                }
            ]
        }
    ]
}

在控制台中删除授权

如果您分配有对目标服务的管理员角色,那么可以除去帐户中服务之间的任何授权。 如果除去了源服务为其相依服务创建的任何访问策略,那么源服务将无法完成工作流程或访问目标服务。

  1. 在 IBM Cloud 控制台中,单击管理 > 访问 (IAM),然后选择授权。
  2. 确定要从帐户中除去的授权所在的行。
  3. 单击操作图标操作图标 > 删除。
  4. 选择除去。

如果从帐户中除去了源服务,那么该服务为其相依服务创建的任何策略都会被自动删除。 同样,如果从帐户中删除了相依服务,那么委派给该服务的所有访问策略也将被删除。

使用 CLI 删除授权

如果您分配有对目标服务的管理员角色,那么可以除去帐户中服务之间的任何授权。 如果除去了源服务为其相依服务创建的任何访问策略,那么源服务将无法完成工作流程或访问目标服务。

要授权源服务访问目标服务,请运行 ibmcloud iam authorization-policy-create 命令。

下面的示例删除了一个授权策略:

ibmcloud iam authorization-policy-delete 12345678-abcd-1a2b-a1b2-1234567890ab

有关此命令可用参数的更多信息,请参阅 ibmcloud iam authorization-policy-delete。

如果从帐户中除去了源服务,那么该服务为其相依服务创建的任何策略都会被自动删除。 同样,如果从帐户中删除了相依服务,那么委派给该服务的所有访问策略也将被删除。

使用应用程序接口删除授权

如果您分配有对目标服务的管理员角色,那么可以除去帐户中服务之间的任何授权。 如果除去了源服务为其相依服务创建的任何访问策略,那么源服务将无法完成工作流程或访问目标服务。

要删除授权策略,请使用 IAM 策略管理 API,如下所示:

curl -X DELETE 'https://iam.cloud.ibm.com/v1/policies/$POLICY_ID' \
-H 'Authorization: Bearer $TOKEN' \
-H 'Content-Type: application/json'
DeletePolicyOptions options = new DeletePolicyOptions.Builder()
        .policyId(examplePolicyId)
        .build();

service.deletePolicy(options).execute();
const params = {
  policyId: examplePolicyId,
};

iamPolicyManagementService.deletePolicy(params)
  .then(res => {
    console.log(JSON.stringify(res, null, 2));
  })
  .catch(err => {
    console.warn(err)
  });
response = iam_policy_management_service.delete_policy(
  policy_id=example_policy_id
).get_result()

print(json.dumps(response, indent=2))
options := iamPolicyManagementService.NewDeletePolicyOptions(
  examplePolicyID,
)

response, err := iamPolicyManagementService.DeletePolicy(options)
if err != nil {
  panic(err)
}

如果从帐户中除去了源服务,那么该服务为其相依服务创建的任何策略都会被自动删除。 同样,如果从帐户中删除了相依服务,那么委派给该服务的所有访问策略也将被删除。

使用 Terraform 移除授权

如果想通过 Terraform 删除授权,则需要从 main.tf 文件中删除该参数。 删除参数后,请按以下步骤配置文件:

  1. 运行 terraform plan 生成 Terraform 执行计划,以预览建议的操作。

    terraform plan
    
  2. 运行 terraform apply 以创建计划中定义的资源。

    terraform apply