hishtory/client/lib/slsa.go

80 lines
2.2 KiB
Go

package lib
import (
"context"
"crypto/sha256"
"encoding/hex"
"fmt"
"io"
"os"
"strconv"
"strings"
"github.com/slsa-framework/slsa-verifier/options"
"github.com/slsa-framework/slsa-verifier/verifiers"
)
func verify(provenance []byte, artifactHash, source, branch, versionTag string) error {
provenanceOpts := &options.ProvenanceOpts{
ExpectedSourceURI: source,
ExpectedBranch: &branch,
ExpectedDigest: artifactHash,
ExpectedVersionedTag: &versionTag,
}
builderOpts := &options.BuilderOpts{}
_, _, err := verifiers.Verify(context.TODO(), provenance, artifactHash, provenanceOpts, builderOpts)
return err
}
func checkForDowngrade(currentVersionS, newVersionS string) error {
currentVersion, err := strconv.Atoi(strings.TrimPrefix(currentVersionS, "v0."))
if err != nil {
return fmt.Errorf("failed to parse current version %#v", currentVersionS)
}
newVersion, err := strconv.Atoi(strings.TrimPrefix(newVersionS, "v0."))
if err != nil {
return fmt.Errorf("failed to parse updated version %#v", newVersionS)
}
if currentVersion > newVersion {
return fmt.Errorf("failed to update because the new version (%#v) is a downgrade compared to the current version (%#v)", newVersionS, currentVersionS)
}
return nil
}
func verifyBinary(binaryPath, attestationPath, versionTag string) error {
if os.Getenv("HISHTORY_DISABLE_SLSA_ATTESTATION") == "true" {
return nil
}
if err := checkForDowngrade(Version, versionTag); err != nil && os.Getenv("HISHTORY_ALLOW_DOWNGRADE") == "true" {
return err
}
attestation, err := os.ReadFile(attestationPath)
if err != nil {
return fmt.Errorf("failed to read attestation file: %v", err)
}
hash, err := getFileHash(binaryPath)
if err != nil {
return err
}
return verify(attestation, hash, "github.com/ddworken/hishtory", "master", versionTag)
}
func getFileHash(binaryPath string) (string, error) {
binaryFile, err := os.Open(binaryPath)
if err != nil {
return "", fmt.Errorf("failed to read binary for verification purposes: %v", err)
}
defer binaryFile.Close()
hasher := sha256.New()
if _, err := io.Copy(hasher, binaryFile); err != nil {
return "", fmt.Errorf("failed to hash binary: %v", err)
}
hash := hex.EncodeToString(hasher.Sum(nil))
return hash, nil
}