Skip to content

Commit

Permalink
Mock attestations
Browse files Browse the repository at this point in the history
  • Loading branch information
felipecruz91 committed Jan 30, 2024
1 parent 9cb2e00 commit d6f705d
Show file tree
Hide file tree
Showing 10 changed files with 2,927 additions and 21 deletions.
10 changes: 6 additions & 4 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ require (
github.com/google/uuid v1.3.1
github.com/hasura/go-graphql-client v0.9.3
github.com/mitchellh/hashstructure/v2 v2.0.1
github.com/secure-systems-lab/go-securesystemslib v0.8.0
github.com/sirupsen/logrus v1.9.3
github.com/stretchr/testify v1.8.4
golang.org/x/oauth2 v0.13.0
Expand All @@ -17,8 +18,8 @@ require (
)

require (
github.com/kr/text v0.2.0 // indirect
github.com/package-url/packageurl-go v0.1.1 // indirect
github.com/shibumi/go-pathspec v1.3.0 // indirect
)

require (
Expand All @@ -34,15 +35,16 @@ require (
github.com/google/s2a-go v0.1.7 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.3.1 // indirect
github.com/googleapis/gax-go/v2 v2.12.0 // indirect
github.com/in-toto/in-toto-golang v0.9.0
github.com/klauspost/compress v1.16.5 // indirect
github.com/openvex/go-vex v0.2.5
github.com/pmezard/go-difflib v1.0.0 // indirect
go.opencensus.io v0.24.0 // indirect
golang.org/x/crypto v0.14.0 // indirect
golang.org/x/crypto v0.17.0 // indirect
golang.org/x/net v0.17.0 // indirect
golang.org/x/sync v0.4.0 // indirect
golang.org/x/sys v0.13.0 // indirect
golang.org/x/text v0.13.0 // indirect
golang.org/x/sys v0.15.0 // indirect
golang.org/x/text v0.14.0 // indirect
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20231002182017-d307bd883b97 // indirect
Expand Down
22 changes: 14 additions & 8 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
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/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/codahale/rfc6979 v0.0.0-20141003034818-6a90f24967eb h1:EDmT6Q9Zs+SbUoc7Ik9EfrFqcylYqgPZ9ANSbTAntnE=
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 @@ -97,14 +97,15 @@ github.com/graph-gophers/graphql-transport-ws v0.0.2 h1:DbmSkbIGzj8SvHei6n8Mh9eL
github.com/graph-gophers/graphql-transport-ws v0.0.2/go.mod h1:5BVKvFzOd2BalVIBFfnfmHjpJi/MZ5rOj8G55mXvZ8g=
github.com/hasura/go-graphql-client v0.9.3 h1:Xi3fqa2t9q4nJ2jM2AU8nB6qeAoMpbcYDiOSBnNAN1E=
github.com/hasura/go-graphql-client v0.9.3/go.mod h1:AarJlxO1I59MPqU/TC7gQP0BMFgPEqUTt5LYPvykasw=
github.com/in-toto/in-toto-golang v0.9.0 h1:tHny7ac4KgtsfrG6ybU8gVOZux2H8jN05AXJ9EBM1XU=
github.com/in-toto/in-toto-golang v0.9.0/go.mod h1:xsBVrVsHNsB61++S6Dy2vWosKhuA3lUTQd+eF9HdeMo=
github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns=
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
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/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 @@ -124,6 +125,10 @@ 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/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=
github.com/shibumi/go-pathspec v1.3.0/go.mod h1:Xutfslp817l2I1cZvgcfeMQJG5QnU2lh5tVaaMCl3jE=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
Expand All @@ -148,8 +153,8 @@ go.opentelemetry.io/otel/trace v1.6.3/go.mod h1:GNJQusJlUgZl9/TQBPKU/Y/ty+0iVB5f
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20220314234659-1baeb1ce4c0b/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k=
golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
Expand Down Expand Up @@ -182,15 +187,16 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
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/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=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
Expand Down
7 changes: 4 additions & 3 deletions policy/policy_handler/legacy/builder.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
package legacy

import (
"github.com/atomist-skills/go-skill"
"github.com/atomist-skills/go-skill/policy/types"
"olympos.io/encoding/edn"
)

func BuildLocalEvalMocks(sb *types.SBOM) map[edn.Keyword]edn.RawMessage {
func BuildLocalEvalMocks(sb *types.SBOM, log skill.Logger) map[edn.Keyword]edn.RawMessage {
m := map[edn.Keyword]edn.RawMessage{}
if sb == nil {
return m
Expand All @@ -17,8 +18,8 @@ func BuildLocalEvalMocks(sb *types.SBOM) map[edn.Keyword]edn.RawMessage {
m[GetUserQueryName], _ = edn.Marshal(MockGetUserForLocalEval(sb.Source.Image.Config.Config.User))
}

if sb.Source.Provenance != nil {
m[GetInTotoAttestationsQueryName], _ = edn.Marshal(MockGetInTotoAttestationsForLocalEval(sb))
if len(sb.Attestations) > 0 {
m[GetInTotoAttestationsQueryName], _ = edn.Marshal(MockGetInTotoAttestationsForLocalEval(sb, log))
}

return m
Expand Down
3 changes: 2 additions & 1 deletion policy/policy_handler/legacy/builder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"reflect"
"testing"

"github.com/atomist-skills/go-skill"
"github.com/atomist-skills/go-skill/policy/types"
v1 "github.com/google/go-containerregistry/pkg/v1"
"olympos.io/encoding/edn"
Expand Down Expand Up @@ -91,7 +92,7 @@ func Test_BuildLocalEvalMocks(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := BuildLocalEvalMocks(tt.args.sb); !reflect.DeepEqual(got, tt.want) {
if got := BuildLocalEvalMocks(tt.args.sb, skill.Logger{}); !reflect.DeepEqual(got, tt.want) {
t.Errorf("BuildLocalEvalMocks() = %v, want %v", got, tt.want)
}
})
Expand Down
165 changes: 162 additions & 3 deletions policy/policy_handler/legacy/ssc_metadata.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,28 @@
package legacy

import "github.com/atomist-skills/go-skill/policy/types"
import (
"encoding/base64"
"encoding/json"
"slices"

"github.com/atomist-skills/go-skill"
"github.com/atomist-skills/go-skill/policy/types"
intoto "github.com/in-toto/in-toto-golang/in_toto"
)

const (
GetInTotoAttestationsQueryName = "get-intoto-attestations"
)

const (
SPDXPredicateType = "https://spdx.dev/Document"
ProvenancePredicateType = "https://slsa.dev/provenance/v0.2"
)

var (
allowedPredicateTypes = []string{SPDXPredicateType, ProvenancePredicateType}
)

type ImageAttestationQueryResult struct {
Digest *string `edn:"docker.image/digest"`
Subjects []Subject `edn:"intoto.attestation/_subject"`
Expand All @@ -20,6 +37,148 @@ type Predicate struct {
StartLine *int `edn:"slsa.provenance.from/start-line"` // if field is present then provenance is max-mode
}

func MockGetInTotoAttestationsForLocalEval(sb *types.SBOM) ImageAttestationQueryResult {
return ImageAttestationQueryResult{} // incompatible with local evaluation until SBOM includes the raw attestations
// https://github.com/in-toto/attestation/blob/main/spec/README.md
// https://github.com/secure-systems-lab/dsse/blob/master/envelope.md
func MockGetInTotoAttestationsForLocalEval(sb *types.SBOM, log skill.Logger) ImageAttestationQueryResult {
subjects := []Subject{}

// The envelope is the outtermost layer of the attestation
for _, env := range sb.Attestations {
if env.PayloadType != "application/vnd.in-toto+json" {
log.Warnf("Ignoring non-in-toto attestation, payload type: %s", env.PayloadType)
continue
}

// The envelope's payload is a base64-encoded JSON string
payload, err := base64.StdEncoding.DecodeString(env.Payload)
if err != nil {
log.Errorf("Failed to base64-decode in-toto attestation payload: %v", err)
continue
}

statement, err := unmarshalInTotoStatement(payload)
if err != nil {
log.Errorf("Failed to unmarshal in-toto statement %s: %v", string(payload), err)
continue
}

if !slices.Contains(allowedPredicateTypes, statement.PredicateType) {
log.Warnf("Skipping in-toto statement due to unknown predicate type: %s. Allowed predicated types: %+v", statement.PredicateType, allowedPredicateTypes)
continue
}

subject := Subject{
PredicateType: &statement.PredicateType,
}

if statement.PredicateType == ProvenancePredicateType {
pr, err := decodeProvenance(statement.Predicate)
if err != nil {
log.Errorf("Failed to decode provenance predicate: %+v", err)
continue
}

if step0, found := pr.Metadata.Buildkit.Source.Locations["step0"]; found && len(step0.Locations) > 0 {
ranges := step0.Locations[0].Ranges
if len(ranges) > 0 {
subject.Predicates = []Predicate{{StartLine: &ranges[0].Start.Line}}
}
}
}

subjects = append(subjects, subject)
}

return ImageAttestationQueryResult{
Digest: &sb.Source.Image.Digest,
Subjects: subjects,
}
}

type intotoStatement struct {
intoto.StatementHeader
Predicate json.RawMessage `json:"predicate"`
}

func unmarshalInTotoStatement(content []byte) (*intotoStatement, error) {
var stmt intotoStatement
if err := json.Unmarshal(content, &stmt); err != nil {
return nil, err
}
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"`
}

func decodeProvenance(dt []byte) (s *provenanceDocument, err error) {
var stmt provenanceDocument
if err = json.Unmarshal(dt, &stmt); err != nil {
return nil, err
}
return &stmt, nil
}
Loading

0 comments on commit d6f705d

Please sign in to comment.