Gérer les marques de sécurité à l'aide de l'API Security Command Center

Ce guide explique comment utiliser l'API Security Command Center pour gérer les marques de sécurité. Les marques de sécurité, ou "marques", sont des annotations personnalisables sur les éléments ou les résultats dans Security Command Center qui vous permettent d'ajouter votre propre contexte commercial à ces objets.

Vous ne pouvez ajouter ou mettre à jour des marques de sécurité que sur les éléments compatibles avec Security Command Center. Pour obtenir la liste des éléments compatibles avec Security Command Center, consultez la section Types d'éléments acceptés dans Security Command Center.

Avant de commencer

Pour pouvoir utiliser des marques de sécurité, vous devez configurer un compte de service et un SDK.

Pour ajouter ou modifier des marques de sécurité, vous devez disposer d'un rôle de gestion de l'authentification et des accès incluant des autorisations pour le type de marque que vous souhaitez utiliser :

  • Marques d'éléments : Rédacteur de marques de sécurité d'élément, securitycenter.assetSecurityMarksWriter
  • Marques de résultats : Rédacteur de marques de sécurité de résultat, securitycenter.findingSecurityMarksWriter

Pour en savoir plus sur les rôles IAM dans Security Command Center, consultez la page Contrôle des accès. Pour apprendre à utiliser les marques de sécurité efficacement, consultez la page Utiliser les marques de sécurité Security Command Center.

Ajouter ou mettre à jour des marques de sécurité sur des éléments

Lorsque vous utilisez l'API Security Command Center, l'ajout et la mise à jour de marques de sécurité sont identiques. L'exemple ci-dessous montre comment ajouter des marques de sécurité pour deux paires clé-valeur (key_a, value_a) et (key_b, value_b).

Le code suivant utilise des masques de champ pour garantir que seules ces valeurs sont mises à jour. Si vous n'utilisez pas de masques de champ, toutes les marques de sécurité sont effacées avant d'ajouter les clés et les valeurs données.

gcloud

gcloud scc assets update-marks ASSET_ID \
    --PARENT=PARENT_ID \
    --location=LOCATION \
    --security-marks=SECURITY_MARKS \
    --update-mask=UPDATE_MASK

Remplacez les éléments suivants :

  • ASSET_ID: composant à mettre à jour.
  • PARENT: niveau de la hiérarchie des ressources où se trouve l'asset. Utilisez organization, folder ou project.
  • PARENT_ID: ID numérique de l'organisation, du dossier ou du projet parent, ou ID alphanumérique du projet parent.
  • LOCATION : si la résidence des données est activée, l'emplacement Security Command Center dans lequel mettre à jour une marque de sécurité sur un élément. Si la résidence des données n'est pas activée, utilisez la valeur global.
  • SECURITY_MARKS: paires clé-valeur séparées par des virgules représentant des marques de sécurité et leurs valeurs (par exemple, key_a=value_a,key_b=value_b).
  • UPDATE_MASK: liste des champs de marque de sécurité à mettre à jour pour l'élément, séparés par une virgule (par exemple, marks.key_a,marks.key_b).

Go

import (
	"context"
	"fmt"
	"io"

	securitycenter "cloud.google.com/go/securitycenter/apiv2"
	"cloud.google.com/go/securitycenter/apiv2/securitycenterpb"
	"google.golang.org/genproto/protobuf/field_mask"
)

// addSecurityMarks adds/updates the security marks for the assetName.
// Specifically, it sets "key_a" and "key_b" to "value_a" and "value_b"
// respectively.  assetName is the resource path for an asset.
func addSecurityMarks(w io.Writer, assetName string) error {
	// Specify the value of 'assetName' in one of the following formats:
	// 		assetName := "organizations/{org_id}/locations/{location_id}/assets/{asset_id}"
	//		assetName := "projects/{project_id}/locations/{location_id}/assets/{asset_id}"
	//		assetName := "folders/{folder_id}/locations/{location_id}/assets/{asset_id}"
	// 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.UpdateSecurityMarksRequest{
		// If not set or empty, all marks would be cleared before
		// adding the new marks below.
		UpdateMask: &field_mask.FieldMask{
			Paths: []string{"marks.key_a", "marks.key_b"},
		},
		SecurityMarks: &securitycenterpb.SecurityMarks{
			Name: fmt.Sprintf("%s/securityMarks", assetName),
			// Note keys correspond to the last part of each path.
			Marks: map[string]string{"key_a": "value_a", "key_b": "value_b"},
		},
	}
	updatedMarks, err := client.UpdateSecurityMarks(ctx, req)
	if err != nil {
		return fmt.Errorf("UpdateSecurityMarks: %w", err)
	}

	fmt.Fprintf(w, "Updated marks: %s\n", updatedMarks.Name)
	for k, v := range updatedMarks.Marks {
		fmt.Fprintf(w, "%s = %s\n", k, v)
	}
	return nil

}

Python

def add_to_finding(organization_id, source_name, location_id, finding_name):
    """
    Adds security marks to a finding.
    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'
       finding_name: finding name to add security marks.

    Returns:
        Dict: returns the deleted security marks response.
    """
    from google.cloud import securitycenter_v2
    from google.protobuf import field_mask_pb2

    client = securitycenter_v2.SecurityCenterClient()
    finding_name = f"organizations/{organization_id}/sources/{source_name}/locations/{location_id}/findings/{finding_name}"
    finding_marks_name = f"{finding_name}/securityMarks"

    # Notice the suffix after "marks." in the field mask matches the keys
    # in marks.
    field_mask = field_mask_pb2.FieldMask(
        paths=["marks.finding_key_a", "marks.finding_key_b"]
    )
    marks = {"finding_key_a": "value_a", "finding_key_b": "value_b"}

    updated_marks = client.update_security_marks(
        request={
            "security_marks": {"name": finding_marks_name, "marks": marks},
            "update_mask": field_mask,
        }
    )
    return updated_marks, marks

Consultez la section Gérer les règles pour en savoir plus sur les marques d'éléments dédiées aux détecteurs de Security Health Analytics.

Supprimer des marques de sécurité sur des éléments

La suppression de marques de sécurité spécifiques s'effectue de la même manière pour l'ajout ou la mise à jour de ces dernières, en particulier pour appeler une mise à jour avec un masque de champ, mais sans aucune valeur correspondante. Dans l'exemple ci-dessous, les marques de sécurité dotées des clés key_a et key_b sont supprimées.

gcloud

gcloud scc assets update-marks ASSET_ID \
  --PARENT=PARENT_ID \
  --location=LOCATION \
  --update-mask=UPDATE_MASK
  • ASSET_ID: composant à mettre à jour.
  • PARENT: niveau de la hiérarchie des ressources où se trouve l'asset. Utilisez organization, folder ou project.
  • PARENT_ID: ID numérique de l'organisation, du dossier ou du projet parent, ou ID alphanumérique du projet parent.
  • LOCATION : si la résidence des données est activée, l'emplacement Security Command Center dans lequel supprimer une marque de sécurité d'un élément. Si la résidence des données n'est pas activée, utilisez la valeur global.
  • UPDATE_MASK: liste des champs de marque de sécurité à supprimer de l'élément, séparés par une virgule (par exemple, marks.key_a,marks.key_b).

Node.js

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

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

// Build the full resource path for the finding to update.
/*
 * TODO(developer): Update the following references for your own environment before running the sample.
 */
// const organizationId = 'YOUR_ORGANIZATION_ID';
// const sourceId = 'SOURCE_ID';
// const location = 'LOCATION_ID';
const findingName = `organizations/${organizationId}/sources/${sourceId}/locations/${location}/findings/${findingId}`;

// Construct the request to be sent by the client.
const updateSecurityMarksRequest = {
  securityMarks: {
    name: `${findingName}/securityMarks`,
    // Intentionally, not setting marks to delete them.
  },
  // Only delete marks for the following keys.
  updateMask: {paths: ['marks.key_a', 'marks.key_b']},
};

async function deleteSecurityMarks() {
  const [newMarks] = await client.updateSecurityMarks(
    updateSecurityMarksRequest
  );

  console.log('Updated marks: %j', newMarks);
}
deleteSecurityMarks();

Python

def delete_security_marks(organization_id, asset_name) -> Dict:
    """
    Removes security marks from an asset.
    Args:
       organization_id: organization_id is the numeric ID of the organization. e.g.:organization_id = "111122222444"
       asset_name: is the resource path for an asset that exists in SCC

    Returns:
        Dict: returns the deleted security marks response.
    """
    # Make sure they are there first
    add_to_asset(organization_id, asset_name)
    from google.cloud import securitycenter_v2
    from google.protobuf import field_mask_pb2

    # Create a new client.
    client = securitycenter_v2.SecurityCenterClient()
    asset_name = f"organizations/{organization_id}/assets/{asset_name}"
    marks_name = f"{asset_name}/securityMarks"

    field_mask = field_mask_pb2.FieldMask(paths=["marks.key_a", "marks.key_b"])

    updated_marks = client.update_security_marks(
        request={
            "security_marks": {
                "name": marks_name
                # Note, no marks specified, so the specified values in
                # the fields masks will be deleted.
            },
            "update_mask": field_mask,
        }
    )
    print(updated_marks)
    return updated_marks

Ajouter et supprimer des marques de sécurité dans la même requête

La technique pour ajouter et mettre à jour des marques de sécurité et pour supprimer des marques de sécurité peut être regroupée dans la même requête. Dans l'exemple ci-dessous, key_a est mise à jour alors que key_b est supprimée.

gcloud

gcloud scc assets update-marks ASSET_ID \
    --PARENT=PARENT_ID \
    --location=LOCATION \
    --update-mask=UPDATE_MASK
  • ASSET_ID: composant à mettre à jour.
  • PARENT: niveau de la hiérarchie des ressources où se trouve l'asset. Utilisez organization, folder ou project.
  • PARENT_ID: ID numérique de l'organisation, du dossier ou du projet parent, ou ID alphanumérique du projet parent.
  • LOCATION : si la résidence des données est activée, l'emplacement Security Command Center dans lequel mettre à jour et supprimer les marques de sécurité d'un élément. Si la résidence des données n'est pas activée, utilisez la valeur global.
  • SECURITY_MARKS: paires clé-valeur séparées par une virgule représentant les marques de sécurité que vous souhaitez mettre à jour (par exemple, key_a=value_a). Excluez les marques de sécurité que vous souhaitez supprimer.
  • UPDATE_MASK: liste des champs de marque de sécurité à mettre à jour ou à supprimer, séparés par une virgule (par exemple, marks.key_a,marks.key_b).

Node.js

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

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

// Build the full resource path for the finding to update.
/*
 * TODO(developer): Update the following references for your own environment before running the sample.
 */
// const organizationId = 'YOUR_ORGANIZATION_ID';
// const sourceId = 'SOURCE_ID';
const findingName = `organizations/${organizationId}/sources/${sourceId}/locations/${location}/findings/${findingId}`;

// Construct the request to be sent by the client.
const updateSecurityMarksRequest = {
  securityMarks: {
    name: `${findingName}/securityMarks`,
    marks: {key_a: 'new_value_for_a'},
  },
  // Set the update mask to specify which properties should be updated.
  // If empty, all mutable fields will be updated.
  // For more info on constructing field mask path, see the proto or:
  // https://cloud.google.com/java/docs/reference/protobuf/latest/com.google.protobuf.FieldMask.
  // Since no marks have been added, including "marks.key_b" in the update mask
  // will cause it to be deleted.
  updateMask: {paths: ['marks.key_a', 'marks.key_b']},
};

async function UpdateAndDeleteSecurityMarks() {
  const [newMarks] = await client.updateSecurityMarks(
    updateSecurityMarksRequest
  );

  console.log('New marks: %j', newMarks);
}
UpdateAndDeleteSecurityMarks();

Python

def delete_and_update_marks(organization_id, asset_name) -> Dict:
    """
    Updates and deletes security marks from an asset in the same call.
    Args:
       organization_id: organization_id is the numeric ID of the organization. e.g.:organization_id = "111122222444"
       asset_name: is the resource path for an asset that exists in SCC

    Returns:
        Dict: returns the deleted security marks response.

    """
    # Make sure they are there first
    add_to_asset(organization_id, asset_name)
    from google.cloud import securitycenter_v2
    from google.protobuf import field_mask_pb2

    client = securitycenter_v2.SecurityCenterClient()
    asset_name = f"organizations/{organization_id}/assets/{asset_name}"
    marks_name = f"{asset_name}/securityMarks"

    field_mask = field_mask_pb2.FieldMask(paths=["marks.key_a", "marks.key_b"])
    marks = {"key_a": "new_value_for_a"}

    updated_marks = client.update_security_marks(
        request={
            "security_marks": {"name": marks_name, "marks": marks},
            "update_mask": field_mask,
        }
    )
    print(updated_marks)
    return updated_marks

Ajouter des marques de sécurité aux résultats

L'ajout, la mise à jour et la suppression de marques de sécurité sur des résultats suivent le même processus que la mise à jour de marques de sécurité sur des éléments. La seule différence réside dans le nom de la ressource utilisée dans l'appel d'API. Au lieu d'utiliser une ressource d'élément, vous devez fournir un nom de ressource de résultat.

Par exemple, pour mettre à jour des marques de sécurité dans un résultat, utilisez le code suivant :

gcloud

gcloud scc findings update-marks \
    PARENT/PARENT_ID/sources/SOURCE_ID/locations/LOCATION/findings/FINDING_NAME \
    --security-marks=SECURITY_MARKS \
    --update-mask=UPDATE_MASK

Remplacez les éléments suivants :

  • PARENT: niveau de la hiérarchie des ressources où se trouve la découverte. Utilisez organizations, folders ou projects.
  • PARENT_ID: ID numérique de l'organisation, du dossier ou du projet parent, ou ID alphanumérique du projet parent.
  • SOURCE_ID : ID de la source
  • LOCATION : si la résidence des données est activée, l'emplacement Security Command Center dans lequel mettre à jour une marque de sécurité sur un résultat. Si la résidence des données n'est pas activée, utilisez la valeur global.
  • FINDING_NAME: résultat à mettre à jour.
  • SECURITY_MARKS: paires clé-valeur séparées par des virgules représentant des marques de sécurité et leurs valeurs (par exemple, key_a=value_a,key_b=value_b).
  • UPDATE_MASK: liste des champs de marque de sécurité à mettre à jour pour l'élément, séparés par une virgule (par exemple, marks.key_a,marks.key_b).

Java


import autovalue.shaded.com.google.common.collect.ImmutableMap;
import com.google.cloud.securitycenter.v2.FindingName;
import com.google.cloud.securitycenter.v2.SecurityCenterClient;
import com.google.cloud.securitycenter.v2.SecurityMarks;
import com.google.cloud.securitycenter.v2.UpdateSecurityMarksRequest;
import com.google.protobuf.FieldMask;
import java.io.IOException;

public class AddMarkToFinding {

  public static void main(String[] args) throws IOException {
    // TODO: Replace the sample resource name
    // organizationId: Google Cloud Organization id.
    String organizationId = "{google-cloud-organization-id}";

    // Specify the source-id.
    String sourceId = "{source-id}";

    // Specify the finding-id.
    String findingId = "{finding-id}";

    // Specify the location.
    String location = "global";

    addMarksToFinding(organizationId, sourceId, location, findingId);
  }

  // Demonstrates adding security marks to findings.
  // To add or change security marks, you must have an IAM role that includes permission:
  // Finding marks: Finding Security Marks Writer, securitycenter.findingSecurityMarksWriter
  public static SecurityMarks addMarksToFinding(String organizationId, String sourceId,
      String location, String findingId) 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.
    SecurityCenterClient client = SecurityCenterClient.create();

    // Start setting up a request to add security marks for a finding.
    ImmutableMap markMap = ImmutableMap.of("key_a", "value_a", "key_b", "value_b");

    // Instead of using the FindingName, a plain String can also be used. E.g.:
    // String findingName = String.format("organizations/%s/sources/%s/locations/%s/findings/%s",
    // organizationId, sourceId, location, findingId);
    FindingName findingName = FindingName
        .ofOrganizationSourceLocationFindingName(organizationId, sourceId, location, findingId);

    // Add security marks and field mask for security marks.
    SecurityMarks securityMarks = SecurityMarks.newBuilder()
        .setName(findingName + "/securityMarks")
        .putAllMarks(markMap)
        .build();

    // Set the update mask to specify which properties should be updated.
    // If empty, all mutable fields will be updated.
    // For more info on constructing field mask path, see the proto or:
    // https://cloud.google.com/java/docs/reference/protobuf/latest/com.google.protobuf.FieldMask
    FieldMask updateMask = FieldMask.newBuilder()
        .addPaths("marks.key_a")
        .addPaths("marks.key_b")
        .build();

    UpdateSecurityMarksRequest request = UpdateSecurityMarksRequest.newBuilder()
        .setSecurityMarks(securityMarks)
        .setUpdateMask(updateMask)
        .build();

    // Call the API.
    SecurityMarks response = client.updateSecurityMarks(request);

    System.out.println("Security Marks:" + response);
    return response;
  }
}

Node.js

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

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

// Build the full resource path for the finding to update.
/*
 * TODO(developer): Update the following references for your own environment before running the sample.
 */
// const organizationId = 'YOUR_ORGANIZATION_ID';
// const sourceId = 'SOURCE_ID';
const findingName = `organizations/${organizationId}/sources/${sourceId}/locations/${location}/findings/${findingId}`;

// Construct the request to be sent by the client.
const updateSecurityMarksRequest = {
  securityMarks: {
    name: `${findingName}/securityMarks`,
    marks: {key_a: 'value_a', key_b: 'value_b'},
  },
  // Only update the marks with these keys.
  updateMask: {paths: ['marks.key_a', 'marks.key_b']},
};

async function addFindingSecurityMarks() {
  const [newMarks] = await client.updateSecurityMarks(
    updateSecurityMarksRequest
  );

  console.log('New marks: %j', newMarks);
}
addFindingSecurityMarks();

Python

def add_to_finding(organization_id, source_name, location_id, finding_name):
    """
    Adds security marks to a finding.
    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'
       finding_name: finding name to add security marks.

    Returns:
        Dict: returns the deleted security marks response.
    """
    from google.cloud import securitycenter_v2
    from google.protobuf import field_mask_pb2

    client = securitycenter_v2.SecurityCenterClient()
    finding_name = f"organizations/{organization_id}/sources/{source_name}/locations/{location_id}/findings/{finding_name}"
    finding_marks_name = f"{finding_name}/securityMarks"

    # Notice the suffix after "marks." in the field mask matches the keys
    # in marks.
    field_mask = field_mask_pb2.FieldMask(
        paths=["marks.finding_key_a", "marks.finding_key_b"]
    )
    marks = {"finding_key_a": "value_a", "finding_key_b": "value_b"}

    updated_marks = client.update_security_marks(
        request={
            "security_marks": {"name": finding_marks_name, "marks": marks},
            "update_mask": field_mask,
        }
    )
    return updated_marks, marks

Les marques de sécurité sont traitées lors des analyses par lot (qui s'exécutent deux fois par jour), pas en temps réel. Un délai de 12 à 24 heures peut être nécessaire avant que les marques de sécurité ne soient traitées et que les règles d'application qui permettent de résoudre ou de rouvrir des résultats ne soient appliquées.

Répertorier des éléments avec des filtres de marque de sécurité

Une fois les marques de sécurité définies dans un élément, elles peuvent être utilisées dans l'argument de filtre de l'appel d'API ListAssets. Par exemple, pour interroger tous les éléments utilisant key_a = value_a, utilisez le code suivant :

gcloud

  # ORGANIZATION=12344321
  FILTER="security_marks.marks.key_a = \"value_a\""

  gcloud scc assets list $ORGANIZATION \
      --filter="$FILTER"

Go

import (
	"context"
	"fmt"
	"io"

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

// listAssetsWithMarks prints assets that have a mark of key_a equal to value_a
// to w for orgID.  orgID is the numeric Organization ID.
func listAssetsWithMarks(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.ListAssetsRequest{
		// Parent must be in one of the following formats:
		//		"organizations/{orgId}"
		//		"projects/{projectId}"
		//		"folders/{folderId}"
		Parent: fmt.Sprintf("organizations/%s", orgID),
		Filter: `security_marks.marks.key_a = "value_a"`,
	}

	it := client.ListAssets(ctx, req)
	for {
		result, err := it.Next()
		if err == iterator.Done {
			break
		}
		if err != nil {
			return fmt.Errorf("ListAssets: %w", err)
		}
		asset := result.Asset
		properties := asset.SecurityCenterProperties
		fmt.Fprintf(w, "Asset Name: %s, ", asset.Name)
		fmt.Fprintf(w, "Resource Name %s, ", properties.ResourceName)
		fmt.Fprintf(w, "Resource Type %s\n", properties.ResourceType)
	}
	return nil
}

Java

static ImmutableList<ListAssetsResult> listAssetsWithQueryMarks(
    OrganizationName organizationName) {
  try (SecurityCenterClient client = SecurityCenterClient.create()) {
    // Start setting up a request to list all assets filtered by a specific security mark.
    // Parent must be in one of the following formats:
    //    OrganizationName organizationName = OrganizationName.of("organization-id");
    //    ProjectName projectName = ProjectName.of("project-id");
    //    FolderName folderName = FolderName.of("folder-id");
    ListAssetsRequest request =
        ListAssetsRequest.newBuilder()
            .setParent(organizationName.toString())
            .setFilter("security_marks.marks.key_a = \"value_a\"")
            .build();

    // Call the API.
    ListAssetsPagedResponse response = client.listAssets(request);

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

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
 */
// parent: must be in one of the following formats:
//    `organizations/${organization_id}`
//    `projects/${project_id}`
//    `folders/${folder_id}`
const parent = `organizations/${organizationId}`;

// Call the API with automatic pagination.
async function listAssetsWithSecurityMarks() {
  const [response] = await client.listAssets({
    parent: parent,
    filter: 'security_marks.marks.key_a="value_a"',
  });
  let count = 0;
  Array.from(response).forEach(result =>
    console.log(
      `${++count} ${result.asset.name} ${
        result.asset.securityCenterProperties.resourceName
      }`
    )
  );
}

listAssetsWithSecurityMarks();

Python

from google.cloud import securitycenter

client = securitycenter.SecurityCenterClient()

# 'parent' must be in one of the following formats:
#   "organizations/{organization_id}"
#   "projects/{project_id}"
#   "folders/{folder_id}"
parent = f"organizations/{organization_id}"

marks_filter = 'security_marks.marks.key_a = "value_a"'
# Call the API and print results.
asset_iterator = client.list_assets(
    request={"parent": parent, "filter": marks_filter}
)
for i, asset_result in enumerate(asset_iterator):
    print(i, asset_result)

Répertorier des résultats avec des filtres de marque de sécurité

Une fois les marques de sécurité définies dans un résultat, elles peuvent être utilisées dans l'argument de filtre de l'appel d'API ListFindings. Par exemple, pour interroger tous les éléments utilisant key_a != value_a, utilisez le code suivant :

gcloud

gcloud scc findings list PARENT/PARENT_ID \
    --location=LOCATION \
    --source=SOURCE_ID \
    --filter=FILTER
  • PARENT: niveau de la hiérarchie des ressources où se trouve la découverte. Utilisez organizations, folders ou projects.
  • PARENT_ID: ID numérique de l'organisation, du dossier ou du projet parent, ou ID alphanumérique du projet parent.
  • LOCATION : si la résidence des données est activée, l'emplacement Security Command Center dans lequel lister les résultats. Si la résidence des données n'est pas activée, utilisez la valeur global.
  • SOURCE_ID : ID de la source
  • FILTER: filtre à appliquer aux résultats. Par exemple, pour exclure les résultats associés à la marque de sécurité key_a=value_a, utilisez "NOT security_marks.marks.key_a=\"value_a\"".

Go

import (
	"context"
	"fmt"
	"io"

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

// listFindingsWithMarks prints findings that don't have a security mark
// key_a equal to value_a to w.  sourceName is the full resource name
// of the source to search for findings under.
func listFindingsWithMarks(w io.Writer, sourceName string) error {
	// sourceName := "{parent}/sources/{sourceId}"
	// 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: `NOT security_marks.marks.key_a="value_a"`,
	}
	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.Finding;
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;
import java.util.ArrayList;
import java.util.List;

public class ListFindingMarksWithFilter {

  public static void main(String[] args) throws IOException {
    // TODO: Replace the sample resource name
    // organizationId: Google Cloud Organization id.
    String organizationId = "{google-cloud-organization-id}";

    // Specify the source-id.
    String sourceId = "{source-id}";

    // Specify the location.
    String location = "global";

    listFindingsWithQueryMarks(organizationId, sourceId, location);
  }

  // Demonstrates how to filter and list findings by security mark.
  public static List<Finding> listFindingsWithQueryMarks(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.
    SecurityCenterClient client = SecurityCenterClient.create();

    // Start setting up a request to list all findings filtered by a specific security mark.
    // 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);

    // Lists findings where the 'security_marks.marks.key_a' field does not equal 'value_a'.
    String filter = "NOT security_marks.marks.key_a=\"value_a\"";

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

    // Call the API.
    List<Finding> listFindings = new ArrayList<>();
    Iterable<ListFindingsResult> resultList = client.listFindings(request).iterateAll();
    resultList.forEach(result -> listFindings.add(result.getFinding()));

    for (Finding finding : listFindings) {
      System.out.println("List findings: " + finding);
    }
    return listFindings;
  }
}

Node.js

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

// Creates a new client.
const client = new SecurityCenterClient();
//  Build the full resource path for the source to search for findings.

// The source path supports mutliple formats:
// - `${parent}/sources/${sourceId}` without a location
// - `${parent}/sources/${sourceId}/locations/${location}` with a location
// where parent must be in one of the following formats:
// - `organizations/${organization_id}`
// - `folders/${folder_id}`
// - `projects/${project_id}`

/*
 * TODO(developer): Update the following references for your own environment before running the sample.
 */
// const organizationId = 'YOUR_ORGANIZATION_ID';
// const sourceId = 'SOURCE_ID';

const sourceName = `organizations/${organizationId}/sources/${sourceId}`;

// Construct the request to be sent by the client.
const listFindingsRequest = {
  // List findings across all sources.
  parent: sourceName,
  filter: 'NOT security_marks.marks.key_a="value_a"',
};

async function listFindingsWithSecurityMarks() {
  const [response] = await client.listFindings(listFindingsRequest);
  let count = 0;
  Array.from(response).forEach(result =>
    console.log(
      `${++count} ${result.finding.name} ${result.finding.resourceName}`
    )
  );
}
listFindingsWithSecurityMarks();

Python

def list_findings_with_security_marks(organization_id, source_name, location_id) -> int:
    """
    lists all filtered findings with security marks across an organization.
    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 filtered findings with security marks across the organization.
    """
    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}"
    # below filter is used to list active and unmuted findings without security marks acknowledgement as true.
    finding_result_iterator = client.list_findings(
        request={
            "parent": all_sources,
            "filter": 'NOT security_marks.marks.ACK="true" AND NOT mute="MUTED" AND state="ACTIVE"',
        }
    )
    # 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

Étape suivante