mirror of
https://github.com/ddworken/hishtory.git
synced 2025-02-22 21:41:01 +01:00
Move a bunch of update-specific code out of the generic lib.go file and into the update command
This commit is contained in:
parent
f3e4a4e1e6
commit
6d6a1a5e12
@ -1,8 +1,21 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path"
|
||||
"runtime"
|
||||
"syscall"
|
||||
|
||||
"github.com/ddworken/hishtory/client/data"
|
||||
"github.com/ddworken/hishtory/client/hctx"
|
||||
"github.com/ddworken/hishtory/client/lib"
|
||||
"github.com/ddworken/hishtory/shared"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
@ -10,10 +23,232 @@ var updateCmd = &cobra.Command{
|
||||
Use: "update",
|
||||
Short: "Securely update hishtory to the latest version",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
lib.CheckFatalError(lib.Update(hctx.MakeContext()))
|
||||
lib.CheckFatalError(update(hctx.MakeContext()))
|
||||
},
|
||||
}
|
||||
|
||||
func update(ctx context.Context) error {
|
||||
// Download the binary
|
||||
downloadData, err := lib.GetDownloadData()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if downloadData.Version == "v0."+lib.Version {
|
||||
fmt.Printf("Latest version (v0.%s) is already installed\n", lib.Version)
|
||||
return nil
|
||||
}
|
||||
err = downloadFiles(downloadData)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Verify the SLSA attestation
|
||||
var slsaError error
|
||||
if runtime.GOOS == "darwin" {
|
||||
slsaError = verifyBinaryMac(ctx, getTmpClientPath(), downloadData)
|
||||
} else {
|
||||
slsaError = lib.VerifyBinary(ctx, getTmpClientPath(), getTmpClientPath()+".intoto.jsonl", downloadData.Version)
|
||||
}
|
||||
if slsaError != nil {
|
||||
err = lib.HandleSlsaFailure(slsaError)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Unlink the existing binary so we can overwrite it even though it is still running
|
||||
if runtime.GOOS == "linux" {
|
||||
homedir := hctx.GetHome(ctx)
|
||||
err = syscall.Unlink(path.Join(homedir, data.GetHishtoryPath(), "hishtory"))
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to unlink %s for update: %w", path.Join(homedir, data.GetHishtoryPath(), "hishtory"), err)
|
||||
}
|
||||
}
|
||||
|
||||
// Install the new one
|
||||
cmd := exec.Command("chmod", "+x", getTmpClientPath())
|
||||
var stdout bytes.Buffer
|
||||
cmd.Stdout = &stdout
|
||||
var stderr bytes.Buffer
|
||||
cmd.Stderr = &stderr
|
||||
err = cmd.Run()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to chmod +x the update (stdout=%#v, stderr=%#v): %w", stdout.String(), stderr.String(), err)
|
||||
}
|
||||
cmd = exec.Command(getTmpClientPath(), "install")
|
||||
cmd.Stdout = os.Stdout
|
||||
stderr = bytes.Buffer{}
|
||||
cmd.Stdin = os.Stdin
|
||||
err = cmd.Run()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to install update (stderr=%#v), is %s in a noexec directory? (if so, set the TMPDIR environment variable): %w", stderr.String(), getTmpClientPath(), err)
|
||||
}
|
||||
fmt.Printf("Successfully updated hishtory from v0.%s to %s\n", lib.Version, downloadData.Version)
|
||||
return nil
|
||||
}
|
||||
|
||||
func verifyBinaryMac(ctx context.Context, binaryPath string, downloadData shared.UpdateInfo) error {
|
||||
// On Mac, binary verification is a bit more complicated since mac binaries are code
|
||||
// signed. To verify a signed binary, we:
|
||||
// 1. Download the unsigned binary
|
||||
// 2. Strip the real signature from the signed binary and the ad-hoc signature from the unsigned binary
|
||||
// 3. Assert that those binaries match
|
||||
// 4. Use SLSA to verify the unsigned binary (pre-strip)
|
||||
// Yes, this is complicated. But AFAICT, it is the only solution here.
|
||||
|
||||
// Step 1: Download the "unsigned" binary that actually has an ad-hoc signature from the
|
||||
// go compiler.
|
||||
unsignedBinaryPath := binaryPath + "-unsigned"
|
||||
var err error = nil
|
||||
if runtime.GOOS == "darwin" && runtime.GOARCH == "amd64" {
|
||||
err = downloadFile(unsignedBinaryPath, downloadData.DarwinAmd64UnsignedUrl)
|
||||
} else if runtime.GOOS == "darwin" && runtime.GOARCH == "arm64" {
|
||||
err = downloadFile(unsignedBinaryPath, downloadData.DarwinArm64UnsignedUrl)
|
||||
} else {
|
||||
err = fmt.Errorf("verifyBinaryMac() called for the unhandled branch GOOS=%s, GOARCH=%s", runtime.GOOS, runtime.GOARCH)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Step 2: Create the .nosig files that have no signatures whatsoever
|
||||
noSigSuffix := ".nosig"
|
||||
err = stripCodeSignature(binaryPath, binaryPath+noSigSuffix)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = stripCodeSignature(unsignedBinaryPath, unsignedBinaryPath+noSigSuffix)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Step 3: Compare the binaries
|
||||
err = assertIdenticalBinaries(binaryPath+noSigSuffix, unsignedBinaryPath+noSigSuffix)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Step 4: Use SLSA to verify the unsigned binary
|
||||
return lib.VerifyBinary(ctx, unsignedBinaryPath, getTmpClientPath()+".intoto.jsonl", downloadData.Version)
|
||||
}
|
||||
|
||||
func assertIdenticalBinaries(bin1Path, bin2Path string) error {
|
||||
bin1, err := os.ReadFile(bin1Path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
bin2, err := os.ReadFile(bin2Path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(bin1) != len(bin2) {
|
||||
return fmt.Errorf("unsigned binaries have different lengths (len(%s)=%d, len(%s)=%d)", bin1Path, len(bin1), bin2Path, len(bin2))
|
||||
}
|
||||
differences := make([]string, 0)
|
||||
for i := range bin1 {
|
||||
b1 := bin1[i]
|
||||
b2 := bin2[i]
|
||||
if b1 != b2 {
|
||||
differences = append(differences, fmt.Sprintf("diff at index %d: %s[%d]=%x, %s[%d]=%x", i, bin1Path, i, b1, bin2Path, i, b2))
|
||||
}
|
||||
}
|
||||
for _, d := range differences {
|
||||
hctx.GetLogger().Infof("comparing binaries: %#v\n", d)
|
||||
}
|
||||
if len(differences) > 5 {
|
||||
return fmt.Errorf("found %d differences in the binary", len(differences))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func stripCodeSignature(inPath, outPath string) error {
|
||||
_, err := exec.LookPath("codesign_allocate")
|
||||
if err != nil {
|
||||
return fmt.Errorf("your system is missing the codesign_allocate tool, so we can't verify the SLSA attestation (you can bypass this by setting `export HISHTORY_DISABLE_SLSA_ATTESTATION=true` in your shell)")
|
||||
}
|
||||
cmd := exec.Command("codesign_allocate", "-i", inPath, "-o", outPath, "-r")
|
||||
var stdout bytes.Buffer
|
||||
cmd.Stdout = &stdout
|
||||
var stderr bytes.Buffer
|
||||
cmd.Stderr = &stderr
|
||||
err = cmd.Run()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to use codesign_allocate to strip signatures on binary=%v (stdout=%#v, stderr%#v): %w", inPath, stdout.String(), stderr.String(), err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func downloadFiles(updateInfo shared.UpdateInfo) error {
|
||||
clientUrl := ""
|
||||
clientProvenanceUrl := ""
|
||||
if runtime.GOOS == "linux" && runtime.GOARCH == "amd64" {
|
||||
clientUrl = updateInfo.LinuxAmd64Url
|
||||
clientProvenanceUrl = updateInfo.LinuxAmd64AttestationUrl
|
||||
} else if runtime.GOOS == "linux" && runtime.GOARCH == "arm64" {
|
||||
clientUrl = updateInfo.LinuxArm64Url
|
||||
clientProvenanceUrl = updateInfo.LinuxArm64AttestationUrl
|
||||
} else if runtime.GOOS == "linux" && runtime.GOARCH == "arm" {
|
||||
clientUrl = updateInfo.LinuxArm7Url
|
||||
clientProvenanceUrl = updateInfo.LinuxArm7AttestationUrl
|
||||
} else if runtime.GOOS == "darwin" && runtime.GOARCH == "amd64" {
|
||||
clientUrl = updateInfo.DarwinAmd64Url
|
||||
clientProvenanceUrl = updateInfo.DarwinAmd64AttestationUrl
|
||||
} else if runtime.GOOS == "darwin" && runtime.GOARCH == "arm64" {
|
||||
clientUrl = updateInfo.DarwinArm64Url
|
||||
clientProvenanceUrl = updateInfo.DarwinArm64AttestationUrl
|
||||
} else {
|
||||
return fmt.Errorf("no update info found for GOOS=%s, GOARCH=%s", runtime.GOOS, runtime.GOARCH)
|
||||
}
|
||||
err := downloadFile(getTmpClientPath(), clientUrl)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = downloadFile(getTmpClientPath()+".intoto.jsonl", clientProvenanceUrl)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func getTmpClientPath() string {
|
||||
tmpDir := "/tmp/"
|
||||
if os.Getenv("TMPDIR") != "" {
|
||||
tmpDir = os.Getenv("TMPDIR")
|
||||
}
|
||||
return path.Join(tmpDir, "hishtory-client")
|
||||
}
|
||||
|
||||
func downloadFile(filename, url string) error {
|
||||
// Download the data
|
||||
resp, err := http.Get(url)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to download file at %s to %s: %w", url, filename, err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode != 200 {
|
||||
return fmt.Errorf("failed to download file at %s due to resp_code=%d", url, resp.StatusCode)
|
||||
}
|
||||
|
||||
// Delete the file if it already exists. This is necessary due to https://openradar.appspot.com/FB8735191
|
||||
if _, err := os.Stat(filename); err == nil {
|
||||
err = os.Remove(filename)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to delete file %v when trying to download a new version", filename)
|
||||
}
|
||||
}
|
||||
|
||||
// Create the file
|
||||
out, err := os.Create(filename)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to save file to %s: %w", filename, err)
|
||||
}
|
||||
defer out.Close()
|
||||
|
||||
_, err = io.Copy(out, resp.Body)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(updateCmd)
|
||||
}
|
||||
|
@ -12,14 +12,11 @@ import (
|
||||
"math/rand"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/exec"
|
||||
"os/user"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"runtime"
|
||||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
_ "embed" // for embedding config.sh
|
||||
@ -383,6 +380,13 @@ func readFileToArray(path string) ([]string, error) {
|
||||
return lines, nil
|
||||
}
|
||||
|
||||
func getServerHostname() string {
|
||||
if server := os.Getenv("HISHTORY_SERVER"); server != "" {
|
||||
return server
|
||||
}
|
||||
return "https://api.hishtory.dev"
|
||||
}
|
||||
|
||||
func GetDownloadData() (shared.UpdateInfo, error) {
|
||||
respBody, err := ApiGet("/api/v1/download")
|
||||
if err != nil {
|
||||
@ -396,235 +400,6 @@ func GetDownloadData() (shared.UpdateInfo, error) {
|
||||
return downloadData, nil
|
||||
}
|
||||
|
||||
func getTmpClientPath() string {
|
||||
tmpDir := "/tmp/"
|
||||
if os.Getenv("TMPDIR") != "" {
|
||||
tmpDir = os.Getenv("TMPDIR")
|
||||
}
|
||||
return path.Join(tmpDir, "hishtory-client")
|
||||
}
|
||||
|
||||
func Update(ctx context.Context) error {
|
||||
// Download the binary
|
||||
downloadData, err := GetDownloadData()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if downloadData.Version == "v0."+Version {
|
||||
fmt.Printf("Latest version (v0.%s) is already installed\n", Version)
|
||||
return nil
|
||||
}
|
||||
err = downloadFiles(downloadData)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Verify the SLSA attestation
|
||||
var slsaError error
|
||||
if runtime.GOOS == "darwin" {
|
||||
slsaError = verifyBinaryMac(ctx, getTmpClientPath(), downloadData)
|
||||
} else {
|
||||
slsaError = verifyBinary(ctx, getTmpClientPath(), getTmpClientPath()+".intoto.jsonl", downloadData.Version)
|
||||
}
|
||||
if slsaError != nil {
|
||||
err = handleSlsaFailure(slsaError)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Unlink the existing binary so we can overwrite it even though it is still running
|
||||
if runtime.GOOS == "linux" {
|
||||
homedir := hctx.GetHome(ctx)
|
||||
err = syscall.Unlink(path.Join(homedir, data.GetHishtoryPath(), "hishtory"))
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to unlink %s for update: %w", path.Join(homedir, data.GetHishtoryPath(), "hishtory"), err)
|
||||
}
|
||||
}
|
||||
|
||||
// Install the new one
|
||||
cmd := exec.Command("chmod", "+x", getTmpClientPath())
|
||||
var stdout bytes.Buffer
|
||||
cmd.Stdout = &stdout
|
||||
var stderr bytes.Buffer
|
||||
cmd.Stderr = &stderr
|
||||
err = cmd.Run()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to chmod +x the update (stdout=%#v, stderr=%#v): %w", stdout.String(), stderr.String(), err)
|
||||
}
|
||||
cmd = exec.Command(getTmpClientPath(), "install")
|
||||
cmd.Stdout = os.Stdout
|
||||
stderr = bytes.Buffer{}
|
||||
cmd.Stdin = os.Stdin
|
||||
err = cmd.Run()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to install update (stderr=%#v), is %s in a noexec directory? (if so, set the TMPDIR environment variable): %w", stderr.String(), getTmpClientPath(), err)
|
||||
}
|
||||
fmt.Printf("Successfully updated hishtory from v0.%s to %s\n", Version, downloadData.Version)
|
||||
return nil
|
||||
}
|
||||
|
||||
func verifyBinaryMac(ctx context.Context, binaryPath string, downloadData shared.UpdateInfo) error {
|
||||
// On Mac, binary verification is a bit more complicated since mac binaries are code
|
||||
// signed. To verify a signed binary, we:
|
||||
// 1. Download the unsigned binary
|
||||
// 2. Strip the real signature from the signed binary and the ad-hoc signature from the unsigned binary
|
||||
// 3. Assert that those binaries match
|
||||
// 4. Use SLSA to verify the unsigned binary (pre-strip)
|
||||
// Yes, this is complicated. But AFAICT, it is the only solution here.
|
||||
|
||||
// Step 1: Download the "unsigned" binary that actually has an ad-hoc signature from the
|
||||
// go compiler.
|
||||
unsignedBinaryPath := binaryPath + "-unsigned"
|
||||
var err error = nil
|
||||
if runtime.GOOS == "darwin" && runtime.GOARCH == "amd64" {
|
||||
err = downloadFile(unsignedBinaryPath, downloadData.DarwinAmd64UnsignedUrl)
|
||||
} else if runtime.GOOS == "darwin" && runtime.GOARCH == "arm64" {
|
||||
err = downloadFile(unsignedBinaryPath, downloadData.DarwinArm64UnsignedUrl)
|
||||
} else {
|
||||
err = fmt.Errorf("verifyBinaryMac() called for the unhandled branch GOOS=%s, GOARCH=%s", runtime.GOOS, runtime.GOARCH)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Step 2: Create the .nosig files that have no signatures whatsoever
|
||||
noSigSuffix := ".nosig"
|
||||
err = stripCodeSignature(binaryPath, binaryPath+noSigSuffix)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = stripCodeSignature(unsignedBinaryPath, unsignedBinaryPath+noSigSuffix)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Step 3: Compare the binaries
|
||||
err = assertIdenticalBinaries(binaryPath+noSigSuffix, unsignedBinaryPath+noSigSuffix)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Step 4: Use SLSA to verify the unsigned binary
|
||||
return verifyBinary(ctx, unsignedBinaryPath, getTmpClientPath()+".intoto.jsonl", downloadData.Version)
|
||||
}
|
||||
|
||||
func assertIdenticalBinaries(bin1Path, bin2Path string) error {
|
||||
bin1, err := os.ReadFile(bin1Path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
bin2, err := os.ReadFile(bin2Path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(bin1) != len(bin2) {
|
||||
return fmt.Errorf("unsigned binaries have different lengths (len(%s)=%d, len(%s)=%d)", bin1Path, len(bin1), bin2Path, len(bin2))
|
||||
}
|
||||
differences := make([]string, 0)
|
||||
for i := range bin1 {
|
||||
b1 := bin1[i]
|
||||
b2 := bin2[i]
|
||||
if b1 != b2 {
|
||||
differences = append(differences, fmt.Sprintf("diff at index %d: %s[%d]=%x, %s[%d]=%x", i, bin1Path, i, b1, bin2Path, i, b2))
|
||||
}
|
||||
}
|
||||
for _, d := range differences {
|
||||
hctx.GetLogger().Infof("comparing binaries: %#v\n", d)
|
||||
}
|
||||
if len(differences) > 5 {
|
||||
return fmt.Errorf("found %d differences in the binary", len(differences))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func stripCodeSignature(inPath, outPath string) error {
|
||||
_, err := exec.LookPath("codesign_allocate")
|
||||
if err != nil {
|
||||
return fmt.Errorf("your system is missing the codesign_allocate tool, so we can't verify the SLSA attestation (you can bypass this by setting `export HISHTORY_DISABLE_SLSA_ATTESTATION=true` in your shell)")
|
||||
}
|
||||
cmd := exec.Command("codesign_allocate", "-i", inPath, "-o", outPath, "-r")
|
||||
var stdout bytes.Buffer
|
||||
cmd.Stdout = &stdout
|
||||
var stderr bytes.Buffer
|
||||
cmd.Stderr = &stderr
|
||||
err = cmd.Run()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to use codesign_allocate to strip signatures on binary=%v (stdout=%#v, stderr%#v): %w", inPath, stdout.String(), stderr.String(), err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func downloadFiles(updateInfo shared.UpdateInfo) error {
|
||||
clientUrl := ""
|
||||
clientProvenanceUrl := ""
|
||||
if runtime.GOOS == "linux" && runtime.GOARCH == "amd64" {
|
||||
clientUrl = updateInfo.LinuxAmd64Url
|
||||
clientProvenanceUrl = updateInfo.LinuxAmd64AttestationUrl
|
||||
} else if runtime.GOOS == "linux" && runtime.GOARCH == "arm64" {
|
||||
clientUrl = updateInfo.LinuxArm64Url
|
||||
clientProvenanceUrl = updateInfo.LinuxArm64AttestationUrl
|
||||
} else if runtime.GOOS == "linux" && runtime.GOARCH == "arm" {
|
||||
clientUrl = updateInfo.LinuxArm7Url
|
||||
clientProvenanceUrl = updateInfo.LinuxArm7AttestationUrl
|
||||
} else if runtime.GOOS == "darwin" && runtime.GOARCH == "amd64" {
|
||||
clientUrl = updateInfo.DarwinAmd64Url
|
||||
clientProvenanceUrl = updateInfo.DarwinAmd64AttestationUrl
|
||||
} else if runtime.GOOS == "darwin" && runtime.GOARCH == "arm64" {
|
||||
clientUrl = updateInfo.DarwinArm64Url
|
||||
clientProvenanceUrl = updateInfo.DarwinArm64AttestationUrl
|
||||
} else {
|
||||
return fmt.Errorf("no update info found for GOOS=%s, GOARCH=%s", runtime.GOOS, runtime.GOARCH)
|
||||
}
|
||||
err := downloadFile(getTmpClientPath(), clientUrl)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = downloadFile(getTmpClientPath()+".intoto.jsonl", clientProvenanceUrl)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func downloadFile(filename, url string) error {
|
||||
// Download the data
|
||||
resp, err := http.Get(url)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to download file at %s to %s: %w", url, filename, err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode != 200 {
|
||||
return fmt.Errorf("failed to download file at %s due to resp_code=%d", url, resp.StatusCode)
|
||||
}
|
||||
|
||||
// Delete the file if it already exists. This is necessary due to https://openradar.appspot.com/FB8735191
|
||||
if _, err := os.Stat(filename); err == nil {
|
||||
err = os.Remove(filename)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to delete file %v when trying to download a new version", filename)
|
||||
}
|
||||
}
|
||||
|
||||
// Create the file
|
||||
out, err := os.Create(filename)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to save file to %s: %w", filename, err)
|
||||
}
|
||||
defer out.Close()
|
||||
|
||||
_, err = io.Copy(out, resp.Body)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func getServerHostname() string {
|
||||
if server := os.Getenv("HISHTORY_SERVER"); server != "" {
|
||||
return server
|
||||
}
|
||||
return "https://api.hishtory.dev"
|
||||
}
|
||||
|
||||
func httpClient() *http.Client {
|
||||
return &http.Client{}
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ func checkForDowngrade(currentVersionS, newVersionS string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func verifyBinary(ctx context.Context, binaryPath, attestationPath, versionTag string) error {
|
||||
func VerifyBinary(ctx context.Context, binaryPath, attestationPath, versionTag string) error {
|
||||
if os.Getenv("HISHTORY_DISABLE_SLSA_ATTESTATION") == "true" {
|
||||
return nil
|
||||
}
|
||||
@ -87,7 +87,7 @@ func getFileHash(binaryPath string) (string, error) {
|
||||
return hash, nil
|
||||
}
|
||||
|
||||
func handleSlsaFailure(srcErr error) error {
|
||||
func HandleSlsaFailure(srcErr error) error {
|
||||
fmt.Printf("\nFailed to verify SLSA provenance! This is likely due to a SLSA bug (SLSA is a brand new standard, and like all new things, has bugs). Ignoring this failure means falling back to the way most software does updates. Do you want to ignore this failure and update anyways? [y/N]")
|
||||
reader := bufio.NewReader(os.Stdin)
|
||||
resp, err := reader.ReadString('\n')
|
||||
|
Loading…
Reference in New Issue
Block a user