New structure

Signed-off-by: Morten Linderud <morten@linderud.pw>
This commit is contained in:
Morten Linderud 2021-05-18 20:59:51 +02:00
parent adadb52e73
commit 3505f1b571
No known key found for this signature in database
GPG Key ID: E742683BA08CB2FF
14 changed files with 505 additions and 364 deletions

View File

@ -8,7 +8,6 @@ import (
"os"
"os/exec"
"path/filepath"
"strings"
"github.com/foxboron/sbctl/logging"
)
@ -126,31 +125,3 @@ func GenerateBundle(bundle *Bundle) (bool, error) {
logging.Print("Wrote EFI bundle %s\n", bundle.Output)
return true, nil
}
func FormatBundle(name string, bundle *Bundle) {
logging.Println(name)
logging.Print("\tSigned:\t\t")
if ok, _ := VerifyFile(DBCert, name); ok {
logging.Ok("Signed")
} else {
logging.NotOk("Not Signed")
}
esp := GetESP()
logging.Print("\tESP Location:\t%s\n", esp)
logging.Print("\tOutput:\t\t└─%s\n", strings.TrimPrefix(bundle.Output, esp))
logging.Print("\tEFI Stub Image:\t └─%s\n", bundle.EFIStub)
if bundle.Splash != "" {
logging.Print("\tSplash Image:\t ├─%s\n", bundle.Splash)
}
logging.Print("\tCmdline:\t ├─%s\n", bundle.Cmdline)
logging.Print("\tOS Release:\t ├─%s\n", bundle.OSRelease)
logging.Print("\tKernel Image:\t ├─%s\n", bundle.KernelImage)
logging.Print("\tInitramfs Image: └─%s\n", bundle.Initramfs)
if bundle.AMDMicrocode != "" {
logging.Print("\tAMD Microcode: └─%s\n", bundle.AMDMicrocode)
}
if bundle.IntelMicrocode != "" {
logging.Print("\tIntel Microcode: └─%s\n", bundle.IntelMicrocode)
}
logging.Println("")
}

99
cmd/sbctl/bundle.go Normal file
View File

@ -0,0 +1,99 @@
package main
import (
"os"
"path/filepath"
"github.com/foxboron/sbctl"
"github.com/foxboron/sbctl/logging"
"github.com/spf13/cobra"
)
var (
amducode string
intelucode string
splashImg string
osRelease string
efiStub string
kernelImg string
cmdline string
initramfs string
espPath string
saveBundle bool
)
var bundleCmd = &cobra.Command{
Use: "bundle",
Short: "Bundle the needed files for an EFI stub image",
RunE: func(cmd *cobra.Command, args []string) error {
if len(args) < 1 {
logging.Print("Requires a file to sign...\n")
os.Exit(1)
}
checkFiles := []string{amducode, intelucode, splashImg, osRelease, efiStub, kernelImg, cmdline, initramfs}
for _, path := range checkFiles {
if path == "" {
continue
}
if _, err := os.Stat(path); os.IsNotExist(err) {
logging.Print("%s does not exist!\n", path)
os.Exit(1)
}
}
bundle := sbctl.NewBundle()
output, err := filepath.Abs(args[0])
if err != nil {
return err
}
// Fail early if user wants to save bundle but doesn't have permissions
var bundles sbctl.Bundles
if saveBundle {
// "err" needs to have been declared before this, otherwise it's necessary
// to use ":=", which shadows the "bundles" variable
bundles, err = sbctl.ReadBundleDatabase(sbctl.BundleDBPath)
if err != nil {
return err
}
}
bundle.Output = output
bundle.IntelMicrocode = intelucode
bundle.AMDMicrocode = amducode
bundle.KernelImage = kernelImg
bundle.Initramfs = initramfs
bundle.Cmdline = cmdline
bundle.Splash = splashImg
bundle.OSRelease = osRelease
bundle.EFIStub = efiStub
bundle.ESP = espPath
if err = sbctl.CreateBundle(*bundle); err != nil {
return err
}
if saveBundle {
bundles[bundle.Output] = bundle
sbctl.WriteBundleDatabase(sbctl.BundleDBPath, bundles)
}
return nil
},
}
func bundleCmdFlags(cmd *cobra.Command) {
esp := sbctl.GetESP()
f := cmd.Flags()
f.StringVarP(&amducode, "amducode", "a", "", "AMD microcode location")
f.StringVarP(&intelucode, "intelucode", "i", "", "Intel microcode location")
f.StringVarP(&splashImg, "splash-img", "l", "", "Boot splash image location")
f.StringVarP(&osRelease, "os-release", "o", "/usr/lib/os-release", "OS Release file location")
f.StringVarP(&efiStub, "efi-stub", "e", "/usr/lib/systemd/boot/efi/linuxx64.efi.stub", "EFI Stub location")
f.StringVarP(&kernelImg, "kernel-img", "k", "/boot/vmlinuz-linux", "Kernel image location")
f.StringVarP(&cmdline, "cmdline", "c", "/etc/kernel/cmdline", "Cmdline location")
f.StringVarP(&initramfs, "initramfs", "f", "/boot/initramfs-linux.img", "Initramfs location")
f.StringVarP(&espPath, "esp", "p", esp, "ESP location")
f.BoolVarP(&saveBundle, "save", "s", false, "save bundle to the database")
}
func init() {
bundleCmdFlags(bundleCmd)
CliCommands = append(CliCommands, cliCommand{
Cmd: bundleCmd,
})
}

51
cmd/sbctl/completions.go Normal file
View File

@ -0,0 +1,51 @@
package main
import (
"os"
"github.com/spf13/cobra"
)
var completionCmd = &cobra.Command{Use: "completion"}
func completionBashCmd() *cobra.Command {
var completionCmd = &cobra.Command{
Use: "bash",
Hidden: true,
Run: func(cmd *cobra.Command, args []string) {
rootCmd.GenBashCompletion(os.Stdout)
},
}
return completionCmd
}
func completionZshCmd() *cobra.Command {
var completionCmd = &cobra.Command{
Use: "zsh",
Hidden: true,
Run: func(cmd *cobra.Command, args []string) {
rootCmd.GenZshCompletion(os.Stdout)
},
}
return completionCmd
}
func completionFishCmd() *cobra.Command {
var completionCmd = &cobra.Command{
Use: "fish",
Hidden: true,
Run: func(cmd *cobra.Command, args []string) {
rootCmd.GenFishCompletion(os.Stdout, true)
},
}
return completionCmd
}
func init() {
completionCmd.AddCommand(completionBashCmd())
completionCmd.AddCommand(completionZshCmd())
completionCmd.AddCommand(completionFishCmd())
CliCommands = append(CliCommands, cliCommand{
Cmd: completionCmd,
})
}

20
cmd/sbctl/create-keys.go Normal file
View File

@ -0,0 +1,20 @@
package main
import (
"github.com/foxboron/sbctl"
"github.com/spf13/cobra"
)
var createKeysCmd = &cobra.Command{
Use: "create-keys",
Short: "Create a set of secure boot signing keys",
RunE: func(cmd *cobra.Command, args []string) error {
return sbctl.CreateKeys()
},
}
func init() {
CliCommands = append(CliCommands, cliCommand{
Cmd: createKeysCmd,
})
}

20
cmd/sbctl/enroll-keys.go Normal file
View File

@ -0,0 +1,20 @@
package main
import (
"github.com/foxboron/sbctl"
"github.com/spf13/cobra"
)
var enrollKeysCmd = &cobra.Command{
Use: "enroll-keys",
Short: "Enroll the current keys to EFI",
RunE: func(cmd *cobra.Command, args []string) error {
return sbctl.SyncKeys()
},
}
func init() {
CliCommands = append(CliCommands, cliCommand{
Cmd: enrollKeysCmd,
})
}

View File

@ -0,0 +1,30 @@
package main
import (
"github.com/foxboron/sbctl"
"github.com/spf13/cobra"
)
var (
sign bool
)
var generateBundlesCmd = &cobra.Command{
Use: "generate-bundles",
Short: "Generate all EFI stub bundles",
RunE: func(cmd *cobra.Command, args []string) error {
return sbctl.GenerateAllBundles(sign)
},
}
func generateBundlesCmdFlags(cmd *cobra.Command) {
f := cmd.Flags()
f.BoolVarP(&sign, "sign", "s", false, "Sign all the generated bundles")
}
func init() {
generateBundlesCmdFlags(generateBundlesCmd)
CliCommands = append(CliCommands, cliCommand{
Cmd: generateBundlesCmd,
})
}

73
cmd/sbctl/list-bundles.go Normal file
View File

@ -0,0 +1,73 @@
package main
import (
"strings"
"github.com/foxboron/sbctl"
"github.com/foxboron/sbctl/logging"
"github.com/spf13/cobra"
)
type JsonBundle struct {
sbctl.Bundle
IsSigned bool `json:"is_signed"`
}
var listBundlesCmd = &cobra.Command{
Use: "list-bundles",
Short: "List stored bundles",
RunE: func(cmd *cobra.Command, args []string) error {
bundles := []JsonBundle{}
var isSigned bool
err := sbctl.BundleIter(
func(s *sbctl.Bundle) error {
ok, err := sbctl.VerifyFile(sbctl.DBCert, s.Output)
if err != nil {
return err
}
logging.Println("Enrolled bundles:\n")
logging.Println(s.Output)
logging.Print("\tSigned:\t\t")
if ok {
isSigned = true
logging.Ok("Signed")
} else {
isSigned = false
logging.NotOk("Not Signed")
}
esp := sbctl.GetESP()
logging.Print("\tESP Location:\t%s\n", esp)
logging.Print("\tOutput:\t\t└─%s\n", strings.TrimPrefix(s.Output, esp))
logging.Print("\tEFI Stub Image:\t └─%s\n", s.EFIStub)
if s.Splash != "" {
logging.Print("\tSplash Image:\t ├─%s\n", s.Splash)
}
logging.Print("\tCmdline:\t ├─%s\n", s.Cmdline)
logging.Print("\tOS Release:\t ├─%s\n", s.OSRelease)
logging.Print("\tKernel Image:\t ├─%s\n", s.KernelImage)
logging.Print("\tInitramfs Image: └─%s\n", s.Initramfs)
if s.AMDMicrocode != "" {
logging.Print("\tAMD Microcode: └─%s\n", s.AMDMicrocode)
}
if s.IntelMicrocode != "" {
logging.Print("\tIntel Microcode: └─%s\n", s.IntelMicrocode)
}
bundles = append(bundles, JsonBundle{*s, isSigned})
logging.Println("")
return nil
})
if err != nil {
return err
}
if cmdOptions.JsonOutput {
JsonOut(bundles)
}
return nil
},
}
func init() {
CliCommands = append(CliCommands, cliCommand{
Cmd: listBundlesCmd,
})
}

View File

@ -52,330 +52,7 @@ func JsonOut(v interface{}) error {
return nil
}
func createKeysCmd() *cobra.Command {
return &cobra.Command{
Use: "create-keys",
Short: "Create a set of secure boot signing keys",
RunE: func(cmd *cobra.Command, args []string) error {
return sbctl.CreateKeys()
},
}
}
func enrollKeysCmd() *cobra.Command {
return &cobra.Command{
Use: "enroll-keys",
Short: "Enroll the current keys to EFI",
RunE: func(cmd *cobra.Command, args []string) error {
return sbctl.SyncKeys()
},
}
}
func signCmd() *cobra.Command {
var save bool
var output string
cmd := &cobra.Command{
Use: "sign",
Short: "Sign a file with secure boot keys",
RunE: func(cmd *cobra.Command, args []string) error {
if len(args) < 1 {
logging.Print("Requires a file to sign\n")
os.Exit(1)
}
// Ensure we have absolute paths
file, err := filepath.Abs(args[0])
if err != nil {
return err
}
if output == "" {
output = file
} else {
output, err = filepath.Abs(output)
if err != nil {
return err
}
}
if err := sbctl.Sign(file, output, save); err != nil {
return err
}
return nil
},
}
f := cmd.Flags()
f.BoolVarP(&save, "save", "s", false, "save file to the database")
f.StringVarP(&output, "output", "o", "", "output filename. Default replaces the file")
return cmd
}
func signAllCmd() *cobra.Command {
var generate bool
cmd := &cobra.Command{
Use: "sign-all",
Short: "Sign all enrolled files with secure boot keys",
RunE: func(cmd *cobra.Command, args []string) error {
if generate {
if err := sbctl.GenerateAllBundles(true); err != nil {
logging.Fatal(err)
}
}
files, err := sbctl.ReadFileDatabase(sbctl.DBPath)
if err != nil {
return err
}
for _, entry := range files {
if err := sbctl.SignFile(sbctl.DBKey, sbctl.DBCert, entry.File, entry.OutputFile, entry.Checksum); err != nil {
logging.Fatal(err)
continue
}
// Update checksum after we signed it
checksum := sbctl.ChecksumFile(entry.File)
entry.Checksum = checksum
files[entry.File] = entry
sbctl.WriteFileDatabase(sbctl.DBPath, files)
}
return nil
},
}
f := cmd.Flags()
f.BoolVarP(&generate, "generate", "g", false, "run all generate-* sub-commands before signing")
return cmd
}
func removeFileCmd() *cobra.Command {
return &cobra.Command{
Use: "remove-file",
Short: "Remove file from database",
RunE: func(cmd *cobra.Command, args []string) error {
if len(args) < 1 {
logging.Println("Need to specify file")
os.Exit(1)
}
files, err := sbctl.ReadFileDatabase(sbctl.DBPath)
if err != nil {
return err
}
if _, ok := files[args[0]]; !ok {
logging.Print("File %s doesn't exist in database!\n", args[0])
os.Exit(1)
}
delete(files, args[0])
sbctl.WriteFileDatabase(sbctl.DBPath, files)
return nil
},
}
}
func verifyCmd() *cobra.Command {
return &cobra.Command{
Use: "verify",
Short: "Find and check if files in the ESP are signed or not",
RunE: func(cmd *cobra.Command, args []string) error {
if err := sbctl.VerifyESP(); err != nil {
// Really need to sort out the low level error handling
return err
}
return nil
},
}
}
func bundleCmd() *cobra.Command {
var amducode string
var intelucode string
var splashImg string
var osRelease string
var efiStub string
var kernelImg string
var cmdline string
var initramfs string
var espPath string
var save bool
cmd := &cobra.Command{
Use: "bundle",
Short: "Bundle the needed files for an EFI stub image",
RunE: func(cmd *cobra.Command, args []string) error {
if len(args) < 1 {
logging.Print("Requires a file to sign...\n")
os.Exit(1)
}
checkFiles := []string{amducode, intelucode, splashImg, osRelease, efiStub, kernelImg, cmdline, initramfs}
for _, path := range checkFiles {
if path == "" {
continue
}
if _, err := os.Stat(path); os.IsNotExist(err) {
logging.Print("%s does not exist!\n", path)
os.Exit(1)
}
}
bundle := sbctl.NewBundle()
output, err := filepath.Abs(args[0])
if err != nil {
return err
}
// Fail early if user wants to save bundle but doesn't have permissions
var bundles sbctl.Bundles
if save {
// "err" needs to have been declared before this, otherwise it's necessary
// to use ":=", which shadows the "bundles" variable
bundles, err = sbctl.ReadBundleDatabase(sbctl.BundleDBPath)
if err != nil {
return err
}
}
bundle.Output = output
bundle.IntelMicrocode = intelucode
bundle.AMDMicrocode = amducode
bundle.KernelImage = kernelImg
bundle.Initramfs = initramfs
bundle.Cmdline = cmdline
bundle.Splash = splashImg
bundle.OSRelease = osRelease
bundle.EFIStub = efiStub
bundle.ESP = espPath
if err = sbctl.CreateBundle(*bundle); err != nil {
return err
}
if save {
bundles[bundle.Output] = bundle
sbctl.WriteBundleDatabase(sbctl.BundleDBPath, bundles)
sbctl.FormatBundle(bundle.Output, bundle)
}
return nil
},
}
esp := sbctl.GetESP()
f := cmd.Flags()
f.StringVarP(&amducode, "amducode", "a", "", "AMD microcode location")
f.StringVarP(&intelucode, "intelucode", "i", "", "Intel microcode location")
f.StringVarP(&splashImg, "splash-img", "l", "", "Boot splash image location")
f.StringVarP(&osRelease, "os-release", "o", "/usr/lib/os-release", "OS Release file location")
f.StringVarP(&efiStub, "efi-stub", "e", "/usr/lib/systemd/boot/efi/linuxx64.efi.stub", "EFI Stub location")
f.StringVarP(&kernelImg, "kernel-img", "k", "/boot/vmlinuz-linux", "Kernel image location")
f.StringVarP(&cmdline, "cmdline", "c", "/etc/kernel/cmdline", "Cmdline location")
f.StringVarP(&initramfs, "initramfs", "f", "/boot/initramfs-linux.img", "Initramfs location")
f.StringVarP(&espPath, "esp", "p", esp, "ESP location")
f.BoolVarP(&save, "save", "s", false, "save bundle to the database")
return cmd
}
func generateBundlesCmd() *cobra.Command {
var sign bool
cmd := &cobra.Command{
Use: "generate-bundles",
Short: "Generate all EFI stub bundles",
RunE: func(cmd *cobra.Command, args []string) error {
return sbctl.GenerateAllBundles(sign)
},
}
f := cmd.Flags()
f.BoolVarP(&sign, "sign", "s", false, "Sign all the generated bundles")
return cmd
}
func listBundlesCmd() *cobra.Command {
return &cobra.Command{
Use: "list-bundles",
Short: "List stored bundles",
RunE: func(cmd *cobra.Command, args []string) error {
_, err := sbctl.ListBundles()
if err != nil {
return err
}
return nil
},
}
}
func removeBundleCmd() *cobra.Command {
return &cobra.Command{
Use: "remove-bundle",
Short: "Remove bundle from database",
RunE: func(cmd *cobra.Command, args []string) error {
if len(args) < 1 {
logging.Print("Need to specify file\n")
os.Exit(1)
}
bundles, err := sbctl.ReadBundleDatabase(sbctl.BundleDBPath)
if err != nil {
return err
}
if _, ok := bundles[args[0]]; !ok {
logging.Print("Bundle %s doesn't exist in database!\n", args[0])
os.Exit(1)
}
delete(bundles, args[0])
sbctl.WriteBundleDatabase(sbctl.BundleDBPath, bundles)
return nil
},
}
}
func completionBashCmd() *cobra.Command {
var completionCmd = &cobra.Command{
Use: "bash",
Hidden: true,
Run: func(cmd *cobra.Command, args []string) {
rootCmd.GenBashCompletion(os.Stdout)
},
}
return completionCmd
}
func completionZshCmd() *cobra.Command {
var completionCmd = &cobra.Command{
Use: "zsh",
Hidden: true,
Run: func(cmd *cobra.Command, args []string) {
rootCmd.GenZshCompletion(os.Stdout)
},
}
return completionCmd
}
func completionFishCmd() *cobra.Command {
var completionCmd = &cobra.Command{
Use: "fish",
Hidden: true,
Run: func(cmd *cobra.Command, args []string) {
rootCmd.GenFishCompletion(os.Stdout, true)
},
}
return completionCmd
}
func main() {
cmds := []*cobra.Command{
createKeysCmd(),
enrollKeysCmd(),
signCmd(),
signAllCmd(),
verifyCmd(),
bundleCmd(),
generateBundlesCmd(),
removeBundleCmd(),
listBundlesCmd(),
removeFileCmd(),
}
for _, c := range cmds {
rootCmd.AddCommand(c)
}
completionCmd := &cobra.Command{Use: "completion"}
completionCmd.AddCommand(completionBashCmd())
completionCmd.AddCommand(completionZshCmd())
completionCmd.AddCommand(completionFishCmd())
rootCmd.AddCommand(completionCmd)
for _, cmd := range CliCommands {
baseFlags(cmd.Cmd)
rootCmd.AddCommand(cmd.Cmd)

View File

@ -0,0 +1,38 @@
package main
import (
"os"
"github.com/foxboron/sbctl"
"github.com/foxboron/sbctl/logging"
"github.com/spf13/cobra"
)
var removeBundleCmd = &cobra.Command{
Use: "remove-bundle",
Short: "Remove bundle from database",
RunE: func(cmd *cobra.Command, args []string) error {
if len(args) < 1 {
logging.Print("Need to specify file\n")
os.Exit(1)
}
bundles, err := sbctl.ReadBundleDatabase(sbctl.BundleDBPath)
if err != nil {
return err
}
if _, ok := bundles[args[0]]; !ok {
logging.Print("Bundle %s doesn't exist in database!\n", args[0])
os.Exit(1)
}
delete(bundles, args[0])
sbctl.WriteBundleDatabase(sbctl.BundleDBPath, bundles)
return nil
},
}
func init() {
CliCommands = append(CliCommands, cliCommand{
Cmd: removeBundleCmd,
})
}

37
cmd/sbctl/remove-files.go Normal file
View File

@ -0,0 +1,37 @@
package main
import (
"os"
"github.com/foxboron/sbctl"
"github.com/foxboron/sbctl/logging"
"github.com/spf13/cobra"
)
var removeFileCmd = &cobra.Command{
Use: "remove-file",
Short: "Remove file from database",
RunE: func(cmd *cobra.Command, args []string) error {
if len(args) < 1 {
logging.Println("Need to specify file")
os.Exit(1)
}
files, err := sbctl.ReadFileDatabase(sbctl.DBPath)
if err != nil {
return err
}
if _, ok := files[args[0]]; !ok {
logging.Print("File %s doesn't exist in database!\n", args[0])
os.Exit(1)
}
delete(files, args[0])
sbctl.WriteFileDatabase(sbctl.DBPath, files)
return nil
},
}
func init() {
CliCommands = append(CliCommands, cliCommand{
Cmd: removeFileCmd,
})
}

55
cmd/sbctl/sign-all.go Normal file
View File

@ -0,0 +1,55 @@
package main
import (
"github.com/foxboron/sbctl"
"github.com/foxboron/sbctl/logging"
"github.com/spf13/cobra"
)
var (
generate bool
)
var signAllCmd = &cobra.Command{
Use: "sign-all",
Short: "Sign all enrolled files with secure boot keys",
RunE: func(cmd *cobra.Command, args []string) error {
if generate {
if err := sbctl.GenerateAllBundles(true); err != nil {
logging.Fatal(err)
}
}
files, err := sbctl.ReadFileDatabase(sbctl.DBPath)
if err != nil {
return err
}
for _, entry := range files {
if err := sbctl.SignFile(sbctl.DBKey, sbctl.DBCert, entry.File, entry.OutputFile, entry.Checksum); err != nil {
logging.Fatal(err)
continue
}
// Update checksum after we signed it
checksum := sbctl.ChecksumFile(entry.File)
entry.Checksum = checksum
files[entry.File] = entry
sbctl.WriteFileDatabase(sbctl.DBPath, files)
}
return nil
},
}
func signAllCmdFlags(cmd *cobra.Command) {
f := cmd.Flags()
f.BoolVarP(&generate, "generate", "g", false, "run all generate-* sub-commands before signing")
}
func init() {
signAllCmdFlags(signAllCmd)
CliCommands = append(CliCommands, cliCommand{
Cmd: signAllCmd,
})
}

58
cmd/sbctl/sign.go Normal file
View File

@ -0,0 +1,58 @@
package main
import (
"os"
"path/filepath"
"github.com/foxboron/sbctl"
"github.com/foxboron/sbctl/logging"
"github.com/spf13/cobra"
)
var (
save bool
output string
)
var signCmd = &cobra.Command{
Use: "sign",
Short: "Sign a file with secure boot keys",
RunE: func(cmd *cobra.Command, args []string) error {
if len(args) < 1 {
logging.Print("Requires a file to sign\n")
os.Exit(1)
}
// Ensure we have absolute paths
file, err := filepath.Abs(args[0])
if err != nil {
return err
}
if output == "" {
output = file
} else {
output, err = filepath.Abs(output)
if err != nil {
return err
}
}
if err := sbctl.Sign(file, output, save); err != nil {
return err
}
return nil
},
}
func signCmdFlags(cmd *cobra.Command) {
f := cmd.Flags()
f.BoolVarP(&save, "save", "s", false, "save file to the database")
f.StringVarP(&output, "output", "o", "", "output filename. Default replaces the file")
}
func init() {
signCmdFlags(signCmd)
CliCommands = append(CliCommands, cliCommand{
Cmd: signCmd,
})
}

24
cmd/sbctl/verify.go Normal file
View File

@ -0,0 +1,24 @@
package main
import (
"github.com/foxboron/sbctl"
"github.com/spf13/cobra"
)
var verifyCmd = &cobra.Command{
Use: "verify",
Short: "Find and check if files in the ESP are signed or not",
RunE: func(cmd *cobra.Command, args []string) error {
if err := sbctl.VerifyESP(); err != nil {
// Really need to sort out the low level error handling
return err
}
return nil
},
}
func init() {
CliCommands = append(CliCommands, cliCommand{
Cmd: verifyCmd,
})
}

View File

@ -341,15 +341,3 @@ func GenerateAllBundles(sign bool) error {
return nil
}
func ListBundles() (Bundles, error) {
bundles, err := ReadBundleDatabase(BundleDBPath)
if err != nil {
return nil, fmt.Errorf("couldn't open database: %v", err)
}
logging.Println("Enrolled bundles:\n")
for key, bundle := range bundles {
FormatBundle(key, bundle)
}
return bundles, nil
}