-
Notifications
You must be signed in to change notification settings - Fork 41
Expand file tree
/
Copy pathsshd.go
More file actions
129 lines (114 loc) · 3.68 KB
/
sshd.go
File metadata and controls
129 lines (114 loc) · 3.68 KB
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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
package sshd
import (
"fmt"
"io/ioutil"
"os/exec"
"golang.org/x/crypto/ssh"
"github.com/deis/builder/pkg/controller"
"github.com/Masterminds/cookoo"
"github.com/Masterminds/cookoo/log"
)
const (
builderKeyLocation = "/var/run/secrets/api/auth/builder-key"
)
// ParseHostKeys parses the host key files.
//
// By default it looks in /etc/ssh for host keys of the patterh ssh_host_{{TYPE}}_key.
//
// Params:
// - keytypes ([]string): Key types to parse. Defaults to []string{rsa, dsa, ecdsa}
// - enableV1 (bool): Allow V1 keys. By default this is disabled.
// - path (string): Override the lookup pattern. If %s, it will be replaced with the keytype.
//
// Returns:
// []ssh.Signer
func ParseHostKeys(c cookoo.Context, p *cookoo.Params) (interface{}, cookoo.Interrupt) {
log.Debugf(c, "Parsing ssh host keys")
hostKeyTypes := p.Get("keytypes", []string{"rsa", "dsa", "ecdsa"}).([]string)
pathTpl := p.Get("path", "/etc/ssh/ssh_host_%s_key").(string)
hostKeys := make([]ssh.Signer, 0, len(hostKeyTypes))
for _, t := range hostKeyTypes {
path := fmt.Sprintf(pathTpl, t)
if key, err := ioutil.ReadFile(path); err == nil {
if hk, err := ssh.ParsePrivateKey(key); err == nil {
log.Infof(c, "Parsed host key %s.", path)
hostKeys = append(hostKeys, hk)
} else {
log.Errf(c, "Failed to parse host key %s (skipping): %s", path, err)
}
}
}
if c.Get("enableV1", false).(bool) {
path := "/etc/ssh/ssh_host_key"
if key, err := ioutil.ReadFile(path); err != nil {
log.Errf(c, "Failed to read ssh_host_key")
} else if hk, err := ssh.ParsePrivateKey(key); err == nil {
log.Infof(c, "Parsed host key %s.", path)
hostKeys = append(hostKeys, hk)
} else {
log.Errf(c, "Failed to parse host key %s: %s", path, err)
}
}
return hostKeys, nil
}
// AuthKey authenticates based on a public key.
//
// Params:
// - metadata (ssh.ConnMetadata)
// - key (ssh.PublicKey)
//
// Returns:
// *ssh.Permissions
//
func AuthKey(c cookoo.Context, p *cookoo.Params) (interface{}, cookoo.Interrupt) {
log.Debugf(c, "Starting ssh authentication")
key := p.Get("key", nil).(ssh.PublicKey)
userInfo, err := controller.UserInfoFromKey(key)
if err != nil {
return nil, err
}
userInfo.Key = string(ssh.MarshalAuthorizedKey(key))
c.Put("userinfo", userInfo)
log.Infof(c, "Key accepted for user %s.", userInfo.Username)
perm := &ssh.Permissions{
Extensions: map[string]string{
"user": userInfo.Username,
},
}
return perm, nil
}
// Configure creates a new SSH configuration object.
//
// Config sets a PublicKeyCallback handler that forwards public key auth
// requests to the route named "pubkeyAuth".
//
// This assumes certain details about our environment, like the location of the
// host keys. It also provides only key-based authentication.
// ConfigureServerSshConfig
//
// Returns:
// An *ssh.ServerConfig
func Configure(c cookoo.Context, p *cookoo.Params) (interface{}, cookoo.Interrupt) {
router := c.Get("cookoo.Router", nil).(*cookoo.Router)
cfg := &ssh.ServerConfig{
PublicKeyCallback: func(m ssh.ConnMetadata, k ssh.PublicKey) (*ssh.Permissions, error) {
c.Put("metadata", m)
c.Put("key", k)
pubkeyAuth := c.Get("route.sshd.pubkeyAuth", "pubkeyAuth").(string)
err := router.HandleRequest(pubkeyAuth, c, true)
return c.Get("pubkeyAuth", &ssh.Permissions{}).(*ssh.Permissions), err
},
}
return cfg, nil
}
// GenSSHKeys generates the default set of SSH host keys.
func GenSSHKeys(c cookoo.Context, p *cookoo.Params) (interface{}, cookoo.Interrupt) {
log.Debugf(c, "Generating ssh keys for sshd")
// Generate a new key
out, err := exec.Command("ssh-keygen", "-A").CombinedOutput()
if err != nil {
log.Infof(c, "ssh-keygen: %s", out)
return nil, err
}
return nil, nil
}