-
Notifications
You must be signed in to change notification settings - Fork 9
/
sign.go
93 lines (80 loc) · 2.3 KB
/
sign.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
package main
import (
"fmt"
log "github.com/sirupsen/logrus"
"io/ioutil"
"os"
"path/filepath"
"strings"
"github.com/urfave/cli/v2"
"golang.org/x/crypto/ssh"
)
var (
// SignCommand is the sign CLI command.
SignCommand = &cli.Command{
Name: "sign",
Usage: "sign an ssh public key",
Action: Sign,
}
)
// Sign will request the configured Hallow endpoint sign the provided SSH
// public key.
func Sign(c *cli.Context) error {
hallow, err := hallowClientFromCLI(c)
if err != nil {
return err
}
for _, path := range c.Args().Slice() {
l := log.WithFields(log.Fields{"hallow.public_key.path": path})
dirname := filepath.Dir(path)
basename := filepath.Base(path)
if !strings.HasSuffix(basename, ".pub") {
l.Warn("filepath doesn't end in .pub")
return fmt.Errorf("hallow-cli: '%s' does not end with .pub", path)
}
certName := fmt.Sprintf("%s-cert.pub", basename[:len(basename)-4])
certPath := filepath.Join(dirname, certName)
l.Debug("Opening public key")
fd, err := os.Open(path)
if err != nil {
l.WithFields(log.Fields{"error": err}).Warn("failed to open file")
return err
}
// since we're in a loop, we're not going to defer, since we don't
// want to overflow open FDs.
pubkeyBytes, err := ioutil.ReadAll(fd)
if err != nil {
l.WithFields(log.Fields{"error": err}).Warn("failed to read public key")
fd.Close()
return err
}
fd.Close()
pubKey, comment, _, _, err := ssh.ParseAuthorizedKey(pubkeyBytes)
if err != nil {
l.WithFields(log.Fields{"error": err}).Warn("failed to parse public key")
return err
}
l.Debug("Requesting Certificate from Hallow")
pubKey, err = hallow.RequestCertificate(c.Context, pubKey, comment)
if err != nil {
l.WithFields(log.Fields{"error": err}).Warn("hallow failed to sign our key")
return err
}
l = l.WithFields(log.Fields{"hallow.certificate.path": certPath})
l.Debug("Creating certificate file")
fd, err = os.Create(certPath)
if err != nil {
l.WithFields(log.Fields{"error": err}).Warn("can't write cert to disk")
return err
}
_, err = fd.Write(ssh.MarshalAuthorizedKey(pubKey))
if err != nil {
l.WithFields(log.Fields{"error": err}).Warn("failed to write cert to open file")
fd.Close()
return err
}
fd.Close()
l.Debug("Successfully wrote Certificate out")
}
return nil
}