Skip to content

Commit

Permalink
Base64-decoding + ungzip SBOM (#50)
Browse files Browse the repository at this point in the history
* Base64-decode SBOM

Signed-off-by: felipecruz91 <[email protected]>

* Remove logging

* Initialize logger in unit test

* Remove unused structs

---------

Signed-off-by: felipecruz91 <[email protected]>
Co-authored-by: Christian Dupuis <[email protected]>
  • Loading branch information
felipecruz91 and cdupuis authored Feb 12, 2024
1 parent 4c44198 commit a4f20cd
Show file tree
Hide file tree
Showing 9 changed files with 72 additions and 90 deletions.
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module github.com/atomist-skills/go-skill

go 1.19
go 1.21.6

require (
cloud.google.com/go/logging v1.8.1
Expand All @@ -25,7 +25,7 @@ require (
require (
cloud.google.com/go v0.110.8 // indirect
cloud.google.com/go/compute v1.23.0 // indirect
cloud.google.com/go/compute/metadata v0.2.3 // indirect
cloud.google.com/go/compute/metadata v0.2.3
cloud.google.com/go/iam v1.1.2 // indirect
cloud.google.com/go/longrunning v0.5.1 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
Expand Down
7 changes: 7 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/codahale/rfc6979 v0.0.0-20141003034818-6a90f24967eb h1:EDmT6Q9Zs+SbUoc7Ik9EfrFqcylYqgPZ9ANSbTAntnE=
github.com/codahale/rfc6979 v0.0.0-20141003034818-6a90f24967eb/go.mod h1:ZjrT6AXHbDs86ZSdt/osfBi5qfexBrKUdONk989Wnk4=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
Expand Down Expand Up @@ -79,6 +80,7 @@ github.com/google/go-containerregistry v0.18.0 h1:ShE7erKNPqRh5ue6Z9DUOlk04WsnFW
github.com/google/go-containerregistry v0.18.0/go.mod h1:u0qB2l7mvtWVR5kNcbFIhFY1hLbf8eeGapA+vbFDCtQ=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/martian/v3 v3.3.2 h1:IqNFLAmvJOgVlpdEBiQbDc2EwKW77amAycfTuWKdfvw=
github.com/google/martian/v3 v3.3.2/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk=
github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o=
github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
Expand All @@ -105,7 +107,9 @@ github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYs
github.com/klauspost/compress v1.16.5 h1:IFV2oUNUzZaz+XyusxpLzpzS8Pt5rh0Z16For/djlyI=
github.com/klauspost/compress v1.16.5/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
Expand All @@ -125,6 +129,7 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/secure-systems-lab/go-securesystemslib v0.8.0 h1:mr5An6X45Kb2nddcFlbmfHkLguCE9laoZCUzEEpIZXA=
github.com/secure-systems-lab/go-securesystemslib v0.8.0/go.mod h1:UH2VZVuJfCYR8WgMlCU1uFsOUU+KeyrTWcSS73NBOzU=
github.com/shibumi/go-pathspec v1.3.0 h1:QUyMZhFo0Md5B8zV8x2tesohbb5kfbpTi9rBnKh5dkI=
Expand Down Expand Up @@ -191,6 +196,7 @@ golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4=
golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
Expand Down Expand Up @@ -243,6 +249,7 @@ google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
Expand Down
4 changes: 3 additions & 1 deletion handle.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,9 @@ func createHttpHandler(handlers Handlers) func(http.ResponseWriter, *http.Reques

start := time.Now()
logger.Debugf("Skill execution started")
logger.Debugf("Incoming event message: %s", sanitizeEvent(body))
if req.Event.Type != "sync-request" {
logger.Debugf("Incoming event message: %s", sanitizeEvent(body))
}

defer func() {
logger.Debugf("Closing event handler '%s'", name)
Expand Down
20 changes: 8 additions & 12 deletions log.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,17 @@ import (
"strings"
"time"

"cloud.google.com/go/compute/metadata"
"cloud.google.com/go/logging"
"github.com/atomist-skills/go-skill/internal"
"github.com/sirupsen/logrus"
"golang.org/x/oauth2/google"
"olympos.io/encoding/edn"
)

var (
Log *logrus.Logger
projectID string
Log *logrus.Logger
projectID string
instanceID string
)

func init() {
Expand All @@ -61,14 +62,8 @@ func init() {

// try to obtain the GCP project id
if _, ok := os.LookupEnv("K_SERVICE"); ok {
ctx := context.Background()
credentials, err := google.FindDefaultCredentials(ctx, "https://www.googleapis.com/auth/compute")
if err == nil {
Log.Debugf("Found project id %s", credentials.ProjectID)
projectID = credentials.ProjectID
} else {
Log.Warnf("Failed to obtain project id: %s", err)
}
projectID, _ = metadata.ProjectID()
instanceID, _ = metadata.InstanceID()
}
}

Expand Down Expand Up @@ -115,7 +110,7 @@ func createLogger(ctx context.Context, event EventIncoming) Logger {

var doLog = func(msg string, level edn.Keyword) {
// Don't send logs when evaluating policies locally
if os.Getenv("SCOUT_LOCAL_POLICY_EVALUATION") == "true" {
if os.Getenv("SCOUT_LOCAL_POLICY_EVALUATION") == "true" || event.Type == "sync-request" {
return
}
bs, err := edn.MarshalPPrint(internal.LogBody{Logs: []internal.LogEntry{{
Expand Down Expand Up @@ -152,6 +147,7 @@ func createLogger(ctx context.Context, event EventIncoming) Logger {
labels["skill_namespace"] = event.Skill.Namespace
labels["skill_version"] = event.Skill.Version
labels["workspace_id"] = event.WorkspaceId
labels["instance_id"] = instanceID
}

var doGcpLog = func(msg string, level edn.Keyword) {
Expand Down
3 changes: 3 additions & 0 deletions policy/policy_handler/legacy/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@ import (
)

func BuildLocalEvalMocks(sb *types.SBOM, log skill.Logger) map[edn.Keyword]edn.RawMessage {
log.Info("Building local evaluation mocks")
m := map[edn.Keyword]edn.RawMessage{}
if sb == nil {
log.Info("No SBOM provided, returning empty map")
return m
}

Expand All @@ -18,6 +20,7 @@ func BuildLocalEvalMocks(sb *types.SBOM, log skill.Logger) map[edn.Keyword]edn.R
m[GetUserQueryName], _ = edn.Marshal(MockGetUserForLocalEval(sb.Source.Image.Config.Config.User))
}

log.Infof("SBOM has %d attestations", len(sb.Attestations))
if len(sb.Attestations) > 0 {
m[GetInTotoAttestationsQueryName], _ = edn.Marshal(MockGetInTotoAttestationsForLocalEval(sb, log))
}
Expand Down
10 changes: 9 additions & 1 deletion policy/policy_handler/legacy/builder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,9 +90,17 @@ func Test_BuildLocalEvalMocks(t *testing.T) {
},
},
}

logger := skill.Logger{
Info: func(msg string) {},
Infof: func(format string, a ...any) {

},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := BuildLocalEvalMocks(tt.args.sb, skill.Logger{}); !reflect.DeepEqual(got, tt.want) {
if got := BuildLocalEvalMocks(tt.args.sb, logger); !reflect.DeepEqual(got, tt.want) {
t.Errorf("BuildLocalEvalMocks() = %v, want %v", got, tt.want)
}
})
Expand Down
70 changes: 3 additions & 67 deletions policy/policy_handler/legacy/ssc_metadata.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ func MockGetInTotoAttestationsForLocalEval(sb *types.SBOM, log skill.Logger) Ima
if statement.PredicateType == ProvenancePredicateType && sb.Source.Provenance != nil && sb.Source.Provenance.SourceMap != nil {
for _, i := range sb.Source.Provenance.SourceMap.Instructions {
if i.Instruction == "FROM_RUNTIME" {
log.Infof("Found max-mode provenance instruction: %+v", i)
subject.Predicates = []Predicate{{StartLine: &i.StartLine}}
break
}
Expand All @@ -83,6 +84,8 @@ func MockGetInTotoAttestationsForLocalEval(sb *types.SBOM, log skill.Logger) Ima
subjects = append(subjects, subject)
}

log.Infof("Subjects: %+v", subjects)

return ImageAttestationQueryResult{
Digest: &sb.Source.Image.Digest,
Subjects: subjects,
Expand All @@ -101,70 +104,3 @@ func unmarshalInTotoStatement(content []byte) (*intotoStatement, error) {
}
return &stmt, nil
}

type provenanceDocument struct {
Invocation struct {
ConfigSource struct {
Uri string `json:"uri"`
Digest struct {
SHA1 string `json:"sha1"`
}
EntryPoint string `json:"entryPoint"`
} `json:"configSource"`
Parameters struct {
Args map[string]string `json:"args"`
} `json:"parameters"`
} `json:"invocation"`
BuildConfig struct {
DigestMapping map[string]string `json:"digestMapping"`
LLBDefinition []llbDefinition `json:"llbDefinition"`
} `json:"buildConfig"`
Metadata struct {
Buildkit struct {
VCS struct {
Revision string `json:"revision"`
Source string `json:"source"`
} `json:"vcs"`
Source struct {
Locations map[string]struct {
Locations []struct {
SourceIndex int `json:"sourceIndex"`
Ranges []struct {
Start struct {
Line int `json:"line"`
} `json:"start"`
End struct {
Line int `json:"line"`
} `json:"end"`
} `json:"ranges"`
} `json:"locations"`
} `json:"locations"`
Infos []struct {
Path string `json:"filename"`
Data string `json:"data"`
} `json:"infos"`
} `json:"source"`
Layers map[string][][]struct {
MediaType string `json:"mediaType"`
Digest string `json:"digest"`
Size int `json:"size"`
} `json:"layers"`
} `json:"https://mobyproject.org/buildkit@v1#metadata"`
} `json:"metadata"`
}

type llbDefinition struct {
ID string `json:"id"`
OP struct {
OP struct {
Source struct {
Identifier string `json:"identifier"`
} `json:"source"`
} `json:"Op"`
Platform struct {
OS string `json:"OS"`
Architecture string `json:"Architecture"`
Variant string `json:"Variant"`
}
} `json:"op"`
}
8 changes: 5 additions & 3 deletions policy/policy_handler/legacy/ssc_metadata_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,7 @@ func TestMockGetInTotoAttestationsForLocalEval(t *testing.T) {
}

type args struct {
sb *types.SBOM
log skill.Logger
sb *types.SBOM
}
tests := []struct {
name string
Expand Down Expand Up @@ -102,7 +101,10 @@ func TestMockGetInTotoAttestationsForLocalEval(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := MockGetInTotoAttestationsForLocalEval(tt.args.sb, tt.args.log); !reflect.DeepEqual(got, tt.want) {
logger := skill.Logger{
Infof: func(format string, a ...any) {},
}
if got := MockGetInTotoAttestationsForLocalEval(tt.args.sb, logger); !reflect.DeepEqual(got, tt.want) {
t.Errorf("MockGetInTotoAttestationsForLocalEval() = %v, want %v", got, tt.want)
}
})
Expand Down
36 changes: 32 additions & 4 deletions policy/policy_handler/local.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
package policy_handler

import (
"bytes"
"compress/gzip"
"context"
"encoding/base64"
"encoding/json"
"fmt"

"github.com/atomist-skills/go-skill"
"github.com/atomist-skills/go-skill/policy/data"
"github.com/atomist-skills/go-skill/policy/goals"
"github.com/atomist-skills/go-skill/policy/policy_handler/legacy"
"github.com/atomist-skills/go-skill/policy/types"
"io"
"olympos.io/encoding/edn"
)

Expand All @@ -18,7 +22,9 @@ type SyncRequestMetadata struct {
QueryResults map[edn.Keyword]edn.RawMessage `edn:"fixedQueryResults"`
Packages []legacy.Package `edn:"packages"` // todo remove when no longer used
User string `edn:"imgConfigUser"` // The user from the image config blob // todo remove when no longer used
SBOM *types.SBOM `edn:"sbom"`
SBOM string `edn:"sbom"`
ContentType string `edn:"contentType"`
Encoding string `edn:"encoding"`
}

func WithLocal() Opt {
Expand Down Expand Up @@ -59,8 +65,30 @@ func buildLocalDataSources(ctx context.Context, req skill.RequestContext, _ goal
return nil, fmt.Errorf("failed to unmarshal SyncRequest metadata: %w", err)
}

if srMeta.SBOM != nil {
srMeta.QueryResults = legacy.BuildLocalEvalMocks(srMeta.SBOM, req.Log)
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 = legacy.BuildLocalEvalMocks(sbom, req.Log)
}

fixedQueryResults := map[string][]byte{}
Expand Down

0 comments on commit a4f20cd

Please sign in to comment.