IBM Cloud Docs
使用授权来授予服务之间的访问权

使用授权来授予服务之间的访问权

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

IAM的许多功能都集中在管理和执行用户和应用程序对 IBM Cloud 资源的访问。 然而,您可能还会遇到其他情况,需要提供一种服务,以便访问其他服务中的用户资源。 此类型访问权称为授权。

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

授权从属服务

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

具有从属服务的

S2S 授权。
S2S授权如何与从属服务协同工作

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

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

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

在控制台中创建授权

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

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

  2. 单击创建

  3. 选择源帐户。

    • 如果需要访问目标的源位于此帐户中,请选择 此帐户
    • 如果需要访问目标的源位于其他帐户中,请选择 其他帐户。 然后,输入源帐户的帐户标识。
  4. 选择需要访问权的一个或多个服务。

    • 您可以选择单个服务,并指定是希望源包含所有资源,仅包含在特定资源组中的实例,还是仅包含帐户中的特定实例。
    • 新建 您还可以选择 所有启用身份和访问权的服务,然后选择或输入资源组标识。

    新建 将资源组作为源输入,使资源组中的服务实例能够访问帐户中的目标资源。 如果您不希望授予对资源的直接访问权,那么可能要设置此访问级别。

  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 提供程序插件。 有关更多信息,请参阅 Terraform on IBM Cloud®入门 教程。 该插件对用于完成此任务的 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 资源需要源服务,目标服务和角色。 源服务被授予对目标服务的访问权,角色是该访问权所允许的许可权级别。 (可选) 您可以添加授权描述和事务标识。

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

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

    terraform init
    
  3. main.tf 文件供应资源。 有关更多信息,请参阅 使用 Terraform 供应基础架构

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

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

      terraform apply
      

使用API创建授权

要授权源服务访问目标服务,请使用 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,其中存储区和密钥是资源类型,并且列出了用于指定特定资源的标识。

创建使用 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

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

使用 API 除去授权

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

要删除授权策略,请使用 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