Sicherheitsergebnisse mit Security Command Center API auflisten

>

Security Command Center-Ergebnisse modellieren die potenziellen Sicherheitsrisiken der Assets einer Organisation. Ein Ergebnis bezieht sich immer auf einen bestimmten Asset im Security Command Center.

In diesem Leitfaden erfahren Sie, wie Sie mit Security Command Center-Clientbibliotheken auf die Ergebnisse einer Organisation zugreifen. Jedes Ergebnis gehört zu einer Quelle. Die meisten Detektoren oder Ergebnisanbieter liefern Ergebnisse innerhalb derselben Quelle.

Hinweis

Bevor Sie eine Quelle einrichten können, müssen Sie die folgenden Schritte ausführen:

Seitengröße

Alle Security Command Center API-Listen sind paginiert. Jede Antwort gibt eine Seite mit Ergebnissen und ein Token zurück, um die nächste Seite zurückzugeben. Die Seitengröße kann konfiguriert werden. Die Standardseitengröße ist 10. Sie kann auf ein Minimum von 1 und maximal 1.000 festgelegt werden.

Alle Ergebnisse in einer Organisation auflisten

gcloud

  # ORGANIZATION_ID=organization-id

  gcloud scc findings list $ORGANIZATION_ID

Führen Sie den folgenden Befehl aus, um weitere Beispiele aufzurufen:

  gcloud scc findings list --help

Python

from google.cloud import securitycenter

# Create a client.
client = securitycenter.SecurityCenterClient()

# organization_id is the numeric ID of the organization. e.g.:
# organization_id = "111122222444"
org_name = "organizations/{org_id}".format(org_id=organization_id)
# The "sources/-" suffix lists findings across all sources.  You
# also use a specific source_name instead.
all_sources = "{org_name}/sources/-".format(org_name=org_name)
finding_result_iterator = client.list_findings(all_sources)
for i, finding_result in enumerate(finding_result_iterator):
    print(
        "{}: name: {} resource: {}".format(
            i, finding_result.finding.name, finding_result.finding.resource_name
        )
    )

Java

static ImmutableList<ListFindingsResult> listAllFindings(OrganizationName organizationName) {
  try (SecurityCenterClient client = SecurityCenterClient.create()) {
    // OrganizationName organizationName = OrganizationName.of(/*organizationId=*/"123234324");
    // "-" Indicates listing across all sources.
    SourceName sourceName = SourceName.of(organizationName.getOrganization(), "-");

    ListFindingsRequest.Builder request =
        ListFindingsRequest.newBuilder().setParent(sourceName.toString());

    // Call the API.
    ListFindingsPagedResponse response = client.listFindings(request.build());

    // This creates one list for all findings.  If your organization has a large number of
    // findings this can cause out of memory issues.  You can process them in incrementally
    // by returning the Iterable returned response.iterateAll() directly.
    ImmutableList<ListFindingsResult> results = ImmutableList.copyOf(response.iterateAll());
    System.out.println("Findings:");
    System.out.println(results);
    return results;
  } catch (IOException e) {
    throw new RuntimeException("Couldn't create client.", e);
  }
}

Go

import (
	"context"
	"fmt"
	"io"

	securitycenter "cloud.google.com/go/securitycenter/apiv1"
	"google.golang.org/api/iterator"
	securitycenterpb "google.golang.org/genproto/googleapis/cloud/securitycenter/v1"
)

// 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: %v", err)
	}
	defer client.Close() // Closing the client safely cleans up background resources.

	req := &securitycenterpb.ListFindingsRequest{
		// List findings across all sources.
		Parent: fmt.Sprintf("organizations/%s/sources/-", orgID),
	}
	it := client.ListFindings(ctx, req)
	for {
		result, err := it.Next()
		if err == iterator.Done {
			break
		}
		if err != nil {
			return fmt.Errorf("it.Next: %v", 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
}

Node.js

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

// Creates a new client.
const client = new SecurityCenterClient();
//  organizationId is the numeric ID of the organization.
/*
 * TODO(developer): Uncomment the following lines
 */
// const organizationId = "1234567777";

async function listAllFindings() {
  const [response] = await client.listFindings({
    // List findings across all sources.
    parent: `organizations/${organizationId}/sources/-`,
  });
  let count = 0;
  Array.from(response).forEach(result =>
    console.log(
      `${++count} ${result.finding.name} ${result.finding.resourceName}`
    )
  );
}
listAllFindings();

Ergebnisse filtern

Für eine Organisation gibt es wahrscheinlich viele Erkenntnisse. Im obigen Beispiel wird kein Filter verwendet. Daher werden alle Ergebnisdatensätze zurückgegeben. Mit Security Command Center können Sie Ergebnisfilter verwenden, um nur Informationen zu den gewünschten Ergebnissen zu erhalten, und das übergeordnete Element auf eine bestimmte Quelle zu beschränken.

Die Ergebnisfilter sind mit "where"-Klauseln in SQL-Anweisungen vergleichbar, mit Ausnahme von Spalten. Sie gelten für die von der API zurückgegebenen Objekte.

Das folgende Beispiel zeigt nur Ergebnisse mit der Kategorie "MEDIUM_RISK_ONE" an. Bestimmte Kategorien können sich ändern. Sie sollten daher anhand der Dokumentation eines Ergebnisanbieters die von ihm verwendeten Kategorien ermitteln.

gcloud

  # ORGANIZATION_ID=organization-id
  # SOURCE_ID="source-id"
  FILTER="category=\"MEDIUM_RISK_ONE\""

  gcloud scc findings list $ORGANIZATION_ID --source=$SOURCE_ID --filter="$FILTER"

Führen Sie den folgenden Befehl aus, um weitere Beispiele aufzurufen:

  gcloud scc findings list --help

Python

from google.cloud import securitycenter

# Create a new client.
client = securitycenter.SecurityCenterClient()

# source_name is the resource path for a source that has been
# created previously (you can use list_sources to find a specific one).
# Its format is:
# source_name = "organizations/{organization_id}/sources/{source_id}"
# e.g.:
# source_name = "organizations/111122222444/sources/1234"
# You an also use a wild-card "-" for all sources:
#   source_name = "organizations/111122222444/sources/-"
finding_result_iterator = client.list_findings(
    source_name, filter_='category="MEDIUM_RISK_ONE"'
)
# Iterate an print all finding names and the resource they are
# in reference to.
for i, finding_result in enumerate(finding_result_iterator):
    print(
        "{}: name: {} resource: {}".format(
            i, finding_result.finding.name, finding_result.finding.resource_name
        )
    )

Java

static ImmutableList<ListFindingsResult> listFilteredFindings(SourceName sourceName) {
  try (SecurityCenterClient client = SecurityCenterClient.create()) {
    // SourceName sourceName = SourceName.of(/*organizationId=*/"123234324",
    // /*sourceId=*/"423432321");

    // Create filter to category of MEDIUM_RISK_ONE
    String filter = "category=\"MEDIUM_RISK_ONE\"";

    ListFindingsRequest.Builder request =
        ListFindingsRequest.newBuilder().setParent(sourceName.toString()).setFilter(filter);

    // Call the API.
    ListFindingsPagedResponse response = client.listFindings(request.build());

    // This creates one list for all findings.  If your organization has a large number of
    // findings this can cause out of memory issues.  You can process them in incrementally
    // by returning the Iterable returned response.iterateAll() directly.
    ImmutableList<ListFindingsResult> results = ImmutableList.copyOf(response.iterateAll());
    System.out.println("Findings:");
    System.out.println(results);
    return results;
  } catch (IOException e) {
    throw new RuntimeException("Couldn't create client.", e);
  }
}

Go

import (
	"context"
	"fmt"
	"io"

	securitycenter "cloud.google.com/go/securitycenter/apiv1"
	"google.golang.org/api/iterator"
	securitycenterpb "google.golang.org/genproto/googleapis/cloud/securitycenter/v1"
)

// 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 := "organizations/111122222444/sources/1234"
	// All sources.
	// sourceName := "organizations/111122222444/sources/-"
	// 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: %v", 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: %v", 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
}

Node.js

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

// Creates a new client.
const client = new SecurityCenterClient();
//  sourceName is the full resource path of the source to search for
//  findings.
/*
 * TODO(developer): Uncomment the following lines
 */
// const sourceName = "organizations/111122222444/sources/1234";

async function listFilteredFindings() {
  const [response] = await client.listFindings({
    // List findings across all sources.
    parent: sourceName,
    filter: 'category="MEDIUM_RISK_ONE"',
  });
  let count = 0;
  Array.from(response).forEach(result =>
    console.log(
      `${++count} ${result.finding.name} ${result.finding.resourceName}`
    )
  );
}
listFilteredFindings();

Security Command Center unterstützt auch vollständige JSON-Arrays und Objekte als potenzielle Attribut-Typen. Sie können nach folgenden Kriterien filtern:

  • Arrayelemente
  • Vollständige JSON-Objekte mit partieller Stringübereinstimmung im Objekt
  • Untergeordnete JSON-Objekt-Felder

Untergeordnete Felder müssen Zahlen, Strings oder boolesche Werte enthalten und müssen die folgenden Operatoren verwenden:

  • Strings:
    • Vollständige Gleichheit =
    • Teilstring, der mit : übereinstimmt
  • Nummern:
    • Ungleichungen <, >, <=, >=
    • Gleichheit =
  • Boolesche Werte:
    • Gleichheit =

In den Beispielen weiter unten auf dieser Seite wird davon ausgegangen, dass das folgende JSON-Objekt ein Quellattribut für ein Ergebnis ist:

{
    "outer_object": {
        "middle_object": {
            "deeply_nested_object": {
                "x": 123,
            },
            "y": "some-string-value",
        },
        "z": "some-other-string-value",
        "u": ["list-element-1", "list-element-2", "list-element-3", ],
    },
}

Beispiel für das Filtern von Ergebnissen

In diesem Beispiel ist das vorherige JSON-Objekt ein Quellattribut namens my_property für ein Ergebnis. Das folgende Beispiel enthält Abfragen für Ergebnisse, die das Objekt als Attribut haben. Sie können diese Filter auch mit anderen Filtern verwenden, indem Sie AND und OR in der Abfrage verwenden.

# ORGANIZATION_ID=organization-id
# SOURCE_ID="source-id"

gcloud scc findings list $ORGANIZATION_ID --source=$SOURCE_ID \
  --filter="source_properties.my_property.outer_object.middle_object.deeply_nested_object.x = 123"

gcloud scc findings list $ORGANIZATION_ID --source=$SOURCE_ID \
  --filter="source_properties.my_property.outer_object.middle_object.y = \"some-string-value\""

gcloud scc findings list $ORGANIZATION_ID --source=$SOURCE_ID \
  --filter="source_properties.my_property.outer_object.middle_object.y : \"string-value\""

gcloud scc findings list $ORGANIZATION_ID --source=$SOURCE_ID \
  --filter="source_properties.my_property.outer_object.z = \"some-other-string-value\""

gcloud scc findings list $ORGANIZATION_ID --source=$SOURCE_ID \
  --filter="source_properties.my_property.outer_object.z : \"other-string-value\""

gcloud scc findings list $ORGANIZATION_ID --source=$SOURCE_ID \
  --filter="source_properties.my_property.outer_object.u : \"list-element-1\""

gcloud scc findings list $ORGANIZATION_ID --source=$SOURCE_ID \
  --filter="source_properties.my_property.outer_object.u : \"list-element-2\""

gcloud scc findings list $ORGANIZATION_ID --source=$SOURCE_ID \
  --filter="source_properties.my_property.outer_object.u : \"list-element-3\""

Beispiel für das Sortieren von Ergebnissen

Sie können Ergebnisse nach strengen untergeordneten Feldern sortieren, die einfache Typen sind, wie Strings, Zahlen und boolesche Werte. In diesem Beispiel ist das vorherige JSON-Objekt ein Quellattribut namens my_property für ein Ergebnis. Das folgende Beispiel enthält Abfragen zum Sortieren der Ergebnisfelder:

# ORGANIZATION_ID=organization-id
# SOURCE_ID="source-id"

gcloud scc findings list $ORGANIZATION_ID --source=$SOURCE_ID \
  --order-by="source_properties.my_property.outer_object.middle_object.deeply_nested_object.x DESC"

gcloud scc findings list $ORGANIZATION_ID --source=$SOURCE_ID \
  --order-by="source_properties.my_property.outer_object.middle_object.deeply_nested_object.x"

gcloud scc findings list $ORGANIZATION_ID --source=$SOURCE_ID \
  --order-by="source_properties.my_property.outer_object.middle_object.y DESC"

gcloud scc findings list $ORGANIZATION_ID --source=$SOURCE_ID \
  --order-by="source_properties.my_property.outer_object.middle_object.y"

gcloud scc findings list $ORGANIZATION_ID --source=$SOURCE_ID \
  --order-by="source_properties.my_property.outer_object.z DESC"

gcloud scc findings list $ORGANIZATION_ID --source=$SOURCE_ID \
  --order-by="source_properties.my_property.outer_object.z"

Abfragen zu einem bestimmten Zeitpunkt

Mit Security Command Center können Sie die Ergebnisse ab einer bestimmten Snapshot-Zeit auflisten:

gcloud

  # ORGANIZATION_ID=organization-id
  # SOURCE_ID="source-id"
  # READ_TIME follows the format YYYY-MM-DDThh:mm:ss.ffffffZ
  READ_TIME=2019-02-28T07:00:06.861Z

  gcloud scc findings list $ORGANIZATION_ID --source=$SOURCE_ID --read-time=$READ_TIME

Führen Sie den folgenden Befehl aus, um weitere Beispiele aufzurufen:

  gcloud scc findings list --help

Python

from google.cloud import securitycenter
from google.protobuf.timestamp_pb2 import Timestamp
from datetime import timedelta, datetime

# Create a new client.
client = securitycenter.SecurityCenterClient()

# source_name is the resource path for a source that has been
# created previously (you can use list_sources to find a specific one).
# Its format is:
# source_name = "organizations/{organization_id}/sources/{source_id}"
# e.g.:
# source_name = "organizations/111122222444/sources/1234"
# You an also use a wild-card "-" for all sources:
#   source_name = "organizations/111122222444/sources/-"
five_days_ago = Timestamp()
five_days_ago.FromDatetime(datetime.now() - timedelta(days=5))

finding_result_iterator = client.list_findings(source_name, read_time=five_days_ago)
for i, finding_result in enumerate(finding_result_iterator):
    print(
        "{}: name: {} resource: {}".format(
            i, finding_result.finding.name, finding_result.finding.resource_name
        )
    )

Java

static ImmutableList<ListFindingsResult> listFindingsAtTime(SourceName sourceName) {
  try (SecurityCenterClient client = SecurityCenterClient.create()) {
    // SourceName sourceName = SourceName.of(/*organizationId=*/"123234324",
    // /*sourceId=*/"423432321");

    // 5 days ago
    Instant fiveDaysAgo = Instant.now().minus(Duration.ofDays(5));

    ListFindingsRequest.Builder request =
        ListFindingsRequest.newBuilder()
            .setParent(sourceName.toString())
            .setReadTime(
                Timestamp.newBuilder()
                    .setSeconds(fiveDaysAgo.getEpochSecond())
                    .setNanos(fiveDaysAgo.getNano()));

    // Call the API.
    ListFindingsPagedResponse response = client.listFindings(request.build());

    // This creates one list for all findings.  If your organization has a large number of
    // findings this can cause out of memory issues.  You can process them in incrementally
    // by returning the Iterable returned response.iterateAll() directly.
    ImmutableList<ListFindingsResult> results = ImmutableList.copyOf(response.iterateAll());
    System.out.println("Findings:");
    System.out.println(results);
    return results;
  } catch (IOException e) {
    throw new RuntimeException("Couldn't create client.", e);
  }
}

Go

import (
	"context"
	"fmt"
	"io"
	"time"

	securitycenter "cloud.google.com/go/securitycenter/apiv1"
	"github.com/golang/protobuf/ptypes"
	"google.golang.org/api/iterator"
	securitycenterpb "google.golang.org/genproto/googleapis/cloud/securitycenter/v1"
)

// listFindingsAtTime prints findings that where present for a specific source
// as of five days ago to w. sourceName is the full resource name of the
// source to search for findings under.
func listFindingsAtTime(w io.Writer, sourceName string) error {
	// Specific source.
	// sourceName := "organizations/111122222444/sources/1234"
	// All sources.
	// sourceName := "organizations/111122222444/sources/-"
	ctx := context.Background()
	client, err := securitycenter.NewClient(ctx)
	if err != nil {
		return fmt.Errorf("securitycenter.NewClient: %v", err)
	}
	defer client.Close() // Closing the client safely cleans up background resources.
	fiveDaysAgo, err := ptypes.TimestampProto(time.Now().AddDate(0, 0, -5))
	if err != nil {
		return fmt.Errorf("Error converting five days ago: %v", err)
	}

	req := &securitycenterpb.ListFindingsRequest{
		Parent:   sourceName,
		ReadTime: fiveDaysAgo,
	}
	it := client.ListFindings(ctx, req)
	for {
		result, err := it.Next()
		if err == iterator.Done {
			break
		}
		if err != nil {
			return fmt.Errorf("it.Next: %v", 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
}

Node.js

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

// Creates a new client.
const client = new SecurityCenterClient();
// sourceName is the fully qualified source name to search for findings
// under.
/*
 * TODO(developer): Uncomment the following lines
 */
// const sourceName = "organizations/111122222444/sources/1234";

const fiveDaysAgo = new Date();
fiveDaysAgo.setDate(fiveDaysAgo.getDate() - 5);

async function listFindingsAtTime() {
  const [response] = await client.listFindings({
    // List findings across all sources.
    parent: sourceName,
    readTime: {
      seconds: Math.floor(fiveDaysAgo.getTime() / 1000),
      nanos: (fiveDaysAgo.getTime() % 1000) * 1e6,
    },
  });
  let count = 0;
  Array.from(response).forEach(result =>
    console.log(
      `${++count} ${result.finding.name} ${result.finding.resourceName}`
    )
  );
}
listFindingsAtTime();

Beispiele für Filter

Im Folgenden sind einige weitere nützliche Filter für Ergebnisse aufgeführt.

Ergebnisse, die nach einem bestimmten Zeitpunkt erfasst wurden

Diese Beispielfilter stimmen mit Ergebnissen überein, die erst nach Mittwoch, 5. Juni 2019, 22:12:05 Uhr (GMT) aufgetreten sind. Mit dem Filter event_time können Sie die Zeit in den folgenden Formaten und Typen angeben:

  • Unix-Zeit (in Millisekunden) als Ganzzahlliteral

    "event_time > 1559772725000"
    
  • RFC 3339 als String-Literal

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