Skip to content

Commit 782447c

Browse files
author
Benton Roberts
committed
add support for x509-encrypted PEM secrets
1 parent f2f9769 commit 782447c

File tree

6 files changed

+44
-17
lines changed

6 files changed

+44
-17
lines changed

.goxc.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,6 @@
1111
],
1212
"Arch": "amd64",
1313
"BuildConstraints": "linux",
14-
"PackageVersion": "0.5.1",
14+
"PackageVersion": "0.5.2",
1515
"ConfigVersion": "0.9"
16-
}
16+
}

README.md

+2
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ Here's the command-line help:
5858
path to key file (default "~/.ssh/id_rsa")
5959
-port int
6060
server receiving port (default 1067)
61+
-pwd string
62+
password for encrypted RSA key
6163
-server
6264
run key server instead of command
6365
-version

config.go

+8
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,12 @@ import (
88
)
99

1010
const DEFAULT_KEYPATH = `~/.ssh/id_rsa`
11+
const DEFAULT_PWD = `$RSA_KEY_PWD`
1112

1213
// Represents this app's possible configuration values
1314
type Config struct {
1415
KeyPath string
16+
Pwd string
1517
Server bool
1618
Port int
1719
Wait int
@@ -25,6 +27,7 @@ func newConfig() Config {
2527
server = flag.Bool("server", false, "run key server instead of command")
2628
port = flag.Int("port", SERVER_RECV_PORT, "server receiving port")
2729
wait = flag.Int("wait", CLIENT_TIMEOUT, "client timeout, in seconds")
30+
pwd = flag.String("pwd", DEFAULT_PWD, "password for encrypted RSA key")
2831
)
2932
flag.Parse()
3033
if *print_v {
@@ -45,9 +48,14 @@ func newConfig() Config {
4548
}
4649
keyPath = filepath.Join(home, `.ssh`, `id_rsa`)
4750
}
51+
rsaPasswd := *pwd
52+
if *pwd == DEFAULT_PWD {
53+
rsaPasswd = os.Getenv(`RSA_KEY_PWD`)
54+
}
4855
return Config{
4956
Server: *server,
5057
KeyPath: keyPath,
58+
Pwd: rsaPasswd,
5159
Port: *port,
5260
Wait: *wait,
5361
}

main.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ const (
1515
)
1616

1717
// Package version & timestamp - interpolated by goxc
18-
const VERSION = "0.5.1"
19-
const SOURCE_DATE = "2015-10-27T10:48:34-04:00"
18+
const VERSION = "0.5.2"
19+
const SOURCE_DATE = "2016-07-04T21:46:43-07:00"
2020

2121
func main() {
2222
config := newConfig()

make.sh

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,15 @@
22
# runs goxc in each product directory
33
set -e
44

5+
goxc
56
echo "Building static linux binary for docker-ssh-exec..."
67
mkdir -p pkg
78
buildcmd='CGO_ENABLED=0 go build -a --installsuffix cgo --ldflags="-s" -o pkg/docker-ssh-exec'
89
docker run --rm -it -v "$GOPATH":/gopath -v "$(pwd)":/app -e "GOPATH=/gopath" \
9-
-w /app golang:1.5 sh -c "$buildcmd"
10+
-w /app golang:1.6 sh -c "$buildcmd"
1011

1112
echo "Building docker image for docker-ssh-exec..."
1213
docker build --no-cache=true --tag mdsol/docker-ssh-exec .
1314
rm -f pkg/docker-ssh-exec
1415

15-
echo "Done. To make a release, run: goxc"
1616
exit 0

server.go

+28-11
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
package main
22

33
import (
4+
"crypto/x509"
5+
"encoding/pem"
46
"fmt"
57
"io/ioutil"
68
"net"
79
"os"
10+
"regexp"
811
)
912

1013
func server(config Config) {
@@ -33,19 +36,33 @@ func server(config Config) {
3336
IP: clientAddr.IP,
3437
Port: clientAddr.Port + 1,
3538
})
36-
37-
response := os.Getenv(KEY_DATA_ENV_VAR)
38-
if response == `` {
39-
keyData, err := ioutil.ReadFile(config.KeyPath)
40-
if err == nil {
41-
response = string(keyData)
42-
} else {
43-
response = fmt.Sprintf("ERROR reading keyfile %s: %s!",
44-
config.KeyPath, err)
45-
fmt.Println(response)
39+
var keyData []byte
40+
keyData = []byte(os.Getenv(KEY_DATA_ENV_VAR))
41+
if len(keyData) == 0 {
42+
keyData, err = ioutil.ReadFile(config.KeyPath)
43+
if err != nil {
44+
fmt.Printf("ERROR reading keyfile %s: %s!\n", config.KeyPath, err)
45+
}
46+
}
47+
pemBlock, _ := pem.Decode(keyData)
48+
if pemBlock != nil {
49+
if x509.IsEncryptedPEMBlock(pemBlock) {
50+
fmt.Println("Decrypting private key with passphrase...")
51+
decoded, err := x509.DecryptPEMBlock(pemBlock, []byte(config.Pwd))
52+
if err == nil {
53+
header := `PRIVATE KEY` // default key type in header
54+
matcher := regexp.MustCompile("-----BEGIN (.*)-----")
55+
if matches := matcher.FindSubmatch(keyData); len(matches) > 1 {
56+
header = string(matches[1])
57+
}
58+
keyData = pem.EncodeToMemory(
59+
&pem.Block{Type: header, Bytes: decoded})
60+
} else {
61+
fmt.Printf("Error decrypting PEM-encoded secret: %s\n", err)
62+
}
4663
}
4764
}
48-
_, err = writeSocket.Write([]byte(response))
65+
_, err = writeSocket.Write(keyData)
4966
if err != nil {
5067
fmt.Printf("ERROR writing data to socket:%s!\n", err)
5168
}

0 commit comments

Comments
 (0)