Security Command Center API를 사용하여 보안 소스 관리

이 가이드에서는 Security Command Center API를 사용하여 발견 항목을 생성하는 소스를 만드는 방법을 설명합니다. 소스를 추가하면 Security Command Center는 적절한 소스를 만들어 관련 권한을 할당합니다.

Security Command Center의 IAM 역할은 조직, 폴더, 프로젝트 수준에서 부여할 수 있습니다. 발견 항목, 애셋, 보안 소스를 보거나 수정하거나 만들거나 업데이트할 수 있는 기능은 액세스 권한이 부여된 수준에 따라 다릅니다. Security Command Center 역할에 대해 자세히 알아보려면 액세스 제어를 참조하세요.

시작하기 전에

소스를 설정하기 전에 Security Command Center API로 인증해야 합니다.

소스 만들기

이 예시에서는 Security Command Center에 사용되는 특정 표시 이름과 설명이 있는 소스를 만드는 방법을 보여줍니다.

서버가 자동으로 ID를 소스에 할당합니다.

Python

from google.cloud import securitycenter

client = securitycenter.SecurityCenterClient()
# organization_id is the numeric ID of the organization. e.g.:
# organization_id = "111122222444"
org_name = f"organizations/{organization_id}"

created = client.create_source(
    request={
        "parent": org_name,
        "source": {
            "display_name": "Customized Display Name",
            "description": "A new custom source that does X",
        },
    }
)
print(f"Created Source: {created.name}")

자바

static Source createSource(OrganizationName organizationName) {
  try (SecurityCenterClient client = SecurityCenterClient.create()) {
    // Start setting up a request to create a source in an organization.
    // OrganizationName organizationName = OrganizationName.of(/*organizationId=*/"123234324");
    Source source =
        Source.newBuilder()
            .setDisplayName("Customized Display Name")
            .setDescription("A new custom source that does X")
            .build();

    CreateSourceRequest.Builder request =
        CreateSourceRequest.newBuilder().setParent(organizationName.toString()).setSource(source);

    // Call the API.
    Source response = client.createSource(request.build());

    System.out.println("Created Source: " + response);
    return response;
  } catch (IOException e) {
    throw new RuntimeException("Couldn't create client.", e);
  }
}

Go

import (
	"context"
	"fmt"
	"io"

	securitycenter "cloud.google.com/go/securitycenter/apiv1"
	"cloud.google.com/go/securitycenter/apiv1/securitycenterpb"
)

// createSource creates a new source for organization orgID. orgID is
// the numeric identifier of the organization
func createSource(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.CreateSourceRequest{
		Source: &securitycenterpb.Source{
			DisplayName: "Customized Display Name",
			Description: "A new custom source that does X",
		},
		Parent: fmt.Sprintf("organizations/%s", orgID),
	}
	source, err := client.CreateSource(ctx, req)
	if err != nil {
		return fmt.Errorf("CreateSource: %w", err)
	}

	fmt.Fprintf(w, "New source created: %s\n", source.Name)
	fmt.Fprintf(w, "Display Name: %s\n", source.DisplayName)
	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 numeric organization identifier.
/*
 * TODO(developer): Uncomment the following lines
 */
// const organizationId = "1234567777";
async function createSource() {
  const [source] = await client.createSource({
    source: {
      displayName: 'Customized Display Name',
      description: 'A new custom source that does X',
    },
    parent: client.organizationPath(organizationId),
  });
  console.log('New Source: %j', source);
}
createSource();

API

API에서 organizations.sources.create 메서드에 요청을 수행합니다. 요청 본문에 소스의 인스턴스가 포함됩니다.

  POST https://securitycenter.googleapis.com/API_VERSION/organizations/ORGANIZATION_ID/sources -d

  {
    "name": "SOURCE_NAME",
    "description": "SOURCE_DESCRIPTION",
    "displayName": "DISPLAY_NAME"
  }

다음을 바꿉니다.

  • API_VERSION: 타겟이 되는 API 버전입니다.
  • ORGANIZATION_ID: 조직 ID입니다.
  • SOURCE_NAME: 소스 이름입니다.
  • SOURCE_DESCRIPTION: 소스에 대한 설명입니다(최대 1,024자).
  • DISPLAY_NAME: 소스의 표시 이름입니다(1~64자).

소스는 발견 항목이 생성될 때까지 Security Command Center 콘솔에 표시되지 않습니다. 특정 소스 가져오기의 안내에 따라 발견 항목이 생성되었는지 확인할 수 있습니다.

소스 업데이트

소스가 생성된 후 소스의 표시 이름 및 설명을 업데이트할 수 있습니다. 필드 마스크를 사용하여 하나의 필드만 업데이트할 수도 있습니다. 아래 예시에서는 필드 마스크를 사용하여 표시 이름만 업데이트하고 설명은 변경하지 않습니다.

Python

from google.cloud import securitycenter
from google.protobuf import field_mask_pb2

client = securitycenter.SecurityCenterClient()

# Field mask to only update the display name.
field_mask = field_mask_pb2.FieldMask(paths=["display_name"])

# '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"
updated = client.update_source(
    request={
        "source": {"name": source_name, "display_name": "Updated Display Name"},
        "update_mask": field_mask,
    }
)
print(f"Updated Source: {updated}")

자바

static Source updateSource(SourceName sourceName) {
  try (SecurityCenterClient client = SecurityCenterClient.create()) {
    // Start setting up a request to update a source.
    // SourceName sourceName = SourceName.of(/*organization=*/"123234324",/*source=*/
    // "423432321");
    Source source =
        Source.newBuilder()
            .setDisplayName("Updated Display Name")
            .setName(sourceName.toString())
            .build();
    FieldMask updateMask = FieldMask.newBuilder().addPaths("display_name").build();

    UpdateSourceRequest.Builder request =
        UpdateSourceRequest.newBuilder().setSource(source).setUpdateMask(updateMask);

    // Call the API.
    Source response = client.updateSource(request.build());

    System.out.println("Updated Source: " + response);
    return response;
  } catch (IOException e) {
    throw new RuntimeException("Couldn't create client.", e);
  }
}

Go

import (
	"context"
	"fmt"
	"io"

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

// updateSource changes a sources display name to "New Display Name" for a
// specific source. sourceName is the full resource name of the source to be
// updated.
func updateSource(w io.Writer, sourceName string) error {
	// sourceName := "organizations/111122222444/sources/1234"
	// 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.UpdateSourceRequest{
		Source: &securitycenterpb.Source{
			Name:        sourceName,
			DisplayName: "New Display Name",
		},
		// Only update the display name field (if not set all mutable
		// fields of the source will be updated.
		UpdateMask: &field_mask.FieldMask{
			Paths: []string{"display_name"},
		},
	}
	source, err := client.UpdateSource(ctx, req)
	if err != nil {
		return fmt.Errorf("UpdateSource: %w", err)
	}
	fmt.Fprintf(w, "Source Name: %s, ", source.Name)
	fmt.Fprintf(w, "Display name: %s, ", source.DisplayName)
	fmt.Fprintf(w, "Description: %s\n", source.Description)

	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 to the update target.
/*
 * TODO(developer): Uncomment the following lines
 */
// const sourceName = "organizations/111122222444/sources/1234";
async function updateSource() {
  const [source] = await client.updateSource({
    source: {
      name: sourceName,
      displayName: 'New Display Name',
    },
    // Only update the display name field (if not set all mutable
    // fields of the source will be updated.
    updateMask: {paths: ['display_name']},
  });
  console.log('Updated source: %j', source);
}

updateSource();

API

API에서 organizations.sources.patch 메서드에 요청을 수행합니다. 요청 본문에 소스의 인스턴스가 포함됩니다.

  PATCH https://securitycenter.googleapis.com/API_VERSION/organizations/ORGANIZATION_ID/sources/SOURCE_ID?updateMask=displayName -d

  {
    "description": "SOURCE_DESCRIPTION",
    "displayName": "DISPLAY_NAME",
  }

다음을 바꿉니다.

  • API_VERSION: 타겟이 되는 API 버전입니다.
  • ORGANIZATION_ID: 조직 ID입니다.
  • SOURCE_ID: 소스 ID입니다. 소스 ID 가져오기에 대한 안내는 소스 ID 가져오기를 참조하세요.
  • SOURCE_DESCRIPTION: 소스에 대한 설명입니다(최대 1,024자).
  • DISPLAY_NAME: 소스의 표시 이름입니다(1~64자).

특정 소스 가져오기

소스의 절대적 리소스 이름으로 Security Command Center를 쿼리하여 소스가 적절하게 생성 또는 업데이트되었는지 확인합니다.

gcloud

  # Note: For GCloud you can use either full resource name or just ID Flags.
  # In this example, we are using ID Flags.
  # ORGANIZATION_ID=12344321
  # SOURCE_ID=43211234

  gcloud scc sources describe $ORGANIZATION_ID --source=$SOURCE_ID

더 많은 예시를 보려면 다음을 실행하세요.

  gcloud scc sources describe --help

Python

from google.cloud import securitycenter

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"
source = client.get_source(request={"name": source_name})

print(f"Source: {source}")

자바

static Source getSource(SourceName sourceName) {
  try (SecurityCenterClient client = SecurityCenterClient.create()) {
    // Start setting up a request to get a source.
    // SourceName sourceName = SourceName.of(/*organization=*/"123234324",/*source=*/
    // "423432321");
    GetSourceRequest.Builder request =
        GetSourceRequest.newBuilder().setName(sourceName.toString());

    // Call the API.
    Source response = client.getSource(request.build());

    System.out.println("Source: " + response);
    return response;
  } catch (IOException e) {
    throw new RuntimeException("Couldn't create client.", e);
  }
}

Go

import (
	"context"
	"fmt"
	"io"

	securitycenter "cloud.google.com/go/securitycenter/apiv1"
	"cloud.google.com/go/securitycenter/apiv1/securitycenterpb"
)

// getSource retrieves a source by its resource name and print it to w.
// sourceName is the full resource name of the source to be updated.
func getSource(w io.Writer, sourceName string) error {
	// sourceName := "organizations/111122222444/sources/1234"
	// 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.GetSourceRequest{
		Name: sourceName,
	}
	source, err := client.GetSource(ctx, req)
	if err != nil {
		return fmt.Errorf("GetSource: %w", err)
	}
	fmt.Fprintf(w, "Source: %v\n", source.Name)
	fmt.Fprintf(w, "Display Name: %v\n", source.DisplayName)
	fmt.Fprintf(w, "Description: %v\n", source.Description)
	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 name of the source to be retrieved.
/*
 * TODO(developer): Uncomment the following lines
 */
// const sourceName = "organizations/111122222444/sources/1234";
async function getSource() {
  const [source] = await client.getSource({name: sourceName});
  console.log('Source: %j', source);
}

getSource();

API

API에서 organizations.sources.get 메서드에 요청을 수행합니다. 요청 본문이 비어 있습니다.

  GET https://securitycenter.googleapis.com/API_VERSION/organizations/ORGANIZATION_ID/sources/SOURCE_ID

다음을 바꿉니다.

  • API_VERSION: 타겟이 되는 API 버전입니다.
  • ORGANIZATION_ID: 조직 ID입니다.
  • SOURCE_ID: 소스 ID입니다.

소스 나열

Security Command Center를 사용하면 특정 소스를 나열하고 현재 조직에서 사용할 수 있는 모든 소스를 나열할 수 있습니다.

Python

from google.cloud import securitycenter

# Create a new client.
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}"

# Call the API and print out each existing source.
for i, source in enumerate(client.list_sources(request={"parent": parent})):
    print(i, source)

자바

static ImmutableList<Source> listSources(OrganizationName organizationName) {
  try (SecurityCenterClient client = SecurityCenterClient.create()) {
    // Start setting up a request to list sources in an organization, project, or folder.
    // 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");
    ListSourcesRequest.Builder request =
        ListSourcesRequest.newBuilder().setParent(organizationName.toString());

    // Call the API.
    ListSourcesPagedResponse response = client.listSources(request.build());

    // This creates one list for all sources.  If your organization has a large number of sources
    // this can cause out of memory issues.  You can process them batches by returning
    // the Iterable returned response.iterateAll() directly.
    ImmutableList<Source> results = ImmutableList.copyOf(response.iterateAll());
    System.out.println("Sources:");
    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"
	"cloud.google.com/go/securitycenter/apiv1/securitycenterpb"
	"google.golang.org/api/iterator"
)

// listSources prints all sources in  orgID to w.  orgID is the numeric
// identifier of the organization.
func listSources(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.ListSourcesRequest{
		// Parent must be in one of the following formats:
		//		"organizations/{orgId}"
		//		"projects/{projectId}"
		//		"folders/{folderId}"
		Parent: fmt.Sprintf("organizations/%s", orgID),
	}
	it := client.ListSources(ctx, req)
	for {
		source, err := it.Next()
		if err == iterator.Done {
			break
		}
		if err != nil {
			return fmt.Errorf("it.Next: %w", err)
		}
		fmt.Fprintf(w, "Source Name: %s, ", source.Name)
		fmt.Fprintf(w, "Display name: %s, ", source.DisplayName)
		fmt.Fprintf(w, "Description: %s\n", source.Description)
	}
	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
 */
// 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 listSources() {
  const [response] = await client.listSources({parent: parent});
  let count = 0;
  console.log('Sources:');
  Array.from(response).forEach(source =>
    console.log('%d %j', ++count, source)
  );
}

listSources();

API

API에서 organizations.sources.list 메서드에 요청을 수행합니다. 요청 본문이 비어 있습니다.

  GET https://securitycenter.googleapis.com/API_VERSION/organizations/ORGANIZATION_ID/sources

다음을 바꿉니다.

  • API_VERSION: 타겟이 되는 API 버전입니다.
  • ORGANIZATION_ID: 조직 ID입니다.

다음 단계

SDK를 사용하여 Security Command Center에 액세스에 대해 자세히 알아보기