Skip to content

Commit 717491e

Browse files
authored
Merge pull request #1119 from lacework/afiune/GROW-1361
https://lacework.atlassian.net/browse/GROW-1361
2 parents 7460c80 + 895def6 commit 717491e

File tree

11 files changed

+346
-132
lines changed

11 files changed

+346
-132
lines changed

api/entities.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ const (
3535
MachineDetailsEntityType
3636
UsersEntityType
3737
ImagesEntityType
38+
ContainersEntityType
3839
)
3940

4041
// EntityTypes is the list of available entity types
@@ -43,6 +44,7 @@ var EntityTypes = map[EntityType]string{
4344
MachineDetailsEntityType: "MachineDetails",
4445
UsersEntityType: "Users",
4546
ImagesEntityType: "Images",
47+
ContainersEntityType: "Containers",
4648
}
4749

4850
// Search expects the response and the search filters
@@ -75,6 +77,9 @@ func (svc *EntitiesService) Search(response interface{}, filters SearchFilter) e
7577
case *ImagesEntityResponse:
7678
apiPath = fmt.Sprintf(apiV2EntitiesSearch, EntityTypes[ImagesEntityType])
7779

80+
case *ContainersEntityResponse:
81+
apiPath = fmt.Sprintf(apiV2EntitiesSearch, EntityTypes[ContainersEntityType])
82+
7883
default:
7984
return errors.New("missing implementation for the provided entity response")
8085
}

api/entities_containers.go

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
//
2+
// Author:: Salim Afiune Maya (<[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+
"github.com/lacework/go-sdk/internal/array"
25+
)
26+
27+
// ListContainers returns a list of Active Containers from the last 7 days
28+
func (svc *EntitiesService) ListContainers() (response ContainersEntityResponse, err error) {
29+
now := time.Now().UTC()
30+
before := now.AddDate(0, 0, -7) // 7 days from ago
31+
err = svc.Search(&response,
32+
SearchFilter{
33+
TimeFilter: &TimeFilter{
34+
StartTime: &before,
35+
EndTime: &now,
36+
},
37+
},
38+
)
39+
return
40+
}
41+
42+
// ListContainersWithFilters returns a list of Active Containers based on a user defined filter
43+
func (svc *EntitiesService) ListContainersWithFilters(filters SearchFilter) (response ContainersEntityResponse, err error) {
44+
err = svc.Search(&response, filters)
45+
return
46+
}
47+
48+
// ListAllContainers iterates over all pages to return all active container information at once
49+
func (svc *EntitiesService) ListAllContainers() (response ContainersEntityResponse, err error) {
50+
response, err = svc.ListContainers()
51+
if err != nil {
52+
return
53+
}
54+
55+
var (
56+
all []ContainerEntity
57+
pageOk bool
58+
)
59+
for {
60+
all = append(all, response.Data...)
61+
62+
pageOk, err = svc.client.NextPage(&response)
63+
if err == nil && pageOk {
64+
continue
65+
}
66+
break
67+
}
68+
69+
response.Data = all
70+
response.ResetPaging()
71+
return
72+
}
73+
74+
// ListAllContainersWithFilters iterates over all pages to return all active container information at once based on a user defined filter
75+
func (svc *EntitiesService) ListAllContainersWithFilters(filters SearchFilter) (response ContainersEntityResponse, err error) {
76+
response, err = svc.ListContainersWithFilters(filters)
77+
if err != nil {
78+
return
79+
}
80+
81+
var (
82+
all []ContainerEntity
83+
pageOk bool
84+
)
85+
86+
for {
87+
all = append(all, response.Data...)
88+
89+
pageOk, err = svc.client.NextPage(&response)
90+
if err == nil && pageOk {
91+
continue
92+
}
93+
break
94+
}
95+
96+
response.Data = all
97+
response.ResetPaging()
98+
return
99+
}
100+
101+
type ContainersEntityResponse struct {
102+
Data []ContainerEntity `json:"data"`
103+
Paging V2Pagination `json:"paging"`
104+
}
105+
106+
// Fulfill Pageable interface (look at api/v2.go)
107+
func (r ContainersEntityResponse) PageInfo() *V2Pagination {
108+
return &r.Paging
109+
}
110+
func (r *ContainersEntityResponse) ResetPaging() {
111+
r.Paging = V2Pagination{}
112+
}
113+
114+
// Total returns the total number of active containers
115+
func (r *ContainersEntityResponse) Total() int {
116+
uniqMIDs := []int{}
117+
for _, container := range r.Data {
118+
if !array.ContainsInt(uniqMIDs, container.Mid) {
119+
uniqMIDs = append(uniqMIDs, container.Mid)
120+
}
121+
}
122+
return len(uniqMIDs)
123+
}
124+
125+
// Count returns the number of active containers with the provided image ID
126+
func (r *ContainersEntityResponse) Count(imageID string) int {
127+
uniqMIDs := []int{}
128+
for _, container := range r.Data {
129+
if container.ImageID == imageID &&
130+
!array.ContainsInt(uniqMIDs, container.Mid) {
131+
uniqMIDs = append(uniqMIDs, container.Mid)
132+
}
133+
}
134+
return len(uniqMIDs)
135+
}
136+
137+
type ContainerEntity struct {
138+
ContainerName string `json:"containerName"`
139+
ImageID string `json:"imageId"`
140+
Mid int `json:"mid"`
141+
StartTime time.Time `json:"startTime"`
142+
EndTime time.Time `json:"endTime"`
143+
PodName string `json:"podName"`
144+
PropsContainer map[string]interface{} `json:"propsContainer"`
145+
Tags map[string]interface{} `json:"tags"`
146+
}
147+
148+
type ContainerEntityProps struct {
149+
Name string `json:"NAME"`
150+
ContainerType string `json:"CONTAINER_TYPE"`
151+
ImageAuthor string `json:"IMAGE_AUTHOR"`
152+
ImageCreatedTime time.Time `json:"IMAGE_CREATED_TIME"`
153+
ImageID string `json:"IMAGE_ID"`
154+
ImageParentID string `json:"IMAGE_PARENT_ID"`
155+
ImageRepo string `json:"IMAGE_REPO"`
156+
ImageSize int64 `json:"IMAGE_SIZE"`
157+
ImageTag string `json:"IMAGE_TAG"`
158+
ImageVersion string `json:"IMAGE_VERSION"`
159+
Ipv4 string `json:"IPV4"`
160+
}

cli/cmd/flags.go

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ import (
2222
"fmt"
2323
"reflect"
2424
"strings"
25-
"time"
2625

2726
"github.com/pkg/errors"
2827
)
@@ -119,28 +118,3 @@ func stringSliceToMarkdownList(filters []string) string {
119118
}
120119
return fmt.Sprintf(" * %s", strings.Join(filters, "\n * "))
121120
}
122-
123-
// parse the start and end time provided by the user
124-
func parseStartAndEndTime(s, e string) (start time.Time, end time.Time, err error) {
125-
if s == "" {
126-
err = errors.New("when providing an end time, start time should be provided (--start)")
127-
return
128-
}
129-
start, err = time.Parse(time.RFC3339, s)
130-
if err != nil {
131-
err = errors.Wrap(err, "unable to parse start time")
132-
return
133-
}
134-
135-
if e == "" {
136-
end = time.Now()
137-
return
138-
}
139-
end, err = time.Parse(time.RFC3339, e)
140-
if err != nil {
141-
err = errors.Wrap(err, "unable to parse end time")
142-
return
143-
}
144-
145-
return
146-
}

cli/cmd/vuln_container.go

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,15 @@ func init() {
3333

3434
// add start flag to list-assessments command
3535
vulContainerListAssessmentsCmd.Flags().StringVar(&vulCmdState.Start,
36-
"start", "", "start of the time range in UTC (format: yyyy-MM-ddTHH:mm:ssZ)",
36+
"start", "-24h", "start of the time range",
3737
)
3838
// add end flag to list-assessments command
3939
vulContainerListAssessmentsCmd.Flags().StringVar(&vulCmdState.End,
40-
"end", "", "end of the time range in UTC (format: yyyy-MM-ddTHH:mm:ssZ)",
40+
"end", "now", "end of the time range",
41+
)
42+
// range time flag
43+
vulContainerListAssessmentsCmd.Flags().StringVar(&vulCmdState.Range,
44+
"range", "", "natural time range for query",
4145
)
4246
// add repository flag to list-assessments command
4347
vulContainerListAssessmentsCmd.Flags().StringSliceVarP(&vulCmdState.Repositories,
@@ -78,6 +82,10 @@ func init() {
7882
vulContainerShowAssessmentCmd.Flags(),
7983
)
8084

85+
setActiveFlag(
86+
vulContainerListAssessmentsCmd.Flags(),
87+
)
88+
8189
setFixableFlag(
8290
vulContainerScanCmd.Flags(),
8391
vulContainerShowAssessmentCmd.Flags(),

0 commit comments

Comments
 (0)