github.com/tompreston/snapd@v0.0.0-20210817193607-954edfcb9611/cmd/snap/cmd_sign.go (about) 1 // -*- Mode: Go; indent-tabs-mode: t -*- 2 3 /* 4 * Copyright (C) 2014-2021 Canonical Ltd 5 * 6 * This program is free software: you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 3 as 8 * published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 * 18 */ 19 20 package main 21 22 import ( 23 "fmt" 24 "io/ioutil" 25 26 "github.com/jessevdk/go-flags" 27 28 "github.com/snapcore/snapd/asserts/signtool" 29 "github.com/snapcore/snapd/i18n" 30 ) 31 32 var shortSignHelp = i18n.G("Sign an assertion") 33 var longSignHelp = i18n.G(` 34 The sign command signs an assertion using the specified key, using the 35 input for headers from a JSON mapping provided through stdin. The body 36 of the assertion can be specified through a "body" pseudo-header. 37 `) 38 39 type cmdSign struct { 40 Positional struct { 41 Filename flags.Filename 42 } `positional-args:"yes"` 43 44 KeyName keyName `short:"k" default:"default"` 45 } 46 47 func init() { 48 cmd := addCommand("sign", shortSignHelp, longSignHelp, func() flags.Commander { 49 return &cmdSign{} 50 }, map[string]string{ 51 // TRANSLATORS: This should not start with a lowercase letter. 52 "k": i18n.G("Name of the key to use, otherwise use the default key"), 53 }, []argDesc{{ 54 // TRANSLATORS: This needs to begin with < and end with > 55 name: i18n.G("<filename>"), 56 // TRANSLATORS: This should not start with a lowercase letter. 57 desc: i18n.G("File to sign (defaults to stdin)"), 58 }}) 59 cmd.hidden = true 60 cmd.completeHidden = true 61 } 62 63 func (x *cmdSign) Execute(args []string) error { 64 if len(args) > 0 { 65 return ErrExtraArgs 66 } 67 68 useStdin := x.Positional.Filename == "" || x.Positional.Filename == "-" 69 70 var ( 71 statement []byte 72 err error 73 ) 74 if !useStdin { 75 statement, err = ioutil.ReadFile(string(x.Positional.Filename)) 76 } else { 77 statement, err = ioutil.ReadAll(Stdin) 78 } 79 if err != nil { 80 return fmt.Errorf(i18n.G("cannot read assertion input: %v"), err) 81 } 82 83 keypairMgr, err := getKeypairManager() 84 if err != nil { 85 return err 86 } 87 privKey, err := keypairMgr.GetByName(string(x.KeyName)) 88 if err != nil { 89 // TRANSLATORS: %q is the key name, %v the error message 90 return fmt.Errorf(i18n.G("cannot use %q key: %v"), x.KeyName, err) 91 } 92 93 signOpts := signtool.Options{ 94 KeyID: privKey.PublicKey().ID(), 95 Statement: statement, 96 } 97 98 encodedAssert, err := signtool.Sign(&signOpts, keypairMgr) 99 if err != nil { 100 return err 101 } 102 103 _, err = Stdout.Write(encodedAssert) 104 if err != nil { 105 return err 106 } 107 return nil 108 }