-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
258 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
package main | ||
|
||
import ( | ||
"context" | ||
"encoding/json" | ||
"fmt" | ||
"log" | ||
"os/exec" | ||
"sync" | ||
"time" | ||
|
||
"github.com/google/uuid" | ||
"github.com/intelops/kubviz/constants" | ||
"github.com/intelops/kubviz/model" | ||
"github.com/nats-io/nats.go" | ||
"k8s.io/client-go/rest" | ||
) | ||
|
||
func publishTrivySbomReport(report model.Sbom, js nats.JetStreamContext, errCh chan error) { | ||
metrics := model.Reports{ | ||
ID: uuid.New(), | ||
Report: report, | ||
} | ||
metricsJson, _ := json.Marshal(metrics) | ||
_, err := js.Publish(constants.TRIVY_SBOM_SUBJECT, metricsJson) | ||
if err != nil { | ||
errCh <- err | ||
} | ||
|
||
log.Printf("Trivy report with BomFormat:%v has been published\n", metrics.Report.BomFormat) | ||
errCh <- nil | ||
} | ||
|
||
func executeCommandSbom(ctx context.Context, command string) ([]byte, error) { | ||
cmd := exec.CommandContext(ctx, "/bin/sh", "-c", command) | ||
stdout, err := cmd.Output() | ||
|
||
if err != nil { | ||
log.Println("Execute Command Error", err.Error()) | ||
} | ||
|
||
return stdout, nil | ||
} | ||
|
||
func RunTrivySbomScan(config *rest.Config, js nats.JetStreamContext, wg *sync.WaitGroup, errCh chan error) { | ||
defer wg.Done() | ||
images, err := ListImages(config) | ||
log.Println("length of images", len(images)) | ||
|
||
if err != nil { | ||
log.Printf("failed to list images: %v", err) | ||
} | ||
|
||
ctx, cancel := context.WithTimeout(context.Background(), 600*time.Second) | ||
defer cancel() | ||
|
||
var wgc sync.WaitGroup | ||
wgc.Add(len(images)) // Set the wait group count to the number of images | ||
|
||
for i, image := range images { | ||
fmt.Printf("pullable Image %#v\n", image.PullableImage) | ||
|
||
// Start a goroutine for each image | ||
go func(i int, image model.RunningImage) { | ||
defer wgc.Done() | ||
|
||
// Execute the Trivy command with the context | ||
command := fmt.Sprintf("trivy image --format cyclonedx %s", image.PullableImage) | ||
out, err := executeCommandSbom(ctx, command) | ||
|
||
if ctx.Err() == context.DeadlineExceeded { | ||
log.Printf("Command execution timeout for image %s", image.PullableImage) | ||
return // Move on to the next image | ||
} | ||
|
||
if err != nil { | ||
log.Printf("Error executing Trivy for image %s: %v", image.PullableImage, err) | ||
return // Move on to the next image in case of an error | ||
} | ||
|
||
// Check if the output is empty or invalid JSON | ||
if len(out) == 0 { | ||
log.Printf("Trivy output is empty for image %s", image.PullableImage) | ||
return // Move on to the next image | ||
} | ||
|
||
// Extract the JSON data from the output | ||
var report model.Sbom | ||
err = json.Unmarshal(out, &report) | ||
if err != nil { | ||
log.Printf("Error unmarshaling JSON data for image %s: %v", image.PullableImage, err) | ||
return // Move on to the next image in case of an error | ||
} | ||
|
||
// Publish the report using the given function | ||
publishTrivySbomReport(report, js, errCh) | ||
}(i, image) | ||
} | ||
|
||
// Wait for all the goroutines to complete | ||
wgc.Wait() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
package model | ||
|
||
import ( | ||
"time" | ||
|
||
"github.com/google/uuid" | ||
) | ||
|
||
type Reports struct { | ||
ID uuid.UUID | ||
Report Sbom | ||
} | ||
|
||
type Sbom struct { | ||
Schema string `json:"$schema"` | ||
BomFormat string `json:"bomFormat"` | ||
SpecVersion string `json:"specVersion"` | ||
SerialNumber string `json:"serialNumber"` | ||
Version int `json:"version"` | ||
Metadata struct { | ||
Timestamp time.Time `json:"timestamp"` | ||
Tools []struct { | ||
Vendor string `json:"vendor"` | ||
Name string `json:"name"` | ||
Version string `json:"version"` | ||
} `json:"tools"` | ||
Component struct { | ||
BomRef string `json:"bom-ref"` | ||
Type string `json:"type"` | ||
Name string `json:"name"` | ||
Purl string `json:"purl"` | ||
Properties []struct { | ||
Name string `json:"name"` | ||
Value string `json:"value"` | ||
} `json:"properties"` | ||
} `json:"component"` | ||
} `json:"metadata"` | ||
Components []struct { | ||
BomRef string `json:"bom-ref"` | ||
Type string `json:"type"` | ||
Name string `json:"name"` | ||
Version string `json:"version"` | ||
Properties []struct { | ||
Name string `json:"name"` | ||
Value string `json:"value"` | ||
} `json:"properties"` | ||
Hashes []struct { | ||
Alg string `json:"alg"` | ||
Content string `json:"content"` | ||
} `json:"hashes,omitempty"` | ||
Licenses []struct { | ||
Expression string `json:"expression"` | ||
} `json:"licenses,omitempty"` | ||
Purl string `json:"purl,omitempty"` | ||
} `json:"components"` | ||
Dependencies []struct { | ||
Ref string `json:"ref"` | ||
DependsOn []string `json:"dependsOn"` | ||
} `json:"dependencies"` | ||
Vulnerabilities []interface{} `json:"vulnerabilities"` | ||
} |