Skip to content

Commit ea0229c

Browse files
feat: vuln host show-assessment filter by collector type (#1302)
- Add new `collector_type` flag to `lacework vuln host show-assessement` cmd. To allow filtering by Agent/Agentless results - Default `collector_type` is `Agentless` - If no flag is set by the user and agentless results are not found, we automatically try agent - If agentless flag is explicitly set by the user, and no agentless integration is found return error and link to docs. - Display collector_type in host details output. Jira: https://lacework.atlassian.net/browse/GROW-2294 --------- Signed-off-by: Darren Murray <[email protected]> Signed-off-by: Salim Afiune Maya <[email protected]> Co-authored-by: Salim Afiune <[email protected]>
1 parent 65a27a0 commit ea0229c

File tree

12 files changed

+394
-119
lines changed

12 files changed

+394
-119
lines changed

api/entities.go

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,14 @@ const (
3636
UsersEntityType
3737
ImagesEntityType
3838
ContainersEntityType
39+
MachineEntityType
3940
)
4041

4142
// EntityTypes is the list of available entity types
4243
var EntityTypes = map[EntityType]string{
4344
NoneEntityType: "None",
4445
MachineDetailsEntityType: "MachineDetails",
46+
MachineEntityType: "Machines",
4547
UsersEntityType: "Users",
4648
ImagesEntityType: "Images",
4749
ContainersEntityType: "Containers",
@@ -51,19 +53,18 @@ var EntityTypes = map[EntityType]string{
5153
//
5254
// e.g.
5355
//
54-
// var (
55-
// response = &api.MachineDetailsEntityResponse{}
56-
// now = time.Now().UTC()
57-
// before = now.AddDate(0, 0, -7) // 7 days from ago
58-
// filters = api.SearchFilter{
59-
// TimeFilter: &api.TimeFilter{
60-
// StartTime: &before,
61-
// EndTime: &now,
62-
// },
63-
// }
64-
// )
65-
// lacework.V2.Entities.Search(response, filters)
66-
//
56+
// var (
57+
// response = &api.MachineDetailsEntityResponse{}
58+
// now = time.Now().UTC()
59+
// before = now.AddDate(0, 0, -7) // 7 days from ago
60+
// filters = api.SearchFilter{
61+
// TimeFilter: &api.TimeFilter{
62+
// StartTime: &before,
63+
// EndTime: &now,
64+
// },
65+
// }
66+
// )
67+
// lacework.V2.Entities.Search(response, filters)
6768
func (svc *EntitiesService) Search(response interface{}, filters SearchFilter) error {
6869
var apiPath string
6970

@@ -80,6 +81,9 @@ func (svc *EntitiesService) Search(response interface{}, filters SearchFilter) e
8081
case *ContainersEntityResponse:
8182
apiPath = fmt.Sprintf(apiV2EntitiesSearch, EntityTypes[ContainersEntityType])
8283

84+
case *MachinesEntityResponse:
85+
apiPath = fmt.Sprintf(apiV2EntitiesSearch, EntityTypes[MachineEntityType])
86+
8387
default:
8488
return errors.New("missing implementation for the provided entity response")
8589
}

api/entities_machines.go

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
//
2+
// Author:: Darren Murray (<[email protected]>)
3+
// Copyright:: Copyright 2023, Lacework Inc.
4+
// License:: Apache License, Version 2.0
5+
//
6+
// Licensed under the Apache License, Version 2.0 (the "License");
7+
// you may not use this file except in compliance with the License.
8+
// You may obtain a copy of the License at
9+
//
10+
// http://www.apache.org/licenses/LICENSE-2.0
11+
//
12+
// Unless required by applicable law or agreed to in writing, software
13+
// distributed under the License is distributed on an "AS IS" BASIS,
14+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
// See the License for the specific language governing permissions and
16+
// limitations under the License.
17+
//
18+
19+
package api
20+
21+
import (
22+
"time"
23+
)
24+
25+
// ListMachines returns a list of MachineEntity from the last 7 days
26+
func (svc *EntitiesService) ListMachines() (response MachinesEntityResponse, err error) {
27+
now := time.Now().UTC()
28+
before := now.AddDate(0, 0, -7) // 7 days from ago
29+
err = svc.Search(&response,
30+
SearchFilter{
31+
TimeFilter: &TimeFilter{
32+
StartTime: &before,
33+
EndTime: &now,
34+
},
35+
},
36+
)
37+
return
38+
}
39+
40+
// ListMachinesWithFilters returns a list of UserEntity based on a user defined filter
41+
func (svc *EntitiesService) ListMachinesWithFilters(filters SearchFilter) (response MachinesEntityResponse, err error) {
42+
err = svc.Search(&response, filters)
43+
return
44+
}
45+
46+
// ListAllMachines iterates over all pages to return all machine details at once
47+
func (svc *EntitiesService) ListAllMachines() (response MachinesEntityResponse, err error) {
48+
response, err = svc.ListMachines()
49+
if err != nil {
50+
return
51+
}
52+
53+
var (
54+
all []MachineEntity
55+
pageOk bool
56+
)
57+
for {
58+
all = append(all, response.Data...)
59+
60+
pageOk, err = svc.client.NextPage(&response)
61+
if err == nil && pageOk {
62+
continue
63+
}
64+
break
65+
}
66+
67+
response.ResetPaging()
68+
response.Data = all
69+
return
70+
}
71+
72+
// ListAllMachinesWithFilters iterates over all pages to return all machine details at once based on a user defined filter
73+
func (svc *EntitiesService) ListAllMachinesWithFilters(filters SearchFilter) (response MachinesEntityResponse, err error) {
74+
response, err = svc.ListMachinesWithFilters(filters)
75+
if err != nil {
76+
return
77+
}
78+
79+
var (
80+
all []MachineEntity
81+
pageOk bool
82+
)
83+
84+
for {
85+
all = append(all, response.Data...)
86+
87+
pageOk, err = svc.client.NextPage(&response)
88+
if err == nil && pageOk {
89+
continue
90+
}
91+
break
92+
}
93+
94+
response.ResetPaging()
95+
response.Data = all
96+
return
97+
}
98+
99+
type MachinesEntityResponse struct {
100+
Data []MachineEntity `json:"data"`
101+
Paging V2Pagination `json:"paging"`
102+
103+
v2PageMetadata `json:"-"`
104+
}
105+
106+
// Fulfill Pageable interface (look at api/v2.go)
107+
func (r MachinesEntityResponse) PageInfo() *V2Pagination {
108+
return &r.Paging
109+
}
110+
func (r *MachinesEntityResponse) ResetPaging() {
111+
r.Paging = V2Pagination{}
112+
r.Data = nil
113+
}
114+
115+
type MachineEntity struct {
116+
AwsInstanceID string `json:"awsInstanceId"`
117+
Hostname string `json:"hostname"`
118+
EntityType string `json:"entityType"`
119+
EndTime time.Time `json:"endTime"`
120+
Mid int `json:"mid"`
121+
PrimaryIpAddr string `json:"primaryIpAddr"`
122+
StartTime time.Time `json:"startTime"`
123+
Tags struct {
124+
// Shared Tags
125+
Cluster string `json:"Cluster,omitempty"`
126+
Env string `json:"Env,omitempty"`
127+
Arch string `json:"arch,omitempty"`
128+
ExternalIP string `json:"ExternalIp,omitempty"`
129+
Hostname string `json:"Hostname,omitempty"`
130+
InstanceID string `json:"InstanceId,omitempty"`
131+
InternalIP string `json:"InternalIp,omitempty"`
132+
LwTokenShort string `json:"LwTokenShort,omitempty"`
133+
Os string `json:"os,omitempty"`
134+
VMInstanceType string `json:"VmInstanceType,omitempty"`
135+
VMProvider string `json:"VmProvider,omitempty"`
136+
Zone string `json:"Zone,omitempty"`
137+
ClusterLocation string `json:"cluster-location,omitempty"`
138+
ClusterName string `json:"cluster-name,omitempty"`
139+
ClusterUid string `json:"cluster-uid,omitempty"`
140+
CreatedBy string `json:"created-by,omitempty"`
141+
LwKubernetesCluster string `json:"lw_KubernetesCluster,omitempty"`
142+
KubeLabels string `json:"kube-labels,omitempty"`
143+
144+
// AWS Tags
145+
Account string `json:"Account,omitempty"`
146+
AmiId string `json:"AmiId,omitempty"`
147+
SubnetId string `json:"SubnetId,omitempty"`
148+
VpcId string `json:"VpcId,omitempty"`
149+
150+
// GCP Tags
151+
GCEtags string `json:"GCEtags,omitempty"`
152+
InstanceName string `json:"InstanceName,omitempty"`
153+
NumericProjectId string `json:"NumericProjectId,omitempty"`
154+
ProjectId string `json:"ProjectId,omitempty"`
155+
EnableOslogin string `json:"enable-oslogin,omitempty"`
156+
GciEnsureGkeDocker string `json:"gci-ensure-gke-docker,omitempty"`
157+
GciUpdateStrategy string `json:"gci-update-strategy,omitempty"`
158+
GoogleComputeEnablePcid string `json:"google-compute-enable-pcid,omitempty"`
159+
InstanceTemplate string `json:"instance-template,omitempty"`
160+
} `json:"machineTags"`
161+
}

api/v2_vulnerabilities.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,7 @@ type VulnerabilityHost struct {
471471
ExceptionProps []interface{} `json:"exception_props"`
472472
Hostname string `json:"hostname"`
473473
McEvalGUID string `json:"mc_eval_guid"`
474+
CollectorType string `json:"collector_type"`
474475
} `json:"evalCtx"`
475476
FeatureKey struct {
476477
Name string `json:"name"`

cli/cmd/vuln_host.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,12 @@ func init() {
101101
"local", "l", false,
102102
"automatically generate the package manifest from the local host",
103103
)
104+
105+
// the collector_type of the assessment
106+
vulHostShowAssessmentCmd.Flags().StringVar(&vulCmdState.CollectorType,
107+
"collector_type", vulnHostCollectorTypeAgentless,
108+
"filter assessments by collector type (Agent or Agentless)",
109+
)
104110
}
105111

106112
func cvesSummary(hosts []api.VulnerabilityHost) map[string]VulnCveSummary {

0 commit comments

Comments
 (0)