Skip to content

Commit

Permalink
Add CheckImageArchitectures
Browse files Browse the repository at this point in the history
Signed-off-by: Tamal Saha <[email protected]>
  • Loading branch information
tamalsaha committed Dec 13, 2024
1 parent 7784488 commit 5b4eb7f
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 6 deletions.
69 changes: 69 additions & 0 deletions pkg/lib/tests.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,12 @@ limitations under the License.
package lib

import (
"errors"
"fmt"
"os"
"strings"

v1 "github.com/google/go-containerregistry/pkg/v1"
"k8s.io/apimachinery/pkg/util/sets"
"sigs.k8s.io/yaml"
)
Expand Down Expand Up @@ -51,6 +53,73 @@ func CheckImageExists(files []string) error {
return nil
}

var desiredArchs = sets.New("amd64", "arm64")

func CheckImageArchitectures(files []string, archSkipList []string) error {
archSkipSet := sets.NewString(archSkipList...)

images, err := LoadImageList(files)
if err != nil {
return err
}

var missing []string
missingArchs := map[string][]string{}
for _, img := range images {
obj, found, err := ImageManifest(img)
if err != nil || !found {
missing = append(missing, img)
continue
}
switch mf := obj.(type) {
case *v1.IndexManifest:
var archs []string
for _, d := range mf.Manifests {
if d.Platform != nil && d.Platform.Architecture != "" {
archs = append(archs, d.Platform.Architecture)
}
}
if missing := sets.List(desiredArchs.Difference(sets.New[string](archs...))); len(missing) > 0 {
missingArchs[img] = missing
} else {
fmt.Println("✔ " + img)
}
case *v1.Manifest:
if mf.Config.MediaType != "application/vnd.cncf.helm.config.v1+json" {
missingArchs[img] = []string{"arm64"}
}
default:
missingArchs[img] = []string{"amd64", "arm64"}
}
}

var fail bool
if len(missing) > 0 {
fmt.Println("----------------------------------------")
fmt.Println("Missing Images:")
fmt.Println(strings.Join(missing, "\n"))
fail = true
}

if len(missingArchs) > 0 {
fmt.Println("----------------------------------------")
fmt.Println("Missing Architectures:")
for img, archs := range missingArchs {
if !archSkipSet.Has(img) {
fmt.Printf("X %s %v\n", img, archs)
fail = true
} else {
fmt.Printf("[skipped] %s %v\n", img, archs)
}
}
}

if fail {
return errors.New("missing images and/or architectures")
}
return nil
}

func LoadImageList(files []string) ([]string, error) {
result := sets.New[string]()
for _, filename := range files {
Expand Down
12 changes: 6 additions & 6 deletions pkg/lib/trivy.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ limitations under the License.
package lib

import (
"encoding/json"
"errors"
"fmt"
"net/http"
Expand All @@ -27,7 +28,6 @@ import (
"github.com/google/go-containerregistry/pkg/v1/remote/transport"
shell "gomodules.xyz/go-sh"
"kubeops.dev/scanner/apis/trivy"
"sigs.k8s.io/yaml"
)

// trivy image ubuntu --security-checks vuln --format json --quiet
Expand Down Expand Up @@ -80,28 +80,28 @@ func ImageManifest(ref string) (any, bool, error) {
data, err := crane.Manifest(ref, crane.WithAuthFromKeychain(authn.DefaultKeychain))
if err != nil {
if ImageNotFound(err) {
return "", false, nil
return nil, false, nil
}
return nil, false, err
}
var obj map[string]any
if err = yaml.Unmarshal(data, &obj); err != nil {
if err = json.Unmarshal(data, &obj); err != nil {
return nil, false, err
}
if _, ok := obj["manifests"]; ok {
var mf v1.IndexManifest
if err := yaml.Unmarshal(data, &mf); err != nil {
if err := json.Unmarshal(data, &mf); err != nil {
return nil, false, err
}
return &mf, true, nil
} else if _, ok := obj["layers"]; ok {
var mf v1.Manifest
if err := yaml.Unmarshal(data, &mf); err != nil {
if err := json.Unmarshal(data, &mf); err != nil {
return nil, false, err
}
return &mf, true, nil
}
return nil, true, fmt.Errorf("unknown image manifest format")
return nil, false, fmt.Errorf("unknown image manifest format")
}

func ImageNotFound(err error) bool {
Expand Down

0 comments on commit 5b4eb7f

Please sign in to comment.