使用混合型工作檢查外部來源的資料

本主題說明如何使用混合型工作和混合型工作觸發條件,檢查外部資料是否含有私密資訊。如要進一步瞭解混合型工作和混合型工作觸發條件 (包括混合型環境的範例),請參閱「混合型工作和混合型工作觸發條件」一文。

混合型工作和混合型工作觸發條件簡介

透過混合型工作和混合型工作觸發條件,您可以擴大 Sensitive Data Protection 的保護範圍,不只簡單的內容檢查要求Google Cloud 儲存空間存放區掃描。使用混合型工作和混合型工作觸發條件,您可以將資料從幾乎任何來源 (包括外部來源) 直接串流至 Sensitive Data Protection,並讓 Sensitive Data Protection 檢查資料中的私密資訊。 Google CloudSensitive Data Protection 會自動儲存及匯總掃描結果,以供進一步分析。

比較混合型工作和混合型工作觸發條件

建立混合工作後,工作會持續執行,直到您停止為止。只要資料路徑正確且格式正確,這些端點就會接受所有傳入資料。

混合型工作觸發條件的運作方式與混合型工作類似,但您不需要在混合型工作觸發條件中明確停止工作。在每天結束時,Sensitive Data Protection 會自動停止混合型工作觸發條件內的工作。

此外,使用混合式工作觸發條件時,您可以在觸發條件內停止及啟動新工作,不必重新設定 hybridInspect 要求。舉例來說,您可以將資料傳送至混合工作觸發程序,然後停止現有工作、變更設定、在該觸發程序中啟動新工作,然後繼續將資料傳送至同一觸發程序。

如需更多有關哪種選項適合您使用案例的指引,請參閱本頁的「常見的混合檢查情境」。

字詞定義

本主題使用下列詞彙:

  • 外部資料:儲存在外部的資料 Google Cloud ,或 Sensitive Data Protection 原生不支援的資料。

  • 混合型工作:設定為掃描幾乎所有來源資料的檢查工作。

  • 混合型工作觸發條件:設定為掃描幾乎任何來源資料的工作觸發條件。

  • hybridInspect 要求:包含要檢查的外部資料的要求。傳送這項要求時,請指定要將要求傳送至的混合式工作或混合式工作觸發程序。

如要瞭解工作和工作觸發條件的一般資訊,請參閱「工作和工作觸發條件」一文。

混合式檢查程序

混合檢查程序分為三個步驟。

  1. 選擇要傳送至 Sensitive Data Protection 的資料。

    資料可能來自 Google Cloud 內部或外部。舉例來說,您可以設定自訂指令碼或應用程式,將資料傳送至 Sensitive Data Protection,以便檢查來自其他雲端服務、內部部署資料存放區或幾乎任何其他資料來源的傳輸中資料。

  2. 在 Sensitive Data Protection 中從頭開始設定混合型工作或混合型工作觸發條件,也可以使用檢查範本

    設定混合式工作或混合式工作觸發條件後,Sensitive Data Protection 會主動監聽傳送給它的資料。當自訂指令碼或應用程式將資料傳送至這項混合式工作或混合式工作觸發條件時,系統會檢查資料,並根據設定儲存結果。

    設定混合式工作或混合式工作觸發條件時,您可以指定要儲存或發布調查結果的位置。選項包括儲存至 BigQuery,以及向 Pub/Sub、Cloud Monitoring 或電子郵件發布通知。

  3. hybridInspect 要求傳送至混合工作或混合工作觸發條件。

    hybridInspect 要求包含要掃描的資料。在要求中,加入描述內容的中繼資料 (又稱為「標籤」和「資料表 ID」),讓 Sensitive Data Protection 識別您要追蹤的資訊。舉例來說,如果您要掃描多個要求中的相關資料 (例如同一個資料庫表格中的資料列),可以在這些相關要求中使用相同的中繼資料。接著,您就可以收集、統計及分析該資料庫資料表的結果。

混合型工作執行及檢查要求時,Sensitive Data Protection 會產生檢查結果,相較之下,Pub/Sub 通知等動作會在應用程式結束混合式工作時才會發生。

說明混合式工作檢查程序的圖表

注意事項

使用混合型工作和工作觸發條件時,請注意下列幾點:

  • 混合型工作和混合型工作觸發條件不支援篩選和取樣。
  • 作業和作業觸發程序不受服務等級目標 (SLO) 限制,但您可以採取一些步驟來縮短延遲時間。詳情請參閱「工作延遲時間」。

事前準備

設定及使用混合式工作或混合式工作觸發程序前,請務必完成下列事項:

建立新專案、啟用計費功能,並啟用 Sensitive Data Protection

  1. Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
  2. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  3. Make sure that billing is enabled for your Google Cloud project.

  4. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  5. Make sure that billing is enabled for your Google Cloud project.

  6. Enable the Sensitive Data Protection API.

    Enable the API

  7. 設定資料來源

    您必須先將資料傳送至 Sensitive Data Protection,才能讓這項服務檢查資料。無論您使用哪種方法設定混合型工作或混合型工作觸發條件,都必須設定外部來源,將資料傳送至 DLP API。

    如要瞭解混合檢查要求的必要格式,請參閱「混合內容項目格式」。如要瞭解可在要求中加入哪些類型的中繼資料,請參閱「可提供的中繼資料類型」。

    建立混合型工作或混合型工作觸發條件

    如要讓 Sensitive Data Protection 檢查您傳送的資料,請先設定混合型工作或混合型工作觸發條件。如要瞭解該建立哪種檢查,請參閱本頁的「常見的混合檢查情境」。

    控制台

    前往 Google Cloud 控制台的「Create job or job trigger」(建立工作或工作觸發條件) 頁面:

    前往「建立工作或工作觸發條件」

    以下各節說明如何填寫「建立工作或工作觸發條件」頁面中與混合檢查作業相關的章節。

    選擇輸入資料

    在本節中,您將指定 Sensitive Data Protection 要檢查的輸入資料。

    1. 選用:如要為工作命名,請在「Job ID」(工作 ID) 欄位中輸入值。如果將這個欄位留空,Sensitive Data Protection 會自動產生識別碼。
    2. 選用:從「資源位置」選單中,選擇要儲存混合式工作或混合式工作觸發條件的區域。詳情請參閱「指定處理位置」。
    3. 在「儲存空間類型」部分,選取「混合」。

    4. 選用:在「Description」(說明) 中,說明您要建立的混合式工作或混合式工作觸發條件。舉例來說,您可以納入要檢查的資料來源相關資訊。

    5. 選用:如要新增必要標籤,請按一下「新增標籤」,然後輸入您希望 hybridInspect 請求提供的標籤。如果 hybridInspect 要求未指定這個標籤,這個混合式工作或混合式工作觸發條件就不會處理該要求。最多可新增 10 個必要標籤。詳情請參閱本頁面的「要求來自 hybridInspect 要求的標籤」。

    6. 選用:在「選用標籤」中,輸入要附加至傳送至這項工作或工作觸發程序的任何 hybridInspect 要求結果的鍵/值組合。最多可以新增 10 個選用標籤。詳情請參閱「選用標籤」。

    7. 選用:如要使用「表格資料選項」,請在 hybridInspect 要求中傳送表格資料,並輸入主鍵資料欄的欄位名稱。詳情請參閱表格資料選項

    8. 按一下「繼續」

    設定偵測作業

    在這個部分中,您可以指定 Sensitive Data Protection 要檢查輸入資料中的哪些類型私密/機密資料。可用的選項包括:

    • 範本:如果您已在目前專案中建立範本,並想用來定義 Sensitive Data Protection 偵測參數,請按一下「範本名稱」欄位,然後從顯示的清單中選擇範本。
    • InfoTypes:Sensitive Data Protection 會選取最常見的內建 infoType 進行偵測。如要變更 infoType 或選擇要使用的自訂 infoType,請按一下「管理 infoType」。您也可以在「檢查規則集」和「信賴度門檻」部分微調偵測條件。詳情請參閱「設定偵測功能」。

    設定偵測作業的參數後,按一下「繼續」

    新增動作

    您可以在這個部分指定要儲存每次檢查掃描結果的位置,以及是否要在掃描完成時透過電子郵件或 Pub/Sub 通知訊息接收通知。如未將發現項目儲存至 BigQuery,掃描結果只會包含與發現項目的數量和 infoType 相關的統計資料。

    • 儲存至 BigQuery:每次執行掃描時,Sensitive Data Protection 都會將掃描結果儲存至您在此指定的 BigQuery 表格。如果未指定資料表 ID,BigQuery 會在首次執行掃描時,為新資料表指派預設名稱。如果您指定現有的資料表,Sensitive Data Protection 會將掃描結果附加至該資料表。
    • 發布至 Pub/Sub:工作完成後,系統會發出 Pub/Sub 訊息。

    • 透過電子郵件通知:作業完成後,系統會傳送電子郵件訊息。

    • 發布至 Cloud Monitoring:工作完成後,系統會將發現項目發布至 Monitoring。

    選擇動作後,按一下「繼續」

    排程

    在本節中,您可以指定要建立立即執行的單一工作,還是在 Sensitive Data Protection 收到經過適當路徑傳送及格式化的資料時,就執行工作觸發條件。

    執行下列其中一個步驟:

    • 如要立即執行混合式工作,請選擇「無 (建立後立即執行一次性工作)」

    • 如要設定工作,讓工作在收到來源資料時觸發,請選擇「建立觸發條件來定期執行工作」

      混合型工作觸發條件會匯總 API 呼叫,讓您查看發現項目的結果與趨勢隨時間變化的情形。

    詳情請參閱「混合型工作和混合型工作觸發條件比較」。

    查看

    您可以在這裡查看掃描的 JSON 摘要。請務必記下混合式作業或混合式工作觸發條件的名稱,將資料傳送至 Sensitive Data Protection 進行檢查時,需要提供這項資訊。

    查看 JSON 摘要後,按一下「建立」

    Sensitive Data Protection 會立即啟動混合型工作或混合型工作觸發條件。 當您傳送hybridInspect要求給這個混合型工作或混合型工作觸發條件時,系統就會開始檢查掃描。

    API

    工作在 DLP API 中會以 DlpJobs 資源表示。如要建立混合工作,請呼叫 projects.locations.dlpJobs.create 方法。

    工作觸發條件在 DLP API 中會以 JobTrigger 資源表示。如要建立混合工作觸發程序,請呼叫 projects.locations.jobTriggers.create 方法。

    您建立的 DlpJobsJobTrigger 物件必須具備下列設定:

    1. inspectJob 欄位中,設定 InspectJobConfig 物件。
    2. InspectJobConfig 物件的 storageConfig 欄位中,設定 StorageConfig 物件。
    3. StorageConfig 物件的 hybridOptions 欄位中,設定 HybridOptions 物件。這個物件包含您要檢查的資料相關中繼資料
    4. InspectJobConfig 物件的 actions 欄位中,加入您希望 Sensitive Data Protection 在每個工作結束時執行的任何動作 (Action)。

      這項作業不支援 publishSummaryToCsccpublishFindingsToCloudDataCatalog 動作。如要進一步瞭解動作,請參閱「動作」。

    5. 執行下列一或多項操作,指定要掃描的內容和掃描方式:

      • inspectTemplateName 欄位設為要使用的檢查範本完整資源名稱 (如有)。

      • 設定 inspectConfig 欄位。

      如果同時設定 inspectTemplateNameinspectConfig 欄位,系統會合併兩者的設定。

    JSON 範例簡介

    以下分頁包含 JSON 範例,您可以傳送至 Sensitive Data Protection,建立混合型工作混合型工作觸發條件。這些混合型工作和混合型工作觸發條件範例的設定如下:

    • 如果要求有 appointment-bookings-comments 標籤,請處理任何 hybridInspect 要求。
    • 掃描「電子郵件地址」hybridInspect要求中的內容。
    • "env": "prod" 標籤附加至發現項目。
    • 如果是表格資料,請取得 booking_id 欄 (主鍵) 中與找到私密資料的儲存格位於同一列的儲存格值。Sensitive Data Protection 會將這個 ID 附加至發現項目,方便您追蹤發現項目來自的特定資料列。
    • 在作業停止時傳送電子郵件。電子郵件會傳送給 IAM 專案擁有者和技術重要聯絡人
    • 工作停止時,將結果傳送至 Cloud Monitoring。

    如要查看 JSON 範例,請參閱下列分頁。

    混合型工作

    這個分頁包含 JSON 範例,可用於建立混合式工作。

    如要建立混合工作,請將 POST 要求傳送至下列端點。

    HTTP 方法和網址

    POST https://dlp.googleapis.com/v2/projects/PROJECT_ID/locations/REGION/dlpJobs
    

    更改下列內容:

    • PROJECT_ID:您要儲存混合式作業的專案 ID
    • REGION:要儲存混合工作職缺的地理區域

    JSON 輸入

    {
      "jobId": "postgresql-table-comments",
      "inspectJob": {
        "actions": [
          {
            "jobNotificationEmails": {}
          },
          {
            "publishToStackdriver": {}
          }
        ],
        "inspectConfig": {
          "infoTypes": [
            {
              "name": "EMAIL_ADDRESS"
            }
          ],
          "minLikelihood": "POSSIBLE",
          "includeQuote": true
        },
        "storageConfig": {
          "hybridOptions": {
            "description": "Hybrid job for data from the comments field of a table that contains customer appointment bookings",
            "requiredFindingLabelKeys": [
              "appointment-bookings-comments"
            ],
            "labels": {
              "env": "prod"
            },
            "tableOptions": {
              "identifyingFields": [
                {
                  "name": "booking_id"
                }
              ]
            }
          }
        }
      }
    }
    

    JSON 輸出

    {
    "name": "projects/PROJECT_ID/locations/REGION/dlpJobs/i-postgresql-table-comments",
    "type": "INSPECT_JOB",
    "state": "ACTIVE",
    "inspectDetails": {
      "requestedOptions": {
        "snapshotInspectTemplate": {},
        "jobConfig": {
          "storageConfig": {
            "hybridOptions": {
              "description": "Hybrid job for data from the comments field of a table that contains customer appointment bookings",
              "requiredFindingLabelKeys": [
                "appointment-bookings-comments"
              ],
              "labels": {
                "env": "prod"
              },
              "tableOptions": {
                "identifyingFields": [
                  {
                    "name": "booking_id"
                  }
                ]
              }
            }
          },
          "inspectConfig": {
            "infoTypes": [
              {
                "name": "EMAIL_ADDRESS"
              }
            ],
            "minLikelihood": "POSSIBLE",
            "limits": {},
            "includeQuote": true
          },
          "actions": [
            {
              "jobNotificationEmails": {}
            },
            {
              "publishToStackdriver": {}
            }
          ]
        }
      },
      "result": {
        "hybridStats": {}
      }
    },
    "createTime": "JOB_CREATION_DATETIME",
    "startTime": "JOB_START_DATETIME"
    }
    

    Sensitive Data Protection 會建立混合式工作並產生工作 ID。在本範例中,工作 ID 為 i-postgresql-table-comments。記下工作 ID。 您需要在 hybridInspect 要求中提供這項資訊。

    如要停止混合工作,您必須明確呼叫 projects.locations.dlpJobs.finish 方法。DLP API 不會自動停止混合式工作。相較之下,DLP API 會在每天結束時,自動停止混合式工作觸發條件內的工作。

    混合型工作觸發條件

    這個分頁包含 JSON 範例,可用於建立混合式工作觸發程序。

    如要建立混合式工作觸發條件,請將 POST 要求傳送至下列端點。

    HTTP 方法和網址

    POST https://dlp.googleapis.com/v2/projects/PROJECT_ID/locations/REGION/jobTriggers
    

    更改下列內容:

    • PROJECT_ID:您要儲存混合式工作觸發條件的專案 ID
    • REGION:要儲存混合工作觸發程序的地理區域

    JSON 輸入

    {
        "triggerId": "postgresql-table-comments",
        "jobTrigger": {
          "triggers": [
            {
              "manual": {}
            }
          ],
          "inspectJob": {
            "actions": [
              {
                "jobNotificationEmails": {}
              },
              {
                "publishToStackdriver": {}
              }
            ],
            "inspectConfig": {
              "infoTypes": [
                  {
                    "name": "EMAIL_ADDRESS"
                  }
              ],
              "minLikelihood": "POSSIBLE",
              "limits": {},
              "includeQuote": true
            },
            "storageConfig": {
              "hybridOptions": {
                "description": "Hybrid job trigger for data from the comments field of a table that contains customer appointment bookings",
                "requiredFindingLabelKeys": [
                    "appointment-bookings-comments"
                  ],
                "labels": {
                  "env": "prod"
                },
                "tableOptions": {
                  "identifyingFields": [
                    {
                      "name": "booking_id"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    

    JSON 輸出

    {
    "name": "projects/PROJECT_ID/locations/REGION/jobTriggers/postgresql-table-comments",
    "inspectJob": {
      "storageConfig": {
        "hybridOptions": {
          "description": "Hybrid job trigger for data from the comments field of a table that contains customer appointment bookings",
          "requiredFindingLabelKeys": [
            "appointment-bookings-comments"
          ],
          "labels": {
            "env": "prod"
          },
          "tableOptions": {
            "identifyingFields": [
              {
                "name": "booking_id"
              }
            ]
          }
        }
      },
      "inspectConfig": {
        "infoTypes": [
          {
            "name": "EMAIL_ADDRESS"
          }
        ],
        "minLikelihood": "POSSIBLE",
        "limits": {},
        "includeQuote": true
      },
      "actions": [
        {
          "jobNotificationEmails": {}
        },
        {
          "publishToStackdriver": {}
        }
      ]
    },
    "triggers": [
      {
        "manual": {}
      }
    ],
    "createTime": ""JOB_CREATION_DATETIME",
    "updateTime": "TRIGGER_UPDATE_DATETIME",
    "status": "HEALTHY"
    }
    

    Sensitive Data Protection 會建立混合型工作觸發條件。輸出內容包含混合工作觸發條件的名稱。在本例中,該值為 postgresql-table-comments。請記下名稱,您需要在hybridInspect要求中提供這項資訊。

    與混合式工作不同,DLP API 會在每天結束時,自動停止混合式工作觸發條件內的工作。因此,您不需要明確呼叫 projects.locations.dlpJobs.finish 方法。

    建立混合式工作或混合式工作觸發條件時,您可以使用下列 API 參考頁面上的 APIs Explorer:

    在「Request parameters」(要求參數) 欄位中,輸入 projects/PROJECT_ID/locations/REGION。然後,在「Request body」(要求主體) 欄位中,貼上您要建立物件的範例 JSON。

    即使在 API Explorer 中建立,成功提出的要求仍會建立混合工作或混合工作觸發條件。

    如要瞭解如何透過 JSON 將要求傳送至 DLP API 的一般資訊,請參閱 JSON 快速入門

    將資料傳送至混合型工作或混合型工作觸發條件

    如要檢查資料,您必須以正確格式將 hybridInspect 要求傳送至混合型工作或混合型工作觸發條件。

    混合內容項目格式

    以下是傳送至 Sensitive Data Protection 的 hybridInspect 要求簡單範例,供混合型工作或混合型工作觸發條件處理。請注意 JSON 物件的結構,包括 hybridItem 欄位,其中包含下列欄位:

    • item:包含要檢查的實際內容。
    • findingDetails:包含要與內容建立關聯的中繼資料。
    {
      "hybridItem": {
        "item": {
          "value": "My email is test@example.org"
        },
        "findingDetails": {
          "containerDetails": {
            "fullPath": "10.0.0.2:logs1:app1",
            "relativePath": "app1",
            "rootPath": "10.0.0.2:logs1",
            "type": "logging_sys",
            "version": "1.2"
          },
          "labels": {
            "env": "prod",
            "appointment-bookings-comments": ""
          }
        }
      }
    }
    

    如要進一步瞭解混合檢查項目內容,請參閱 HybridContentItem 物件的 API 參考資料內容。

    混合式檢查端點

    如要使用混合型工作或混合型工作觸發條件檢查資料,請將 hybridInspect 要求傳送至正確的端點。

    混合式作業的 HTTP 方法和網址

    POST https://dlp.googleapis.com/v2/projects/PROJECT_ID/locations/REGION/dlpJobs/JOB_ID:hybridInspect
    

    如要進一步瞭解這個端點,請參閱 projects.locations.dlpJobs.hybridInspect 方法的 API 參考頁面。

    混合式工作觸發條件的 HTTP 方法和網址

    https://dlp.googleapis.com/v2/projects/PROJECT_ID/locations/REGION/jobTriggers/TRIGGER_NAME:hybridInspect
    

    如要進一步瞭解這個端點,請參閱 projects.locations.jobTriggers.hybridInspect 方法的 API 參考頁面。

    更改下列內容:

    • PROJECT_ID:您的專案 ID
    • REGION:您要儲存 hybridInspect 要求的地理區域。這個區域必須與混合式作業的區域相同。
    • JOB_ID:您為混合工作提供的 ID,前置字串為 i-

      如要查詢工作 ID,請在敏感資料保護中,依序點選「檢查」>「檢查工作」

    • TRIGGER_NAME:您為混合工作觸發條件指定的名稱。

      如要查詢工作觸發條件的名稱,請在 Sensitive Data Protection 中,依序點選「檢查」> 工作觸發條件

    要求 hybridInspect 要求的標籤

    如要控管混合型工作或混合型工作觸發條件可處理的要求,可以設定必要標籤。hybridInspect 如果混合型工作或混合型工作觸發條件的任何 hybridInspect 要求未包含這些必要標籤,就會遭到拒絕。

    如要設定必要標籤,請按照下列步驟操作:

    1. 建立混合工作或混合工作觸發條件時,請將 requiredFindingLabelKeys 欄位設為必要標籤清單。

      以下範例會在混合式工作或混合式工作觸發條件中,將 appointment-bookings-comments 設為必要標籤。

      "hybridOptions": {
        ...
        "requiredFindingLabelKeys": [
          "appointment-bookings-comments"
        ],
        "labels": {
          "env": "prod"
        },
        ...
      }
      
    2. hybridInspect 要求中,於 labels 欄位中,將每個必要標籤新增為鍵值組合中的鍵。對應值可以是空字串。

      下列範例會在 hybridInspect 要求中設定必要標籤 appointment-bookings-comments

      {
        "hybridItem": {
          "item": {
            "value": "My email is test@example.org"
          },
          "findingDetails": {
            "containerDetails": {...},
            "labels": {
              "appointment-bookings-comments": ""
            }
          }
        }
      }
      

    如果 hybridInspect 要求未包含必要標籤,您會收到類似下列內容的錯誤訊息:

    {
      "error": {
        "code": 400,
        "message": "Trigger required labels that were not included: [appointment-bookings-comments]",
        "status": "INVALID_ARGUMENT"
      }
    }
    

    程式碼範例:建立混合式工作觸發條件並將資料傳送至該條件

    C#

    如要瞭解如何安裝及使用 Sensitive Data Protection 的用戶端程式庫,請參閱這篇文章

    如要驗證 Sensitive Data Protection,請設定應用程式預設憑證。 詳情請參閱「為本機開發環境設定驗證」。

    
    using System;
    using Google.Api.Gax.ResourceNames;
    using Google.Api.Gax;
    using Google.Cloud.Dlp.V2;
    using Grpc.Core;
    
    public class SendDataToTheHybridJobTrigger
    {
        public static DlpJob SendToHybridJobTrigger(
           string projectId,
           string jobTriggerId,
           string text = null)
        {
            // Instantiate the dlp client.
            var dlp = DlpServiceClient.Create();
    
            // Construct the hybrid finding details which will be used as metadata with the content.
            // Refer to this for more information: https://cloud.google.com/dlp/docs/reference/rpc/google.privacy.dlp.v2#google.privacy.dlp.v2.Container
            var findingDetails = new HybridFindingDetails
            {
                ContainerDetails = new Container
                {
                    FullPath = "10.0.0.2:logs1:aap1",
                    RelativePath = "app1",
                    RootPath = "10.0.0.2:logs1",
                    Type = "System Logs"
                }
            };
    
            // Construct the hybrid content item using the finding details and text to be inspected.
            var hybridContentItem = new HybridContentItem
            {
                Item = new ContentItem { Value = text ?? "My email is ariel@example.org and name is Ariel." },
                FindingDetails = findingDetails
            };
    
            var jobTriggerName = new JobTriggerName(projectId, jobTriggerId);
    
            // Construct the request to activate the Job Trigger.
            var activate = new ActivateJobTriggerRequest
            {
                JobTriggerName = jobTriggerName
            };
    
            DlpJob triggerJob = null;
    
            try
            {
                // Call the API to activate the trigger.
                triggerJob = dlp.ActivateJobTrigger(activate);
            }
            catch (RpcException)
            {
                ListDlpJobsRequest listJobsRequest = new ListDlpJobsRequest
                {
                    ParentAsLocationName = new LocationName(projectId, "global"),
                    Filter = $"trigger_name={jobTriggerName}"
                };
    
                PagedEnumerable<ListDlpJobsResponse, DlpJob> res = dlp.ListDlpJobs(listJobsRequest);
                foreach (DlpJob j in res)
                {
                    triggerJob = j;
                }
            }
    
            // Construct the request using hybrid content item.
            var request = new HybridInspectJobTriggerRequest
            {
                HybridItem = hybridContentItem,
                JobTriggerName = jobTriggerName
            };
    
            // Call the API.
            HybridInspectResponse _ = dlp.HybridInspectJobTrigger(request);
    
            Console.WriteLine($"Hybrid job created successfully. Job name: {triggerJob.Name}");
    
            return triggerJob;
        }
    }
    

    Go

    如要瞭解如何安裝及使用 Sensitive Data Protection 的用戶端程式庫,請參閱這篇文章

    如要驗證 Sensitive Data Protection,請設定應用程式預設憑證。 詳情請參閱「為本機開發環境設定驗證」。

    import (
    	"context"
    	"fmt"
    	"io"
    	"log"
    	"time"
    
    	dlp "cloud.google.com/go/dlp/apiv2"
    	"cloud.google.com/go/dlp/apiv2/dlppb"
    )
    
    // inspectDataToHybridJobTrigger uses the Data Loss Prevention API to inspect sensitive
    // information using Hybrid jobs trigger that scans payloads of data sent from
    // virtually any source and stores findings in Google Cloud.
    func inspectDataToHybridJobTrigger(w io.Writer, projectID, textToDeIdentify, jobTriggerName string) error {
    	// projectId := "your-project-id"
    	// jobTriggerName := "your-job-trigger-name"
    	// textToDeIdentify := "My email is test@example.org"
    
    	ctx := context.Background()
    
    	// Initialize a client once and reuse it to send multiple requests. Clients
    	// are safe to use across goroutines. When the client is no longer needed,
    	// call the Close method to cleanup its resources.
    	client, err := dlp.NewClient(ctx)
    	if err != nil {
    		return err
    	}
    
    	// Closing the client safely cleans up background resources.
    	defer client.Close()
    
    	// Specify the content to be inspected.
    	contentItem := &dlppb.ContentItem{
    		DataItem: &dlppb.ContentItem_Value{
    			Value: textToDeIdentify,
    		},
    	}
    
    	// Contains metadata to associate with the content.
    	// Refer to https://cloud.google.com/dlp/docs/reference/rpc/google.privacy.dlp.v2#container for specifying the paths in container object.
    	container := &dlppb.Container{
    		Type:         "logging_sys",
    		FullPath:     "10.0.0.2:logs1:app1",
    		RelativePath: "app1",
    		RootPath:     "10.0.0.2:logs1",
    		Version:      "1.2",
    	}
    
    	// Set the required label.
    	labels := map[string]string{
    		"env":                           "prod",
    		"appointment-bookings-comments": "",
    	}
    
    	hybridFindingDetails := &dlppb.HybridFindingDetails{
    		ContainerDetails: container,
    		Labels:           labels,
    	}
    
    	hybridContentItem := &dlppb.HybridContentItem{
    		Item:           contentItem,
    		FindingDetails: hybridFindingDetails,
    	}
    
    	// Activate the job trigger.
    	activateJobreq := &dlppb.ActivateJobTriggerRequest{
    		Name: jobTriggerName,
    	}
    
    	dlpJob, err := client.ActivateJobTrigger(ctx, activateJobreq)
    	if err != nil {
    		log.Printf("Error from return part %v", err)
    		return err
    	}
    	// Build the hybrid inspect request.
    	req := &dlppb.HybridInspectJobTriggerRequest{
    		Name:       jobTriggerName,
    		HybridItem: hybridContentItem,
    	}
    
    	// Send the hybrid inspect request.
    	_, err = client.HybridInspectJobTrigger(ctx, req)
    	if err != nil {
    		return err
    	}
    
    	getDlpJobReq := &dlppb.GetDlpJobRequest{
    		Name: dlpJob.Name,
    	}
    
    	var result *dlppb.DlpJob
    	for i := 0; i < 5; i++ {
    		// Get DLP job
    		result, err = client.GetDlpJob(ctx, getDlpJobReq)
    		if err != nil {
    			fmt.Printf("Error getting DLP job: %v\n", err)
    			return err
    		}
    
    		// Check if processed bytes is greater than 0
    		if result.GetInspectDetails().GetResult().GetProcessedBytes() > 0 {
    			break
    		}
    
    		// Wait for 5 seconds before checking again
    		time.Sleep(5 * time.Second)
    		i++
    	}
    
    	fmt.Fprintf(w, "Job Name: %v\n", result.Name)
    	fmt.Fprintf(w, "Job State: %v\n", result.State)
    
    	inspectionResult := result.GetInspectDetails().GetResult()
    	fmt.Fprint(w, "Findings: \n")
    	for _, v := range inspectionResult.GetInfoTypeStats() {
    		fmt.Fprintf(w, "Infotype: %v\n", v.InfoType.Name)
    		fmt.Fprintf(w, "Likelihood: %v\n", v.GetCount())
    	}
    
    	fmt.Fprint(w, "successfully inspected data using hybrid job trigger ")
    	return nil
    }
    

    Java

    如要瞭解如何安裝及使用 Sensitive Data Protection 的用戶端程式庫,請參閱這篇文章

    如要驗證 Sensitive Data Protection,請設定應用程式預設憑證。 詳情請參閱「為本機開發環境設定驗證」。

    
    import com.google.api.gax.rpc.InvalidArgumentException;
    import com.google.cloud.dlp.v2.DlpServiceClient;
    import com.google.privacy.dlp.v2.ActivateJobTriggerRequest;
    import com.google.privacy.dlp.v2.Container;
    import com.google.privacy.dlp.v2.ContentItem;
    import com.google.privacy.dlp.v2.DlpJob;
    import com.google.privacy.dlp.v2.GetDlpJobRequest;
    import com.google.privacy.dlp.v2.HybridContentItem;
    import com.google.privacy.dlp.v2.HybridFindingDetails;
    import com.google.privacy.dlp.v2.HybridInspectJobTriggerRequest;
    import com.google.privacy.dlp.v2.InfoTypeStats;
    import com.google.privacy.dlp.v2.InspectDataSourceDetails;
    import com.google.privacy.dlp.v2.JobTriggerName;
    import com.google.privacy.dlp.v2.ListDlpJobsRequest;
    
    public class InspectDataToHybridJobTrigger {
    
      public static void main(String[] args) throws Exception {
        // TODO(developer): Replace these variables before running the sample.
        // The Google Cloud project id to use as a parent resource.
        String projectId = "your-project-id";
        // The job trigger id used to for processing a hybrid job trigger.
        String jobTriggerId = "your-job-trigger-id";
        // The string to de-identify.
        String textToDeIdentify = "My email is test@example.org and my name is Gary.";
        inspectDataToHybridJobTrigger(textToDeIdentify, projectId, jobTriggerId);
      }
    
      // Inspects data using a hybrid job trigger.
      // Hybrid jobs trigger allows to scan payloads of data sent from virtually any source for
      // sensitive information and then store the findings in Google Cloud.
      public static void inspectDataToHybridJobTrigger(
          String textToDeIdentify, String projectId, String jobTriggerId) throws Exception {
        // Initialize client that will be used to send requests. This client only needs to be created
        // once, and can be reused for multiple requests. After completing all of your requests, call
        // the "close" method on the client to safely clean up any remaining background resources.
        try (DlpServiceClient dlpClient = DlpServiceClient.create()) {
          // Specify the content to be inspected.
          ContentItem contentItem = ContentItem.newBuilder().setValue(textToDeIdentify).build();
    
          // Contains metadata to associate with the content.
          // Refer to https://cloud.google.com/dlp/docs/reference/rest/v2/Container for specifying the
          // paths in container object.
          Container container =
              Container.newBuilder()
                  .setFullPath("10.0.0.2:logs1:app1")
                  .setRelativePath("app1")
                  .setRootPath("10.0.0.2:logs1")
                  .setType("logging_sys")
                  .setVersion("1.2")
                  .build();
    
          HybridFindingDetails hybridFindingDetails =
              HybridFindingDetails.newBuilder().setContainerDetails(container).build();
    
          HybridContentItem hybridContentItem =
              HybridContentItem.newBuilder()
                  .setItem(contentItem)
                  .setFindingDetails(hybridFindingDetails)
                  .build();
    
          // Activate the job trigger.
          ActivateJobTriggerRequest activateJobTriggerRequest =
              ActivateJobTriggerRequest.newBuilder()
                  .setName(JobTriggerName.of(projectId, jobTriggerId).toString())
                  .build();
    
          DlpJob dlpJob;
    
          try {
            dlpJob = dlpClient.activateJobTrigger(activateJobTriggerRequest);
          } catch (InvalidArgumentException e) {
            ListDlpJobsRequest request =
                ListDlpJobsRequest.newBuilder()
                    .setParent(JobTriggerName.of(projectId, jobTriggerId).toString())
                    .setFilter("trigger_name=" + JobTriggerName.of(projectId, jobTriggerId).toString())
                    .build();
    
            // Retrieve the DLP jobs triggered by the job trigger
            DlpServiceClient.ListDlpJobsPagedResponse response = dlpClient.listDlpJobs(request);
            dlpJob = response.getPage().getResponse().getJobs(0);
          }
    
          // Build the hybrid inspect request.
          HybridInspectJobTriggerRequest request =
              HybridInspectJobTriggerRequest.newBuilder()
                  .setName(JobTriggerName.of(projectId, jobTriggerId).toString())
                  .setHybridItem(hybridContentItem)
                  .build();
    
          // Send the hybrid inspect request.
          dlpClient.hybridInspectJobTrigger(request);
    
          // Build a request to get the completed job
          GetDlpJobRequest getDlpJobRequest =
              GetDlpJobRequest.newBuilder().setName(dlpJob.getName()).build();
    
          DlpJob result = null;
    
          do {
            result = dlpClient.getDlpJob(getDlpJobRequest);
            Thread.sleep(5000);
          } while (result.getInspectDetails().getResult().getProcessedBytes() <= 0);
    
          System.out.println("Job status: " + result.getState());
          System.out.println("Job name: " + result.getName());
          // Parse the response and process results.
          InspectDataSourceDetails.Result inspectionResult = result.getInspectDetails().getResult();
          System.out.println("Findings: ");
          for (InfoTypeStats infoTypeStat : inspectionResult.getInfoTypeStatsList()) {
            System.out.println("\tInfoType: " + infoTypeStat.getInfoType().getName());
            System.out.println("\tCount: " + infoTypeStat.getCount() + "\n");
          }
        }
      }
    }

    Node.js

    如要瞭解如何安裝及使用 Sensitive Data Protection 的用戶端程式庫,請參閱這篇文章

    如要驗證 Sensitive Data Protection,請設定應用程式預設憑證。 詳情請參閱「為本機開發環境設定驗證」。

    // Imports the Google Cloud Data Loss Prevention library
    const DLP = require('@google-cloud/dlp');
    
    // Instantiates a client
    const dlpClient = new DLP.DlpServiceClient();
    
    // The project ID to run the API call under.
    // const projectId = "your-project-id";
    
    // The string to de-identify
    // const string = 'My email is test@example.org';
    
    // Job Trigger ID
    // const jobTriggerId = 'your-job-trigger-id';
    
    async function inspectDataToHybridJobTrigger() {
      // Contains metadata to associate with the content.
      const container = {
        full_path: '10.0.0.2:logs1:app1',
        relative_path: 'app1',
        root_path: '10.0.0.2:logs1',
        type: 'logging_sys',
        version: '1.2',
      };
    
      const labels = {env: 'prod', 'appointment-bookings-comments': ''};
    
      // Build the hybrid content item.
      const hybridContentItem = {
        item: {value: string},
        findingDetails: {
          containerDetails: container,
          labels,
        },
      };
      let jobName;
      const fullTriggerName = `projects/${projectId}/jobTriggers/${jobTriggerId}`;
      // Activate the job trigger.
      try {
        const response = await dlpClient.activateJobTrigger({
          name: fullTriggerName,
        });
        jobName = response[0].name;
      } catch (err) {
        console.log(err);
        if (err.code === 3) {
          const response = await dlpClient.listDlpJobs({
            parent: fullTriggerName,
            filter: `trigger_name=${fullTriggerName}`,
          });
          jobName = response[0][0].name;
        }
        // Ignore error related to job trigger already active
        if (err.code !== 3) {
          console.log(err.message);
          return;
        }
      }
      // Build the hybrid inspect request.
      const request = {
        name: `projects/${projectId}/jobTriggers/${jobTriggerId}`,
        hybridItem: hybridContentItem,
      };
      // Send the hybrid inspect request.
      await dlpClient.hybridInspectJobTrigger(request);
      // Waiting for a maximum of 15 minutes for the job to get complete.
      let job;
      let numOfAttempts = 30;
      while (numOfAttempts > 0) {
        // Fetch DLP Job status
        [job] = await dlpClient.getDlpJob({name: jobName});
    
        if (job.state === 'FAILED') {
          console.log('Job Failed, Please check the configuration.');
          return;
        }
        // Check if the job has completed.
        if (job.inspectDetails.result.processedBytes > 0) {
          break;
        }
        // Sleep for a short duration before checking the job status again.
        await new Promise(resolve => {
          setTimeout(() => resolve(), 30000);
        });
        numOfAttempts -= 1;
      }
      // Finish the job once the inspection is complete.
      await dlpClient.finishDlpJob({name: jobName});
    
      // Print out the results.
      const infoTypeStats = job.inspectDetails.result.infoTypeStats;
      if (infoTypeStats.length > 0) {
        infoTypeStats.forEach(infoTypeStat => {
          console.log(
            `  Found ${infoTypeStat.count} instance(s) of infoType ${infoTypeStat.infoType.name}.`
          );
        });
      } else {
        console.log('No findings.');
      }
    }
    await inspectDataToHybridJobTrigger();

    PHP

    如要瞭解如何安裝及使用 Sensitive Data Protection 的用戶端程式庫,請參閱這篇文章

    如要驗證 Sensitive Data Protection,請設定應用程式預設憑證。 詳情請參閱「為本機開發環境設定驗證」。

    
    use Google\ApiCore\ApiException;
    use Google\Cloud\Dlp\V2\ActivateJobTriggerRequest;
    use Google\Cloud\Dlp\V2\Client\DlpServiceClient;
    use Google\Cloud\Dlp\V2\Container;
    use Google\Cloud\Dlp\V2\ContentItem;
    use Google\Cloud\Dlp\V2\DlpJob\JobState;
    use Google\Cloud\Dlp\V2\GetDlpJobRequest;
    use Google\Cloud\Dlp\V2\HybridContentItem;
    use Google\Cloud\Dlp\V2\HybridFindingDetails;
    use Google\Cloud\Dlp\V2\HybridInspectJobTriggerRequest;
    use Google\Cloud\Dlp\V2\ListDlpJobsRequest;
    
    /**
     * Inspect data hybrid job trigger.
     * Send data to the hybrid job or hybrid job trigger.
     *
     * @param string $callingProjectId  The Google Cloud project id to use as a parent resource.
     * @param string $string            The string to inspect (will be treated as text).
     */
    
    function inspect_send_data_to_hybrid_job_trigger(
        // TODO(developer): Replace sample parameters before running the code.
        string $callingProjectId,
        string $jobTriggerId,
        string $string
    ): void {
        // Instantiate a client.
        $dlp = new DlpServiceClient();
    
        $content = (new ContentItem())
            ->setValue($string);
    
        $container = (new Container())
            ->setFullPath('10.0.0.2:logs1:app1')
            ->setRelativePath('app1')
            ->setRootPath('10.0.0.2:logs1')
            ->setType('logging_sys')
            ->setVersion('1.2');
    
        $findingDetails = (new HybridFindingDetails())
            ->setContainerDetails($container)
            ->setLabels([
                'env' => 'prod',
                'appointment-bookings-comments' => ''
            ]);
    
        $hybridItem = (new HybridContentItem())
            ->setItem($content)
            ->setFindingDetails($findingDetails);
    
        $parent = "projects/$callingProjectId/locations/global";
        $name = "projects/$callingProjectId/locations/global/jobTriggers/" . $jobTriggerId;
    
        $triggerJob = null;
        try {
            $activateJobTriggerRequest = (new ActivateJobTriggerRequest())
                ->setName($name);
            $triggerJob = $dlp->activateJobTrigger($activateJobTriggerRequest);
        } catch (ApiException $e) {
            $listDlpJobsRequest = (new ListDlpJobsRequest())
                ->setParent($parent)
                ->setFilter('trigger_name=' . $name);
            $result = $dlp->listDlpJobs($listDlpJobsRequest);
            foreach ($result as $job) {
                $triggerJob = $job;
            }
        }
        $hybridInspectJobTriggerRequest = (new HybridInspectJobTriggerRequest())
            ->setName($name)
            ->setHybridItem($hybridItem);
    
        $dlp->hybridInspectJobTrigger($hybridInspectJobTriggerRequest);
    
        $numOfAttempts = 10;
        do {
            printf('Waiting for job to complete' . PHP_EOL);
            sleep(10);
            $getDlpJobRequest = (new GetDlpJobRequest())
                ->setName($triggerJob->getName());
            $job = $dlp->getDlpJob($getDlpJobRequest);
            if ($job->getState() != JobState::RUNNING) {
                break;
            }
            $numOfAttempts--;
        } while ($numOfAttempts > 0);
    
        // Print finding counts.
        printf('Job %s status: %s' . PHP_EOL, $job->getName(), JobState::name($job->getState()));
        switch ($job->getState()) {
            case JobState::DONE:
                $infoTypeStats = $job->getInspectDetails()->getResult()->getInfoTypeStats();
                if (count($infoTypeStats) === 0) {
                    printf('No findings.' . PHP_EOL);
                } else {
                    foreach ($infoTypeStats as $infoTypeStat) {
                        printf(
                            '  Found %s instance(s) of infoType %s' . PHP_EOL,
                            $infoTypeStat->getCount(),
                            $infoTypeStat->getInfoType()->getName()
                        );
                    }
                }
                break;
            case JobState::FAILED:
                printf('Job %s had errors:' . PHP_EOL, $job->getName());
                $errors = $job->getErrors();
                foreach ($errors as $error) {
                    var_dump($error->getDetails());
                }
                break;
            case JobState::PENDING:
                printf('Job has not completed. Consider a longer timeout or an asynchronous execution model' . PHP_EOL);
                break;
            default:
                printf('Unexpected job state. Most likely, the job is either running or has not yet started.');
        }
    }

    Python

    如要瞭解如何安裝及使用 Sensitive Data Protection 的用戶端程式庫,請參閱這篇文章

    如要驗證 Sensitive Data Protection,請設定應用程式預設憑證。 詳情請參閱「為本機開發環境設定驗證」。

    import time
    
    import google.cloud.dlp
    
    
    def inspect_data_to_hybrid_job_trigger(
        project: str,
        trigger_id: str,
        content_string: str,
    ) -> None:
        """
        Uses the Data Loss Prevention API to inspect sensitive information
        using Hybrid jobs trigger that scans payloads of data sent from
        virtually any source and stores findings in Google Cloud.
        Args:
            project: The Google Cloud project id to use as a parent resource.
            trigger_id: The job trigger identifier for hybrid job trigger.
            content_string: The string to inspect.
        """
    
        # Instantiate a client.
        dlp = google.cloud.dlp_v2.DlpServiceClient()
    
        # Construct the `item` to inspect.
        item = {"value": content_string}
    
        # Construct the container details that contains metadata to be
        # associated with the content. For more details, please refer to
        # https://cloud.google.com/dlp/docs/reference/rest/v2/Container
        container_details = {
            "full_path": "10.0.0.2:logs1:app1",
            "relative_path": "app1",
            "root_path": "10.0.0.2:logs1",
            "type_": "logging_sys",
            "version": "1.2",
        }
    
        # Construct hybrid inspection configuration.
        hybrid_config = {
            "item": item,
            "finding_details": {
                "container_details": container_details,
                "labels": {
                    "env": "prod",
                    "appointment-bookings-comments": "",
                },
            },
        }
    
        # Convert the trigger id into a full resource id.
        trigger_id = f"projects/{project}/jobTriggers/{trigger_id}"
    
        # Activate the job trigger.
        dlp_job = dlp.activate_job_trigger(request={"name": trigger_id})
    
        # Call the API.
        dlp.hybrid_inspect_job_trigger(
            request={
                "name": trigger_id,
                "hybrid_item": hybrid_config,
            }
        )
    
        # Get inspection job details.
        job = dlp.get_dlp_job(request={"name": dlp_job.name})
    
        # Wait for dlp job to get finished.
        while job.inspect_details.result.processed_bytes <= 0:
            time.sleep(5)
            job = dlp.get_dlp_job(request={"name": dlp_job.name})
    
        # Print the results.
        print(f"Job name: {dlp_job.name}")
        if job.inspect_details.result.info_type_stats:
            for finding in job.inspect_details.result.info_type_stats:
                print(f"Info type: {finding.info_type.name}; Count: {finding.count}")
        else:
            print("No findings.")
    
    

    常見的混合式檢查情境

    以下各節說明混合檢查的常見用途,以及對應的工作流程。

    執行單次掃描

    在 Google Cloud 以外執行資料庫的一次性掃描,做為資料庫每季抽查的一部分。

    1. 使用Google Cloud 控制台DLP API 建立混合式工作。

    2. 呼叫 projects.locations.dlpJobs.hybridInspect,將資料傳送至工作。如要檢查更多資料,請視需要重複執行這個步驟。

    3. 傳送資料以供檢查後,請呼叫 projects.locations.dlpJobs.finish 方法。

      Sensitive Data Protection 會執行 projects.locations.dlpJobs.create 要求中指定的動作。

    設定持續監控

    監控每天新增至資料庫的所有內容,這些內容不屬於 Sensitive Data Protection 原生支援的範圍。

    1. 使用Google Cloud 控制台DLP API 建立混合式工作觸發條件。

    2. 呼叫 projects.locations.jobTriggers.activate 方法,啟用工作觸發程序。

    3. 呼叫 projects.locations.jobTriggers.hybridInspect,將資料傳送至工作觸發條件。如要檢查更多資料,請視需要重複執行這個步驟。

    在這種情況下,您不需要呼叫 projects.locations.dlpJobs.finish 方法。Sensitive Data Protection 會自動將您傳送的資料劃分為多個區塊。只要工作觸發條件處於啟用狀態,Sensitive Data Protection 就會在每天結束時,執行您建立混合式工作觸發條件時指定的動作。

    掃描資料庫中的資料

    掃描資料庫中的資料,同時控管資料分割方式。工作觸發程序中的每個工作都是單一分區。

    1. 使用Google Cloud 控制台DLP API 建立混合式工作觸發條件。

    2. 呼叫 projects.locations.jobTriggers.activate 方法,啟用工作觸發程序。

      系統會傳回單一工作的工作 ID。您會在下一個步驟中用到這項工作 ID。

    3. 呼叫 projects.locations.dlpJobs.hybridInspect,將資料傳送至工作。

      在這種情況下,您會將資料傳送至工作,而非工作觸發程序。這種方法可讓您控管要檢查的資料如何分割。如要在目前分割區中新增更多資料以供檢查,請重複這個步驟。

    4. 將資料傳送至工作後,請呼叫 projects.locations.dlpJobs.finish 方法。

      Sensitive Data Protection 會執行 projects.locations.jobTriggers.create 要求中指定的動作。

    5. 如要為下一個分割區建立其他工作,請再次啟動工作觸發程序,然後將資料傳送至產生的工作。

    監控來自 Proxy 的流量

    監控在兩個自訂應用程式之間安裝的 Proxy 流量。

    1. 使用Google Cloud 控制台DLP API 建立混合式工作觸發條件。

    2. 呼叫 projects.locations.jobTriggers.activate 方法,啟動工作觸發程序。

    3. 呼叫 projects.locations.jobTriggers.hybridInspect,將資料傳送至工作觸發條件。如要檢查更多資料,請視需要重複執行這個步驟。

      您可以針對所有網路流量無限期呼叫這項要求。請務必在每個要求中加入中繼資料

    在這種情況下,您不需要呼叫 projects.locations.dlpJobs.finish 方法。Sensitive Data Protection 會自動將您傳送的資料劃分為多個分區。只要工作觸發條件處於啟用狀態,Sensitive Data Protection 就會在每天結束時,執行您建立混合式工作觸發條件時指定的動作。

    後續步驟