From 6d1aa6b0136ab3f3f4d054301d66348731fbfce3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Feb 2026 15:31:43 +0000 Subject: [PATCH] build(deps): bump github.com/digitalocean/godo from 1.172.0 to 1.175.0 Bumps [github.com/digitalocean/godo](https://github.com/digitalocean/godo) from 1.172.0 to 1.175.0. - [Release notes](https://github.com/digitalocean/godo/releases) - [Changelog](https://github.com/digitalocean/godo/blob/main/CHANGELOG.md) - [Commits](https://github.com/digitalocean/godo/compare/v1.172.0...v1.175.0) --- updated-dependencies: - dependency-name: github.com/digitalocean/godo dependency-version: 1.175.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 +- .../github.com/digitalocean/godo/CHANGELOG.md | 17 ++ .../github.com/digitalocean/godo/apps.gen.go | 33 ++- .../digitalocean/godo/apps_accessors.go | 40 +++ .../github.com/digitalocean/godo/databases.go | 21 +- vendor/github.com/digitalocean/godo/godo.go | 4 +- .../digitalocean/godo/gradientai.go | 2 +- vendor/github.com/digitalocean/godo/nfs.go | 32 +-- .../digitalocean/godo/nfs_actions.go | 29 ++- .../github.com/digitalocean/godo/security.go | 246 ++++++++++++++++++ vendor/modules.txt | 2 +- 12 files changed, 383 insertions(+), 49 deletions(-) create mode 100644 vendor/github.com/digitalocean/godo/security.go diff --git a/go.mod b/go.mod index 6708a892c..529511415 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.25.0 require ( github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc - github.com/digitalocean/godo v1.172.0 + github.com/digitalocean/godo v1.175.0 github.com/go-logr/logr v1.4.3 github.com/google/go-cmp v0.7.0 github.com/google/uuid v1.6.0 diff --git a/go.sum b/go.sum index 2c839674b..c05a3a07f 100644 --- a/go.sum +++ b/go.sum @@ -27,8 +27,8 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/digitalocean/godo v1.172.0 h1:7AYPfmCUlScyoQJF+3rVw17HR3V1+ogf2qmf2SND/DI= -github.com/digitalocean/godo v1.172.0/go.mod h1:xQsWpVCCbkDrWisHA72hPzPlnC+4W5w/McZY5ij9uvU= +github.com/digitalocean/godo v1.175.0 h1:tpfwJFkBzpePxvvFazOn69TXctdxuFlOs7DMVXsI7oU= +github.com/digitalocean/godo v1.175.0/go.mod h1:xQsWpVCCbkDrWisHA72hPzPlnC+4W5w/McZY5ij9uvU= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/emicklei/go-restful/v3 v3.13.0 h1:C4Bl2xDndpU6nJ4bc1jXd+uTmYPVUwkD6bFY/oTyCes= diff --git a/vendor/github.com/digitalocean/godo/CHANGELOG.md b/vendor/github.com/digitalocean/godo/CHANGELOG.md index eb64c895b..41fd1e2aa 100644 --- a/vendor/github.com/digitalocean/godo/CHANGELOG.md +++ b/vendor/github.com/digitalocean/godo/CHANGELOG.md @@ -1,5 +1,22 @@ # Change Log +## [1.175.0] - 2026-02-12 + +- #952 - @bentranter - security: add cspm scanning functionality for public preview +- #951 - @v-amanjain-afk - Add performance tier in nfs model + +## [1.174.0] - 2026-02-09 + +- #946 - @blesswinsamuel - apps: Update app spec to support InactivitySleep configuration +- #949 - @lprasanth-nadiminti - Add DOSettings with ServiceCnames support for database clusters +- #945 - @v-amanjain-afk - switch performance tier of nfs share +- #947 - @ZachEddy - apps: Add secure header app spec field to godo + +## [1.173.0] - 2026-01-22 + +- #942 - @anup-deka - Fix data type +- #941 - @v-amanjain-afk - removed deprecated region from nfs api + ## [1.172.0] - 2026-01-13 - #932 - @fumblehool - APPS-12654: Add CancelJobInvocation API diff --git a/vendor/github.com/digitalocean/godo/apps.gen.go b/vendor/github.com/digitalocean/godo/apps.gen.go index 3a43c1ae0..148028cdf 100644 --- a/vendor/github.com/digitalocean/godo/apps.gen.go +++ b/vendor/github.com/digitalocean/godo/apps.gen.go @@ -319,7 +319,8 @@ type AppIngressSpec struct { LoadBalancer AppIngressSpecLoadBalancer `json:"load_balancer,omitempty"` LoadBalancerSize int64 `json:"load_balancer_size,omitempty"` // Rules for configuring HTTP ingress for component routes, CORS, rewrites, and redirects. - Rules []*AppIngressSpecRule `json:"rules,omitempty"` + Rules []*AppIngressSpecRule `json:"rules,omitempty"` + SecureHeader *AppSecureHeaderSpec `json:"secure_header,omitempty"` } // AppIngressSpecLoadBalancer the model 'AppIngressSpecLoadBalancer' @@ -376,6 +377,13 @@ type AppIngressSpecRuleStringMatch struct { Exact string `json:"exact,omitempty"` } +type AppSecureHeaderSpec struct { + // The name of the header to set. + Key string `json:"key,omitempty"` + // The value of the header to set. + Value string `json:"value,omitempty"` +} + // AppInstance struct for AppInstance type AppInstance struct { // The name of the component this instance belongs to. @@ -565,9 +573,11 @@ type AppServiceSpec struct { // A list of configured alerts which apply to the component. Alerts []*AppAlertSpec `json:"alerts,omitempty"` // A list of configured log forwarding destinations. - LogDestinations []*AppLogDestinationSpec `json:"log_destinations,omitempty"` - Termination *AppServiceSpecTermination `json:"termination,omitempty"` - LivenessHealthCheck *HealthCheckSpec `json:"liveness_health_check,omitempty"` + LogDestinations []*AppLogDestinationSpec `json:"log_destinations,omitempty"` + Termination *AppServiceSpecTermination `json:"termination,omitempty"` + // A configuration for putting the service to sleep after it has been inactive. Note: this is in Private Preview. + InactivitySleep *AppServiceSpecInactivitySleep `json:"inactivity_sleep,omitempty"` + LivenessHealthCheck *HealthCheckSpec `json:"liveness_health_check,omitempty"` } // AppServiceSpecHealthCheck struct for AppServiceSpecHealthCheck @@ -590,6 +600,13 @@ type AppServiceSpecHealthCheck struct { Port int64 `json:"port,omitempty"` } +// AppServiceSpecInactivitySleep struct for AppServiceSpecInactivitySleep +type AppServiceSpecInactivitySleep struct { + // The number of seconds to wait before putting the service to sleep after it has been inactive. Minimum 600, Maximum 86400. + AfterSeconds int32 `json:"after_seconds,omitempty"` + LoadingPage *InactivitySleepLoadingPage `json:"loading_page,omitempty"` +} + // AppServiceSpecTermination struct for AppServiceSpecTermination type AppServiceSpecTermination struct { // The number of seconds to wait between selecting a container instance for termination and issuing the TERM signal. Selecting a container instance for termination begins an asynchronous drain of new requests on upstream load-balancers. Default: 15 seconds, Minimum 1, Maximum 110. @@ -1320,6 +1337,14 @@ const ( ImageSourceSpecRegistryType_Ghcr ImageSourceSpecRegistryType = "GHCR" ) +// InactivitySleepLoadingPage struct for InactivitySleepLoadingPage +type InactivitySleepLoadingPage struct { + // Whether to show a loading page while the service is waking up from sleep. Defaults to false. If this is enabled and there is a request header `Accept` containing `text/html`, then the app will show a loading page with a 503 status code until the service is woken up. + Enabled bool `json:"enabled,omitempty"` + // A custom loading page to display when the service is woken up from sleep. If not provided, a default loading page will be shown. + CustomURL string `json:"custom_url,omitempty"` +} + // AppInstanceSize struct for AppInstanceSize type AppInstanceSize struct { Name string `json:"name,omitempty"` diff --git a/vendor/github.com/digitalocean/godo/apps_accessors.go b/vendor/github.com/digitalocean/godo/apps_accessors.go index 753f7222b..ec5b7a304 100644 --- a/vendor/github.com/digitalocean/godo/apps_accessors.go +++ b/vendor/github.com/digitalocean/godo/apps_accessors.go @@ -1869,6 +1869,14 @@ func (a *AppServiceSpec) GetImage() *ImageSourceSpec { return a.Image } +// GetInactivitySleep returns the InactivitySleep field. +func (a *AppServiceSpec) GetInactivitySleep() *AppServiceSpecInactivitySleep { + if a == nil { + return nil + } + return a.InactivitySleep +} + // GetInstanceCount returns the InstanceCount field. func (a *AppServiceSpec) GetInstanceCount() int64 { if a == nil { @@ -2021,6 +2029,22 @@ func (a *AppServiceSpecHealthCheck) GetTimeoutSeconds() int32 { return a.TimeoutSeconds } +// GetAfterSeconds returns the AfterSeconds field. +func (a *AppServiceSpecInactivitySleep) GetAfterSeconds() int32 { + if a == nil { + return 0 + } + return a.AfterSeconds +} + +// GetLoadingPage returns the LoadingPage field. +func (a *AppServiceSpecInactivitySleep) GetLoadingPage() *InactivitySleepLoadingPage { + if a == nil { + return nil + } + return a.LoadingPage +} + // GetDrainSeconds returns the DrainSeconds field. func (a *AppServiceSpecTermination) GetDrainSeconds() int32 { if a == nil { @@ -4069,6 +4093,22 @@ func (i *ImageSourceSpecDeployOnPush) GetEnabled() bool { return i.Enabled } +// GetCustomURL returns the CustomURL field. +func (i *InactivitySleepLoadingPage) GetCustomURL() string { + if i == nil { + return "" + } + return i.CustomURL +} + +// GetEnabled returns the Enabled field. +func (i *InactivitySleepLoadingPage) GetEnabled() bool { + if i == nil { + return false + } + return i.Enabled +} + // GetCompletedAt returns the CompletedAt field. func (j *JobInvocation) GetCompletedAt() time.Time { if j == nil { diff --git a/vendor/github.com/digitalocean/godo/databases.go b/vendor/github.com/digitalocean/godo/databases.go index 0fe799572..18711b873 100644 --- a/vendor/github.com/digitalocean/godo/databases.go +++ b/vendor/github.com/digitalocean/godo/databases.go @@ -237,6 +237,7 @@ type Database struct { ProjectID string `json:"project_id,omitempty"` StorageSizeMib uint64 `json:"storage_size_mib,omitempty"` MetricsEndpoints []*ServiceAddress `json:"metrics_endpoints,omitempty"` + DOSettings *DOSettings `json:"do_settings,omitempty"` } // DatabaseCA represents a database ca. @@ -263,6 +264,11 @@ type ServiceAddress struct { Port int `json:"port"` } +// DOSettings contains DigitalOcean-specific settings for a database cluster. +type DOSettings struct { + ServiceCnames []string `json:"service_cnames,omitempty"` +} + // DatabaseUser represents a user in the database type DatabaseUser struct { Name string `json:"name,omitempty"` @@ -347,6 +353,7 @@ type DatabaseCreateRequest struct { ProjectID string `json:"project_id"` StorageSizeMib uint64 `json:"storage_size_mib,omitempty"` Rules []*DatabaseCreateFirewallRule `json:"rules"` + DOSettings *DOSettings `json:"do_settings,omitempty"` } // DatabaseResizeRequest can be used to initiate a database resize operation. @@ -470,6 +477,7 @@ type DatabaseReplica struct { Tags []string `json:"tags,omitempty"` StorageSizeMib uint64 `json:"storage_size_mib,omitempty"` Size string `json:"size"` + DOSettings *DOSettings `json:"do_settings,omitempty"` } // DatabasePool represents a database connection pool @@ -527,12 +535,13 @@ type DatabaseCreateDBRequest struct { // DatabaseCreateReplicaRequest is used to create a new read-only replica type DatabaseCreateReplicaRequest struct { - Name string `json:"name"` - Region string `json:"region"` - Size string `json:"size"` - PrivateNetworkUUID string `json:"private_network_uuid"` - Tags []string `json:"tags,omitempty"` - StorageSizeMib uint64 `json:"storage_size_mib,omitempty"` + Name string `json:"name"` + Region string `json:"region"` + Size string `json:"size"` + PrivateNetworkUUID string `json:"private_network_uuid"` + Tags []string `json:"tags,omitempty"` + StorageSizeMib uint64 `json:"storage_size_mib,omitempty"` + DOSettings *DOSettings `json:"do_settings,omitempty"` } // DatabaseUpdateFirewallRulesRequest is used to set the firewall rules for a database diff --git a/vendor/github.com/digitalocean/godo/godo.go b/vendor/github.com/digitalocean/godo/godo.go index 9f69b8a11..c3fbd9d31 100644 --- a/vendor/github.com/digitalocean/godo/godo.go +++ b/vendor/github.com/digitalocean/godo/godo.go @@ -21,7 +21,7 @@ import ( ) const ( - libraryVersion = "1.172.0" + libraryVersion = "1.175.0" defaultBaseURL = "https://api.digitalocean.com/" userAgent = "godo/" + libraryVersion mediaType = "application/json" @@ -78,6 +78,7 @@ type Client struct { Kubernetes KubernetesService LoadBalancers LoadBalancersService Monitoring MonitoringService + Security SecurityService Nfs NfsService NfsActions NfsActionsService OneClick OneClickService @@ -306,6 +307,7 @@ func NewClient(httpClient *http.Client) *Client { c.Kubernetes = &KubernetesServiceOp{client: c} c.LoadBalancers = &LoadBalancersServiceOp{client: c} c.Monitoring = &MonitoringServiceOp{client: c} + c.Security = &SecurityServiceOp{client: c} c.Nfs = &NfsServiceOp{client: c} c.NfsActions = &NfsActionsServiceOp{client: c} c.VPCNATGateways = &VPCNATGatewaysServiceOp{client: c} diff --git a/vendor/github.com/digitalocean/godo/gradientai.go b/vendor/github.com/digitalocean/godo/gradientai.go index 8b0ee4da8..74207ff6f 100644 --- a/vendor/github.com/digitalocean/godo/gradientai.go +++ b/vendor/github.com/digitalocean/godo/gradientai.go @@ -371,7 +371,7 @@ type Workspace struct { Name string `json:"name,omitempty"` Description string `json:"description,omitempty"` CreatedByEmail string `json:"created_by_email,omitempty"` - CreatedBy uint64 `json:"created_by,omitempty"` + CreatedBy string `json:"created_by,omitempty"` CreatedAt *Timestamp `json:"created_at,omitempty"` UpdatedAt *Timestamp `json:"updated_at,omitempty"` DeletedAt *Timestamp `json:"deleted_at,omitempty"` diff --git a/vendor/github.com/digitalocean/godo/nfs.go b/vendor/github.com/digitalocean/godo/nfs.go index 1ef6aae92..da04bb19a 100644 --- a/vendor/github.com/digitalocean/godo/nfs.go +++ b/vendor/github.com/digitalocean/godo/nfs.go @@ -78,6 +78,8 @@ type Nfs struct { Host string `json:"host"` // MountPath is the path at which the share will be available MountPath string `json:"mount_path"` + //PerformanceTier is the performance tier of the NFS share + PerformanceTier string `json:"performance_tier"` } type NfsSnapshot struct { @@ -99,10 +101,11 @@ type NfsSnapshot struct { // NfsCreateRequest represents a request to create an NFS share. type NfsCreateRequest struct { - Name string `json:"name"` - SizeGib int `json:"size_gib"` - Region string `json:"region"` - VpcIDs []string `json:"vpc_ids,omitempty"` + Name string `json:"name"` + SizeGib int `json:"size_gib"` + Region string `json:"region"` + VpcIDs []string `json:"vpc_ids,omitempty"` + PerformanceTier string `json:"performance_tier,omitempty"` } // nfsRoot represents a response from the DigitalOcean API @@ -166,9 +169,6 @@ func (s *NfsServiceOp) Get(ctx context.Context, nfsShareId string, region string if nfsShareId == "" { return nil, nil, NewArgError("id", "cannot be empty") } - if region == "" { - return nil, nil, NewArgError("region", "cannot be empty") - } path := fmt.Sprintf("%s/%s", nfsBasePath, nfsShareId) @@ -194,10 +194,6 @@ func (s *NfsServiceOp) Get(ctx context.Context, nfsShareId string, region string // List returns a list of NFS shares. func (s *NfsServiceOp) List(ctx context.Context, opts *ListOptions, region string) ([]*Nfs, *Response, error) { - if region == "" { - return nil, nil, NewArgError("region", "cannot be empty") - } - path, err := addOptions(nfsBasePath, opts) if err != nil { return nil, nil, err @@ -235,10 +231,6 @@ func (s *NfsServiceOp) Delete(ctx context.Context, nfsShareId string, region str if nfsShareId == "" { return nil, NewArgError("id", "cannot be empty") } - if region == "" { - return nil, NewArgError("region", "cannot be empty") - } - path := fmt.Sprintf("%s/%s", nfsBasePath, nfsShareId) deleteOpts := &nfsOptions{Region: region} @@ -265,9 +257,6 @@ func (s *NfsServiceOp) GetSnapshot(ctx context.Context, nfsSnapshotID string, re if nfsSnapshotID == "" { return nil, nil, NewArgError("snapshotID", "cannot be empty") } - if region == "" { - return nil, nil, NewArgError("region", "cannot be empty") - } path := fmt.Sprintf("%s/%s", nfsSnapshotsBasePath, nfsSnapshotID) @@ -293,9 +282,6 @@ func (s *NfsServiceOp) GetSnapshot(ctx context.Context, nfsSnapshotID string, re // List returns a list of NFS snapshots. func (s *NfsServiceOp) ListSnapshots(ctx context.Context, opts *ListOptions, nfsShareId, region string) ([]*NfsSnapshot, *Response, error) { - if region == "" { - return nil, nil, NewArgError("region", "cannot be empty") - } path, err := addOptions(nfsSnapshotsBasePath, opts) if err != nil { @@ -334,10 +320,6 @@ func (s *NfsServiceOp) DeleteSnapshot(ctx context.Context, nfsSnapshotID string, if nfsSnapshotID == "" { return nil, NewArgError("snapshotID", "cannot be empty") } - if region == "" { - return nil, NewArgError("region", "cannot be empty") - } - path := fmt.Sprintf("%s/%s", nfsSnapshotsBasePath, nfsSnapshotID) deleteOpts := &nfsOptions{Region: region} diff --git a/vendor/github.com/digitalocean/godo/nfs_actions.go b/vendor/github.com/digitalocean/godo/nfs_actions.go index 7c68cca8e..c35d59625 100644 --- a/vendor/github.com/digitalocean/godo/nfs_actions.go +++ b/vendor/github.com/digitalocean/godo/nfs_actions.go @@ -14,6 +14,7 @@ type NfsActionsService interface { Snapshot(ctx context.Context, nfsShareId string, nfsSnapshotName string, region string) (*NfsAction, *Response, error) Attach(ctx context.Context, nfsShareId string, vpcID string, region string) (*NfsAction, *Response, error) Detach(ctx context.Context, nfsShareId string, vpcID string, region string) (*NfsAction, *Response, error) + SwitchPerformanceTier(ctx context.Context, nfsShareId string, tier string) (*NfsAction, *Response, error) } // NfsActionsServiceOp handles communication with the NFS action related @@ -69,11 +70,15 @@ type NfsDetachParams struct { VpcID string `json:"vpc_id"` } +// NfsSwitchPerformanceTierParams represents parameters to switch the performance tier of an NFS share. +type NfsSwitchPerformanceTierParams struct { + PerformanceTier string `json:"performance_tier"` +} + // Resize an NFS share func (s *NfsActionsServiceOp) Resize(ctx context.Context, nfsShareId string, size uint64, region string) (*NfsAction, *Response, error) { request := &NfsActionRequest{ - Type: "resize", - Region: region, + Type: "resize", Params: &NfsResizeParams{ SizeGib: size, }, @@ -85,8 +90,7 @@ func (s *NfsActionsServiceOp) Resize(ctx context.Context, nfsShareId string, siz // Snapshot an NFS share func (s *NfsActionsServiceOp) Snapshot(ctx context.Context, nfsShareId, nfsSnapshotName, region string) (*NfsAction, *Response, error) { request := &NfsActionRequest{ - Type: "snapshot", - Region: region, + Type: "snapshot", Params: &NfsSnapshotParams{ Name: nfsSnapshotName, }, @@ -98,8 +102,7 @@ func (s *NfsActionsServiceOp) Snapshot(ctx context.Context, nfsShareId, nfsSnaps // Attach an NFS share func (s *NfsActionsServiceOp) Attach(ctx context.Context, nfsShareId, vpcID, region string) (*NfsAction, *Response, error) { request := &NfsActionRequest{ - Type: "attach", - Region: region, + Type: "attach", Params: &NfsAttachParams{ VpcID: vpcID, }, @@ -111,8 +114,7 @@ func (s *NfsActionsServiceOp) Attach(ctx context.Context, nfsShareId, vpcID, reg // Detach an NFS share func (s *NfsActionsServiceOp) Detach(ctx context.Context, nfsShareId, vpcID, region string) (*NfsAction, *Response, error) { request := &NfsActionRequest{ - Type: "detach", - Region: region, + Type: "detach", Params: &NfsAttachParams{ VpcID: vpcID, }, @@ -121,6 +123,17 @@ func (s *NfsActionsServiceOp) Detach(ctx context.Context, nfsShareId, vpcID, reg return s.doAction(ctx, nfsShareId, request) } +// Switch performance tier of an NFS share +func (s *NfsActionsServiceOp) SwitchPerformanceTier(ctx context.Context, nfsShareId string, tier string) (*NfsAction, *Response, error) { + request := &NfsActionRequest{ + Type: "switch_performance_tier", + Params: &NfsSwitchPerformanceTierParams{ + PerformanceTier: tier, + }, + } + + return s.doAction(ctx, nfsShareId, request) +} func (s *NfsActionsServiceOp) doAction(ctx context.Context, nfsShareId string, request *NfsActionRequest) (*NfsAction, *Response, error) { if request == nil { return nil, nil, NewArgError("request", "request can't be nil") diff --git a/vendor/github.com/digitalocean/godo/security.go b/vendor/github.com/digitalocean/godo/security.go new file mode 100644 index 000000000..47da7b983 --- /dev/null +++ b/vendor/github.com/digitalocean/godo/security.go @@ -0,0 +1,246 @@ +package godo + +import ( + "context" + "fmt" + "net/http" +) + +const ( + securityScansBasePath = "v2/security/scans" + securityScansFindingsPath = "findings" + securityAffectedResources = "affected_resources" +) + +// SecurityService is an interface for interacting with the CSPM endpoints of +// the DigitalOcean API. +type SecurityService interface { + CreateScan(context.Context, *CreateScanRequest) (*Scan, *Response, error) + ListScans(context.Context, *ListOptions) ([]*Scan, *Response, error) + GetScan(context.Context, string, *ScanFindingsOptions) (*Scan, *Response, error) + GetLatestScan(context.Context, *ScanFindingsOptions) (*Scan, *Response, error) + ListFindingAffectedResources(context.Context, *ListFindingAffectedResourcesRequest, *ListOptions) ([]*AffectedResource, *Response, error) +} + +// SecurityServiceOp handles communication with security scan related methods of the DigitalOcean API. +type SecurityServiceOp struct { + client *Client +} + +var _ SecurityService = &SecurityServiceOp{} + +// CreateScanRequest contains the request payload to create a scan. +type CreateScanRequest struct { + Resources []string `json:"resources,omitempty"` +} + +// ScanFindingsOptions contains the query parameters for paginating and +// filtering scan findings. +type ScanFindingsOptions struct { + ListOptions + Type string `url:"type,omitempty"` + Severity string `url:"severity,omitempty"` +} + +// Scan represents a CSPM scan. +type Scan struct { + ID string `json:"id,omitempty"` + Status string `json:"status,omitempty"` + CreatedAt string `json:"created_at,omitempty"` + Findings []*ScanFinding `json:"findings,omitempty"` +} + +func (s *Scan) Completed() bool { + return s.Status == "COMPLETED" +} + +// ScanFinding represents a finding within a scan. +type ScanFinding struct { + RuleUUID string `json:"rule_uuid,omitempty"` + Name string `json:"name,omitempty"` + Details string `json:"details,omitempty"` + FoundAt string `json:"found_at,omitempty"` + Severity string `json:"severity,omitempty"` + BusinessImpact string `json:"business_impact,omitempty"` + TechnicalDetails string `json:"technical_details,omitempty"` + MitigationSteps []*ScanMitigationStep `json:"mitigation_steps,omitempty"` + AffectedResourcesCount int `json:"affected_resources_count,omitempty"` +} + +// ScanMitigationStep represents a mitigation step for a scan finding. +type ScanMitigationStep struct { + Step int `json:"step,omitempty"` + Title string `json:"title,omitempty"` + Description string `json:"description,omitempty"` +} + +// An AffectedResource represents a resource affected by a scan finding. +type AffectedResource struct { + URN string `json:"urn,omitempty"` + Name string `json:"name,omitempty"` + Type string `json:"type,omitempty"` +} + +type scanRoot struct { + Scan *Scan `json:"scan"` +} + +type scansRoot struct { + Scans []*Scan `json:"scans"` + Links *Links `json:"links"` + Meta *Meta `json:"meta"` +} + +type affectedResourcesRoot struct { + AffectedResources []*AffectedResource `json:"affected_resources"` + Links *Links `json:"links"` + Meta *Meta `json:"meta"` +} + +// CreateScan initiates a new CSPM scan. +func (s *SecurityServiceOp) CreateScan(ctx context.Context, createScanRequest *CreateScanRequest) (*Scan, *Response, error) { + if createScanRequest == nil { + return nil, nil, NewArgError("createScanRequest", "cannot be nil") + } + + req, err := s.client.NewRequest(ctx, http.MethodPost, securityScansBasePath, createScanRequest) + if err != nil { + return nil, nil, err + } + + scan := &Scan{} + resp, err := s.client.Do(ctx, req, scan) + if err != nil { + return nil, resp, err + } + + return scan, resp, nil +} + +// ListScans lists all CSPM scans. +func (s *SecurityServiceOp) ListScans(ctx context.Context, opts *ListOptions) ([]*Scan, *Response, error) { + path, err := addOptions(securityScansBasePath, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest(ctx, http.MethodGet, path, nil) + if err != nil { + return nil, nil, err + } + + root := new(scansRoot) + resp, err := s.client.Do(ctx, req, root) + if err != nil { + return nil, resp, err + } + if l := root.Links; l != nil { + resp.Links = l + } + if m := root.Meta; m != nil { + resp.Meta = m + } + + return root.Scans, resp, nil +} + +// GetScan retrieves a scan by its UUID with optional findings filters. +func (s *SecurityServiceOp) GetScan(ctx context.Context, scanUUID string, opts *ScanFindingsOptions) (*Scan, *Response, error) { + if scanUUID == "" { + return nil, nil, NewArgError("scanUUID", "cannot be empty") + } + + path := fmt.Sprintf("%s/%s", securityScansBasePath, scanUUID) + path, err := addOptions(path, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest(ctx, http.MethodGet, path, nil) + if err != nil { + return nil, nil, err + } + + root := &scanRoot{} + resp, err := s.client.Do(ctx, req, root) + if err != nil { + return nil, resp, err + } + + return root.Scan, resp, nil +} + +// GetLatestScan retrieves the latest scan with optional findings filters. +func (s *SecurityServiceOp) GetLatestScan(ctx context.Context, opts *ScanFindingsOptions) (*Scan, *Response, error) { + path := fmt.Sprintf("%s/latest", securityScansBasePath) + path, err := addOptions(path, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest(ctx, http.MethodGet, path, nil) + if err != nil { + return nil, nil, err + } + + root := &scanRoot{} + resp, err := s.client.Do(ctx, req, root) + if err != nil { + return nil, resp, err + } + + return root.Scan, resp, nil +} + +// ListFindingAffectedResourcesRequest contains the fields to list the +// affected resources for a scan finding. +type ListFindingAffectedResourcesRequest struct { + ScanUUID string + FindingUUID string +} + +// ListFindingAffectedResources lists the affected resources for a scan +// finding. +func (s *SecurityServiceOp) ListFindingAffectedResources(ctx context.Context, listFindingAffectedResourcesRequest *ListFindingAffectedResourcesRequest, opts *ListOptions) ([]*AffectedResource, *Response, error) { + if listFindingAffectedResourcesRequest == nil { + return nil, nil, NewArgError("listFindingAffectedResourcesRequest", "cannot be nil") + } + if listFindingAffectedResourcesRequest.ScanUUID == "" { + return nil, nil, NewArgError("scanUUID", "cannot be empty") + } + if listFindingAffectedResourcesRequest.FindingUUID == "" { + return nil, nil, NewArgError("findingUUID", "cannot be empty") + } + + path := fmt.Sprintf( + "%s/%s/%s/%s/%s", + securityScansBasePath, + listFindingAffectedResourcesRequest.ScanUUID, + securityScansFindingsPath, + listFindingAffectedResourcesRequest.FindingUUID, + securityAffectedResources, + ) + path, err := addOptions(path, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest(ctx, http.MethodGet, path, nil) + if err != nil { + return nil, nil, err + } + + root := &affectedResourcesRoot{} + resp, err := s.client.Do(ctx, req, root) + if err != nil { + return nil, resp, err + } + if l := root.Links; l != nil { + resp.Links = l + } + if m := root.Meta; m != nil { + resp.Meta = m + } + + return root.AffectedResources, resp, nil +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 2b8e969e5..312ab1222 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -33,7 +33,7 @@ github.com/coreos/go-systemd/v22/journal # github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc ## explicit github.com/davecgh/go-spew/spew -# github.com/digitalocean/godo v1.172.0 +# github.com/digitalocean/godo v1.175.0 ## explicit; go 1.23.0 github.com/digitalocean/godo github.com/digitalocean/godo/metrics