Skip to content

Commit

Permalink
Generate sboms using new sbom object
Browse files Browse the repository at this point in the history
The build context will now generate the sboms using the new sbom package

Signed-off-by: Adolfo García Veytia (Puerco) <[email protected]>
  • Loading branch information
puerco committed Mar 9, 2022
1 parent 1068d54 commit c08e720
Showing 1 changed file with 11 additions and 103 deletions.
114 changes: 11 additions & 103 deletions pkg/build/sbom.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,10 @@
package build

import (
"encoding/json"
"fmt"
"log"
"os"
"path/filepath"
"strings"

"chainguard.dev/apko/pkg/sbom/cyclonedx"
osr "github.com/dominodatalab/os-release"
"chainguard.dev/apko/pkg/sbom"
"gitlab.alpinelinux.org/alpine/go/pkg/repository"
)

Expand All @@ -38,108 +33,21 @@ func bomPurl(ns string, pkg *repository.Package) string {
func (bc *Context) GenerateSBOM() error {
log.Printf("generating SBOM")

installedDB, err := os.Open(filepath.Join(bc.WorkDir, "lib", "apk", "db", "installed"))
if err != nil {
return fmt.Errorf("unable to open APK installed db: %w", err)
}
defer installedDB.Close()

// repository.ParsePackageIndex closes the file itself
packages, err := repository.ParsePackageIndex(installedDB)
if err != nil {
return fmt.Errorf("unable to parse APK installed db: %w", err)
}

// TODO(kaniini): figure out something better to do than this
osName := "Alpine Linux"
osID := "alpine"
osVersion := "Unknown"

osReleaseData, err := os.ReadFile(filepath.Join(bc.WorkDir, "etc", "os-release"))
if err == nil {
info := osr.Parse(string(osReleaseData))

osName = info.Name
osID = info.ID
osVersion = info.VersionID
}

pkgComponents := []cyclonedx.Component{}
pkgDependencies := []cyclonedx.Dependency{}

for _, pkg := range packages {
// add the component
c := cyclonedx.Component{
BOMRef: bomRef(osID, pkg),
Name: pkg.Name,
Version: pkg.Version,
Description: pkg.Description,
Licenses: []cyclonedx.License{
{
Expression: pkg.License,
},
},
PUrl: bomPurl(osID, pkg),
// TODO(kaniini): Talk with CycloneDX people about adding "package" type.
Type: "operating-system",
}
// TODO(puerco): Split GenerateSBOM into context implementation
s := sbom.NewWithWorkDir(bc.WorkDir)

pkgComponents = append(pkgComponents, c)

// walk the dependency list
depRefs := []string{}
for _, dep := range pkg.Dependencies {
// TODO(kaniini): Properly handle virtual dependencies...
if strings.ContainsRune(dep, ':') {
continue
}

i := strings.IndexAny(dep, " ~<>=/!")
if i > -1 {
dep = dep[:i]
}
if dep == "" {
continue
}

depRefs = append(depRefs, fmt.Sprintf("pkg:apk/%s/%s", osID, dep))
}

d := cyclonedx.Dependency{
Ref: bomRef(osID, pkg),
DependsOn: depRefs,
}
pkgDependencies = append(pkgDependencies, d)
}

rootComponent := cyclonedx.Component{
BOMRef: fmt.Sprintf("pkg:apk/%s", osID),
Name: osName,
Version: osVersion,
Type: "operating-system",
Components: pkgComponents,
}

bom := cyclonedx.Document{
BOMFormat: "CycloneDX",
SpecVersion: "1.4",
Version: 1,
Components: []cyclonedx.Component{rootComponent},
Dependencies: pkgDependencies,
}

out, err := os.Create(bc.SBOMPath)
// Generate the packages externally as we may
// move the package reader somewhere else
packages, err := s.ReadPackageIndex()
if err != nil {
return fmt.Errorf("unable to open SBOM path %s for writing: %w", bc.SBOMPath, err)
return fmt.Errorf("getting installed packagesx from sbom: %w", err)
}
defer out.Close()

enc := json.NewEncoder(out)
enc.SetIndent("", " ")
s.Options.OutputDir = bc.SBOMPath
s.Options.Packages = packages

err = enc.Encode(bom)
files, err := s.Generate()
if err != nil {
return fmt.Errorf("unable to encode BOM: %w", err)
return fmt.Errorf("generating SBOMs: %w", err)
}

return nil
Expand Down

0 comments on commit c08e720

Please sign in to comment.