Mencantumkan temuan keamanan menggunakan Security Command Center API

Temuan Security Command Center membuat model potensi risiko keamanan aset dalam project atau organisasi. Temuan selalu terkait dengan aset tertentu di Security Command Center.

Panduan ini menunjukkan cara menggunakan library klien Security Command Center untuk mengakses temuan. Setiap temuan berasal dari sumber. Sebagian besar detektor atau penyedia temuan menghasilkan temuan dalam sumber yang sama.

Peran IAM untuk Security Command Center dapat diberikan di tingkat organisasi, folder, atau project. Kemampuan Anda untuk melihat, mengedit, membuat, atau memperbarui temuan, aset, dan sumber keamanan bergantung pada tingkat akses yang Anda terima. Untuk mempelajari peran Security Command Center lebih lanjut, lihat Kontrol akses.

Sebelum memulai

Sebelum menyiapkan sumber, Anda harus menyelesaikan hal-hal berikut:

Ukuran halaman

Semua API daftar Security Command Center memiliki penomoran halaman. Setiap respons menampilkan halaman hasil dan token untuk menampilkan halaman berikutnya. Ukuran halaman dapat dikonfigurasi. Ukuran halaman default adalah 10. Anda dapat menetapkannya ke minimum 1, dan maksimum 1.000.

Retensi temuan

Temuan tetap tersedia untuk Anda cantumkan atau buat kueri setidaknya selama 13 bulan.

Security Command Center menyimpan snapshot setiap temuan. Ringkasan temuan disimpan setidaknya selama 13 bulan. Jika semua snapshot untuk suatu temuan dihapus, temuan tersebut tidak dapat lagi dicantumkan atau dipulihkan.

Untuk informasi selengkapnya tentang retensi data Security Command Center, lihat Retensi data.

Mencantumkan semua temuan

gcloud

Untuk mencantumkan semua temuan dalam project, folder, atau organisasi, jalankan perintah berikut:

gcloud scc findings list PARENT_TYPE/PARENT_ID \
  --location=LOCATION

Ganti kode berikut:

  • PARENT_TYPE: tingkat hierarki resource yang akan mencantumkan temuan; gunakan organizations, folders, atau projects.
  • PARENT_ID: ID numerik organisasi, folder, atau project, atau ID project alfanumerik.
  • LOCATION: jika aset data diaktifkan, lokasi Security Command Center tempat mencantumkan temuan; jika aset data tidak diaktifkan, gunakan nilai global.

Untuk contoh lainnya, jalankan:

gcloud scc findings list --help

Untuk contoh dalam dokumentasi, lihat gcloud scc findings list.

Go

import (
	"context"
	"fmt"
	"io"

	securitycenter "cloud.google.com/go/securitycenter/apiv2"
	"cloud.google.com/go/securitycenter/apiv2/securitycenterpb"
	"google.golang.org/api/iterator"
)

// listFindings prints all findings in orgID to w. orgID is the numeric
// identifier of the organization.
func listFindings(w io.Writer, orgID string) error {
	// orgID := "12321311"
	// Instantiate a context and a security service client to make API calls.
	ctx := context.Background()
	client, err := securitycenter.NewClient(ctx)
	if err != nil {
		return fmt.Errorf("securitycenter.NewClient: %w", err)
	}
	defer client.Close() // Closing the client safely cleans up background resources.

	req := &securitycenterpb.ListFindingsRequest{
		// List findings across all sources.
		// Parent must be in one of the following formats:
		//		"organizations/{orgId}/sources/-/locations/global"
		//		"projects/{projectId}/sources/-/locations/global"
		//		"folders/{folderId}/sources/-/locations/global"
		Parent: fmt.Sprintf("organizations/%s/sources/-/locations/global", orgID),
	}
	it := client.ListFindings(ctx, req)
	for {
		result, err := it.Next()
		if err == iterator.Done {
			break
		}
		if err != nil {
			return fmt.Errorf("it.Next: %w", err)
		}
		finding := result.Finding
		fmt.Fprintf(w, "Finding Name: %s, ", finding.Name)
		fmt.Fprintf(w, "Resource Name %s, ", finding.ResourceName)
		fmt.Fprintf(w, "Category: %s\n", finding.Category)
	}
	return nil
}

Java


import com.google.cloud.securitycenter.v2.ListFindingsRequest;
import com.google.cloud.securitycenter.v2.ListFindingsResponse.ListFindingsResult;
import com.google.cloud.securitycenter.v2.SecurityCenterClient;
import java.io.IOException;

public class ListAllFindings {

  public static void main(String[] args) throws IOException {
    // organizationId: The source to list all findings for.
    // You can also use project/ folder as the parent resource.
    String organizationId = "google-cloud-organization-id";

    // Specify the location to list the findings.
    String location = "global";

    // The source id to scope the findings.
    String sourceId = "source-id";

    listAllFindings(organizationId, sourceId, location);
  }

  // List all findings under a given parent resource.
  public static void listAllFindings(String organizationId, String sourceId, String location)
      throws IOException {
    // Initialize client that will be used to send requests. This client only needs to be created
    // once, and can be reused for multiple requests.
    try (SecurityCenterClient client = SecurityCenterClient.create()) {
      ListFindingsRequest request =
          ListFindingsRequest.newBuilder()
              // To list findings across all sources, use "-".
              .setParent(
                  String.format("organizations/%s/sources/%s/locations/%s", organizationId,
                      sourceId,
                      location))
              .build();

      for (ListFindingsResult result : client.listFindings(request).iterateAll()) {
        System.out.printf("Finding: %s", result.getFinding().getName());
      }
      System.out.println("\nListing complete.");
    }
  }
}

Node.js

// Imports the Google Cloud client library.
const {SecurityCenterClient} = require('@google-cloud/security-center').v2;

// Creates a new client.
const client = new SecurityCenterClient();

// TODO(developer): Update the following for your own environment.
const organizationId = '1081635000895';
const location = 'global';

// Required. Name of the source the findings belong to. If no location is
// specified, the default is global. The following list shows some examples:
// - `organizations/[organization_id]/sources/[source_id]/locations/[location_id]`
// - `folders/[folder_id]/sources/[source_id]`
// - `folders/[folder_id]/sources/[source_id]/locations/[location_id]`
// - `projects/[project_id]/sources/[source_id]`
// - `projects/[project_id]/sources/[source_id]/locations/[location_id]`
// To groupBy across all sources provide a source_id of `-`.
const parent = `organizations/${organizationId}/sources/-/locations/${location}`;

// Build the list findings request.
const listFindingsRequest = {
  parent,
};

async function listAllFindings() {
  // Call the API.
  const iterable = client.listFindingsAsync(listFindingsRequest);
  let count = 0;

  for await (const response of iterable) {
    // Just print a few for demonstration.
    if (count > 5) break;
    console.log(
      `${++count} ${response.finding.name} ${response.finding.resourceName}`
    );
  }
}

await listAllFindings();

Python

def list_all_findings(organization_id, source_name, location_id) -> int:
    """
    lists all findings for a source
    Args:
       organization_id: organization_id is the numeric ID of the organization. e.g.:organization_id = "111122222444"
       source_name: is the resource path for a source that has been created
       location_id: GCP location id; example: 'global'
    Returns:
        int: returns the count of all findings for a source
    """
    from google.cloud import securitycenter_v2

    # Create a client.
    client = securitycenter_v2.SecurityCenterClient()
    parent = f"organizations/{organization_id}"
    all_sources = f"{parent}/sources/{source_name}/locations/{location_id}"

    # Create the request dictionary
    request = {"parent": all_sources}

    # Print the request for debugging
    print("Request: ", request)

    finding_result_iterator = client.list_findings(request={"parent": all_sources})
    for count, finding_result in enumerate(finding_result_iterator):
        print(
            "{}: name: {} resource: {}".format(
                count, finding_result.finding.name, finding_result.finding.resource_name
            )
        )
    return finding_result_iterator

Output untuk setiap temuan akan terlihat seperti berikut:

{
  "finding": {
    "name": "organizations/ORGANIZATION_ID/sources/SOURCE_ID/findings/FINDING_ID",
    "parent": "organizations/ORGANIZATION_ID/sources/SOURCE_ID",
    "resourceName": "//cloudresourcemanager.googleapis.com/projects/PROJECT_NUMBER",
    "state": "ACTIVE",
    "category": "Malware: Cryptomining Bad Domain",
    "sourceProperties": {
      "sourceId": {
        "projectNumber": "PROJECT_NUMBER",
        "customerOrganizationNumber": "ORGANIZATION_ID"
      },
      "detectionCategory": {
        "technique": "cryptomining",
        "indicator": "domain",
        "ruleName": "bad_domain",
        "subRuleName": "cryptomining"
      },
      "detectionPriority": "LOW",
      "affectedResources": [
        {
          "gcpResourceName": "//cloudresourcemanager.googleapis.com/projects/PROJECT_NUMBER"
        }
      ],
      "evidence": [
        {
          "sourceLogId": {
            "projectId": "PROJECT_ID",
            "resourceContainer": "projects/PROJECT_ID",
            "timestamp": {
              "seconds": "1636566099",
              "nanos": 5.41483849E8
            },
            "insertId": "INSERT_ID"
          }
        }
      ],
      "properties": {
        "domains": ["DOMAIN"],
        "instanceDetails": "/projects/PROJECT_ID/zones/ZONE/instances/INSTANCE_ID",
        "network": {
          "project": "PROJECT_ID",
          "location": "ZONE"
        },
        "dnsContexts": [
          {
            "authAnswer": true,
            "sourceIp": "SOURCE_IP_ADDRESS",
            "queryName": "DOMAIN",
            "queryType": "A",
            "responseCode": "NXDOMAIN"
          }
        ],
        "vpc": {
          "vpcName": "default"
        }
      },
      "findingId": "FINDING_ID",
      "contextUris": {
        "mitreUri": {
          "displayName": "MITRE Link",
          "url": "https://attack.mitre.org/techniques/T1496/"
        },
        "virustotalIndicatorQueryUri": [
          {
            "displayName": "VirusTotal Domain Link",
            "url": "https://www.virustotal.com/gui/domain/DOMAIN/detection"
          }
        ],
        "cloudLoggingQueryUri": [
          {
            "displayName": "Cloud Logging Query Link",
            "url": "https://console.cloud.google.com/logs/query;query\u003dtimestamp%3D%222021-11-10T17:41:39.541483849Z%22%0AinsertId%3D%22INSERT_ID%22%0Aresource.labels.project_id%3D%22PROJECT_ID%22?project\u003dPROJECT_ID"
          }
        ],
        "relatedFindingUri": {}
      }
    },
    "securityMarks": {
      "name": "organizations/ORGANIZATION_ID/sources/SOURCE_ID/findings/FINDING_ID/securityMarks"
    },
    "eventTime": "2021-11-10T17:41:41.594Z",
    "createTime": "2021-11-10T17:41:42.014Z",
    "severity": "LOW",
    "workflowState": "NEW",
    "canonicalName": "projects/PROJECT_NUMBER/sources/SOURCE_ID/findings/FINDING_ID",
    "mute": "UNDEFINED",
    "findingClass": "THREAT",
    "indicator": {
      "domains": ["DOMAIN"]
    }
  },
  "resource": {
    "name": "//cloudresourcemanager.googleapis.com/projects/PROJECT_NUMBER",
    "projectName": "//cloudresourcemanager.googleapis.com/projects/PROJECT_NUMBER",
    "projectDisplayName": "PROJECT_ID",
    "parentName": "//cloudresourcemanager.googleapis.com/organizations/ORGANIZATION_ID",
    "parentDisplayName": "PARENT_NAME",
    "type": "google.cloud.resourcemanager.Project",
    "displayName": "PROJECT_ID"
  }
}

Memfilter temuan

Project, folder, atau organisasi mungkin memiliki banyak temuan. Contoh sebelumnya tidak menggunakan filter, sehingga semua data temuan ditampilkan.

Untuk membantu Anda mendapatkan informasi tentang kolom yang diinginkan saja, Anda dapat menggunakan filter penemuan. Filter ini seperti klausa "where" dalam pernyataan SQL, tetapi bukan kolom, filter ini berlaku untuk objek yang ditampilkan oleh API.

Contoh berikut hanya mencantumkan temuan yang memiliki kategori "MEDIUM_RISK_ONE". Penyedia temuan yang berbeda (juga dikenal sebagai sumber keamanan) menggunakan kumpulan kategori yang berbeda. Untuk menentukan kategori yang dapat Anda gunakan dalam filter, lihat dokumentasi penyedia penemuan.

gcloud

Gunakan perintah berikut untuk memfilter temuan:

gcloud scc findings list PARENT_TYPE/PARENT_ID \
  --location=LOCATION \
  --source=SOURCE_ID \
  --filter="FILTER"

Ganti kode berikut:

  • PARENT_TYPE: tingkat hierarki resource yang akan mencantumkan temuan; gunakan organizations, folders, atau projects.
  • PARENT_ID: ID numerik organisasi, folder, atau project, atau ID project alfanumerik.
  • LOCATION: jika aset data diaktifkan, lokasi Security Command Center tempat mencantumkan temuan dengan filter; jika aset data tidak diaktifkan, gunakan nilai global.
  • SOURCE_ID: ID sumber keamanan yang menyediakan jenis temuan.
  • FILTER: filter yang perlu Anda gunakan. Misalnya, filter berikut hanya menampilkan temuan dari kategori MEDIUM_RISK_ONE:
    --filter="category=\"MEDIUM_RISK_ONE\""

Untuk contoh lainnya, jalankan:

gcloud scc findings list --help

Untuk contoh dalam dokumentasi, lihat gcloud scc findings list.

Go

import (
	"context"
	"fmt"
	"io"

	securitycenter "cloud.google.com/go/securitycenter/apiv2"
	"cloud.google.com/go/securitycenter/apiv2/securitycenterpb"
	"google.golang.org/api/iterator"
)

// listFilteredFindings prints findings with category 'MEDIUM_RISK_ONE' for a
// specific source to w. sourceName is the full resource name of the source
// to search for findings under.
func listFilteredFindings(w io.Writer, sourceName string) error {
	// Specific source:
	// 		sourceName := "{parent}/sources/{sourceId}"
	// All sources:
	// 		sourceName := "{parent}/sources/-"
	// where,
	// Parent must be in one of the following formats:
	//		"organizations/{orgId}"
	//		"projects/{projectId}"
	//		"folders/{folderId}"
	// Instantiate a context and a security service client to make API calls.
	ctx := context.Background()
	client, err := securitycenter.NewClient(ctx)
	if err != nil {
		return fmt.Errorf("securitycenter.NewClient: %w", err)
	}
	defer client.Close() // Closing the client safely cleans up background resources.

	req := &securitycenterpb.ListFindingsRequest{
		Parent: sourceName,
		Filter: `category="MEDIUM_RISK_ONE"`,
	}
	it := client.ListFindings(ctx, req)
	for {
		result, err := it.Next()
		if err == iterator.Done {
			break
		}
		if err != nil {
			return fmt.Errorf("it.Next: %w", err)
		}
		finding := result.Finding
		fmt.Fprintf(w, "Finding Name: %s, ", finding.Name)
		fmt.Fprintf(w, "Resource Name %s, ", finding.ResourceName)
		fmt.Fprintf(w, "Category: %s\n", finding.Category)
	}
	return nil
}

Java


import com.google.cloud.securitycenter.v2.ListFindingsRequest;
import com.google.cloud.securitycenter.v2.ListFindingsResponse.ListFindingsResult;
import com.google.cloud.securitycenter.v2.SecurityCenterClient;
import java.io.IOException;

public class ListFindingsWithFilter {

  public static void main(String[] args) throws IOException {
    // TODO: Replace the variables within {}
    // organizationId: Google Cloud Organization id.
    // You can also use project/ folder as the parent resource.
    String organizationId = "google-cloud-organization-id";

    // Specify the location to list the findings.
    String location = "global";

    // The source id to scope the findings.
    String sourceId = "source-id";

    listFilteredFindings(organizationId, sourceId, location);
  }

  // List filtered findings under a source.
  public static void listFilteredFindings(String organizationId, String sourceId, String location)
      throws IOException {
    // Initialize client that will be used to send requests. This client only needs to be created
    // once, and can be reused for multiple requests.
    try (SecurityCenterClient client = SecurityCenterClient.create()) {

      // Use any one of the following formats:
      //  * organizations/{organization_id}/sources/{source_id}/locations/{location}
      //  * folders/{folder_id}/sources/{source_id}/locations/{location}
      //  * projects/{project_id}/sources/{source_id}/locations/{location}
      String parent = String.format("organizations/%s/sources/%s/locations/%s", organizationId,
          sourceId,
          location);

      // Listing all findings of category "MEDIUM_RISK_ONE".
      String filter = "category=\"MEDIUM_RISK_ONE\"";

      ListFindingsRequest request =
          ListFindingsRequest.newBuilder()
              .setParent(parent)
              .setFilter(filter)
              .build();

      for (ListFindingsResult result : client.listFindings(request).iterateAll()) {
        System.out.printf("Finding: %s", result.getFinding().getName());
      }
      System.out.println("\nListing complete.");
    }
  }
}

Node.js

// Imports the Google Cloud client library.
const {SecurityCenterClient} = require('@google-cloud/security-center').v2;

// Creates a new client.
const client = new SecurityCenterClient();

// TODO(developer): Update the following for your own environment.
const organizationId = '1081635000895';
const location = 'global';

// Required. Name of the source to groupBy. If no location is specified,
// finding is assumed to be in global.
//  The following list shows some examples:
// - `organizations/[organization_id]/sources/[source_id]`
// - `organizations/[organization_id]/sources/[source_id]/locations/[location_id]`
// - `folders/[folder_id]/sources/[source_id]`
// - `folders/[folder_id]/sources/[source_id]/locations/[location_id]`
// - `projects/[project_id]/sources/[source_id]`
// - `projects/[project_id]/sources/[source_id]/locations/[location_id]`
// To groupBy across all sources provide a source_id of `-`.
const parent = `organizations/${organizationId}/sources/-/locations/${location}`;

// Listing all findings of category "MEDIUM_RISK_ONE".
const filter = 'category="MEDIUM_RISK_ONE"';

// Build the list findings with filter request.
const listFilteredFindingsRequest = {
  parent,
  filter,
};

async function listFilteredFindings() {
  // Call the API.
  const iterable = client.listFindingsAsync(listFilteredFindingsRequest);
  let count = 0;
  console.log('Findings:');
  for await (const response of iterable) {
    // Just print a few for demonstration.
    if (count > 5) break;
    console.log(
      `${++count} ${response.finding.name} ${response.finding.resourceName}`
    );
  }
}
await listFilteredFindings();

Python

def list_filtered_findings(organization_id, source_name, location_id) -> int:
    """
    lists filtered findings for a source
    Args:
        organization_id: organization_id is the numeric ID of the organization. e.g.:organization_id = "111122222444"
        source_name: is the resource path for a source that has been created
        location_id: GCP location id; example: 'global'
    Returns:
         int: returns the filtered findings for a source
    """
    count = 0
    from google.cloud import securitycenter_v2

    # Create a new client.
    client = securitycenter_v2.SecurityCenterClient()
    parent = f"organizations/{organization_id}"
    all_sources = f"{parent}/sources/{source_name}/locations/{location_id}"
    finding_result_iterator = client.list_findings(
        request={"parent": all_sources, "filter": 'severity="LOW"'}
    )
    # Iterate an print all finding names and the resource they are
    # in reference to.
    for count, finding_result in enumerate(finding_result_iterator):
        print(
            "{}: name: {} resource: {}".format(
                count, finding_result.finding.name, finding_result.finding.resource_name
            )
        )
    return count

Security Command Center juga mendukung array dan objek JSON lengkap sebagai jenis properti potensial. Anda dapat memfilter berdasarkan:

  • Elemen array
  • Objek JSON lengkap dengan pencocokan string sebagian dalam objek
  • Subkolom objek JSON

Operator yang didukung

Pernyataan kueri untuk temuan Security Command Center mendukung operator yang didukung oleh sebagian besar Google Cloud API.

Daftar berikut menunjukkan penggunaan berbagai operator:

  • state="ACTIVE" AND NOT mute="MUTED"
  • create_time>"2023-08-15T19:05:32.428Z"
  • resource.parent_name:"prod"
  • severity="CRITICAL" OR severity="HIGH"

Daftar berikut menunjukkan semua operator dan fungsi yang didukung dalam pernyataan kueri untuk temuan:

  • Untuk string:
    • = untuk kesetaraan penuh
    • : untuk pencocokan string sebagian
  • Untuk angka:
    • <, >, <=, >= untuk ketidaksetaraan
    • =, != untuk kesetaraan
  • Untuk boolean:
    • = untuk kesetaraan
  • Untuk hubungan logis:
    • AND
    • OR
    • NOT atau -
  • Untuk ekspresi pengelompokan:
    • (, ) (tanda kurung)
  • Untuk array:
    • contains(), fungsi untuk mengkueri temuan dengan kolom array yang berisi minimal satu elemen yang cocok dengan filter yang ditentukan
    • containsOnly(), fungsi untuk membuat kueri temuan dengan kolom array yang hanya berisi elemen yang cocok dengan filter yang ditentukan
  • Untuk alamat IP:
    • inIpRange(), fungsi untuk membuat kueri alamat IP dalam rentang CIDR yang ditentukan

Pemfilteran pada alamat IP

Properti temuan tertentu menyertakan alamat IP. Anda dapat memfilter temuan berdasarkan alamat IP tertentu atau rentang alamat IP.

Alamat IP muncul sebagai string dalam berbagai temuan dan properti temuan, termasuk yang berikut:

  • access.caller_ip
  • connections.destinationIp
  • connections.sourceIp
  • indicator.ip_addresses

Untuk memfilter berdasarkan alamat IP tertentu, Anda dapat menggunakan operator kesetaraan, seperti yang ditunjukkan dalam contoh berikut:

access.caller_ip="192.0.2.0"

Untuk memfilter temuan berdasarkan rentang alamat IP, gunakan fungsi inIpRange. Dengan menggunakan fungsi inIpRange, Anda memfilter temuan hanya ke temuan yang berisi alamat IP dalam rentang CIDR yang ditentukan. Dengan menggunakan operasi NOT dengan inIpRange, Anda dapat memfilter temuan hanya ke temuan yang berisi alamat IP di luar rentang CIDR yang ditentukan.

Contoh berikut menunjukkan sintaksis fungsi inIpRange:

inIpRange(IP_FINDING_FIELD, "CIDR_RANGE")

Jika alamat IP berada dalam elemen array di kolom temuan yang berisi array, gunakan sintaksis berikut dengan fungsi contains dan fungsi inIpRange:

contains(ATTRIBUTE_WITH_ARRAY, inIpRange(IP_FINDING_FIELD, "CIDR_RANGE"))

Pada contoh berikut, fungsi inIpRange mengevaluasi setiap elemen destination_ip array yang terdapat di kolom penemuan connections untuk alamat IP yang berada dalam rentang CIDR yang ditentukan oleh 192.0.2.0/24:

contains(connections, inIpRange(destination_ip, "192.0.2.0/24"))

Contoh berikut menunjukkan perintah gcloud CLI yang menggunakan fungsi inIpRange untuk memfilter temuan yang memiliki alamat IP di kolom connections.source_ip yang berada dalam satu rentang, tetapi tidak dalam rentang lain. Kolom connections adalah kolom jenis array, sehingga fungsi contains digunakan:

gcloud scc findings list PARENT_TYPE/PARENT_ID \
    --location=LOCATION \
    --source=SOURCE_ID \
    --filter="contains(connections, inIpRange(source_ip, \"2001:db8::/32\")) \
      AND NOT contains(connections, inIpRange(source_ip, \"192.0.2.0/24\"))"

Contoh objek JSON

Contoh di halaman ini nanti mengasumsikan bahwa objek JSON berikut adalah atribut temuan:

{
  "outer_object": {
    "middle_object": {
      "deeply_nested_object": {
        "x": 123
      },
      "y": "some-string-value"
    },
    "list_middle_object": [
      {
        "v": 321,
        "w": [
          {
            "a": 3,
            "b": 4
          }
        ]
      }
    ],
    "z": "some-other-string-value",
    "u": [
      "list-element-1",
      "list-element-2",
      "list-element-3"
    ]
  }
}

Contoh pemfilteran temuan

Misalkan contoh JSON sebelumnya adalah atribut temuan yang bernama my_property. Contoh berikut menyertakan kueri untuk temuan yang memiliki objek sebagai properti. Anda juga dapat menggunakan filter ini dengan filter lain menggunakan AND dan OR dalam kueri Anda.

gcloud scc findings list PARENT_TYPE/PARENT_ID \
    --location=LOCATION \
    --source=SOURCE_ID \
    --filter="my_property.outer_object.middle_object.deeply_nested_object.x = 123"

gcloud scc findings list PARENT_TYPE/PARENT_ID \
    --location=LOCATION \
    --source=SOURCE_ID \
    --filter="my_property.outer_object.middle_object.y = \"some-string-value\""

gcloud scc findings list PARENT_TYPE/PARENT_ID \
    --location=LOCATION \
    --source=SOURCE_ID \
    --filter="my_property.outer_object.middle_object.y : \"string-value\""

gcloud scc findings list PARENT_TYPE/PARENT_ID \
    --location=LOCATION \
    --source=SOURCE_ID \
    --filter="my_property.outer_object.z = \"some-other-string-value\""

gcloud scc findings list PARENT_TYPE/PARENT_ID \
    --location=LOCATION \
    --source=SOURCE_ID \
    --filter="my_property.outer_object.z : \"other-string-value\""

gcloud scc findings list PARENT_TYPE/PARENT_ID \
    --location=LOCATION \
    --source=SOURCE_ID \
    --filter="my_property.outer_object.u : \"list-element-1\""

gcloud scc findings list PARENT_TYPE/PARENT_ID \
    --location=LOCATION \
    --source=SOURCE_ID \
    --filter="my_property.outer_object.u : \"list-element-2\""

gcloud scc findings list PARENT_TYPE/PARENT_ID \
    --location=LOCATION \
    --source=SOURCE_ID \
    --filter="my_property.outer_object.u : \"list-element-3\""

Subfilter untuk kolom jenis array

Saat memanggil ListFindings, Anda dapat menggunakan pencocokan substring :, yang melakukan satu pemeriksaan untuk pencocokan string parsial di seluruh konten array. Atau, Anda dapat menjalankan subfilter secara langsung terhadap elemen array dan subkolomnya menggunakan salah satu fungsi berikut:

  • Fungsi contains() untuk menampilkan temuan saat elemen array berisi nilai yang ditentukan.

  • Fungsi containsOnly() untuk menampilkan temuan hanya jika semua elemen array cocok dengan subfilter.

Kedua fungsi ini mendukung kemampuan kueri subfilter seperti berikut:

  • Pencocokan elemen persis: Mencocokkan elemen array yang berisi string persis, "example".
  • Operasi angka tertentu: Mencocokkan elemen array yang lebih besar dari atau sama dengan 100.
  • Pemfilteran kompleks terhadap struktur array: Mencocokkan elemen array yang berisi properti x dengan nilai y yang sesuai.

Format fungsi contains()

Fungsi contains() memiliki format berikut:

contains(ARRAY_ATTRIBUTE_NAME, SUBFILTER)

Ganti kode berikut:

  • ARRAY_ATTRIBUTE_NAME: kolom atau subkolom yang merupakan array jenis (daftar).
  • SUBFILTER: ekspresi yang menentukan nilai yang akan dicari dalam array. Format subfilter berbeda-beda, bergantung pada apakah ARRAY_ATTRIBUTE_NAME adalah array objek atau array elemen jenis primitif. Jika ARRAY_ATTRIBUTE_NAME adalah array objek yang memiliki array bertingkat, Anda dapat menggunakan subfilter cakupan untuk menentukan bahwa Anda ingin semua kondisi terpenuhi dalam elemen ARRAY_ATTRIBUTE_NAME yang sama.

Security Command Center API menampilkan temuan dengan ARRAY_ATTRIBUTE_NAME berisi setidaknya satu elemen yang memenuhi SUBFILTER.

Format fungsi containsOnly()

Fungsi containsOnly() memiliki format berikut:

containsOnly(ARRAY_ATTRIBUTE_NAME, SUBFILTER)

Ganti kode berikut:

  • ARRAY_ATTRIBUTE_NAME: kolom atau subkolom yang merupakan array jenis (daftar). Saat menjalankan kueri menggunakan Security Command Center API, Anda dapat menggunakan fungsi containsOnly() untuk setiap atribut array yang tersedia.
  • SUBFILTER: ekspresi yang menentukan nilai yang akan dicari dalam array. Format subfilter berbeda-beda, bergantung pada apakah ARRAY_ATTRIBUTE_NAME adalah array objek atau array elemen jenis primitif. Jika ARRAY_ATTRIBUTE_NAME adalah array objek yang memiliki array bertingkat, Anda dapat menggunakan subfilter cakupan untuk menentukan bahwa Anda ingin semua kondisi terpenuhi dalam elemen ARRAY_ATTRIBUTE_NAME yang sama.

Security Command Center API menampilkan temuan jika semua elemen ARRAY_ATTRIBUTE_NAME cocok dengan SUBFILTER.

Subfilter untuk array objek

Berikut adalah kutipan dari contoh JSON sebelumnya. Di sini, kolom list_middle_object adalah array objek:

    "list_middle_object": [
      {
        "v": 321,
        "w": [
          {
            "a": 3,
            "b": 4
          }
        ]
      }
    ]

Contoh berikut membuat kueri untuk temuan dengan setidaknya salah satu elemen di kolom list_middle_object memiliki subkolom v dengan nilai lebih besar dari atau sama dengan 321:

gcloud scc findings list PARENT_TYPE/PARENT_ID \
    --location=LOCATION \
    --source=SOURCE_ID \
    --filter="contains(my_property.outer_object.list_middle_object, v  >= 321)"

Untuk contoh praktis yang menggunakan fungsi contains() dan containsOnly(), lihat Temuan yang berisi nilai array tertentu.

Subfilter untuk array yang berisi elemen jenis primitif

Jenis primitif adalah string, angka, dan boolean. Untuk menggunakan fungsi contains() pada array yang berisi jenis primitif, Anda menggunakan kata kunci khusus, elem.

Berikut adalah kutipan dari contoh JSON sebelumnya. Di sini, kolom u adalah array elemen jenis primitif:

"u": ["list-element-1", "list-element-2", "list-element-3"]

Contoh berikut mengkueri temuan dengan setidaknya salah satu elemen di kolom u adalah "list-element-1":

gcloud scc findings list PARENT_TYPE/PARENT_ID \
    --location=LOCATION \
    --source=SOURCE_ID \
    --filter="contains(my_property.outer_object.u, elem = \"list-element-1\")"

Untuk contoh praktis yang menggunakan fungsi contains(), lihat Temuan yang berisi nilai array tertentu.

Subfilter terbatas

Berikut adalah kutipan dari contoh JSON sebelumnya. Di sini, kolom list_middle_object adalah array objek, dan objek dalam array ini berisi array bertingkat.

"list_middle_object": [
  {
    "v": 321,
    "w": [
      {
        "a": 3,
        "b": 4
      }
    ]
  }
]

Contoh berikut mengkueri temuan jika kedua kondisi berikut terpenuhi dalam elemen list_middle_object yang sama:

  • Subkolom v memiliki nilai lebih besar dari atau sama dengan 321.
  • Subkolom w tidak berisi elemen dengan properti a sama dengan 3.
gcloud scc findings list PARENT_TYPE/PARENT_ID \
    --location=LOCATION \
    --source=SOURCE_ID \
    --filter="contains(my_property.outer_object.list_middle_object, v  >= 321 AND -contains(w, a = 3))"

Untuk contoh praktis yang menggunakan fungsi contains(), lihat Temuan yang berisi nilai array tertentu.

Contoh pengurutan temuan

Anda dapat mengurutkan temuan menurut subkolom ketat yang merupakan jenis primitif—string, angka, dan boolean. Misalkan contoh JSON sebelumnya adalah atribut temuan bernama my_property. Contoh berikut menyertakan kueri untuk mengurutkan kolom temuan. Kata kunci DESC menentukan bahwa kolom yang mengikutinya harus diurutkan dalam urutan menurun. Urutan defaultnya adalah menaik.

gcloud scc findings list PARENT_TYPE/PARENT_ID \
    --location=LOCATION \
    --source=SOURCE_ID \
    --order-by="my_property.outer_object.middle_object.deeply_nested_object.x DESC"

gcloud scc findings list PARENT_TYPE/PARENT_ID \
    --location=LOCATION \
    --source=SOURCE_ID \
    --order-by="my_property.outer_object.middle_object.deeply_nested_object.x"

gcloud scc findings list PARENT_TYPE/PARENT_ID \
    --location=LOCATION \
    --source=SOURCE_ID \
    --order-by="my_property.outer_object.middle_object.y DESC"

gcloud scc findings list PARENT_TYPE/PARENT_ID \
    --location=LOCATION \
    --source=SOURCE_ID \
    --order-by="my_property.outer_object.middle_object.y"

gcloud scc findings list PARENT_TYPE/PARENT_ID \
    --location=LOCATION \
    --source=SOURCE_ID \
    --order-by="my_property.outer_object.z DESC"

gcloud scc findings list PARENT_TYPE/PARENT_ID \
    --location=LOCATION \
    --source=SOURCE_ID \
    --order-by="my_property.outer_object.z"

Contoh filter

Bagian berikut menunjukkan contoh praktis untuk menemukan filter.

Memfilter temuan yang terjadi setelah titik waktu tertentu

Contoh filter ini cocok dengan temuan yang terakhir kali terjadi setelah Rabu, 5 Juni 2019 pukul 22.12.05 GMT. Dengan filter event_time, Anda dapat menunjukkan waktu menggunakan format dan jenis berikut:

  • Waktu epoch Unix (dalam milidetik) sebagai literal bilangan bulat

    "event_time > 1559772725000"
    
  • RFC 3339 sebagai literal string

    "event_time > \"2019-06-05T22:34:40+00:00\""
    

Memfilter di kolom jenis array

Contoh berikut menunjukkan penggunaan pencocokan string sebagian pada kolom jenis array dalam filter:

"indicator.domains : \"website.com\""

Security Command Center API menampilkan temuan apa pun dengan string parsial website.com dalam array. Misalnya, ekspresi ini cocok dengan penemuan dengan indicator.domains = [\"onewebsite.com\"] karena "website.com" adalah substring dalam elemen dalam array.

Di bagian berikut, contoh filter menunjukkan beberapa opsi untuk penggunaan pemfilteran jenis array yang kaya menggunakan fungsi contains().

Filter di kolom vulnerability.cve.references

Contoh berikut menampilkan temuan dengan setidaknya satu elemen dalam array vulnerability.cve.references memiliki properti source yang sama dengan SOURCE_OF_REFERENCE dan properti uri yang memiliki FILTERED_URI.

"contains(vulnerability.cve.references, source = \"SOURCE_OF_REFERENCE\" AND uri : \"FILTERED_URI\")"

Ganti kode berikut:

Filter di kolom indicator.domains

Contoh berikut menampilkan temuan dengan setidaknya satu domain indikator memiliki mycompanyprefix dan .ca.

"contains(indicator.domains, elem : \"mycompanyprefix\" AND elem : \".ca\")"

Filter di kolom indicator.ip_addresses

Contoh berikut menampilkan temuan dengan setidaknya satu elemen dalam array indicator.ip_addresses sama dengan IP_ADDRESS.

"contains(indicator.ip_addresses, elem = \"IP_ADDRESS\")"

Ganti IP_ADDRESS dengan alamat IP yang terkait dengan temuan yang Anda telusuri.

Memfilter penerima tugas sistem eksternal

Contoh berikut menampilkan temuan dengan setidaknya satu elemen dalam array external_systems.EXTERNAL_SYSTEM_NAME.assignees sama dengan ASSIGNEE.

"contains(external_systems.EXTERNAL_SYSTEM_NAME.assignees, elem = \"ASSIGNEE\")"

Ganti kode berikut:

  • EXTERNAL_SYSTEM_NAME: nama sistem SIEM/SOAR pihak ketiga—misalnya, demisto.
  • ASSIGNEE: penerima tugas di sistem eksternal.

Filter di kolom resource.folders.resource_folder

Contoh berikut menampilkan temuan dengan setidaknya satu elemen dalam array resource.folders.resource_folder tidak sama dengan FOLDER_NAME.

"contains(resource.folders.resource_folder, -(elem = \"FOLDER_NAME\"))"

Filter di kolom resource.folders.resource_folder_display_name

Contoh berikut menampilkan temuan dengan setidaknya satu elemen dalam array resource.folders.resource_folder_display_name sama dengan DISPLAY_NAME.

"contains(resource.folders.resource_folder_display_name, elem = \"DISPLAY_NAME\")"

Ganti DISPLAY_NAME dengan nama folder yang ditentukan pengguna yang terkait dengan temuan yang Anda telusuri.

Filter hanya menyertakan akun layanan tertentu

Contoh berikut hanya menampilkan temuan jika setiap nilai anggota entri iam_bindings sama dengan salah satu akun layanan yang disediakan.

containsOnly(iam_bindings, (member = SERVICE_ACCOUNT1 OR member = SERVICE_ACCOUNT2 OR member = "SERVICE_ACCOUNT3 "))

Ganti SERVICE_ACCOUNT1, SERVICE_ACCOUNT2, dan SERVICE_ACCOUNT3 dengan alamat email untuk akun layanan.

Untuk mempelajari cara menggunakan fungsi contains() dan containsOnly() dalam filter penemuan, lihat Subfilter untuk kolom jenis array.

Langkah selanjutnya

Pelajari lebih lanjut cara menyiapkan notifikasi temuan.