本頁說明如何透過許可政策中的條件角色繫結,管理特定資源的存取權。您可以在條件運算式中使用資源屬性,根據資源的名稱、類型和 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.type
和 resource.service
屬性。使用這些額外屬性後,條件較不會影響對名稱相似的不同資源類型的存取權。本節範例會使用 resource.name
和 resource.type
屬性控管存取權。
如要根據名稱前置字串,授予專案中 Compute Engine 磁碟和執行個體的存取權,請按照下列步驟操作:
控制台
前往 Trusted Cloud 控制台的「IAM」IAM頁面。
在主體清單中找到所需主體,然後按一下
按鈕。在「編輯權限」面板中,找到要設定條件的角色。然後在「IAM condition (optional)」(IAM 條件 (選用)) 下方,按一下「Add IAM condition」(新增 IAM 條件)。
在「編輯條件」面板中,輸入條件的標題和說明 (說明為選填)。
您可以使用「條件建構工具」或「條件編輯器」新增條件運算式。條件建構工具提供互動式介面,可供選取所需的條件類型、運算子,以及運算式的其他適用詳細資料。條件編輯器提供以文字為基礎的介面,可使用 CEL 語法手動輸入運算式。
條件建構工具:
- 從條件建構工具中刪除所有現有的條件欄位。條件建構工具中應只有「新增」按鈕。
- 建立分組條件運算式,如果資源是以前置字串開頭的磁碟,則評估結果為
true
:- 按一下「新增」下拉式選單,然後點選「分組條件」。
- 從「條件類型」下拉式選單中,選取「資源」>「類型」。
- 在「運算子」下拉式選單中,選取「是」。
- 在「資源類型」下拉式選單中,選取「compute.googleapis.com/Disk」。
- 按一下剛輸入條件下方第一個「新增」按鈕,即可在運算式中新增其他子句。
- 從「條件類型」下拉式選單中,選取「資源」>「名稱」。
- 在「運算子」下拉式選單中,選取「開頭為」。
- 在「Value」(值) 欄位中,以適當格式輸入資源名稱,包括所需前置字串。舉例來說,使用
projects/PROJECT_ID/region/ZONE_ID/disks/PREFIX
可識別專案PROJECT_ID
和區域ZONE_ID
中名稱開頭為PREFIX
的磁碟。 - 在每個條件類型左側,按一下「且」,確保兩個子句都必須為真。
- 建立分組條件運算式,如果資源是以前述前置字元開頭的執行個體,則評估結果為
true
:- 按一下現有條件群組外的「新增」按鈕,然後按一下「已分組的條件」。
- 從「條件類型」下拉式選單中,選取「資源」>「類型」。
- 在「運算子」下拉式選單中,選取「是」。
- 從「Resource Type」(資源類型) 下拉式選單中,選取「compute.googleapis.com/Instance」。
- 在同一個條件群組中,按一下「新增」。
- 從「條件類型」下拉式選單中,選取「資源」>「名稱」。
- 在「運算子」下拉式選單中,選取「開頭為」。
- 在「Value」(值) 欄位中,以適當格式輸入所需前置字串的資源名稱。舉例來說,使用
projects/PROJECT_ID/zones/ZONE_ID/instances/PREFIX
可找出專案PROJECT_ID
和區域ZONE_ID
中,名稱以PREFIX
開頭的執行個體。 - 確認群組中連結條件的邏輯運算子已設為「And」。
- 建立分組條件運算式,如果資源不是磁碟或執行個體,則評估結果為
true
:- 點選現有條件群組外的「新增」按鈕,然後點選「條件群組」。
- 從「條件類型」下拉式選單中,選取「資源」>「類型」。
- 在「運算子」下拉式選單中,選取「不是」。
- 在「資源類型」下拉式選單中,選取「compute.googleapis.com/Disk」。
- 在同一個條件群組中,按一下「新增」。
- 從「條件類型」下拉式選單中,選取「資源」>「類型」。
- 在「運算子」下拉式選單中,選取「不是」。
- 從「Resource Type」(資源類型) 下拉式選單中,選取「compute.googleapis.com/Instance」。
- 確認群組中連結條件的邏輯運算子已設為「And」。
確認連結所有條件運算式群組的邏輯運算子為「Or」。
按一下「儲存」即可套用條件。
關閉「編輯條件」面板後,再次按一下「編輯權限」面板中的「儲存」,即可更新允許政策。
條件編輯器:
按一下「條件編輯器」分頁標籤,然後輸入下列運算式:
(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")
輸入運算式後,您可以選擇點選文字方塊右上方的「執行 Lint」,Lint CEL 語法。
按一下「儲存」即可套用條件。
關閉「編輯條件」面板後,再次按一下「編輯權限」面板中的「儲存」,即可更新允許政策。
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.service
和 resource.type
屬性。
請參考以下範例。以上一節的 Compute Engine 範例為例,下列運算式會禁止存取 compute.disks.list
和 compute.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')