Skip to content

Commit

Permalink
Initial (and last) commit
Browse files Browse the repository at this point in the history
  • Loading branch information
aidansteele committed Nov 27, 2019
0 parents commit 5f91bb0
Show file tree
Hide file tree
Showing 10 changed files with 692 additions and 0 deletions.
56 changes: 56 additions & 0 deletions README.md
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
10 changes: 10 additions & 0 deletions go.mod
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
)
16 changes: 16 additions & 0 deletions go.sum
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=
130 changes: 130 additions & 0 deletions kms-ssh-agent/kmsagent/agent.go
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")
}
Loading

0 comments on commit 5f91bb0

Please sign in to comment.