Security Health Analytics のカスタム モジュールをコーディングする

このページでは、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 式を含んでいます。

カスタム定義モジュールをコーディングするには、次の手順に従います。

  1. yaml ファイル名拡張子を持つテキスト ファイルを作成します。

  2. テキスト ファイルで resource_selector プロパティを作成し、スキャンするカスタム モジュールに 1 ~ 5 個のリソースタイプを指定します。カスタム モジュール定義でリソースタイプを複数回指定できません。次に例を示します。

    resource_selector:
     resource_types:
     ‐ cloudkms.googleapis.com/CryptoKey

    指定するリソースタイプは Security Command Center でサポートされている必要があります。サポートされているリソースタイプの一覧については、サポートされているリソースタイプをご覧ください。

  3. predicate プロパティを作成し、スキャンするリソースタイプのプロパティを確認する 1 つ以上の CEL 式を指定します。CEL 式で参照するあらゆるプロパティは、resource_selector で指定した各リソースタイプの Google Cloud API 定義に存在している必要があります。検出結果をトリガーするには、式を TRUE に解決する必要があります。たとえば、次の式では、2592000s より大きい rotationPeriod 値のみが検出結果をトリガーします。

    predicate:
     expression: resource.rotationPeriod > duration("2592000s")

    CEL 式の作成のヘルプについては、次のリソースをご覧ください。

  4. カスタム モジュールが検出する脆弱性または構成ミスを説明する description プロパティを作成します。この説明は、調査員が検出された問題を理解できるように、各検出結果のインスタンスに表示されます。テキストは引用符で囲む必要があります。次に例を示します。

    description: "The rotation period of
     the identified cryptokey resource exceeds 30 days, the
     maximum rotation period that our security guidelines allow."
  5. 検出された問題の解決方法を説明する 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 コンソールを使用してカスタム モジュールを作成または更新する場合、エスケープ文字は必要ありません。

  6. severity プロパティを作成し、このモジュールによって作成される検出結果のデフォルトの重大度を指定します。severity プロパティでよく使用される値は、LOWMEDIUMHIGHCRITICAL です。次に例を示します。

    severity: MEDIUM
  7. 必要に応じて、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"
    
  8. gcloud CLI でアクセスできるロケーションにファイルを保存します。

  9. 次のコマンドで、定義を 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 セクションには、durationviolation の 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: ここで、rotationPeriodresource のプロパティです。
  • resource.metadata.name: ここで、namemetadataresource のサブプロパティ)のサブプロパティです。

IAM ポリシーのプロパティを参照する

リソースの IAM ポリシー プロパティを参照することで、リソースの IAM ポリシーを評価する CEL 式を作成できます。使用できるプロパティは、バインディングとバインディング内のロールのみです。

IAM ポリシー プロパティを参照する場合、policy はトップレベル プロパティです。

次に、IAM ポリシーのプロパティとそれらを取得する方法の例を示します。

  • policy.bindings: ここで、bindingspolicy のプロパティです。
  • policy.version: ここで、versionpolicy のプロパティです。

その他の例については、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/CryptoKeycloudkms.googleapis.com/CryptoKeyVersion の 2 つのリソースタイプをチェックする invalid_cryptokey というカスタム モジュールを定義する場合、CryptoKeyCryptoKeyVersion の両方のリソースタイプに name プロパティが含まれているため、次の式を作成できます。

    predicate:
    resource.name.matches("projects/project1/locations/us-central1/keyRings/keyring1/cryptoKeys/.*")

    ただし、式で評価する importTimerotationPeriod のプロパティは両方のリソースタイプで共有されないため、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 ファイルにコーディングする場合は、namevalue のペアを custom_output プロパティの下に properties として記述します。

Google Cloud コンソールと YAML ファイルのどちらを使用しているかに関わらず、次のルールが適用されます。

  • name を引用符なしのテキスト文字列として指定します。
  • value は次のいずれかとして指定します。

    • プロパティの値を返すには、次の形式でプロパティを指定します。

      RESOURCE_TYPE.PROPERTY.PROPERTY_TO_RETURN

    例:

    • RESOURCE_TYPEresourcepolicy のいずれかにできます。
    • 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"

次のステップ

カスタム モジュールをテスト、送信、表示、更新する方法については、次のページをご覧ください。