Skip to content

Commit

Permalink
JSON Schemas for attestors with generation scripts (#197)
Browse files Browse the repository at this point in the history
* setting up json schemas for attestors
---------

Signed-off-by: chaosinthecrd <[email protected]>
Signed-off-by: John Kjell <[email protected]>
Co-authored-by: John Kjell <[email protected]>
  • Loading branch information
ChaosInTheCRD and jkjell authored May 10, 2024
1 parent 87975b4 commit f346f85
Show file tree
Hide file tree
Showing 50 changed files with 4,094 additions and 48 deletions.
20 changes: 20 additions & 0 deletions .github/workflows/verify-schemagen.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
name: Docgen
on:
workflow_dispatch:
push:
branches: ["main", "release-*"]
pull_request:
permissions:
contents: read

jobs:
docgen:
name: Verify Docgen
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2
- uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0
with:
go-version: "1.21.x"
- run: ./schemagen/verify.sh
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,9 @@ $(CONTROLLER_GEN): $(LOCALBIN)
test: ## Run the go unit tests
go test -v -coverprofile=profile.cov -covermode=atomic ./...

.PHONY: schema
schema: ## Generate the attestor schema json files
go run ./schemagen/schema.go

help: ## Display this help screen
@grep -h -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
6 changes: 5 additions & 1 deletion attestation/aws-iid/aws-iid.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import (
"github.com/in-toto/go-witness/attestation"
"github.com/in-toto/go-witness/cryptoutil"
"github.com/in-toto/go-witness/log"
"github.com/invopop/jsonschema"
)

const (
Expand Down Expand Up @@ -99,7 +100,6 @@ func New() *Attestor {
session: *sess,
conf: conf,
}

}

func (a *Attestor) Name() string {
Expand All @@ -114,6 +114,10 @@ func (a *Attestor) RunType() attestation.RunType {
return RunType
}

func (a *Attestor) Schema() *jsonschema.Schema {
return jsonschema.Reflect(&a)
}

func (a *Attestor) Attest(ctx *attestation.AttestationContext) error {
a.hashes = ctx.Hashes()

Expand Down
5 changes: 5 additions & 0 deletions attestation/commandrun/commandrun.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"github.com/in-toto/go-witness/attestation"
"github.com/in-toto/go-witness/attestation/environment"
"github.com/in-toto/go-witness/cryptoutil"
"github.com/invopop/jsonschema"
)

const (
Expand Down Expand Up @@ -123,6 +124,10 @@ type CommandRun struct {
environmentBlockList map[string]struct{}
}

func (a *CommandRun) Schema() *jsonschema.Schema {
return jsonschema.Reflect(&a)
}

func (rc *CommandRun) Attest(ctx *attestation.AttestationContext) error {
if len(rc.Cmd) == 0 {
return attestation.ErrAttestor{
Expand Down
5 changes: 5 additions & 0 deletions attestation/environment/environment.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"strings"

"github.com/in-toto/go-witness/attestation"
"github.com/invopop/jsonschema"
)

const (
Expand Down Expand Up @@ -92,6 +93,10 @@ func (a *Attestor) RunType() attestation.RunType {
return RunType
}

func (a *Attestor) Schema() *jsonschema.Schema {
return jsonschema.Reflect(&a)
}

func (a *Attestor) Attest(ctx *attestation.AttestationContext) error {
a.OS = runtime.GOOS
a.Variables = make(map[string]string)
Expand Down
4 changes: 3 additions & 1 deletion attestation/factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (

"github.com/in-toto/go-witness/cryptoutil"
"github.com/in-toto/go-witness/registry"
"github.com/invopop/jsonschema"
)

var (
Expand All @@ -32,6 +33,7 @@ type Attestor interface {
Type() string
RunType() RunType
Attest(ctx *AttestationContext) error
Schema() *jsonschema.Schema
}

// Subjecter allows attestors to expose bits of information that will be added to
Expand Down Expand Up @@ -110,7 +112,7 @@ func GetAttestor(nameOrType string) (Attestor, error) {
return attestors[0], nil
}

// Deprecated: use AddAttestors instead
// Deprecated: use GetAttestors instead
func Attestors(nameOrTypes []string) ([]Attestor, error) {
return GetAttestors(nameOrTypes)
}
Expand Down
8 changes: 7 additions & 1 deletion attestation/factory_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ package attestation
import (
"testing"

"github.com/invopop/jsonschema"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
Expand All @@ -27,7 +28,8 @@ func TestRegistry(t *testing.T) {
name: "prerun",
predicateType: "https://witness.dev/test/prerun",
runType: PreMaterialRunType,
}, {
},
{
name: "execute",
predicateType: "https://witness.dev/test/execute",
runType: ExecuteRunType,
Expand Down Expand Up @@ -70,6 +72,10 @@ func (a *dummyAttestor) RunType() RunType {
return a.runType
}

func (a *dummyAttestor) Schema() *jsonschema.Schema {
return jsonschema.Reflect(&a)
}

func (a *dummyAttestor) Attest(*AttestationContext) error {
return nil
}
10 changes: 9 additions & 1 deletion attestation/gcp-iit/gcp-iit.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (
"github.com/in-toto/go-witness/attestation/jwt"
"github.com/in-toto/go-witness/cryptoutil"
"github.com/in-toto/go-witness/log"
"github.com/invopop/jsonschema"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
Expand Down Expand Up @@ -98,6 +99,14 @@ func (a *Attestor) RunType() attestation.RunType {
return RunType
}

func (a *Attestor) Schema() *jsonschema.Schema {
// NOTE: This isn't ideal. For some reason the reflect function is return an empty schema when passing in `p`
// TODO: Fix this later
schema := jsonschema.Reflect(&a)
schema.Definitions["Attestor"].Properties.Set("jwt", jsonschema.Reflect(&a.JWT))
return schema
}

func (a *Attestor) Attest(ctx *attestation.AttestationContext) error {
tokenURL := identityTokenURL(defaultIdentityTokenHost, defaultServiceAccount)
identityToken, err := getMetadata(tokenURL)
Expand Down Expand Up @@ -171,7 +180,6 @@ func (a *Attestor) getInstanceData() {

a.ProjectID = projID
a.ProjectNumber = projNum

}

func (a *Attestor) Subjects() map[string]cryptoutil.DigestSet {
Expand Down
23 changes: 12 additions & 11 deletions attestation/git/git.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
"github.com/go-git/go-git/v5/plumbing/object"
"github.com/in-toto/go-witness/attestation"
"github.com/in-toto/go-witness/cryptoutil"
"github.com/invopop/jsonschema"
)

const (
Expand Down Expand Up @@ -113,11 +114,14 @@ func (a *Attestor) RunType() attestation.RunType {
return RunType
}

func (a *Attestor) Schema() *jsonschema.Schema {
return jsonschema.Reflect(&a)
}

func (a *Attestor) Attest(ctx *attestation.AttestationContext) error {
repo, err := git.PlainOpenWithOptions(ctx.WorkingDir(), &git.PlainOpenOptions{
DetectDotGit: true,
})

if err != nil {
return err
}
Expand Down Expand Up @@ -151,20 +155,19 @@ func (a *Attestor) Attest(ctx *attestation.AttestationContext) error {
a.Remotes = append(a.Remotes, remote.Config().URLs...)
}

//get all the refs for the repo
refs, err := repo.References()
if err != nil {
return err
}

//iterate over the refs and add them to the attestor
// iterate over the refs and add them to the attestor
err = refs.ForEach(func(ref *plumbing.Reference) error {
//only add the ref if it points to the head
// only add the ref if it points to the head
if ref.Hash() != head.Hash() {
return nil
}

//add the ref name to the attestor
// add the ref name to the attestor
a.Refs = append(a.Refs, ref.Name().String())

return nil
Expand Down Expand Up @@ -194,8 +197,7 @@ func (a *Attestor) Attest(ctx *attestation.AttestationContext) error {
var tagList []Tag

err = tags.ForEach(func(t *object.Tag) error {

//check if the tag points to the head
// check if the tag points to the head
if t.Target.String() != head.Hash().String() {
return nil
}
Expand All @@ -210,7 +212,6 @@ func (a *Attestor) Attest(ctx *attestation.AttestationContext) error {
})
return nil
})

if err != nil {
return fmt.Errorf("iterate tags error: %s", err)
}
Expand Down Expand Up @@ -260,7 +261,7 @@ func (a *Attestor) Subjects() map[string]cryptoutil.DigestSet {
}: a.CommitHash,
}

//add author email
// add author email
subjectName = fmt.Sprintf("authoremail:%v", a.AuthorEmail)
ds, err := cryptoutil.CalculateDigestSetFromBytes([]byte(a.AuthorEmail), hashes)
if err != nil {
Expand All @@ -269,7 +270,7 @@ func (a *Attestor) Subjects() map[string]cryptoutil.DigestSet {

subjects[subjectName] = ds

//add committer email
// add committer email
subjectName = fmt.Sprintf("committeremail:%v", a.CommitterEmail)
ds, err = cryptoutil.CalculateDigestSetFromBytes([]byte(a.CommitterEmail), hashes)
if err != nil {
Expand All @@ -278,7 +279,7 @@ func (a *Attestor) Subjects() map[string]cryptoutil.DigestSet {

subjects[subjectName] = ds

//add parent hashes
// add parent hashes
for _, parentHash := range a.ParentHashes {
subjectName = fmt.Sprintf("parenthash:%v", parentHash)
ds, err = cryptoutil.CalculateDigestSetFromBytes([]byte(parentHash), hashes)
Expand Down
9 changes: 9 additions & 0 deletions attestation/github/github.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import (
"github.com/in-toto/go-witness/attestation/jwt"
"github.com/in-toto/go-witness/cryptoutil"
"github.com/in-toto/go-witness/log"
"github.com/invopop/jsonschema"
)

const (
Expand Down Expand Up @@ -124,6 +125,14 @@ func (a *Attestor) RunType() attestation.RunType {
return RunType
}

func (a *Attestor) Schema() *jsonschema.Schema {
// NOTE: This isn't ideal. For some reason the reflect function is return an empty schema when passing in `p`
// TODO: Fix this later
schema := jsonschema.Reflect(&a)
schema.Definitions["Attestor"].Properties.Set("jwt", jsonschema.Reflect(&a.JWT))
return schema
}

// Attest performs the attestation for the github environment.
func (a *Attestor) Attest(ctx *attestation.AttestationContext) error {
if os.Getenv("GITHUB_ACTIONS") != "true" {
Expand Down
9 changes: 9 additions & 0 deletions attestation/gitlab/gitlab.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
"github.com/in-toto/go-witness/attestation/jwt"
"github.com/in-toto/go-witness/cryptoutil"
"github.com/in-toto/go-witness/log"
"github.com/invopop/jsonschema"
)

const (
Expand Down Expand Up @@ -101,6 +102,14 @@ func (a *Attestor) RunType() attestation.RunType {
return RunType
}

func (a *Attestor) Schema() *jsonschema.Schema {
// NOTE: This isn't ideal. For some reason the reflect function is return an empty schema when passing in `p`
// TODO: Fix this later
schema := jsonschema.Reflect(&a)
schema.Definitions["Attestor"].Properties.Set("jwt", jsonschema.Reflect(&a.JWT))
return schema
}

func (a *Attestor) Attest(ctx *attestation.AttestationContext) error {
if os.Getenv("GITLAB_CI") != "true" {
return ErrNotGitlab{}
Expand Down
5 changes: 5 additions & 0 deletions attestation/jwt/jwt.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"net/http"

"github.com/in-toto/go-witness/attestation"
"github.com/invopop/jsonschema"
"gopkg.in/square/go-jose.v2"
"gopkg.in/square/go-jose.v2/jwt"
)
Expand Down Expand Up @@ -86,6 +87,10 @@ func New(opts ...Option) *Attestor {
return a
}

func (a *Attestor) Schema() *jsonschema.Schema {
return jsonschema.Reflect(&a)
}

func (a *Attestor) Attest(ctx *attestation.AttestationContext) error {
if a.token == "" {
return ErrInvalidToken(a.token)
Expand Down
7 changes: 7 additions & 0 deletions attestation/link/link.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (
"github.com/in-toto/go-witness/attestation/product"
"github.com/in-toto/go-witness/cryptoutil"
"github.com/in-toto/go-witness/registry"
"github.com/invopop/jsonschema"
"google.golang.org/protobuf/types/known/structpb"
)

Expand Down Expand Up @@ -94,6 +95,12 @@ func (l *Link) RunType() attestation.RunType {
return RunType
}

func (l *Link) Schema() *jsonschema.Schema {
// NOTE: This isn't ideal. For some reason the reflect function is return an empty schema when passing in `p`
// TODO: Fix this later
return jsonschema.Reflect(&v0.Link{})
}

func (l *Link) Export() bool {
return l.export
}
Expand Down
9 changes: 9 additions & 0 deletions attestation/material/material.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"github.com/in-toto/go-witness/attestation"
"github.com/in-toto/go-witness/attestation/file"
"github.com/in-toto/go-witness/cryptoutil"
"github.com/invopop/jsonschema"
)

const (
Expand Down Expand Up @@ -80,6 +81,14 @@ func New(opts ...Option) *Attestor {
return attestor
}

func (a *Attestor) Schema() *jsonschema.Schema {
// NOTE: This isn't ideal. For some reason the reflect function is return an empty schema when passing in `a`
// TODO: Fix this later
return jsonschema.Reflect(struct {
Materials map[string]cryptoutil.DigestSet
}{})
}

func (a *Attestor) Attest(ctx *attestation.AttestationContext) error {
materials, err := file.RecordArtifacts(ctx.WorkingDir(), nil, ctx.Hashes(), map[string]struct{}{})
if err != nil {
Expand Down
Loading

0 comments on commit f346f85

Please sign in to comment.