依據資源設定存取權

本頁說明如何透過許可政策中的條件角色繫結,管理特定資源的存取權。您可以在條件運算式中使用資源屬性,根據資源的名稱、類型和 Trusted Cloud by S3NS 服務,控管主體是否可使用權限存取資源。

事前準備

  • 請參閱 Identity and Access Management (IAM) 條件總覽,瞭解 IAM 條件式角色繫結的基本概念。
  • 查看可在條件運算式中使用的資源屬性
  • 資源名稱屬性可控管下列 Trusted Cloud 服務的存取權:
    • BigQuery
    • BigQuery Reservation API
    • Cloud Key Management Service
    • Cloud Logging
    • Cloud SQL
    • Cloud Storage
    • Compute Engine
    • Google Kubernetes Engine

必要的角色

如要取得管理條件角色繫結所需的權限,請要求管理員授予下列 IAM 角色:

  • 如要管理專案存取權: 專案的專案 IAM 管理員 (roles/resourcemanager.projectIamAdmin)
  • 如要管理資料夾的存取權: 在資料夾上擁有資料夾管理員 (roles/resourcemanager.folderAdmin) 角色
  • 如要管理專案、資料夾和機構的存取權: 機構管理員 (roles/resourcemanager.organizationAdmin) 機構
  • 如要管理幾乎所有 Trusted Cloud 資源的存取權: 安全性管理員 (roles/iam.securityAdmin) 在您要管理存取權的專案、資料夾或機構中

如要進一步瞭解如何授予角色,請參閱「管理專案、資料夾和機構的存取權」。

這些預先定義的角色具備管理條件式角色繫結所需的權限。如要查看確切的必要權限,請展開「必要權限」部分:

所需權限

如要管理條件式角色繫結,您必須具備下列權限:

  • 如要管理專案存取權,請按照下列步驟操作:
    • 專案的 resourcemanager.projects.getIamPolicy
    • 專案的 resourcemanager.projects.setIamPolicy
  • 如何管理資料夾的存取權:
    • resourcemanager.folders.getIamPolicy 資料夾
    • resourcemanager.folders.setIamPolicy 資料夾
  • 如何管理機構的存取權:
    • resourcemanager.organizations.getIamPolicy 機構
    • resourcemanager.organizations.setIamPolicy 機構

您或許還可透過自訂角色或其他預先定義的角色取得這些權限。

根據資源名稱前置字串授予一組資源的存取權

您可以使用條件式角色繫結,將資源存取權授予資源名稱符合前置碼的主體,例如名稱開頭為特定字串的 Compute Engine 虛擬機器 (VM) 執行個體。資源名稱前置字串通常用於將資源分組,以達到特定目的或具有特定屬性。

舉例來說,假設您在某些 VM 執行個體上執行工作負載,這些工作負載可能會處理私密的健康資料。其他非機密工作負載必須在同一個專案中執行,且您希望確保開發人員對處理機密資料的 VM 執行個體只有有限的存取權。為達成這個目標,請為資料敏感的 VM 執行個體加上 sensitiveAccess 前置字串,其他 VM 執行個體則加上 devAccess 前置字串。接著,您可以使用條件式角色繫結,確保開發人員能繼續使用一般 devAccess VM 執行個體提高生產力,但不會授予他們 sensitiveAccess VM 執行個體的存取權。

雖然您可以單獨使用 resource.name 條件屬性來管理存取權,但通常也會使用 resource.typeresource.service 屬性。使用這些額外屬性後,條件較不會影響對名稱相似的不同資源類型的存取權。本節範例會使用 resource.nameresource.type 屬性控管存取權。

如要根據名稱前置字串,授予專案中 Compute Engine 磁碟和執行個體的存取權,請按照下列步驟操作:

控制台

  1. 前往 Trusted Cloud 控制台的「IAM」IAM頁面。

    前往 IAM 頁面

  2. 在主體清單中找到所需主體,然後按一下 按鈕。

  3. 在「編輯權限」面板中,找到要設定條件的角色。然後在「IAM condition (optional)」(IAM 條件 (選用)) 下方,按一下「Add IAM condition」(新增 IAM 條件)

  4. 在「編輯條件」面板中,輸入條件的標題和說明 (說明為選填)。

  5. 您可以使用「條件建構工具」或「條件編輯器」新增條件運算式。條件建構工具提供互動式介面,可供選取所需的條件類型、運算子,以及運算式的其他適用詳細資料。條件編輯器提供以文字為基礎的介面,可使用 CEL 語法手動輸入運算式。

    條件建構工具

    1. 從條件建構工具中刪除所有現有的條件欄位。條件建構工具中應只有「新增」按鈕。
    2. 建立分組條件運算式,如果資源是以前置字串開頭的磁碟,則評估結果為 true
      1. 按一下「新增」下拉式選單,然後點選「分組條件」
      2. 從「條件類型」下拉式選單中,選取「資源」>「類型」
      3. 在「運算子」下拉式選單中,選取「是」
      4. 在「資源類型」下拉式選單中,選取「compute.googleapis.com/Disk」
      5. 按一下剛輸入條件下方第一個「新增」按鈕,即可在運算式中新增其他子句。
      6. 從「條件類型」下拉式選單中,選取「資源」>「名稱」
      7. 在「運算子」下拉式選單中,選取「開頭為」
      8. 在「Value」(值) 欄位中,以適當格式輸入資源名稱,包括所需前置字串。舉例來說,使用 projects/PROJECT_ID/region/ZONE_ID/disks/PREFIX 可識別專案 PROJECT_ID 和區域 ZONE_ID 中名稱開頭為 PREFIX 的磁碟。
      9. 在每個條件類型左側,按一下「且」,確保兩個子句都必須為真。
    3. 建立分組條件運算式,如果資源是以前述前置字元開頭的執行個體,則評估結果為 true
      1. 按一下現有條件群組外的「新增」按鈕,然後按一下「已分組的條件」
      2. 從「條件類型」下拉式選單中,選取「資源」>「類型」
      3. 在「運算子」下拉式選單中,選取「是」
      4. 從「Resource Type」(資源類型) 下拉式選單中,選取「compute.googleapis.com/Instance」
      5. 在同一個條件群組中,按一下「新增」
      6. 從「條件類型」下拉式選單中,選取「資源」>「名稱」
      7. 在「運算子」下拉式選單中,選取「開頭為」
      8. 在「Value」(值) 欄位中,以適當格式輸入所需前置字串的資源名稱。舉例來說,使用 projects/PROJECT_ID/zones/ZONE_ID/instances/PREFIX 可找出專案 PROJECT_ID 和區域 ZONE_ID 中,名稱以 PREFIX 開頭的執行個體。
      9. 確認群組中連結條件的邏輯運算子已設為「And」
    4. 建立分組條件運算式,如果資源不是磁碟或執行個體,則評估結果為 true
      1. 點選現有條件群組外的「新增」按鈕,然後點選「條件群組」
      2. 從「條件類型」下拉式選單中,選取「資源」>「類型」
      3. 在「運算子」下拉式選單中,選取「不是」
      4. 在「資源類型」下拉式選單中,選取「compute.googleapis.com/Disk」
      5. 在同一個條件群組中,按一下「新增」
      6. 從「條件類型」下拉式選單中,選取「資源」>「類型」
      7. 在「運算子」下拉式選單中,選取「不是」
      8. 從「Resource Type」(資源類型) 下拉式選單中,選取「compute.googleapis.com/Instance」
      9. 確認群組中連結條件的邏輯運算子已設為「And」
    5. 確認連結所有條件運算式群組的邏輯運算子為「Or」

    6. 按一下「儲存」即可套用條件。

    7. 關閉「編輯條件」面板後,再次按一下「編輯權限」面板中的「儲存」,即可更新允許政策。

    條件編輯器

    1. 按一下「條件編輯器」分頁標籤,然後輸入下列運算式:

      (resource.type == "compute.googleapis.com/Disk" &&
      resource.name.startsWith("projects/PROJECT_ID/zones/ZONE_ID/disks/PREFIX")) ||
      (resource.type == "compute.googleapis.com/Instance" &&
      resource.name.startsWith("projects/PROJECT_ID/zones/ZONE_ID/instances/PREFIX")) ||
      (resource.type != "compute.googleapis.com/Disk" &&
      resource.type != "compute.googleapis.com/Instance")
    2. 輸入運算式後,您可以選擇點選文字方塊右上方的「執行 Lint」Lint CEL 語法。

    3. 按一下「儲存」即可套用條件。

    4. 關閉「編輯條件」面板後,再次按一下「編輯權限」面板中的「儲存」,即可更新允許政策。

gcloud

允許政策是使用「讀取 - 修改 - 寫入」模式設定。

執行 gcloud projects get-iam-policy 指令,取得專案目前的允許政策。在下列範例中,允許政策的 JSON 版本會下載到磁碟上的路徑。

指令:

gcloud projects get-iam-policy project-id --format=json > filepath

系統會下載允許政策的 JSON 格式:

{
  "bindings": [
    {
      "members": [
        "principal://iam.googleapis.com/locations/global/workforcePools/my-pool/subject/my-user@example.com"
      ],
      "role": "roles/owner"
    },
    {
      "members": [
        "principalSet://iam.googleapis.com/locations/global/workforcePools/my-pool/group/my-group"
      ],
      "role": "roles/compute.instanceAdmin"
    }
  ],
  "etag": "BwWKmjvelug=",
  "version": 1
}

如要使用資源名稱前置字串條件設定允許政策,請新增下列醒目顯示的條件運算式。gcloud CLI 會自動更新版本:

{
  "bindings": [
    {
      "members": [
        "principal://iam.googleapis.com/locations/global/workforcePools/my-pool/subject/my-user@example.com"
      ],
      "role": "roles/owner"
    },
    {
      "members": [
        "principalSet://iam.googleapis.com/locations/global/workforcePools/my-pool/group/my-group"
      ],
      "role": "roles/compute.instanceAdmin",
      "condition": {
          "title": "PREFIX_only",
          "description": "Only gives access to VMs with the PREFIX prefix",
          "expression":
            "(resource.type == 'compute.googleapis.com/Disk' &&
            resource.name.startsWith('projects/PROJECT_ID/zones/ZONE_ID/disks/PREFIX')) ||
            (resource.type == 'compute.googleapis.com/Instance' &&
            resource.name.startsWith('projects/PROJECT_ID/zones/ZONE_ID/instances/PREFIX')) ||
            (resource.type != 'compute.googleapis.com/Instance' &&
            resource.type != 'compute.googleapis.com/Disk')"
      }
    }
  ],
  "etag": "BwWKmjvelug=",
  "version": 3
}

接著,執行 gcloud projects set-iam-policy 指令,設定新的允許政策:

gcloud projects set-iam-policy project-id filepath

新的條件式角色繫結會以以下方式授予群組權限:

  • 角色繫結中的成員只能使用磁碟和執行個體權限,存取名稱開頭為指定前置字元的磁碟和執行個體
  • 角色繫結中的成員可以使用執行個體管理員角色 (roles/compute.instanceAdmin) 中的所有其他權限,存取磁碟和執行個體以外的所有資源

REST

使用「讀取 - 修改 - 寫入」模式,允許存取特定資源。

首先,請詳閱專案的允許政策:

Resource Manager API 的 projects.getIamPolicy 方法會取得專案的允許政策。

使用任何要求資料之前,請先替換以下項目:

  • PROJECT_ID:您的 Trusted Cloud 專案 ID。專案 ID 為英數字串,例如 my-project
  • POLICY_VERSION:要傳回的政策版本。要求應指定最新政策版本,即政策版本 3。詳情請參閱在取得政策時指定政策版本

HTTP 方法和網址:

POST https://cloudresourcemanager.googleapis.com/v1/projects/PROJECT_ID:getIamPolicy

JSON 要求主體:

{
  "options": {
    "requestedPolicyVersion": POLICY_VERSION
  }
}

如要傳送要求,請展開以下其中一個選項:

您應該會收到如下的 JSON 回應:

{
  "version": 1,
  "etag": "BwWKmjvelug=",
  "bindings": [
    {
      "role": "roles/owner",
      "members": [
        "principal://iam.googleapis.com/locations/global/workforcePools/my-pool/subject/my-user@example.com
      ]
    },
    {
      "members": [
        "principalSet://iam.googleapis.com/locations/global/workforcePools/my-pool/group/my-group"
      ],
      "role": "roles/compute.instanceAdmin"
    }
  ]
}

接著,修改允許政策,允許存取特定資源。請務必將 version 欄位變更為 3 值:

{
  "version": 3,
  "etag": "BwWKmjvelug=",
  "bindings": [
    {
      "role": "roles/owner",
      "members": [
        "principal://iam.googleapis.com/locations/global/workforcePools/my-pool/subject/my-user@example.com"
      ]
    },
    {
      "role": "roles/compute.instanceAdmin",
      "members": [
        "principalSet://iam.googleapis.com/locations/global/workforcePools/my-pool/group/my-group"
      ],
      "condition": {
          "title": "PREFIX_only",
          "description": "Only gives access to VMs with the PREFIX prefix",
          "expression":
            "(resource.type == 'compute.googleapis.com/Disk' &&
            resource.name.startsWith('projects/PROJECT_ID/zones/ZONE_ID/disks/PREFIX')) ||
            (resource.type == 'compute.googleapis.com/Instance' &&
            resource.name.startsWith('projects/PROJECT_ID/zones/ZONE_ID/instances/PREFIX')) ||
            (resource.type != 'compute.googleapis.com/Instance' &&
            resource.type != 'compute.googleapis.com/Disk')"
      }
    }
  ]
}

最後,請編寫更新後的允許政策:

Resource Manager API 的 projects.setIamPolicy 方法會將要求中的允許政策設為專案的新允許政策。

使用任何要求資料之前,請先替換以下項目:

  • PROJECT_ID:您的 Trusted Cloud 專案 ID。專案 ID 為英數字串,例如 my-project

HTTP 方法和網址:

POST https://cloudresourcemanager.googleapis.com/v1/projects/PROJECT_ID:setIamPolicy

JSON 要求主體:

{
  "policy": {
    "version": 3,
    "etag": "BwWKmjvelug=",
    "bindings": [
      {
        "role": "roles/owner",
        "members": [
          "principal://iam.googleapis.com/locations/global/workforcePools/my-pool/subject/my-user@example.com"
        ]
      },
      {
        "role": "roles/compute.instanceAdmin",
        "members": [
          "principalSet://iam.googleapis.com/locations/global/workforcePools/my-pool/group/my-group"
        ],
        "condition": {
          "title": "Dev_access_only",
          "description": "Only access to devAccess* VMs",
          "expression":
            "(resource.type == 'compute.googleapis.com/Disk' &&
            resource.name.startsWith('projects/PROJECT_ID/zones/ZONE_ID/disks/PREFIX')) ||
            (resource.type == 'compute.googleapis.com/Instance' &&
            resource.name.startsWith('projects/PROJECT_ID/zones/ZONE_ID/instances/PREFIX')) ||
            (resource.type != 'compute.googleapis.com/Instance' &&
            resource.type != 'compute.googleapis.com/Disk')"
        }
      }
    ]
  }
}

如要傳送要求,請展開以下其中一個選項:

回應會包含更新後的允許政策。


從資源名稱擷取值

先前的範例顯示資源名稱 (或資源名稱開頭) 與另一個值之間的布林比較。不過,有時您可能需要比較值與資源名稱的特定部分,而該部分並非位於名稱開頭。

您可以使用 extract() 函式,並指定擷取範本,將資源名稱的相關部分擷取為字串。如有需要,您可以將擷取的字串轉換為其他類型,例如時間戳記。從資源名稱擷取值後,即可與其他值比較。

下列範例顯示使用 extract() 函式的條件運算式。如要進一步瞭解 extract() 函式,請參閱 IAM 條件屬性參考資料

例如:比對過去 30 天的訂單

假設您將訂單資訊儲存在多個 Cloud Storage 值區中,且每個值區中的物件都是依日期整理。一般物件名稱可能類似於以下範例:

projects/_/buckets/acme-orders-aaa/objects/data_lake/orders/order_date=2019-11-03/aef87g87ae0876

您想允許主體存取過去 30 天內的任何訂單。下列條件會比對這些訂單的 Cloud Storage 物件。這項作業會使用 duration()date() 函式,從要求時間減去 30 天 (2,592,000 秒),然後比較該時間戳記與訂單日期:

resource.type == 'storage.googleapis.com/Object' &&
  request.time - duration('2592000s') < date(resource.name.extract('/order_date={date_str}/'))

如要進一步瞭解 date()duration() 函式,請參閱日期/時間屬性參考資料

範例:比對任何位置的 Compute Engine VM

假設您想為任何名稱開頭為 dev- 的 Compute Engine VM,授予主體專案層級的角色,無論 VM 的位置為何。您也希望主體能將該角色用於所有其他資源類型。

VM 的資源名稱格式與 projects/PROJECT_ID/zones/ZONE_ID/instances/INSTANCE_ID 類似。以下條件會針對執行個體名稱開頭為 dev- 字串的 VM,以及 VM 以外的所有資源類型,評估為 true

resource.type != 'compute.googleapis.com/Instance' ||
  resource.name.extract('/instances/{name}').startsWith('dev-')

大括號中的文字會指出要擷取並用於比較的資源名稱部分。在本範例中,擷取範本會擷取字串 /instances/ 第一次出現後的所有字元。

資源型條件的重要使用注意事項

新增以資源為準的條件時,請務必考量條件對主體權限的影響。

自訂角色

請參考以下範例,瞭解如何使用自訂角色。管理員想要建立自訂角色,授予建立 VM 執行個體的權限,但只允許使用者在資源名稱以 staging 名稱前置字串開頭的專案中,使用具有相同名稱前置字串的磁碟建立 VM 執行個體。

為達成這個目標,請確認授予的角色包含建立 VM 執行個體的必要權限,也就是磁碟和執行個體資源類型的權限。然後,請確認條件運算式會檢查磁碟和執行個體的資源名稱。除了這兩種類型,系統不會授予角色中的其他權限。

以下條件運算式會導致非預期的行為。 無法對 Compute Engine VM 執行作業:

resource.type == 'compute.googleapis.com/Disk' &&
 resource.name.startsWith('projects/PROJECT_ID/zones/ZONE_ID/disks/staging')

下列條件運算式同時包含磁碟和執行個體,並會根據這兩種類型的資源名稱管理存取權:

(resource.type == 'compute.googleapis.com/Disk' &&
  resource.name.startsWith('projects/PROJECT_ID/zones/ZONE_ID/disks/staging')) ||
 (resource.type == 'compute.googleapis.com/Instance' &&
  resource.name.startsWith('projects/PROJECT_ID/zones/ZONE_ID/instances/staging'))

下列條件運算式同時包含磁碟和執行個體,並會根據這兩種資源的名稱管理存取權。如果是其他資源類型,條件運算式會授予角色,不論資源名稱為何:

(resource.type == 'compute.googleapis.com/Disk' &&
  resource.name.startsWith('projects/PROJECT_ID/zones/ZONE_ID/disks/staging')) ||
 (resource.type == 'compute.googleapis.com/Instance' &&
  resource.name.startsWith('projects/PROJECT_ID/zones/ZONE_ID/instances/staging')) ||
 (resource.type != 'compute.googleapis.com/Disk' &&
  resource.type != 'compute.googleapis.com/Instance')

僅限家長的權限

在 Trusted Cloud的資源階層中,角色中影響子項資源的部分權限,僅會在父項層級強制執行。舉例來說,如要列出機構中的專案,使用者必須在專案所屬的機構中獲得 resourcemanager.projects.list 權限,而非在專案本身獲得權限。這類權限稱為「僅限父項權限」,而且僅適用於 list 作業。

如要在使用條件時正確授予 *.*.list 權限,條件運算式應根據待列出目標資源的父項資源類型設定 resource.serviceresource.type 屬性。

請參考以下範例。以上一節的 Compute Engine 範例為例,下列運算式會禁止存取 compute.disks.listcompute.instances.list 權限,因為檢查這些權限的資源具有 resource.type 屬性值 cloudresourcemanager.googleapis.com/Project

(resource.type == 'compute.googleapis.com/Disk' &&
  resource.name.startsWith('projects/PROJECT_ID/zones/ZONE_ID/disks/PREFIX')) ||
 (resource.type == 'compute.googleapis.com/Instance' &&
  resource.name.startsWith('projects/PROJECT_ID/zones/ZONE_ID/instances/PREFIX'))

通常會一併授予這些 list 權限,以及資源一般作業的其他權限。如要擴大授予範圍,您可以只擴大 cloudresourcemanager.googleapis.com/Project 類型範圍,也可以擴大範圍,涵蓋所有其他非執行個體或磁碟類型的權限。

(resource.type == 'compute.googleapis.com/Disk' &&
  resource.name.startsWith('projects/PROJECT_ID/zones/ZONE_ID/disks/PREFIX')) ||
 (resource.type == 'compute.googleapis.com/Instance' &&
  resource.name.startsWith('projects/PROJECT_ID/zones/ZONE_ID/instances/PREFIX')) ||
 resource.type == 'cloudresourcemanager.googleapis.com/Project'

(resource.type == 'compute.googleapis.com/Disk' &&
  resource.name.startsWith('projects/PROJECT_ID/zones/ZONE_ID/disks/PREFIX')) ||
 (resource.type == 'compute.googleapis.com/Instance' &&
  resource.name.startsWith('projects/PROJECT_ID/zones/ZONE_ID/instances/PREFIX')) ||
 (resource.type != 'compute.googleapis.com/Disk' &&
  resource.type != 'compute.googleapis.com/Instance')