Skip to content

Commit

Permalink
feat(api): new Vulnerabilities.ListEvaluations() func
Browse files Browse the repository at this point in the history
This new feature is adding two new functions `ListEvalutions()` and
`ListEvaluationsDateRange()` to the `Vulnerabilities` service inside the
Go API client, these endpoints wrap the new API endpoint:

`/external/vulnerabilities/container/GetEvaluationsForDateRange`

The functions will allow users to lists all evaluations in an account.

An example:
```go
package main

import (
	"fmt"
	"log"

	"github.com/lacework/go-sdk/api"
)

func main() {
	lacework, err := api.NewClient("account")
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println(lacework.Vulnerabilities.ListEvaluations())
}
```

Contributes to #156

Signed-off-by: Salim Afiune Maya <[email protected]>
  • Loading branch information
afiune committed Jul 6, 2020
1 parent 3c34eaf commit 10f9bea
Show file tree
Hide file tree
Showing 6 changed files with 510 additions and 8 deletions.
1 change: 1 addition & 0 deletions api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ const (
apiVulnerabilitiesScanStatus = "external/vulnerabilities/container/reqId/%s"
apiVulnerabilitiesReportFromID = "external/vulnerabilities/container/imageId/%s"
apiVulnerabilitiesReportFromDigest = "external/vulnerabilities/container/imageDigest/%s"
apiVulEvaluationsForDateRange = "external/vulnerabilities/container/GetEvaluationsForDateRange"

apiComplianceAwsLatestReport = "external/compliance/aws/GetLatestComplianceReport?AWS_ACCOUNT_ID=%s"
apiComplianceGcpLatestReport = "external/compliance/gcp/GetLatestComplianceReport?GCP_ORG_ID=%s&GCP_PROJ_ID=%s"
Expand Down
14 changes: 10 additions & 4 deletions api/events.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,25 +31,31 @@ type EventsService struct {
client *Client
}

// List leverages ListRange and returns a list of events from the last 7 days
// List leverages ListDateRange and returns a list of events from the last 7 days
func (svc *EventsService) List() (EventsResponse, error) {
var (
now = time.Now().UTC()
from = now.AddDate(0, 0, -7) // 7 days from now
)

return svc.ListRange(from, now)
return svc.ListDateRange(from, now)
}

// ListRange returns a list of Lacework events during the specified date range
// TODO @afiune (to-be-deprecated) ADD-ISSUE
func (svc *EventsService) ListRange(start, end time.Time) (EventsResponse, error) {
svc.client.log.Warn("ListRange() is DEPRECATED: use ListDateRange() instead")
return svc.ListDateRange(start, end)
}

// ListDateRange returns a list of Lacework events during the specified date range
//
// Requirements and specifications:
// * The dates format should be: yyyy-MM-ddTHH:mm:ssZ (example 2019-07-11T21:11:00Z)
// * The START_TIME and END_TIME must be specified in UTC
// * The difference between the START_TIME and END_TIME must not be greater than 7 days
// * The START_TIME must be less than or equal to three months from current date
// * The number of records produced is limited to 5000
func (svc *EventsService) ListRange(start, end time.Time) (
func (svc *EventsService) ListDateRange(start, end time.Time) (
response EventsResponse,
err error,
) {
Expand Down
4 changes: 2 additions & 2 deletions api/events_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ func TestEventsListRangeError(t *testing.T) {
// a tipical user input error could be that they provide the
// date range the other way around, from should be the start
// time, and now should be the end time
response, err := c.Events.ListRange(now, from)
response, err := c.Events.ListDateRange(now, from)
assert.Empty(t, response)
if assert.NotNil(t, err) {
assert.Equal(t,
Expand All @@ -73,7 +73,7 @@ func TestEventsList(t *testing.T) {
fakeServer.MockAPI(
"external/events/GetEventsForDateRange",
func(w http.ResponseWriter, r *http.Request) {
assert.Equal(t, "GET", r.Method, "List or ListRange should be a GET method")
assert.Equal(t, "GET", r.Method, "List or ListDateRange should be a GET method")

start, ok := r.URL.Query()["START_TIME"]
if assert.True(t, ok,
Expand Down
91 changes: 91 additions & 0 deletions api/vulnerabilities.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,14 @@
package api

import (
"encoding/json"
"fmt"
"strconv"
"strings"
"time"

"github.com/lacework/go-sdk/internal/array"
"github.com/pkg/errors"
)

// VulnerabilitiesService is a service that interacts with the vulnerabilities
Expand Down Expand Up @@ -238,3 +242,90 @@ type containerVulnerability struct {
FixVersion string `json:"fix_version"`
Metadata map[string]interface{} `json:"metadata"`
}

// ListEvaluations leverages ListEvaluationsDateRange and returns a list of evaluations from the last 7 days
func (svc *VulnerabilitiesService) ListEvaluations() (VulContainerEvaluationsResponse, error) {
var (
now = time.Now().UTC()
from = now.AddDate(0, 0, -7) // 7 days from now
)

return svc.ListEvaluationsDateRange(from, now)
}

// ListEvaluationsDateRange returns a list of container evaluations during the specified date range
func (svc *VulnerabilitiesService) ListEvaluationsDateRange(start, end time.Time) (
response VulContainerEvaluationsResponse,
err error,
) {
if start.After(end) {
err = errors.New("data range should have a start time before the end time")
return
}

apiPath := fmt.Sprintf(
"%s?START_TIME=%s&END_TIME=%s",
apiVulEvaluationsForDateRange,
start.UTC().Format(time.RFC3339),
end.UTC().Format(time.RFC3339),
)
err = svc.client.RequestDecoder("GET", apiPath, nil, &response)
return
}

type VulContainerEvaluationsResponse struct {
Data []VulContainerEvaluation `json:"data"`
Ok bool `json:"ok"`
Message string `json:"message"`
}

// time type to parse the returned 16 digit time in milliseconds
type Json16DigitTime time.Time

// imeplement Marshal and Unmarshal interfaces
func (j *Json16DigitTime) UnmarshalJSON(b []byte) error {
ms, _ := strconv.Atoi(string(b))
t := time.Unix(0, int64(ms)*int64(time.Millisecond))
*j = Json16DigitTime(t)
return nil
}

func (j Json16DigitTime) MarshalJSON() ([]byte, error) {
return json.Marshal(j)
}

// A few format functions for printing and manipulating the custom date
func (j Json16DigitTime) ToTime() time.Time {
return time.Time(j)
}
func (j Json16DigitTime) Format(s string) string {
return j.ToTime().Format(s)
}
func (j Json16DigitTime) UTC() time.Time {
return j.ToTime().UTC()
}

type VulContainerEvaluation struct {
EvalGuid string `json:"eval_guid"`
EvalStatus string `json:"eval_status"`
EvalType string `json:"eval_type"`
ImageCreatedTime Json16DigitTime `json:"image_created_time"`
ImageDigest string `json:"image_digest"`
ImageID string `json:"image_id"`
ImageNamespace string `json:"image_namespace"`
ImageRegistry string `json:"image_registry"`
ImageRepo string `json:"image_repo"`
ImageScanErrorMsg string `json:"image_scan_error_msg"`
ImageScanStatus string `json:"image_scan_status"`
ImageScanTime Json16DigitTime `json:"image_scan_time"`
ImageSize string `json:"image_size"`
ImageTags []string `json:"image_tags"`
NdvContainers string `json:"ndv_containers"`
NumFixes string `json:"num_fixes"`
NumVulnerabilitiesSeverity1 string `json:"num_vulnerabilities_severity_1"`
NumVulnerabilitiesSeverity2 string `json:"num_vulnerabilities_severity_2"`
NumVulnerabilitiesSeverity3 string `json:"num_vulnerabilities_severity_3"`
NumVulnerabilitiesSeverity4 string `json:"num_vulnerabilities_severity_4"`
NumVulnerabilitiesSeverity5 string `json:"num_vulnerabilities_severity_5"`
StartTime Json16DigitTime `json:"start_time"`
}
Loading

0 comments on commit 10f9bea

Please sign in to comment.