このページでは、Common Expression Language(CEL)と YAML を使用してカスタム モジュール定義をコーディングする方法について説明します。
Google Cloud CLI を使用して、カスタム モジュール定義を Security Health Analytics にアップロードします。
YAML ファイルでは、カスタム モジュール定義は、Security Health Analytics カスタム モジュールの次の要素を定義する、構造化された一連のプロパティで構成されています。
- スキャンするリソース。
- 使用する検出ロジック。
- 検出された問題を迅速に把握し、優先順位を付けて解決するために、セキュリティ チームに提供される情報。
YAML 定義を構成する特定の必須プロパティとオプション プロパティについては、コーディング手順で説明します。
冗長な検出機能の作成を回避する
検出結果の量を制御するには、冗長な機能を含むモジュールを作成して実行しないでください。
たとえば、30 日後にローテーションされない暗号鍵を確認するカスタム モジュールを作成する場合は、90 日という値を使用する確認は不要であるため、組み込みの Security Health Analytics 検出機能 KMS_KEY_NOT_ROTATED を無効にすることを検討してください。
検出機能の無効化の詳細については、検出機能を有効または無効にするをご覧ください。
コーディング手順
Security Health Analytics のカスタム モジュールの定義を、一連の YAML プロパティとしてコーディングします。一部のプロパティでは CEL 式を使用します。
カスタム定義モジュールをコーディング手順は次のとおりです。
- yamlという拡張子を持つテキスト ファイルを作成します。
- テキスト ファイルで - resource_selectorプロパティを作成し、スキャンするカスタム モジュールに 1~5 個のリソースタイプを指定します。カスタム モジュール定義ではリソースタイプを複数回指定できません。例:- resource_selector: resource_types: ‐ cloudkms.googleapis.com/CryptoKey - 指定するリソースタイプは Security Command Center でサポートされている必要があります。サポートされているリソースタイプの一覧については、サポートされるリソースタイプをご覧ください。 
- predicateプロパティを作成し、スキャンするリソースタイプのプロパティを確認する 1 つ以上の CEL 式を指定します。CEL 式で参照するプロパティは、- resource_selectorで指定した各リソースタイプのGoogle Cloud API 定義に存在している必要があります。検出結果をトリガーするには、式を- TRUEに解決する必要があります。たとえば、次の式では、- 2592000sより大きい- rotationPeriod値のみが検出結果をトリガーします。- predicate: expression: resource.rotationPeriod > duration("2592000s")- CEL 式の作成のヘルプについては、次のリソースをご覧ください。 - サポートされるリソースタイプ。各リソースをクリックすると、CEL 式で使用できるプロパティが表示されます。
- CEL 式の作成。
- カスタム モジュールでのリソース プロパティとポリシー プロパティの参照。
 
- カスタム モジュールが検出する脆弱性または構成ミスを説明する - descriptionプロパティを作成します。この説明は、調査担当者が検出された問題を理解できるように、各検出結果のインスタンスに表示されます。テキストは引用符で囲む必要があります。例:- description: "The rotation period of the identified cryptokey resource exceeds 30 days, the maximum rotation period that our security guidelines allow." 
- 検出された問題の解決方法を説明する - recommendationプロパティを作成します。gcloud CLI では、引用符などの特定の文字の前にエスケープ文字が必要です。次の例では、引用符の各組をバックスラッシュでエスケープする方法を示してします。- recommendation: "To fix this issue go to https://console.cloud.google.com/security/kms. Click the key-ring that contains the key. Click the key. Click \"Edit rotation period\". Then set the rotation period to at most 30 days."- Google Cloud コンソールを使用してカスタム モジュールを作成または更新する場合、エスケープ文字は必要ありません。 
- severityプロパティを作成し、このモジュールによって作成される検出結果のデフォルトの重大度を指定します。- severityプロパティでよく使用される値は、- LOW、- MEDIUM、- HIGH、- CRITICALです。次に例を示します。- severity: MEDIUM 
- 必要に応じて、 - custom_outputプロパティを作成し、各検出結果とともに返す追加情報を指定します。1 つ以上の名前と値のペアとして返す情報を指定します。スキャンされたリソースのプロパティ値とリテラル文字列のいずれかを返すことができます。プロパティは- resource.PROPERTY_NAMEとして指定する必要があります。リテラル文字列は引用符で囲む必要があります。次の例は、プロパティ値とスキャンされた- CryptoKeyリソース内の- rotationPeriodの値の両方と、テキスト文字列- "Excessive rotation period for CryptoKey"を返す- custom_output定義を示しています。- custom_output: properties: - name: duration value_expression: expression: resource.rotationPeriod - name: note value_expression: expression: "Excessive rotation period for CryptoKey"
- gcloud CLI でアクセスできるロケーションにファイルを保存します。 
- 次のコマンドで、定義を Security Health Analytics にアップロードします。 - gcloud scc custom-modules sha create \ --organization=organizations/ORGANIZATION_ID \ --display-name="MODULE_DISPLAY_NAME" \ --enablement-state="ENABLED" \ --custom-config-from-file=DEFINITION_FILE_NAME.yaml- 次の値を置き換えます。 - ORGANIZATION_IDは、カスタム モジュールの親組織の ID に置き換えます。または、- --organizationフラグを- --foldersと- --projectのいずれかに置き換え、親のフォルダまたはプロジェクトの ID を指定します。
- MODULE_DISPLAY_NAMEは、カスタム モジュールが検出結果を返すときに、検出結果のカテゴリとして表示する名前に置き換えます。名前は 1~128 文字で、先頭は英小文字にします。それ以降は、英数字とアンダースコアのみを使用してください。
- DEFINITION_FILE_NAMEは、カスタム モジュールの定義を含む YAML ファイルのパスとファイル名に置き換えます。
 - Security Health Analytics カスタム モジュールの操作の詳細については、Security Health Analytics 用のカスタム モジュールの使用をご覧ください。 
新しいカスタム モジュールのスキャン レイテンシ
カスタム モジュールを作成しても、新しいスキャンがトリガーされることはありません。
Security Health Analytics は、次のいずれかが発生するまで、新しいカスタム モジュールの使用を開始しません。
- カスタム モジュール作成後の最初のバッチスキャン。バッチスキャン スケジュールでカスタム モジュールを作成するタイミングによっては、Security Health Analytics がカスタム モジュールの使用を開始するまでに最大 24 時間待つ必要がある場合があります。
- ターゲット リソースが変更されると、リアルタイム スキャンがトリガーされます。
カスタム モジュールの定義の例
次の例は、cloudkms.googleapis.com/CryptoKey リソースの rotationPeriod プロパティの値が 2,592,000 秒(30 日)より大きい場合に検出結果をトリガーする完全なカスタム モジュール定義を示しています。この例では、custom_output セクションに、resource.rotationPeriod の値とテキスト文字列のメモの 2 つのオプションの値が返されます。
ここで、次のことに注意してください。
- 確認するアセットまたはリソースのタイプは、resource_typesの下のresource_selectorセクションに示されます。
- モジュールがリソースに対して実行するチェックと検出ロジックは、expressionで始まるpredicateセクションで定義されます。
- custom_outputセクションには、- durationと- violationの 2 つのカスタム ソース プロパティが定義されています。
- 検出された問題の説明は descriptionプロパティに指定されています。
- 検出された問題の修正に関するガイダンスは、recommendationプロパティに指定されています。ガイダンスには引用符が含まれているため、各引用符の前にエスケープ文字(バックスラッシュ)が必要です。
severity: HIGH
description: "Regular key rotation helps provide protection against
compromised keys, and limits the number of encrypted messages available
to cryptanalysis for a specific key version."
recommendation: "To fix this issue go to
https://console.cloud.google.com/security/kms. Click the key-ring that
contains the key. Click the key. Click \"Edit rotation period\". Then
set the rotation period to at most 30 days."
resource_selector:
  resource_types:
  - cloudkms.googleapis.com/CryptoKey
predicate:
  expression: resource.rotationPeriod > duration("2592000s")
custom_output:
  properties:
    - name: duration
      value_expression:
        expression: resource.rotationPeriod
    - name: violation
      value_expression:
        expression:
          "Excessive rotation period for CryptoKey"
カスタム モジュールのリソース プロパティとポリシー プロパティの参照
カスタム モジュールをGoogle Cloud コンソールで作成したのか、自分で定義を記述したのかに関係なく、カスタム モジュールで評価できるプロパティを検索できる必要があります。また、カスタム モジュール定義でプロパティを参照する方法も理解する必要もあります。
リソースまたはポリシーのプロパティを確認する
Google Cloud リソースのプロパティは、リソースの API 定義で定義されます。この定義を確認するには、サポートされるリソースタイプでリソース名をクリックしてください。
ポリシーのプロパティは、IAM API リファレンス ドキュメントで確認できます。ポリシーのプロパティについては、ポリシーをご覧ください。
カスタム モジュール定義でリソース プロパティを参照する
カスタム モジュールを作成する場合、スキャンされるリソースのプロパティの直接参照は resource で始まり、その後に任意の親プロパティ、最後にターゲット プロパティが続く必要があります。プロパティは、JSON スタイルのドット表記を使用してピリオドで区切ります。
次の例に、リソース プロパティとそれらを取得する方法を示します。
- resourceName: Cloud Asset Inventory にリソースの完全な名前(たとえば、- //cloudresourcemanager.googleapis.com/projects/296605646631)が保存されます。
- resource.rotationPeriod: ここで、- rotationPeriodは- resourceのプロパティです。
- resource.metadata.name: ここで、- nameは- metadata(- resourceのサブプロパティ)のサブプロパティです。
IAM ポリシーのプロパティを参照する
リソースの IAM ポリシー プロパティを参照することで、リソースの IAM ポリシーを評価する CEL 式を作成できます。使用できるプロパティは、バインディングとバインディング内のロールのみです。
IAM ポリシー プロパティを参照する場合、policy はトップレベル プロパティです。
次の例に、IAM ポリシーのプロパティとそれらを取得する方法を示します。
- policy.bindings: ここで、- bindingsは- policyのプロパティです。
- policy.version: ここで、- versionは- policyのプロパティです。
その他の例については、CEL 式の例をご覧ください。
ポリシーのプロパティについては、ポリシーをご覧ください。
CEL 式の記述
カスタム モジュールを作成する場合、CEL 式を使用して、スキャンされたリソースのプロパティを評価します。必要に応じて、CEL 式を使用してカスタム name-value ペアを定義し、検出結果とともに追加情報を返すこともできます。
Google Cloud コンソールでカスタム モジュールを作成するか、YAML ファイルにカスタム モジュール定義を記述するかにかかわらず、定義する CEL 式は同じです。
検出ロジックの CEL 式
カスタム モジュールの検出ロジックをコーディングするには、CEL 式で標準の CEL 演算子を使用し、スキャンされたリソースのプロパティを評価します。
式は、単一の値をチェックするシンプルな式にすることも、複数の値または条件をチェックする複雑な複合式にすることもできます。いずれの場合も、式をブール値 true に解決して検出をトリガーする必要があります。
Google Cloud コンソールでカスタム モジュールを作成する場合は、[モジュールの構成] ページの [式エディタ] でこれらの式を記述します。
カスタム モジュールを YAML ファイルにコーディングする場合は、これらの式を predicate プロパティに追加します。
Google Cloud コンソールと YAML ファイルのどちらを使用するかにかかわらず、リソース プロパティを評価する CEL 式は、次のルールに従う必要があります。
- リソースタイプの API 定義で定義されているように、CEL 式に指定するプロパティは、スキャンされたリソースのプロパティである必要があります。
- カスタム モジュールで複数のリソースタイプが評価される場合、CEL 式で指定するプロパティは、カスタム モジュールが評価する各リソースタイプで共通している必要があります。 - たとえば、 - cloudkms.googleapis.com/CryptoKeyと- cloudkms.googleapis.com/CryptoKeyVersionの 2 つのリソースタイプをチェックする- invalid_cryptokeyというカスタム モジュールを定義する場合、- CryptoKeyと- CryptoKeyVersionの両方のリソースタイプに- nameプロパティが含まれているため、次の式を作成できます。- predicate: resource.name.matches("projects/project1/locations/us-central1/keyRings/keyring1/cryptoKeys/.*")- ただし、式で評価する - importTimeと- rotationPeriodのプロパティは両方のリソースタイプで共有されないため、- invalid_cryptokeyカスタム モジュールで次の式を指定できません。- predicate: resource.importTime >= timestamp("2022-10-02T15:01:23Z") || resource.rotationPeriod > duration("2592000s")
- CEL 式内のすべての列挙型は文字列として表す必要があります。たとえば、 - cloudkms.googleapis.com/CryptoKeyVersionリソースタイプの有効な式は次のとおりです。- resource.state = "PENDING_GENERATION" 
- predicateプロパティに定義した CEL 式の結果はブール値でなければなりません。検出結果は、結果が- trueの場合にのみトリガーされます。
CEL の詳細については、以下をご覧ください。
CEL 式の例
次の表に、リソース プロパティの評価に使用できる CEL 式を示します。これらは、Google Cloud コンソールと YAML カスタム モジュール定義の両方で使用できます。
| リソースの種類 | 説明 | CEL 式 | 
|---|---|---|
| IAM ポリシーを持つリソース | 外部ドメインからのメンバーを識別するための IAM ポリシーの確認 | !policy.bindings.all(binding, binding.members.all(m ,!m.endsWith('@gmail.com'))) | 
| cloudkms.googleapis.com/CryptoKey | Cloud KMS 鍵のローテーション期間の確認 | has(resource.rotationPeriod) && resource.rotationPeriod > duration('60h') | 
| 単一ポリシーを持つ複数のリソースタイプ | リソースタイプに基づいて、リソース名が devまたはdevAccessで始まるかどうかを確認する | (resource.type == 'compute.googleapis.com/Disk' &&
    resource.name.startsWith('projects/PROJECT_ID/regions/
    REGION/disks/devAccess')) || (resource.type ==
    'compute.googleapis.com/Instance ' &&
    resource.name.startsWith('projects/PROJECT_ID/zones/REGION/instances/dev-')) | 
| compute.googleapis.com/Network | ネットワーク ピアに一致する Virtual Private Cloud ピアリング ルール | resource.selfLink.matches('https://www.googleapis.com/compute/v1/projects/PROJECT_ID/global/networks/default') || resource.peerings.exists(p, p.network.matches('https://www.googleapis.com/compute/v1/projects/PROJECT_ID/global/networks/shared$')) | 
| cloudfunctions.googleapis.com/CloudFunction | Cloud Run 関数向けの内部上り(内向き)トラフィックのみを許可する | has(resource.ingressSettings) && resource.ingressSettings.matches('ALLOW_INTERNAL_ONLY') | 
| compute.googleapis.com/Instance | リソース名とパターンの一致 | resource.name.matches('^gcp-vm-(linux|windows)-v\\d+$') | 
| serviceusage.googleapis.com/Service | ストレージ関連の API の有効化のみを許可する | resource.state == 'ENABLED' && !( resource.name.matches('storage-api.googleapis.com') || resource.name.matches('bigquery-json.googleapis.com') || resource.name.matches('bigquery.googleapis.com') || resource.name.matches('sql-component.googleapis.com') || resource.name.matches('spanner.googleapis.com')) | 
| sqladmin.googleapis.com/Instance | 許可リストに登録されたパブリック IP のみを許可する | (resource.instanceType == 'CLOUD_SQL_INSTANCE' && resource.backendType == 'SECOND_GEN' && resource.settings.ipConfiguration.ipv4Enabled ) && !(resource.ipAddresses.all(ip, ip.type != 'PRIMARY' || ip.ipAddress.matches('IP_ADDRESS')))) | 
| dataproc.googleapis.com/Cluster | Dataproc クラスタのプロジェクト ID に部分文字列のテストまたは作成が含まれているかどうかを確認する | has(resource.projectId) && resource.projectId.contains('testing') || resource.projectId.contains('development') | 
カスタム検出プロパティの CEL 式
検出結果クエリに使用できる検出結果ごとに追加情報を返すように、カスタム モジュールによって生成された検出結果とともに返すカスタム プロパティを 10 個まで定義できます。
カスタム プロパティは、JSON の検出結果のソース プロパティと、Google Cloud コンソールの検出結果の詳細の [ソース プロパティ] タブに表示されます。
カスタム プロパティは name-value ペアとして定義します。
 Google Cloud -コンソールでカスタム モジュールを作成する場合は、name-value ペアを、[検出結果の詳細の定義] ページのカスタム検出結果のプロパティのセクションで定義します。
カスタム モジュールを YAML ファイルにコーディングする場合は、name と value のペアを custom_output プロパティの下に properties として記述します。
Google Cloud コンソールと YAML ファイルのどちらを使用しているかにかかわらず、次のルールに従う必要があります。
- nameを引用符なしのテキスト文字列として指定します。
- valueは次のいずれかとして指定します。- プロパティの値を返すには、次の形式でプロパティを指定します。 - RESOURCE_TYPE.PROPERTY.PROPERTY_TO_RETURN
 - 例: - RESOURCE_TYPEは、- resourceまたは- policyのいずれかになります。
- PROPERTYは、返す値を含むプロパティの 1 つ以上の親プロパティです。
- PROPERTY_TO_RETURNは、返す値を含むプロパティです。
- テキスト文字列を返すには、文字列を引用符で囲みます。 
 
次の例は、YAML ファイル内の custom_output に適切に定義された 2 つの name-value ペアを示しています。
custom_output:
  properties:
    - name: duration
      value_expression:
        expression: resource.name
    - name: property_with_text
      value_expression:
        expression: "Note content"次のステップ
カスタム モジュールをテスト、送信、表示、更新する方法については、次のページをご覧ください。
- カスタム モジュールをテストするには、Security Health Analytics のカスタム モジュールをテストするをご覧ください。
- カスタム モジュールをアップロード、表示、更新するには、Security Health Analytics のカスタム モジュールの作成と管理をご覧ください。