-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 5f91bb0
Showing
10 changed files
with
692 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
# `go-kms-signer` | ||
|
||
## Why? | ||
|
||
Because we can. And it's #pre:invent madness season. | ||
|
||
## What | ||
|
||
Two things (right now): | ||
|
||
### `kmssigner` | ||
|
||
This is a Go package that implements the crypto.Signer interface | ||
and allows you to cryptographically sign digests **without the private key ever | ||
being in memory**, powered by the new [KMS asymmetric APIs][kms-asym]. | ||
|
||
[kms-asym]: https://aws.amazon.com/blogs/security/digital-signing-asymmetric-keys-aws-kms/ | ||
|
||
You can do all sorts of amusing things with this, like: | ||
|
||
* An HTTPS web server that can terminate TLS traffic without ever having access | ||
to its own private key. | ||
* An SSH keypair that can't be stolen. | ||
|
||
### `kms-ssh-agent` | ||
|
||
Expanding on that previous point, maybe you want to use SSH to log into systems | ||
and having a private key in `~/.ssh/id_rsa` makes you feel uncomfortable for some | ||
reason. Why not entrust that private key to AWS KMS? Now you can! | ||
|
||
Once you've downloaded `kms-ssh-agent`, you can run: | ||
|
||
# this will: | ||
# * create a new RSA 2048 KMS key | ||
# * set up a socket-activated ssh agent daemon listening at ~/.ssh/kms-ssh-agent.sock | ||
# * configure your ~/.ssh/config to use this unix socket as your IdentityAgent | ||
# * print out the ssh public key for pasting into .ssh/authorized_keys on servers | ||
./kms-ssh-agent install | ||
|
||
# this will: | ||
# * magically ssh into your server using the power of KMS. | ||
ssh ec2-user@<ip> | ||
|
||
## Should I use this? | ||
|
||
_This_, specifically? Probably not. The KMS asymmetric crypto APIs? Definitely, they're | ||
very cool. | ||
|
||
## TODO | ||
|
||
* Maybe a KMS-powered GPG agent because it would be amusing | ||
* A super-duper secure HTTPS server with certificates issued by LetsEncrypt | ||
and private keys stored in KMS. | ||
* systemd socket activation for Linux | ||
* Implement better support for RSA PSS - whatever that is. | ||
* Consider what I'm doing with my life |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
module github.com/glassechidna/go-kms-signer | ||
|
||
go 1.13 | ||
|
||
require ( | ||
github.com/aws/aws-sdk-go v1.25.43 | ||
github.com/davecgh/go-spew v1.1.1 | ||
github.com/pkg/errors v0.8.1 | ||
golang.org/x/crypto v0.0.0-20191122220453-ac88ee75c92c | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
github.com/aws/aws-sdk-go v1.25.43 h1:R5YqHQFIulYVfgRySz9hvBRTWBjudISa+r0C8XQ1ufg= | ||
github.com/aws/aws-sdk-go v1.25.43/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= | ||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= | ||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | ||
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM= | ||
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= | ||
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= | ||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= | ||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= | ||
golang.org/x/crypto v0.0.0-20191122220453-ac88ee75c92c h1:/nJuwDLoL/zrqY6gf57vxC+Pi+pZ8bfhpPkicO5H7W4= | ||
golang.org/x/crypto v0.0.0-20191122220453-ac88ee75c92c/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= | ||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= | ||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||
golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI= | ||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
package kmsagent | ||
|
||
import ( | ||
"bytes" | ||
"errors" | ||
"fmt" | ||
"github.com/davecgh/go-spew/spew" | ||
"github.com/glassechidna/go-kms-signer/kmssigner" | ||
"golang.org/x/crypto/ssh" | ||
"golang.org/x/crypto/ssh/agent" | ||
) | ||
|
||
type kmsagent struct { | ||
signers []*kmssigner.Signer | ||
} | ||
|
||
func New(signers []*kmssigner.Signer) (agent.Agent, error) { | ||
return &kmsagent{signers: signers}, nil | ||
} | ||
|
||
func (k *kmsagent) List() ([]*agent.Key, error) { | ||
var keys []*agent.Key | ||
|
||
for _, signer := range k.signers { | ||
sshsign, err := ssh.NewSignerFromSigner(signer) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
pubkey := sshsign.PublicKey() | ||
keys = append(keys, &agent.Key{ | ||
Format: pubkey.Type(), | ||
Blob: pubkey.Marshal(), | ||
Comment: signer.KeyId(), | ||
}) | ||
} | ||
|
||
return keys, nil | ||
} | ||
|
||
func (k *kmsagent) Sign(key ssh.PublicKey, data []byte) (*ssh.Signature, error) { | ||
for _, signer := range k.signers { | ||
sshsign, err := ssh.NewSignerFromSigner(signer) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
pubkey := sshsign.PublicKey() | ||
if !bytes.Equal(pubkey.Marshal(), key.Marshal()) { | ||
continue | ||
} | ||
|
||
signature, err := sshsign.Sign(nil, data) | ||
spew.Dump(signature, err) | ||
return signature, err | ||
} | ||
|
||
return nil, errors.New("nope") | ||
} | ||
|
||
func (k *kmsagent) Add(key agent.AddedKey) error { | ||
panic("implement me") | ||
} | ||
|
||
func (k *kmsagent) Remove(key ssh.PublicKey) error { | ||
panic("implement me") | ||
} | ||
|
||
func (k *kmsagent) RemoveAll() error { | ||
panic("implement me") | ||
} | ||
|
||
func (k *kmsagent) Lock(passphrase []byte) error { | ||
panic("implement me") | ||
} | ||
|
||
func (k *kmsagent) Unlock(passphrase []byte) error { | ||
panic("implement me") | ||
} | ||
|
||
func (k *kmsagent) Signers() ([]ssh.Signer, error) { | ||
var sshSigners []ssh.Signer | ||
|
||
for _, signer := range k.signers { | ||
sshsign, err := ssh.NewSignerFromSigner(signer) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
sshSigners = append(sshSigners, sshsign) | ||
} | ||
|
||
return sshSigners, nil | ||
} | ||
|
||
func (k *kmsagent) SignWithFlags(key ssh.PublicKey, data []byte, flags agent.SignatureFlags) (*ssh.Signature, error) { | ||
for _, signer := range k.signers { | ||
sshsign, err := ssh.NewSignerFromSigner(signer) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
pubkey := sshsign.PublicKey() | ||
if !bytes.Equal(pubkey.Marshal(), key.Marshal()) { | ||
continue | ||
} | ||
|
||
var algorithm string | ||
switch flags { | ||
case agent.SignatureFlagRsaSha256: | ||
algorithm = ssh.SigAlgoRSASHA2256 | ||
case agent.SignatureFlagRsaSha512: | ||
algorithm = ssh.SigAlgoRSASHA2512 | ||
default: | ||
return nil, fmt.Errorf("agent: unsupported signature flags: %d", flags) | ||
} | ||
|
||
if algoSigner, ok := sshsign.(ssh.AlgorithmSigner); ok { | ||
signature, err := algoSigner.SignWithAlgorithm(nil, data, algorithm) | ||
spew.Dump(signature, err) | ||
return signature, err | ||
} | ||
} | ||
|
||
return nil, errors.New("nope") | ||
} | ||
|
||
func (k *kmsagent) Extension(extensionType string, contents []byte) ([]byte, error) { | ||
panic("implement me") | ||
} |
Oops, something went wrong.