safing-jess/cmd/cmd-checksum.go

111 lines
2.5 KiB
Go

package main
import (
"errors"
"fmt"
"os"
"path/filepath"
"github.com/spf13/cobra"
"github.com/safing/jess/filesig"
)
func init() {
rootCmd.AddCommand(checksum)
checksum.AddCommand(checksumAdd)
checksum.AddCommand(checksumVerify)
}
var (
checksum = &cobra.Command{
Use: "checksum",
Short: "add or verify embedded checksums",
}
checksumAddUsage = "usage: checksum add <file>"
checksumAdd = &cobra.Command{
Use: "add <file>",
Short: "add an embedded checksum to a file",
Long: "add an embedded checksum to a file (support file types: txt, json, yaml)",
RunE: handleChecksumAdd,
}
checksumVerifyUsage = "usage: checksum verify <file>"
checksumVerify = &cobra.Command{
Use: "verify <file>",
Short: "verify the embedded checksum of a file",
Long: "verify the embedded checksum of a file (support file types: txt, json, yaml)",
RunE: handleChecksumVerify,
}
)
func handleChecksumAdd(cmd *cobra.Command, args []string) error {
// Check args.
if len(args) != 1 {
return errors.New(checksumAddUsage)
}
filename := args[0]
data, err := os.ReadFile(filename)
if err != nil {
return fmt.Errorf("failed to read file: %w", err)
}
switch filepath.Ext(filename) {
case ".json":
data, err = filesig.AddJSONChecksum(data)
case ".yml", ".yaml":
data, err = filesig.AddYAMLChecksum(data, filesig.TextPlacementAfterComment)
case ".txt":
data, err = filesig.AddTextFileChecksum(data, "#", filesig.TextPlacementAfterComment)
default:
return errors.New("unsupported file format")
}
if err != nil {
return err
}
// Write back to disk.
fileInfo, err := os.Stat(filename)
if err != nil {
return fmt.Errorf("failed to stat file: %w", err)
}
err = os.WriteFile(filename, data, fileInfo.Mode().Perm())
if err != nil {
return fmt.Errorf("failed to write back file with checksum: %w", err)
}
fmt.Println("checksum added")
return nil
}
func handleChecksumVerify(cmd *cobra.Command, args []string) error {
// Check args.
if len(args) != 1 {
return errors.New(checksumVerifyUsage)
}
filename := args[0]
data, err := os.ReadFile(filename)
if err != nil {
return fmt.Errorf("failed to read file: %w", err)
}
switch filepath.Ext(filename) {
case ".json":
err = filesig.VerifyJSONChecksum(data)
case ".yml", ".yaml":
err = filesig.VerifyYAMLChecksum(data)
case ".txt":
err = filesig.VerifyTextFileChecksum(data, "#")
default:
return errors.New("unsupported file format")
}
if err != nil {
return err
}
fmt.Println("checksum verified")
return nil
}