Mencantumkan temuan keamanan menggunakan Security Command Center API

Temuan Security Command Center memodelkan 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 termasuk dalam suatu 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 diberikan kepada Anda. Untuk mempelajari lebih lanjut peran Security Command Center, lihat Kontrol akses.

Sebelum memulai

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

Ukuran halaman

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

Retensi temuan

Bergantung pada paket Security Command Center Anda, temuan tetap tersedia untuk Anda cantumkan atau kueri selama jangka waktu tertentu. 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 untuk mencantumkan temuan; gunakan organizations, folders, atau projects.
  • PARENT_ID: ID numerik organisasi, folder, atau project, atau ID project alfanumerik.
  • LOCATION: lokasi Security Command Centertempat mencantumkan temuan; jika retensi data diaktifkan, gunakan eu, ksa, atau us; jika tidak, 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 catatan penemuan ditampilkan.

Untuk membantu Anda mendapatkan informasi hanya tentang kolom yang diinginkan, Anda dapat menggunakan filter penemuan. Filter ini seperti klausa "where" dalam pernyataan SQL, tetapi bukan kolom, filter ini diterapkan ke 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 serangkaian kategori yang berbeda. Untuk menentukan kategori yang dapat Anda gunakan dalam filter, lihat dokumentasi penyedia temuan.

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 untuk mencantumkan temuan; gunakan organizations, folders, atau projects.
  • PARENT_ID: ID numerik organisasi, folder, atau project, atau ID project alfanumerik.
  • LOCATION: lokasi Security Command Centertempat mencantumkan temuan dengan filter; jika retensi data diaktifkan, gunakan eu, ksa, atau us; jika tidak, gunakan nilai global.
  • SOURCE_ID: ID sumber keamanan yang menyediakan jenis temuan.
  • FILTER: filter yang perlu Anda gunakan. Misalnya, filter berikut menampilkan temuan dari kategori MEDIUM_RISK_ONE saja:
    --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 potensi jenis properti. Anda dapat memfilter berdasarkan:

  • Elemen array
  • Objek JSON lengkap dengan kecocokan string parsial dalam objek
  • Sub-bidang objek JSON

Operator yang didukung

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

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 parsial
  • Untuk angka:
    • <, >, <=, >= untuk pertidaksamaan
    • =, != untuk kesetaraan
  • Untuk boolean:
    • = untuk kesetaraan
  • Untuk hubungan logis:
    • AND
    • OR
    • NOT atau -
  • Untuk mengelompokkan ekspresi:
    • (, ) (tanda kurung)
  • Untuk array:
    • contains(), fungsi untuk mengkueri temuan dengan kolom array yang berisi setidaknya satu elemen yang cocok dengan filter yang ditentukan
    • containsOnly(), sebuah fungsi untuk membuat kueri temuan dengan kolom array yang hanya berisi elemen yang cocok dengan filter yang ditentukan
  • Untuk alamat IP:
    • inIpRange(), fungsi untuk mengkueri alamat IP dalam rentang CIDR yang ditentukan

Memfilter alamat IP

Properti temuan tertentu mencakup 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:

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

Untuk memfilter 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 dapat memfilter temuan hanya ke temuan yang berisi alamat IP dalam rentang CIDR tertentu. 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"))

Dalam contoh berikut, fungsi inIpRange mengevaluasi setiap elemen destination_ip dari array yang ada dalam 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 lainnya. 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 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 mencakup 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 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 sub-kolom yang berjenis array (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 berjenis 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.

API Security Command Center menampilkan temuan dengan ARRAY_ATTRIBUTE_NAME yang 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 sub-kolom yang berjenis array (daftar). Saat menjalankan kueri menggunakan Security Command Center API, Anda dapat menggunakan fungsi containsOnly() untuk 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 tercakup untuk menentukan bahwa Anda ingin semua kondisi terpenuhi dalam elemen ARRAY_ATTRIBUTE_NAME yang sama.

Security Command Center API menampilkan temuan yang semua elemen ARRAY_ATTRIBUTE_NAME-nya 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 yang setidaknya salah satu elemen di kolom list_middle_object memiliki sub-kolom 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() terhadap 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 membuat kueri untuk temuan yang 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 yang dicakup

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 membuat kueri untuk temuan yang memenuhi kedua kondisi berikut dalam elemen list_middle_object yang sama:

  • Sub-bidang v memiliki nilai yang lebih besar dari atau sama dengan 321.
  • Sub-bidang w tidak berisi elemen dengan properti a yang 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 sub-bidang ketat yang merupakan jenis primitif—string, angka, dan boolean. Misalkan contoh JSON sebelumnya adalah atribut temuan bernama my_property. Contoh berikut mencakup kueri untuk mengurutkan kolom temuan. Kata kunci DESC menentukan bahwa kolom yang mengikutinya harus diurutkan dari atas ke bawah. 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 cara menemukan filter.

Memfilter temuan yang terjadi setelah suatu titik waktu

Contoh filter ini cocok dengan temuan yang baru-baru ini terjadi setelah Rabu, 5 Juni 2019 22.12.05 GMT. Dengan filter event_time, Anda dapat mengekspresikan 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 kolom jenis array

Contoh berikut menunjukkan penggunaan pencocokan string parsial 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, kecocokan temuan dengan indicator.domains = [\"onewebsite.com\"] karena "website.com" adalah substring dalam elemen di array.

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

Memfilter kolom vulnerability.cve.references

Contoh berikut menampilkan temuan yang setidaknya memiliki satu elemen dalam array vulnerability.cve.references yang 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:

Memfilter kolom indicator.domains

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

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

Memfilter kolom indicator.ip_addresses

Contoh berikut menampilkan temuan yang 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 cari.

Memfilter penerima tugas di 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 dalam sistem eksternal.

Memfilter kolom resource.folders.resource_folder

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

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

Memfilter kolom resource.folders.resource_folder_display_name

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

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

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

Filter hanya menyertakan akun layanan tertentu

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

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 temuan, lihat Subfilter untuk kolom jenis array.

Langkah berikutnya

Pelajari lebih lanjut cara menyiapkan notifikasi temuan.