mirror of
https://github.com/Mic92/sops-nix.git
synced 2026-05-13 16:38:45 +08:00
fix public gpg key import
This commit is contained in:
parent
23ffb7df4e
commit
6286c5cc75
5 changed files with 38 additions and 64 deletions
22
README.md
22
README.md
|
|
@ -33,7 +33,10 @@ conversion tool to convert an existing ssh key (we only support RSA keys right n
|
||||||
|
|
||||||
```
|
```
|
||||||
$ nix-shell -p ssh-to-pgp
|
$ nix-shell -p ssh-to-pgp
|
||||||
$ ssh-to-pgp -privkey $HOME/.ssh/id_rsa | gpg --import --quiet
|
$ ssh-to-pgp -private-key -i $HOME/.ssh/id_rsa | gpg --import --quiet
|
||||||
|
2504791468b153b8a3963cc97ba53d1919c5dfd4
|
||||||
|
# This exports the public key
|
||||||
|
$ ssh-to-pgp -i $HOME/.ssh/id_rsa -o $USER.asc
|
||||||
2504791468b153b8a3963cc97ba53d1919c5dfd4
|
2504791468b153b8a3963cc97ba53d1919c5dfd4
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -48,7 +51,7 @@ then your ssh key is encrypted with your password and you need to create a encry
|
||||||
```
|
```
|
||||||
$ cp $HOME/.ssh/id_rsa /tmp/id_rsa
|
$ cp $HOME/.ssh/id_rsa /tmp/id_rsa
|
||||||
$ ssh-keygen -p -N "" -f /tmp/id_rsa
|
$ ssh-keygen -p -N "" -f /tmp/id_rsa
|
||||||
$ ssh-to-pgp -privkey /tmp/id_rsa | gpg --import --quiet
|
$ ssh-to-pgp -private-key -i /tmp/id_rsa | gpg --import --quiet
|
||||||
```
|
```
|
||||||
|
|
||||||
The hex string printed here is your GPG fingerprint that can be exported to `SOPS_PGP_FP`.
|
The hex string printed here is your GPG fingerprint that can be exported to `SOPS_PGP_FP`.
|
||||||
|
|
@ -71,23 +74,20 @@ uid [ unknown] root <root@localhost>
|
||||||
The fingerprint here is `9F89 C5F6 9A10 281A 8350 14B0 9C3D C61F 7520 87EF`, you
|
The fingerprint here is `9F89 C5F6 9A10 281A 8350 14B0 9C3D C61F 7520 87EF`, you
|
||||||
need to remove the space in-between manually.
|
need to remove the space in-between manually.
|
||||||
|
|
||||||
### 3. Get a GPG key for your machine
|
### 3. Get a PGP Public key for your machine
|
||||||
|
|
||||||
The easiest way to add new hosts is using ssh host keys (requires openssh to be enabled).
|
The easiest way to add new hosts is using ssh host keys (requires openssh to be enabled).
|
||||||
Since sops does not natively supports ssh keys yet, nix-sops supports a conversion tool
|
Since sops does not natively supports ssh keys yet, nix-sops supports a conversion tool
|
||||||
to store them as gpg keys.
|
to store them as gpg keys.
|
||||||
|
|
||||||
```
|
```
|
||||||
$ nix-shell -p ssh-to-gpg
|
$ nix-shell -p ssh-to-pgp
|
||||||
# One can use ssh-keyscan over the network
|
$ ssh root@server01 "cat /etc/ssh/ssh_host_rsa_key" | ssh-to-pgp -o server01.asc
|
||||||
$ ssh-keyscan -t rsa server01 | ssh-to-pgp -pubkey - > server01.asc
|
# or with sudo
|
||||||
# server01:22 SSH-2.0-OpenSSH_8.2
|
$ ssh youruser@server01 "sudo cat /etc/ssh/ssh_host_rsa_key" | ssh-to-pgp -o server01.asc
|
||||||
0fd60c8c3b664aceb1796ce02b318df330331003
|
|
||||||
# via ssh command:
|
|
||||||
$ ssh server01 "cat /etc/ssh/ssh_host_rsa_key.pub" | ssh-to-gpg -pubkey - > hosts/server01.asc
|
|
||||||
0fd60c8c3b664aceb1796ce02b318df330331003
|
0fd60c8c3b664aceb1796ce02b318df330331003
|
||||||
# Or just read them locally (or in a ssh session)
|
# Or just read them locally (or in a ssh session)
|
||||||
$ ssh-to-pgp -pubkey /etc/ssh/ssh_host_rsa_key.pub > server01.asc
|
$ ssh-to-pgp -i /etc/ssh/ssh_host_rsa_key -o server01.asc
|
||||||
0fd60c8c3b664aceb1796ce02b318df330331003
|
0fd60c8c3b664aceb1796ce02b318df330331003
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,28 +14,19 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type options struct {
|
type options struct {
|
||||||
publicKey, privateKey, format, out string
|
format, out, in string
|
||||||
|
privateKey bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseFlags(args []string) options {
|
func parseFlags(args []string) options {
|
||||||
var opts options
|
var opts options
|
||||||
f := flag.NewFlagSet(args[0], flag.ExitOnError)
|
f := flag.NewFlagSet(args[0], flag.ExitOnError)
|
||||||
f.StringVar(&opts.publicKey, "pubkey", "", "Path to public key. Reads from standard input if equal to '-'")
|
f.BoolVar(&opts.privateKey, "private-key", false, "Export private key instead of public key")
|
||||||
f.StringVar(&opts.privateKey, "privkey", "", "Path to private key. Reads from standard input if equal to '-'")
|
|
||||||
f.StringVar(&opts.format, "format", "armor", "GPG format encoding (binary|armor)")
|
f.StringVar(&opts.format, "format", "armor", "GPG format encoding (binary|armor)")
|
||||||
|
f.StringVar(&opts.in, "i", "-", "Input path. Reads by default from standard output")
|
||||||
f.StringVar(&opts.out, "o", "-", "Output path. Prints by default to standard output")
|
f.StringVar(&opts.out, "o", "-", "Output path. Prints by default to standard output")
|
||||||
f.Parse(args[1:])
|
f.Parse(args[1:])
|
||||||
|
|
||||||
if opts.publicKey != "" && opts.privateKey != "" {
|
|
||||||
fmt.Fprintln(os.Stderr, "-pubkey and -privkey are mutual exclusive")
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
if opts.publicKey == "" && opts.privateKey == "" {
|
|
||||||
fmt.Fprintln(os.Stderr, "Either -pubkey and -privkey must be specified")
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
return opts
|
return opts
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -43,19 +34,15 @@ func convertKeys(args []string) error {
|
||||||
opts := parseFlags(args)
|
opts := parseFlags(args)
|
||||||
var err error
|
var err error
|
||||||
var sshKey []byte
|
var sshKey []byte
|
||||||
keyPath := opts.privateKey
|
if opts.in == "-" {
|
||||||
if opts.publicKey != "" {
|
|
||||||
keyPath = opts.publicKey
|
|
||||||
}
|
|
||||||
if keyPath == "-" {
|
|
||||||
sshKey, _ = ioutil.ReadAll(os.Stdin)
|
sshKey, _ = ioutil.ReadAll(os.Stdin)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("error reading stdin: %s", err)
|
return fmt.Errorf("error reading stdin: %s", err)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
sshKey, err = ioutil.ReadFile(keyPath)
|
sshKey, err = ioutil.ReadFile(opts.in)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("error reading %s: %s", opts.privateKey, err)
|
return fmt.Errorf("error reading %s: %s", opts.in, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -69,9 +56,9 @@ func convertKeys(args []string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if opts.format == "armor" {
|
if opts.format == "armor" {
|
||||||
keyType := openpgp.PrivateKeyType
|
keyType := openpgp.PublicKeyType
|
||||||
if opts.publicKey != "" {
|
if opts.privateKey {
|
||||||
keyType = openpgp.PublicKeyType
|
keyType = openpgp.PrivateKeyType
|
||||||
}
|
}
|
||||||
writer, err = armor.Encode(writer, keyType, make(map[string]string))
|
writer, err = armor.Encode(writer, keyType, make(map[string]string))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -79,28 +66,21 @@ func convertKeys(args []string) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var fingerprint [20]byte
|
gpgKey, err := sshkeys.SSHPrivateKeyToPGP(sshKey)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
if opts.publicKey != "" {
|
if opts.privateKey {
|
||||||
gpgKey, err := sshkeys.SSHPublicKeyToPGP(sshKey)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
err = gpgKey.Serialize(writer)
|
|
||||||
fingerprint = gpgKey.Fingerprint
|
|
||||||
} else {
|
|
||||||
gpgKey, err := sshkeys.SSHPrivateKeyToPGP(sshKey)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
err = gpgKey.SerializePrivate(writer, nil)
|
err = gpgKey.SerializePrivate(writer, nil)
|
||||||
fingerprint = gpgKey.PrimaryKey.Fingerprint
|
} else {
|
||||||
|
err = gpgKey.Serialize(writer)
|
||||||
}
|
}
|
||||||
if err == nil {
|
if err == nil {
|
||||||
if opts.format == "armor" {
|
if opts.format == "armor" {
|
||||||
writer.Close()
|
writer.Close()
|
||||||
}
|
}
|
||||||
fmt.Fprintf(os.Stderr, "%s\n", hex.EncodeToString(fingerprint[:]))
|
fmt.Fprintf(os.Stderr, "%s\n", hex.EncodeToString(gpgKey.PrimaryKey.Fingerprint[:]))
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,13 +28,12 @@ func TestCli(t *testing.T) {
|
||||||
defer os.RemoveAll(tempdir)
|
defer os.RemoveAll(tempdir)
|
||||||
|
|
||||||
out := path.Join(tempdir, "out")
|
out := path.Join(tempdir, "out")
|
||||||
pubKey := path.Join(assets, "id_rsa.pub")
|
|
||||||
privKey := path.Join(assets, "id_rsa")
|
privKey := path.Join(assets, "id_rsa")
|
||||||
cmds := [][]string{
|
cmds := [][]string{
|
||||||
{"ssh-to-pgp", "-pubkey", pubKey, "-o", out},
|
{"ssh-to-pgp", "-i", privKey, "-o", out},
|
||||||
{"ssh-to-pgp", "-format=armor", "-pubkey", pubKey, "-o", out},
|
{"ssh-to-pgp", "-format=binary", "-i", privKey, "-o", out},
|
||||||
{"ssh-to-pgp", "-privkey", privKey, "-o", out},
|
{"ssh-to-pgp", "-private-key", "-i", privKey, "-o", out},
|
||||||
{"ssh-to-pgp", "-format=armor", "-privkey", privKey, "-o", out},
|
{"ssh-to-pgp", "-format=binary", "-private-key", "-i", privKey, "-o", out},
|
||||||
}
|
}
|
||||||
for _, cmd := range cmds {
|
for _, cmd := range cmds {
|
||||||
err = convertKeys(cmd)
|
err = convertKeys(cmd)
|
||||||
|
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDSeS6SEputIOi2mQhLeIEJnMAink+KcUv38HnaLak3nnLmUsYJnXYB5KZGxaxVtIjr59J8TndmwniZ+wc0rql6Dkif9CsTXgAjxrPiknZNQ7JQbgWUr0pk4jx/K3zLD6i/XAS8QWySNJmY5aJWySbF/K687kUMJ5ql0BX4Tt0RiWL4pIwzZZlLzH4rRySy4z1kbiuOZf8htVRtlGoDGqGViJRpuybSKrmXbevRI7aWjiml2BVTMktPekAPx+MA3t/8EM/uJxtWp7g3BsneHQdKIjR0WEKAITTmuDLEEtIXXEUbgBW0WjbD62nRft/A6/iyWykPJmkLA4WnSLS03caeUxCKoEthZ1xfBPCRNw7xbysQF8CHJz8cAMjZGgBGlOin8EKDhmlma6FZ94cAB5Tr4G3R0h4ky77bPk2/6vvZtyU/AFnDP2HfGaRCDNF+Q7+fR9YmKwcW/vCa2ItIEXgMmBjS+yl0p+4fVaY6Q7bCTbrd6znb6gTGo7nD9Kj/CGU= joerg@turingmachine
|
|
||||||
|
|
@ -33,14 +33,6 @@ func parsePublicKey(publicKey []byte) (*rsa.PublicKey, error) {
|
||||||
return rsaKey, nil
|
return rsaKey, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func SSHPublicKeyToPGP(sshPublicKey []byte) (*packet.PublicKey, error) {
|
|
||||||
rsaKey, err := parsePublicKey(sshPublicKey)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return packet.NewRSAPublicKey(time.Unix(0, 0), rsaKey), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func parsePrivateKey(sshPrivateKey []byte) (*rsa.PrivateKey, error) {
|
func parsePrivateKey(sshPrivateKey []byte) (*rsa.PrivateKey, error) {
|
||||||
privateKey, err := ssh.ParseRawPrivateKey(sshPrivateKey)
|
privateKey, err := ssh.ParseRawPrivateKey(sshPrivateKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -70,7 +62,7 @@ func SSHPrivateKeyToPGP(sshPrivateKey []byte) (*openpgp.Entity, error) {
|
||||||
PrivateKey: packet.NewRSAPrivateKey(timeNull, key),
|
PrivateKey: packet.NewRSAPrivateKey(timeNull, key),
|
||||||
Identities: make(map[string]*openpgp.Identity),
|
Identities: make(map[string]*openpgp.Identity),
|
||||||
}
|
}
|
||||||
uid := packet.NewUserId("root", "", "root@localhost")
|
uid := packet.NewUserId("root", "Imported from SSH", "root@localhost")
|
||||||
isPrimaryID := true
|
isPrimaryID := true
|
||||||
gpgKey.Identities[uid.Id] = &openpgp.Identity{
|
gpgKey.Identities[uid.Id] = &openpgp.Identity{
|
||||||
Name: uid.Id,
|
Name: uid.Id,
|
||||||
|
|
@ -89,6 +81,10 @@ func SSHPrivateKeyToPGP(sshPrivateKey []byte) (*openpgp.Entity, error) {
|
||||||
IssuerKeyId: &gpgKey.PrimaryKey.KeyId,
|
IssuerKeyId: &gpgKey.PrimaryKey.KeyId,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
err = gpgKey.Identities[uid.Id].SelfSignature.SignUserId(uid.Id, gpgKey.PrimaryKey, gpgKey.PrivateKey, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
return gpgKey, nil
|
return gpgKey, nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue