授與服務之間的存取權

使用 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。

    New 輸入資源群組做為來源,可讓資源群組中的服務實體存取您帳戶中的目標資源。 如果您不想讓他人直接存取資源,可能需要設定此存取層級。

  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 Configuration Language 定義資源。 如需詳細資訊,請參閱 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
      

使用 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,其中 bucket 和 keys 是資源類型,ID 則列出來指定特定的資源。

建立使用 resource-group 作為 resourceType

若要建立使用 resource-group 作為來源或目標的授權,請使用 IAM Policy Management 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