1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package token
18
19 import (
20 "errors"
21 "fmt"
22 "io/ioutil"
23 "os"
24
25 "github.com/sassoftware/relic/cmdline/shared"
26 "github.com/sassoftware/relic/lib/certloader"
27 "github.com/sassoftware/relic/lib/passprompt"
28 "github.com/sassoftware/relic/lib/x509tools"
29 "github.com/sassoftware/relic/signers/sigerrors"
30 "github.com/spf13/cobra"
31 )
32
33 var ImportKeyCmd = &cobra.Command{
34 Use: "import-key",
35 Short: "Import a private key to a token",
36 RunE: importKeyCmd,
37 }
38
39 var argPkcs12 bool
40
41 func init() {
42 shared.RootCmd.AddCommand(ImportKeyCmd)
43 addKeyFlags(ImportKeyCmd)
44 ImportKeyCmd.Flags().StringVarP(&argToken, "token", "t", "", "Name of token to import key to")
45 ImportKeyCmd.Flags().StringVarP(&argLabel, "label", "l", "", "Label to attach to imported key")
46 ImportKeyCmd.Flags().StringVarP(&argFile, "file", "f", "", "Private key file to import: PEM, DER, or PGP")
47 ImportKeyCmd.Flags().BoolVar(&argPkcs12, "pkcs12", false, "Import a PKCS12 key and certificate chain")
48 }
49
50 func importKeyCmd(cmd *cobra.Command, args []string) error {
51 if argFile == "" {
52 return errors.New("--file is required")
53 }
54 blob, err := ioutil.ReadFile(argFile)
55 if err != nil {
56 return shared.Fail(err)
57 }
58 prompt := new(passprompt.PasswordPrompt)
59 var cert *certloader.Certificate
60 if argPkcs12 {
61 var err error
62 cert, err = certloader.ParsePKCS12(blob, prompt)
63 if err != nil {
64 return shared.Fail(err)
65 }
66 } else {
67 privKey, err := certloader.ParseAnyPrivateKey(blob, prompt)
68 if err != nil {
69 return shared.Fail(err)
70 }
71 cert = &certloader.Certificate{PrivateKey: privKey}
72 }
73 keyConf, err := newKeyConfig()
74 if err != nil {
75 return err
76 }
77 tok, err := openToken(keyConf.Token)
78 if err != nil {
79 return shared.Fail(err)
80 }
81 var didSomething bool
82 key, err := tok.GetKey(argKeyName)
83 if err == nil {
84 if cert.Leaf == nil {
85 return errors.New("An object with that label already exists in the token")
86 }
87 fmt.Fprintln(os.Stderr, "Private key already exists. Attempting to import certificates.")
88 } else if _, ok := err.(sigerrors.KeyNotFoundError); !ok {
89 return err
90 } else {
91 key, err = tok.Import(argKeyName, cert.PrivateKey)
92 if err != nil {
93 return err
94 }
95 didSomething = true
96 }
97 if cert.Leaf != nil {
98 name := x509tools.FormatSubject(cert.Leaf)
99 err := key.ImportCertificate(cert.Leaf)
100 if err == sigerrors.ErrExist {
101 fmt.Fprintln(os.Stderr, "Certificate already exists:", name)
102 } else if err != nil {
103 return shared.Fail(fmt.Errorf("failed to import %s: %s", name, err))
104 } else {
105 fmt.Fprintln(os.Stderr, "Imported", name)
106 didSomething = true
107 }
108 for _, chain := range cert.Chain() {
109 if chain == cert.Leaf {
110 continue
111 }
112 name = x509tools.FormatSubject(chain)
113 err = tok.ImportCertificate(chain, keyConf.Label)
114 if err == sigerrors.ErrExist {
115 fmt.Fprintln(os.Stderr, "Certificate already exists:", name)
116 } else if err != nil {
117 return shared.Fail(fmt.Errorf("failed to import %s: %s", name, err))
118 } else {
119 fmt.Fprintln(os.Stderr, "Imported", name)
120 didSomething = true
121 }
122 }
123 }
124 if !didSomething {
125 return shared.Fail(errors.New("nothing imported"))
126 }
127 fmt.Fprintln(os.Stderr, "Token CKA_ID: ", formatKeyID(key.GetID()))
128 return nil
129 }
130
View as plain text