From 1ddaf9ef90c2287a9704efd7fd4f501828181acd Mon Sep 17 00:00:00 2001 From: Matthias Glastra Date: Tue, 24 Sep 2024 21:22:39 +0200 Subject: [PATCH] chore: Add additional git attestor output. When the git binary is used to for status we also include the path to the binary and the hash of the binary files. Also by default the git tool used to generate the attestation data is added as contextual information. Signed-off-by: Matthias Glastra --- attestation/git/git.go | 17 +++++++++++++++++ attestation/git/git_bin.go | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+) diff --git a/attestation/git/git.go b/attestation/git/git.go index 1e2b5b2a..4ded0b93 100644 --- a/attestation/git/git.go +++ b/attestation/git/git.go @@ -79,6 +79,9 @@ type Tag struct { } type Attestor struct { + GitTool string `json:"gittool"` + GitBinPath string `json:"gitbinpath,omitempty"` + GitBinHash string `json:"gitbinhash,omitempty"` CommitHash string `json:"commithash"` Author string `json:"author"` AuthorEmail string `json:"authoremail"` @@ -222,11 +225,25 @@ func (a *Attestor) Attest(ctx *attestation.AttestationContext) error { a.TreeHash = commit.TreeHash.String() if GitExists() { + a.GitTool = "go-git+git-bin" + + a.GitBinPath, err = GitGetBinPath() + if err != nil { + return err + } + + a.GitBinHash, err = GitGetBinHash(ctx) + if err != nil { + return err + } + a.Status, err = GitGetStatus(ctx.WorkingDir()) if err != nil { return err } } else { + a.GitTool = "go-git" + a.Status, err = GoGitGetStatus(repo) if err != nil { return err diff --git a/attestation/git/git_bin.go b/attestation/git/git_bin.go index 21432ce7..22853a1a 100644 --- a/attestation/git/git_bin.go +++ b/attestation/git/git_bin.go @@ -15,10 +15,13 @@ package git import ( + "fmt" "os/exec" "strings" "github.com/go-git/go-git/v5" + "github.com/in-toto/go-witness/attestation" + "github.com/in-toto/go-witness/cryptoutil" ) // GitExists checks if the git binary is available. @@ -33,6 +36,40 @@ func GitExists() bool { } } +// GitGetBinPath retrieves the path to the git binary that is used by the attestor. +func GitGetBinPath() (string, error) { + path, err := exec.LookPath("git") + if err != nil { + return "", err + } else { + return path, nil + } +} + +// GitGetBinHash retrieves a sha256 hash of the git binary that is located on the system. +// The path is determined based on exec.LookPath(). +func GitGetBinHash(ctx *attestation.AttestationContext) (string, error) { + path, err := exec.LookPath("git") + if err != nil { + return "", err + } + + gitBinDigest, err := cryptoutil.CalculateDigestSetFromFile(path, ctx.Hashes()) + fmt.Printf("%s", gitBinDigest) + if err != nil { + return "", err + } + + digestMap, err := gitBinDigest.ToNameMap() + if err != nil { + return "", err + } + + return fmt.Sprintf("sha256:%s", digestMap["sha256"]), nil +} + +// GitGetStatus retrieves the status of staging and worktree +// from the git status --porcelain output func GitGetStatus(workDir string) (map[string]Status, error) { // Execute the git status --porcelain command