Skip to content

Commit

Permalink
mock image platform and base image from sbom
Browse files Browse the repository at this point in the history
  • Loading branch information
Paul Norton committed Feb 13, 2024
1 parent 99861aa commit 0a84ee9
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 36 deletions.
93 changes: 61 additions & 32 deletions policy/policy_handler/local.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,26 @@ func getLocalSubscriptionData(_ context.Context, req skill.RequestContext) (*goa
return nil, skill.Configuration{}, nil
}

mockCommonSubscriptionData := goals.CommonSubscriptionQueryResult{
ImageDigest: "localDigest",
_, sbom, err := parseMetadata(req)
if err != nil {
return nil, skill.Configuration{}, err
}

var mockCommonSubscriptionData goals.CommonSubscriptionQueryResult
if sbom != nil {
mockCommonSubscriptionData = goals.CommonSubscriptionQueryResult{
ImageDigest: sbom.Source.Image.Digest,
ImagePlatforms: []goals.ImagePlatform{{
Architecture: sbom.Source.Image.Platform.Architecture,
Os: sbom.Source.Image.Platform.Os,
}},
}
} else {
mockCommonSubscriptionData = goals.CommonSubscriptionQueryResult{
ImageDigest: "localDigest",
}
}

subscriptionData, err := edn.Marshal(mockCommonSubscriptionData)
if err != nil {
return nil, skill.Configuration{}, err
Expand All @@ -61,39 +78,14 @@ func buildLocalDataSources(ctx context.Context, req skill.RequestContext, _ goal
return []data.DataSource{}, nil
}

var srMeta SyncRequestMetadata
err := edn.Unmarshal(req.Event.Context.SyncRequest.Metadata, &srMeta)
srMeta, sbom, err := parseMetadata(req)
if err != nil {
return nil, fmt.Errorf("failed to unmarshal SyncRequest metadata: %w", err)
return nil, err
}

if srMeta.SBOM != "" {
decodedSBOM, err := base64.StdEncoding.DecodeString(srMeta.SBOM)
if err != nil {
return nil, fmt.Errorf("failed to base64-decode SBOM: %w", err)
}
if srMeta.Encoding == "base64+gzip" {
reader := bytes.NewReader(decodedSBOM)
gzreader, err := gzip.NewReader(reader)
defer gzreader.Close() //nolint:errcheck
if err != nil {
return nil, fmt.Errorf("failed to decompress SBOM: %w", err)
}
decodedSBOM, err = io.ReadAll(gzreader)
if err != nil {
return nil, fmt.Errorf("failed to base64-decode SBOM: %w", err)
}
}

var sbom *types.SBOM
// THE SBOM is a JSON here, not edn
if err := json.Unmarshal(decodedSBOM, &sbom); err != nil {
return nil, fmt.Errorf("failed to unmarshal SBOM: %w", err)
}
srMeta.QueryResults, err = mocks.BuildLocalEvalMocks(ctx, req, sbom)
if err != nil {
return nil, fmt.Errorf("failed to build local evaluation mocks: %w", err)
}
srMeta.QueryResults, err = mocks.BuildLocalEvalMocks(ctx, req, sbom)
if err != nil {
return nil, fmt.Errorf("failed to build local evaluation mocks: %w", err)
}

fixedQueryResults := map[string][]byte{}
Expand Down Expand Up @@ -123,3 +115,40 @@ func buildLocalDataSources(ctx context.Context, req skill.RequestContext, _ goal
func shouldTransactLocal(_ context.Context, req skill.RequestContext) bool {
return req.Event.Context.SyncRequest.Name != eventNameLocalEval
}

func parseMetadata(req skill.RequestContext) (SyncRequestMetadata, *types.SBOM, error) {
var srMeta SyncRequestMetadata
err := edn.Unmarshal(req.Event.Context.SyncRequest.Metadata, &srMeta)
if err != nil {
return SyncRequestMetadata{}, nil, fmt.Errorf("failed to unmarshal SyncRequest metadata: %w", err)
}

if srMeta.SBOM == "" {
return srMeta, nil, nil
}

decodedSBOM, err := base64.StdEncoding.DecodeString(srMeta.SBOM)
if err != nil {
return srMeta, nil, fmt.Errorf("failed to base64-decode SBOM: %w", err)
}
if srMeta.Encoding == "base64+gzip" {
reader := bytes.NewReader(decodedSBOM)
gzreader, err := gzip.NewReader(reader)
defer gzreader.Close() //nolint:errcheck
if err != nil {
return srMeta, nil, fmt.Errorf("failed to decompress SBOM: %w", err)
}
decodedSBOM, err = io.ReadAll(gzreader)
if err != nil {
return srMeta, nil, fmt.Errorf("failed to base64-decode SBOM: %w", err)
}
}

var sbom *types.SBOM
// THE SBOM is a JSON here, not edn
if err := json.Unmarshal(decodedSBOM, &sbom); err != nil {
return srMeta, nil, fmt.Errorf("failed to unmarshal SBOM: %w", err)
}

return srMeta, sbom, nil
}
34 changes: 33 additions & 1 deletion policy/policy_handler/mocks/base_image.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package mocks

import (
"fmt"
"github.com/atomist-skills/go-skill/policy/types"
"strings"
)

const (
Expand Down Expand Up @@ -29,11 +31,41 @@ func MockBaseImage(sb *types.SBOM) BaseImageQueryResult {
FromReference: &SubscriptionImage{
Digest: sb.Source.Provenance.BaseImage.Digest,
},
FromRepo: nil, // TODO: this data is not present in the SBOM yet
FromRepo: parseFromReference(sb),
FromTag: &sb.Source.Provenance.BaseImage.Tag,
}
}

func parseFromReference(sb *types.SBOM) *SubscriptionRepository {
// this is registry.com/namespace/repository form
// but minified (omits hub.docker.com and library/ if unnecessary)
fullName := sb.Source.Provenance.BaseImage.Name
if fullName == "" {
return nil
}

parts := strings.SplitN(fullName, "/", 3)
switch len(parts) {
case 1:
return &SubscriptionRepository{
Host: "hub.docker.com",
Repository: fmt.Sprintf("library/%s", parts[0]),
}

case 2:
return &SubscriptionRepository{
Host: "hub.docker.com",
Repository: fmt.Sprintf("%s/%s", parts[0], parts[1]),
}

default:
return &SubscriptionRepository{
Host: parts[0],
Repository: fmt.Sprintf("%s/%s", parts[1], parts[2]),
}
}
}

func MockSupportedTags(sb *types.SBOM) []string {
return []string{} // TODO: query GraphQL for supported tags
}
3 changes: 0 additions & 3 deletions policy/policy_handler/mocks/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,5 @@ func BuildLocalEvalMocks(ctx context.Context, req skill.RequestContext, sb *type
return m, fmt.Errorf("failed to marshal supported tags mock: %w", err)
}

// TODO: Mock ImagePlatforms from CommonSubscriptionQueryResult (required for atomist/no-stale-base-images)
// TODO: Mock packages (required for atomist/license-goal)

return m, nil
}

0 comments on commit 0a84ee9

Please sign in to comment.