Este guia explica o uso da API Security Command Center para criar uma fonte para uma organização gerar descobertas. Quando você adiciona uma fonte, o Security Command Center cria as fontes apropriadas e atribui a elas as permissões relevantes.
Antes de começar
Antes de configurar uma fonte, faça o seguinte:
Como criar uma fonte
Neste exemplo, mostramos como criar uma origem com um nome de exibição e uma descrição específicos usados no painel do Security Command Center.
O servidor atribui automaticamente um ID à origem.
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 = "organizations/{org_id}".format(org_id=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("Created Source: {}".format(created.name))
Java
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"
securitycenterpb "google.golang.org/genproto/googleapis/cloud/securitycenter/v1"
)
// 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: %v", 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: %v", 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();
A fonte não fica visível no painel até gerar descobertas. Verifique se ela foi criada seguindo as instruções em Receber uma fonte específica.
Como atualizar uma fonte
Você pode atualizar o nome de exibição e a descrição de uma fonte depois que ela é criada. Você também pode usar uma máscara de campo para atualizar apenas um campo. O exemplo abaixo usa uma máscara de campo para atualizar apenas o nome de exibição, deixando a descrição inalterada.
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("Updated Source: {}".format(updated))
Java
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"
securitycenterpb "google.golang.org/genproto/googleapis/cloud/securitycenter/v1"
"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: %v", 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: %v", 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();
Como definir políticas do IAM em uma fonte
Depois de criar uma fonte, atualize as políticas de gerenciamento de identidade e acesso (IAM, na sigla em inglês) para permitir
Python
from google.cloud import securitycenter
from google.iam.v1 import policy_pb2
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"
# Get the old policy so we can do an incremental update.
old_policy = client.get_iam_policy(request={"resource": source_name})
print("Old Policy: {}".format(old_policy))
# Setup a new IAM binding.
binding = policy_pb2.Binding()
binding.role = "roles/securitycenter.findingsEditor"
# user_email is an e-mail address known to Cloud IAM (e.g. a gmail address).
# user_mail = user@somedomain.com
binding.members.append("user:{}".format(user_email))
# Setting the e-tag avoids over-write existing policy
updated = client.set_iam_policy(
request={
"resource": source_name,
"policy": {"etag": old_policy.etag, "bindings": [binding]},
}
)
print("Updated Policy: {}".format(updated))
Java
static Policy setIamPolicySource(SourceName sourceName, String userEmail) {
try (SecurityCenterClient client = SecurityCenterClient.create()) {
// userEmail = "someuser@domain.com"
// Set up IAM Policy for the user userMail to use the role findingsEditor.
// The user must be a valid google account.
Policy oldPolicy = client.getIamPolicy(sourceName.toString());
Binding bindings =
Binding.newBuilder()
.setRole("roles/securitycenter.findingsEditor")
.addMembers("user:" + userEmail)
.build();
Policy policy = oldPolicy.toBuilder().addBindings(bindings).build();
// Start setting up a request to set IAM policy for a source.
// SourceName sourceName = SourceName.of("123234324", "423432321");
SetIamPolicyRequest.Builder request =
SetIamPolicyRequest.newBuilder().setPolicy(policy).setResource(sourceName.toString());
// Call the API.
Policy response = client.setIamPolicy(request.build());
System.out.println("Policy: " + 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"
iam "google.golang.org/genproto/googleapis/iam/v1"
)
// setSourceIamPolicy grants user roles/securitycenter.findingsEditor permision
// for a source. sourceName is the full resource name of the source to be
// updated. user is an email address that IAM can grant permissions to.
func setSourceIamPolicy(w io.Writer, sourceName string, user string) error {
// sourceName := "organizations/111122222444/sources/1234"
// user := "someuser@some_domain.com
// 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.
// Retrieve the existing policy so we can update only a specific
// field.
existing, err := client.GetIamPolicy(ctx, &iam.GetIamPolicyRequest{
Resource: sourceName,
})
if err != nil {
return fmt.Errorf("GetIamPolicy(%s): %v", sourceName, err)
}
req := &iam.SetIamPolicyRequest{
Resource: sourceName,
Policy: &iam.Policy{
// Enables partial update of existing policy
Etag: existing.Etag,
Bindings: []*iam.Binding{{
Role: "roles/securitycenter.findingsEditor",
// New IAM Binding for the user.
Members: []string{fmt.Sprintf("user:%s", user)},
},
},
},
}
policy, err := client.SetIamPolicy(ctx, req)
if err != nil {
return fmt.Errorf("SetIamPolicy(%s, %v): %v", sourceName, req.Policy, err)
}
fmt.Fprint(w, "Bindings:\n")
for _, binding := range policy.Bindings {
for _, member := range binding.Members {
fmt.Fprintf(w, "Principal: %s Role: %s\n", member, binding.Role)
}
}
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();
async function setSourceIamPolicy() {
// sourceName is the full resource name of the source to be
// updated.
// user is an email address that IAM can grant permissions to.
/*
* TODO(developer): Uncomment the following lines
*/
// const sourceName = "organizations/111122222444/sources/1234";
// const user = "someuser@domain.com";
const [existingPolicy] = await client.getIamPolicy({
resource: sourceName,
});
const [updatedPolicy] = await client.setIamPolicy({
resource: sourceName,
policy: {
// Enables partial update of existing policy
etag: existingPolicy.etag,
bindings: [
{
role: 'roles/securitycenter.findingsEditor',
// New IAM Binding for the user.
members: [`user:${user}`],
},
],
},
});
console.log('Updated policy: %j', updatedPolicy);
}
setSourceIamPolicy();
Receber uma fonte específica
Verifique se uma origem foi criada ou atualizada corretamente. Para isso, consulte o Security Command Center com o nome do recurso absoluto da origem:
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
Para mais exemplos, execute:
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("Source: {}".format(source))
Java
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"
securitycenterpb "google.golang.org/genproto/googleapis/cloud/securitycenter/v1"
)
// 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: %v", 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: %v", 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();
Como listar fontes
O Security Command Center permite que você liste uma fonte específica e liste todas as fontes atualmente disponíveis em uma organização:
Python
from google.cloud import securitycenter
# Create a new 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)
# Call the API and print out each existing source.
for i, source in enumerate(client.list_sources(request={"parent": org_name})):
print(i, source)
Java
static ImmutableList<Source> listSources(OrganizationName organizationName) {
try (SecurityCenterClient client = SecurityCenterClient.create()) {
// Start setting up a request to list sources in an organization.
// OrganizationName organizationName = OrganizationName.of(/*organizationId=*/"123234324");
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"
"google.golang.org/api/iterator"
securitycenterpb "google.golang.org/genproto/googleapis/cloud/securitycenter/v1"
)
// 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: %v", err)
}
defer client.Close() // Closing the client safely cleans up background resources.
req := &securitycenterpb.ListSourcesRequest{
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: %v", 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
*/
// const organizaionId = "111122222444";
const orgName = client.organizationPath(organizationId);
// Call the API with automatic pagination.
async function listSources() {
const [response] = await client.listSources({parent: orgName});
let count = 0;
console.log('Sources:');
Array.from(response).forEach(source =>
console.log('%d %j', ++count, source)
);
}
listSources();
Receber políticas de IAM
Para verificar se as políticas de IAM apropriadas foram aplicadas a uma fonte, acesse os dados atuais da política de IAM do Security Command Center:
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"
# Get the old policy so we can do an incremental update.
policy = client.get_iam_policy(request={"resource": source_name})
print("Policy: {}".format(policy))
Java
static Policy getIamPolicySource(SourceName sourceName) {
try (SecurityCenterClient client = SecurityCenterClient.create()) {
// Start setting up a request to get IAM policy for a source.
// SourceName sourceName = SourceName.of(/*organization=*/"123234324",/*source=*/
// "423432321");
GetIamPolicyRequest request =
GetIamPolicyRequest.newBuilder().setResource(sourceName.toString()).build();
// Call the API.
Policy response = client.getIamPolicy(request);
System.out.println("Policy: " + 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"
iam "google.golang.org/genproto/googleapis/iam/v1"
)
// getSourceIamPolicy prints the policy for sourceName to w and return it.
// sourceName is the full resource name of the source with the policy of interest.
func getSourceIamPolicy(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: %v", err)
}
defer client.Close() // Closing the client safely cleans up background resources.
req := &iam.GetIamPolicyRequest{
Resource: sourceName,
}
policy, err := client.GetIamPolicy(ctx, req)
if err != nil {
return fmt.Errorf("GetIamPolicy(%s): %v", sourceName, err)
}
fmt.Fprintf(w, "Policy: %v", policy)
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();
async function getSourceIamPolicy() {
// sourceName is the full resource name to retrieve the policy for.
/*
* TODO(developer): Uncomment the following lines
*/
// const sourceName = "organizations/111122222444/sources/1234";
const [existingPolicy] = await client.getIamPolicy({
resource: sourceName,
});
console.log('Current policy: %j', existingPolicy);
}
getSourceIamPolicy();