Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions args.go
Original file line number Diff line number Diff line change
Expand Up @@ -661,6 +661,17 @@ const (
// ArgAlertPolicySlackURLs are the Slack URLs to send alerts to.
ArgAlertPolicySlackURLs = "slack-urls"

// Security Args

// ArgSecurityScanResources are the resources to scan.
ArgSecurityScanResources = "resources"
// ArgSecurityScanFindingSeverity filters findings by severity.
ArgSecurityScanFindingSeverity = "severity"
// ArgSecurityScanFindingType filters findings by type.
ArgSecurityScanFindingType = "type"
// ArgSecurityFindingUUID is the finding UUID for finding operations.
ArgSecurityFindingUUID = "finding-uuid"

// ArgTokenValidationServer is the server used to validate an OAuth token
ArgTokenValidationServer = "token-validation-server"

Expand Down
2 changes: 2 additions & 0 deletions commands/command_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ type CmdConfig struct {
GradientAI func() do.GradientAIService
Nfs func() do.NfsService
NfsActions func() do.NfsActionsService
Security func() do.SecurityService
}

// NewCmdConfig creates an instance of a CmdConfig.
Expand Down Expand Up @@ -152,6 +153,7 @@ func NewCmdConfig(ns string, dc doctl.Config, out io.Writer, args []string, init
c.GradientAI = func() do.GradientAIService { return do.NewGradientAIService(godoClient) }
c.Nfs = func() do.NfsService { return do.NewNfsService(godoClient) }
c.NfsActions = func() do.NfsActionsService { return do.NewNfsActionsService(godoClient) }
c.Security = func() do.SecurityService { return do.NewSecurityService(godoClient) }
return nil
},

Expand Down
3 changes: 3 additions & 0 deletions commands/commands_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,7 @@ type tcMocks struct {
gradientAI *domocks.MockGradientAIService
nfs *domocks.MockNfsService
nfsActions *domocks.MockNfsActionsService
security *domocks.MockSecurityService
}

func withTestClient(t *testing.T, tFn testFn) {
Expand Down Expand Up @@ -351,6 +352,7 @@ func withTestClient(t *testing.T, tFn testFn) {
gradientAI: domocks.NewMockGradientAIService(ctrl),
nfs: domocks.NewMockNfsService(ctrl),
nfsActions: domocks.NewMockNfsActionsService(ctrl),
security: domocks.NewMockSecurityService(ctrl),
}

testConfig := doctl.NewTestConfig()
Expand Down Expand Up @@ -416,6 +418,7 @@ func withTestClient(t *testing.T, tFn testFn) {
GradientAI: func() do.GradientAIService { return tm.gradientAI },
Nfs: func() do.NfsService { return tm.nfs },
NfsActions: func() do.NfsActionsService { return tm.nfsActions },
Security: func() do.SecurityService { return tm.security },
}

tFn(config, tm)
Expand Down
139 changes: 139 additions & 0 deletions commands/displayers/security.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
/*
Copyright 2026 The Doctl Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package displayers

import (
"io"

"github.com/digitalocean/doctl/do"
)

// A SecurityScan is the displayer for showing the results of a single CSPM
// scan.
type SecurityScan struct {
Scan do.Scan
}

var _ Displayable = &SecurityScan{}

func (s *SecurityScan) JSON(out io.Writer) error {
return writeJSON(s.Scan, out)
}

func (s *SecurityScan) Cols() []string {
return []string{"Rule ID", "Name", "Affected Resources", "Found At", "Severity"}
}

func (s *SecurityScan) ColMap() map[string]string {
return map[string]string{
"Rule ID": "Rule ID",
"Name": "Name",
"Affected Resources": "Affected Resources",
"Found At": "Found At",
"Severity": "Severity",
}
}

func (s *SecurityScan) KV() []map[string]any {
out := make([]map[string]any, 0, len(s.Scan.Findings))

for _, finding := range s.Scan.Findings {
o := map[string]any{
"Rule ID": finding.RuleUUID,
"Name": finding.Name,
"Affected Resources": finding.AffectedResourcesCount,
"Found At": finding.FoundAt,
"Severity": finding.Severity,
}
out = append(out, o)
}

return out
}

// SecurityScans is the displayer for showing the results of multiple CSPM
// scans.
type SecurityScans struct {
Scans do.Scans
}

var _ Displayable = &SecurityScans{}

func (s *SecurityScans) JSON(out io.Writer) error {
return writeJSON(s.Scans, out)
}

func (s *SecurityScans) Cols() []string {
return []string{"ID", "Status", "Created At"}
}

func (s *SecurityScans) ColMap() map[string]string {
return map[string]string{
"ID": "ID",
"Status": "Status",
"Created At": "Created At",
}
}

func (s *SecurityScans) KV() []map[string]any {
out := make([]map[string]any, 0, len(s.Scans))

for _, scan := range s.Scans {
o := map[string]any{
"ID": scan.ID,
"Status": scan.Status,
"Created At": scan.CreatedAt,
}
out = append(out, o)
}

return out
}

type SecurityAffectedResource struct {
AffectedResources do.AffectedResources
}

var _ Displayable = &SecurityAffectedResource{}

func (s *SecurityAffectedResource) JSON(out io.Writer) error {
return writeJSON(s.AffectedResources, out)
}

func (s *SecurityAffectedResource) Cols() []string {
return []string{"URN", "Name", "Type"}
}

func (s *SecurityAffectedResource) ColMap() map[string]string {
return map[string]string{
"URN": "URN",
"Name": "Name",
"Type": "Type",
}
}

func (s *SecurityAffectedResource) KV() []map[string]any {
out := make([]map[string]any, 0, len(s.AffectedResources))

for _, resource := range s.AffectedResources {
o := map[string]any{
"URN": resource.URN,
"Name": resource.Name,
"Type": resource.Type,
}
out = append(out, o)
}

return out
}
1 change: 1 addition & 0 deletions commands/doit.go
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,7 @@ func addCommands() {
DoitCmd.AddCommand(Spaces())
DoitCmd.AddCommand(GradientAI())
DoitCmd.AddCommand(Nfs())
DoitCmd.AddCommand(Security())
}

func computeCmd() *Command {
Expand Down
Loading
Loading