import (
"context"
"fmt"
"io"
"time"
securitycenter "cloud.google.com/go/securitycenter/apiv1"
"cloud.google.com/go/securitycenter/apiv1/securitycenterpb"
"github.com/golang/protobuf/ptypes"
structpb "github.com/golang/protobuf/ptypes/struct"
"google.golang.org/genproto/protobuf/field_mask"
)
// updateFindingSourceProperties demonstrates how to update a security finding
// in CSCC. findingName is the full resource name of the finding to update.
func updateFindingSourceProperties(w io.Writer, findingName string) error {
// findingName := "organizations/111122222444/sources/1234/findings/findingid"
// 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.
// Use now as the eventTime for the security finding.
eventTime, err := ptypes.TimestampProto(time.Now())
if err != nil {
return fmt.Errorf("TimestampProto: %w", err)
}
req := &securitycenterpb.UpdateFindingRequest{
Finding: &securitycenterpb.Finding{
Name: findingName,
EventTime: eventTime,
SourceProperties: map[string]*structpb.Value{
"s_value": {
Kind: &structpb.Value_StringValue{StringValue: "new_string_example"},
},
},
},
// Needed to only update the specific source property s_value
// and EventTime. EventTime is a required field.
UpdateMask: &field_mask.FieldMask{
Paths: []string{"event_time", "source_properties.s_value"},
},
}
finding, err := client.UpdateFinding(ctx, req)
if err != nil {
return fmt.Errorf("UpdateFinding: %w", err)
}
fmt.Fprintf(w, "Finding updated: %s\n", finding.Name)
fmt.Fprintf(w, "Finding state: %v\n", finding.State)
fmt.Fprintf(w, "Event time (Epoch Seconds): %d\n", eventTime.Seconds)
fmt.Fprintf(w, "Source Properties:\n")
for k, v := range finding.SourceProperties {
fmt.Fprintf(w, "%s = %v\n", k, v)
}
return nil
}