Skip to content

Commit 9fc1000

Browse files
committed
Autoloading of unencrypted signerd private keys
We now support automatic loading of unencrypted private keys for signerd. The next planned commit is to support loading keys that were encrypted using Amazon's KMS.
1 parent a71e60e commit 9fc1000

3 files changed

Lines changed: 49 additions & 2 deletions

File tree

README.rst

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,7 @@ Effectively the format is::
272272
NumberSignersRequired
273273
MaxCertLifetime
274274
SigningKeyFingerprint
275+
PrivateKeyFile
275276
AuthorizedSigners {
276277
<key fingerprint>: <key identity>
277278
}
@@ -290,7 +291,13 @@ Effectively the format is::
290291
value of 86400 would mean that the server will reject requests for
291292
certificates that are valid for more than 1 day.
292293
- ``SigningKeyFingerprint``: The fingerprint of the key that will be used to
293-
sign complete requests. This should be the fingerprint of your CA.
294+
sign complete requests. This should be the fingerprint of your CA. When using
295+
this option you must, somehow, load the private key into the agent such that
296+
the daemon can use it.
297+
- ``PrivateKeyFile``: A path to a private key file. As of this writing the key
298+
must be unencrypted. Do take explicit care if you're using unencrypted
299+
private keys. The next release / commit will include support for private key
300+
files that are encrypted using Amazon's KMS.
294301
- ``AuthorizedSigners``: A hash keyed by key fingerprints and values of key
295302
ids. I recommend this be set to a username. It will appear in the
296303
resultant SSH certificate in the KeyId field as well in

sign_certd.go

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@ import (
1313
"github.com/codegangsta/cli"
1414
"github.com/gorilla/mux"
1515
"golang.org/x/crypto/ssh"
16+
"golang.org/x/crypto/ssh/agent"
1617
"io"
18+
"io/ioutil"
1719
"log"
1820
"net"
1921
"net/http"
@@ -98,6 +100,41 @@ type signingRequest struct {
98100
cert *ssh.Certificate
99101
}
100102

103+
func (h *certRequestHandler) setupPrivateKeys(config map[string]ssh_ca_util.SignerdConfig) error {
104+
for env, cfg := range config {
105+
if cfg.PrivateKeyFile != "" {
106+
keyContents, err := ioutil.ReadFile(cfg.PrivateKeyFile)
107+
if err != nil {
108+
return fmt.Errorf("Failed reading private key file %s: %v", cfg.PrivateKeyFile, err)
109+
}
110+
key, err := ssh.ParseRawPrivateKey(keyContents)
111+
if err != nil {
112+
return fmt.Errorf("Failed parsing private key %s: %v", cfg.PrivateKeyFile, err)
113+
}
114+
keyToAdd := agent.AddedKey{
115+
PrivateKey: key,
116+
Comment: fmt.Sprintf("ssh-cert-authority-%s-%s", env, cfg.PrivateKeyFile),
117+
LifetimeSecs: 0,
118+
}
119+
agentClient := agent.NewClient(h.sshAgentConn)
120+
err = agentClient.Add(keyToAdd)
121+
if err != nil {
122+
return fmt.Errorf("Unable to add private key %s: %v", cfg.PrivateKeyFile, err)
123+
}
124+
signer, err := ssh.NewSignerFromKey(key)
125+
if err != nil {
126+
return fmt.Errorf("Unable to create signer from pk %s: %v", cfg.PrivateKeyFile, err)
127+
}
128+
keyFp := ssh_ca_util.MakeFingerprint(signer.PublicKey().Marshal())
129+
log.Printf("Added private key for env %s: %s", env, keyFp)
130+
cfg = config[env]
131+
cfg.SigningKeyFingerprint = keyFp
132+
config[env] = cfg
133+
}
134+
}
135+
return nil
136+
}
137+
101138
func (h *certRequestHandler) createSigningRequest(rw http.ResponseWriter, req *http.Request) {
102139
err := req.ParseForm()
103140
if err != nil {
@@ -539,7 +576,6 @@ func makeCertRequestHandler(config map[string]ssh_ca_util.SignerdConfig) certReq
539576

540577
func runSignCertd(config map[string]ssh_ca_util.SignerdConfig) {
541578
log.Println("Server running version", ssh_ca_util.BuildVersion)
542-
log.Println("Server started with config", config)
543579
log.Println("Using SSH agent at", os.Getenv("SSH_AUTH_SOCK"))
544580

545581
sshAgentConn, err := net.Dial("unix", os.Getenv("SSH_AUTH_SOCK"))
@@ -549,6 +585,9 @@ func runSignCertd(config map[string]ssh_ca_util.SignerdConfig) {
549585
}
550586
requestHandler := makeCertRequestHandler(config)
551587
requestHandler.sshAgentConn = sshAgentConn
588+
requestHandler.setupPrivateKeys(config)
589+
590+
log.Println("Server started with config", config)
552591

553592
r := mux.NewRouter()
554593
requests := r.Path("/cert/requests").Subrouter()

util/config.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ type SignerdConfig struct {
2020
SlackUrl string
2121
SlackChannel string
2222
MaxCertLifetime int
23+
PrivateKeyFile string
2324
}
2425

2526
type SignerConfig struct {

0 commit comments

Comments
 (0)