Skip to content

Commit

Permalink
feat: add configurable sbom-format
Browse files Browse the repository at this point in the history
close #4

Signed-off-by: Christian Kotzbauer <[email protected]>
  • Loading branch information
ckotzbauer committed Jan 21, 2022
1 parent 891dfc7 commit 5caebcc
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 16 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ All parameters are cli-flags.
|-----------|----------|---------|-------------|
| `verbosity` | `false` | `info` | Log-level (debug, info, warn, error, fatal, panic) |
| `cron` | `false` | `@hourly` | Backround-Service interval (CRON). All options from [github.com/robfig/cron](github.com/robfig/cron) are allowed |
| `format` | `false` | `json` | SBOM-Format. |
| `git-workingtree` | `false` | `/work` | Directory to place the git-repo. |
| `git-repository` | `true` | `""` | Git-Repository-URL (HTTPS). |
| `git-branch` | `false` | `main` | Git-Branch to checkout. |
Expand Down
13 changes: 9 additions & 4 deletions internal/daemon/daemon.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ func (c *CronService) runBackgroundService() {
logrus.Info("Execute background-service")
workingTree := viper.GetString("git-workingtree")
gitPath := viper.GetString("git-path")
format := viper.GetString("format")
workPath := path.Join(workingTree, gitPath)

gitAccount := git.New(viper.GetString("git-access-token"), viper.GetString("git-author-name"), viper.GetString("git-author-email"))
Expand All @@ -57,13 +58,15 @@ func (c *CronService) runBackgroundService() {

processedSbomFiles := []string{}

sy := syft.New(workingTree, gitPath, format)

for _, ns := range namespaces {
pods := client.ListPods(ns.Name, viper.GetString("pod-label-selector"))
logrus.Debugf("Discovered %v pods in namespace %v", len(pods), ns.Name)
digests := client.GetContainerDigests(pods)

for _, d := range digests {
sbomPath := syft.ExecuteSyft(d, workingTree, gitPath)
sbomPath := sy.ExecuteSyft(d)
processedSbomFiles = append(processedSbomFiles, sbomPath)
}

Expand All @@ -72,7 +75,9 @@ func (c *CronService) runBackgroundService() {

logrus.Debug("Start to remove old SBOMs")
ignoreDirs := []string{".git"}
err := filepath.Walk(workPath, deleteObsoleteFiles(workingTree, ignoreDirs, processedSbomFiles, gitAccount))
fileName := syft.GetFileName(format)

err := filepath.Walk(workPath, deleteObsoleteFiles(workingTree, fileName, ignoreDirs, processedSbomFiles, gitAccount))
if err != nil {
logrus.WithError(err).Error("Could not cleanup old SBOMs")
} else {
Expand All @@ -82,7 +87,7 @@ func (c *CronService) runBackgroundService() {
c.printNextExecution()
}

func deleteObsoleteFiles(workPath string, ignoreDirs, processedSbomFiles []string, gitAccount git.GitAccount) filepath.WalkFunc {
func deleteObsoleteFiles(workPath, fileName string, ignoreDirs, processedSbomFiles []string, gitAccount git.GitAccount) filepath.WalkFunc {
return func(p string, info os.FileInfo, err error) error {
if err != nil {
logrus.WithError(err).Errorf("An error occurred while processing %s", p)
Expand All @@ -98,7 +103,7 @@ func deleteObsoleteFiles(workPath string, ignoreDirs, processedSbomFiles []strin
}
}

if info.Name() == "sbom.json" {
if info.Name() == fileName {
found := false
for _, f := range processedSbomFiles {
if f == p {
Expand Down
60 changes: 48 additions & 12 deletions internal/syft/syft.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,28 @@ import (
"github.com/sirupsen/logrus"
)

func ExecuteSyft(img kubernetes.ImageDigest, gitWorkingTree, gitPath string) string {
name := strings.ReplaceAll(img.Digest, "@", "/")
name = strings.ReplaceAll(path.Join(gitWorkingTree, gitPath, name, "sbom.json"), ":", "_")
type Syft struct {
GitWorkingTree string
GitPath string
SbomFormat string
}

func New(gitWorkingTree, gitPath, sbomFormat string) Syft {
return Syft{
GitWorkingTree: gitWorkingTree,
GitPath: gitPath,
SbomFormat: sbomFormat,
}
}

if pathExists(name) {
func (s *Syft) ExecuteSyft(img kubernetes.ImageDigest) string {
fileName := GetFileName(s.SbomFormat)
filePath := strings.ReplaceAll(img.Digest, "@", "/")
filePath = strings.ReplaceAll(path.Join(s.GitWorkingTree, s.GitPath, filePath, fileName), ":", "_")

if pathExists(filePath) {
logrus.Debugf("Skip image %s", img.Digest)
return name
return filePath
}

logrus.Debugf("Processing image %s", img.Digest)
Expand All @@ -33,10 +48,10 @@ func ExecuteSyft(img kubernetes.ImageDigest, gitWorkingTree, gitPath string) str

if err != nil {
logrus.WithError(err).Error("Image-Pull failed")
return name
return filePath
}

cmd := exec.Command("syft", imagePath, "-o", "json")
cmd := exec.Command("syft", imagePath, "-o", s.SbomFormat)
var errb bytes.Buffer
cmd.Stderr = &errb
stdout, err := cmd.Output()
Expand All @@ -45,25 +60,46 @@ func ExecuteSyft(img kubernetes.ImageDigest, gitWorkingTree, gitPath string) str

if err != nil {
logrus.WithError(err).WithField("stderr", errb.String()).Error("Syft stopped with error")
return name
return filePath
}

dir := filepath.Dir(name)
dir := filepath.Dir(filePath)
err = os.MkdirAll(dir, 0777)

if err != nil {
logrus.WithError(err).Error("Directory could not be created")
return name
return filePath
}

data := []byte(stdout)
err = os.WriteFile(name, data, 0640)
err = os.WriteFile(filePath, data, 0640)

if err != nil {
logrus.WithError(err).Error("SBOM could not be saved")
}

return name
return filePath
}

func GetFileName(sbomFormat string) string {
switch sbomFormat {
case "json":
return "sbom.json"
case "text":
return "sbom.txt"
case "cyclonedx":
return "sbom.xml"
case "cyclonedx-json":
return "sbom.json"
case "spdx":
return "sbom.spdx"
case "spdx-json":
return "sbom.json"
case "table":
return "sbom.txt"
default:
return "sbom.json"
}
}

func pathExists(path string) bool {
Expand Down
1 change: 1 addition & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ func init() {

rootCmd.PersistentFlags().StringVarP(&verbosity, "verbosity", "v", logrus.InfoLevel.String(), "Log-level (debug, info, warn, error, fatal, panic)")
rootCmd.PersistentFlags().StringVarP(&daemonCron, "cron", "c", "@hourly", "Backround-Service interval (CRON)")
rootCmd.PersistentFlags().String("format", "json", "SBOM-Format.")
rootCmd.PersistentFlags().String("git-workingtree", "/work", "Directory to place the git-repo.")
rootCmd.PersistentFlags().String("git-repository", "", "Git-Repository-URL (HTTPS).")
rootCmd.PersistentFlags().String("git-branch", "main", "Git-Branch to checkout.")
Expand Down

0 comments on commit 5caebcc

Please sign in to comment.