mirror of
https://github.com/cloudflare/redoctober.git
synced 2026-01-06 21:47:37 +00:00
Renamed DecryptSign -> SSHSignWith, added tests for SSHSignWith and Usages
This commit is contained in:
@@ -254,14 +254,14 @@ func (c *RemoteServer) Decrypt(req core.DecryptRequest) (*core.ResponseData, err
|
||||
|
||||
}
|
||||
|
||||
// DecryptSign issues an decrypt-sign request to the remote server
|
||||
func (c *RemoteServer) DecryptSign(req core.DecryptSignRequest) (*core.ResponseData, error) {
|
||||
// SSHSignWith issues an SSH-sign-with request to the remote server
|
||||
func (c *RemoteServer) SSHSignWith(req core.SSHSignWithRequest) (*core.ResponseData, error) {
|
||||
reqBytes, err := json.Marshal(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
respBytes, err := c.doAction("decrypt-sign", reqBytes)
|
||||
respBytes, err := c.doAction("ssh-sign-with", reqBytes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -29,14 +29,14 @@ func (signer ROSigner) PublicKey() ssh.PublicKey {
|
||||
}
|
||||
|
||||
func (signer ROSigner) Sign(rand io.Reader, msg []byte) (signature *ssh.Signature, err error) {
|
||||
req := core.DecryptSignRequest{
|
||||
req := core.SSHSignWithRequest{
|
||||
Name: signer.user,
|
||||
Password: signer.pswd,
|
||||
Data: signer.encryptedKey,
|
||||
TBSData: msg,
|
||||
}
|
||||
|
||||
resp, err := signer.server.DecryptSign(req)
|
||||
resp, err := signer.server.SSHSignWith(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -45,14 +45,12 @@ func (signer ROSigner) Sign(rand io.Reader, msg []byte) (signature *ssh.Signatur
|
||||
return nil, errors.New("response status error")
|
||||
}
|
||||
|
||||
var respMsg core.DecryptSignWithDelegates
|
||||
var respMsg core.SSHSignatureWithDelegates
|
||||
err = json.Unmarshal(resp.Response, &respMsg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
respSignature := ssh.Signature{Format: respMsg.SignatureFormat, Blob: respMsg.Signature}
|
||||
return &respSignature, nil
|
||||
return &respMsg.Signature, nil
|
||||
}
|
||||
|
||||
type ROAgent struct {
|
||||
|
||||
@@ -16,6 +16,7 @@ import (
|
||||
"github.com/cloudflare/redoctober/config"
|
||||
"github.com/cloudflare/redoctober/passvault"
|
||||
"github.com/cloudflare/redoctober/persist"
|
||||
"golang.org/x/crypto/ssh"
|
||||
)
|
||||
|
||||
func tempName(t *testing.T) string {
|
||||
@@ -445,6 +446,8 @@ func TestEncryptDecrypt(t *testing.T) {
|
||||
encryptJson := []byte("{\"Name\":\"Carol\",\"Password\":\"Hello\",\"Minimum\":2,\"Owners\":[\"Alice\",\"Bob\",\"Carol\"],\"Data\":\"SGVsbG8gSmVsbG8=\"}")
|
||||
encryptJson2 := []byte("{\"Name\":\"Alice\",\"Password\":\"Hello\",\"Minimum\":2,\"Owners\":[\"Alice\",\"Bob\",\"Carol\"],\"Data\":\"SGVsbG8gSmVsbG8=\",\"Labels\":[\"blue\",\"red\"]}")
|
||||
encryptJson3 := []byte("{\"Name\":\"Alice\",\"Password\":\"Hello\",\"Minimum\":1,\"Owners\":[\"Alice\"],\"Data\":\"SGVsbG8gSmVsbG8=\"}")
|
||||
encryptJson4 := []byte("{\"Name\":\"Alice\",\"Password\":\"Hello\",\"Minimum\":1,\"Owners\":[\"Alice\"],\"Data\":\"SGVsbG8gSmVsbG8=\",\"Usages\":[\"decrypt\"]}")
|
||||
encryptJson5 := []byte("{\"Name\":\"Alice\",\"Password\":\"Hello\",\"Minimum\":1,\"Owners\":[\"Alice\"],\"Data\":\"SGVsbG8gSmVsbG8=\",\"Usages\":[\"unused\"]}")
|
||||
cfg := config.New()
|
||||
|
||||
Init("memory", cfg)
|
||||
@@ -670,6 +673,92 @@ func TestEncryptDecrypt(t *testing.T) {
|
||||
if s.Status != "ok" {
|
||||
t.Fatalf("Error in decrypt, %v", s.Status)
|
||||
}
|
||||
|
||||
// Encrypt with "decrypt" usage
|
||||
respJson, err = Encrypt(encryptJson4)
|
||||
if err != nil {
|
||||
t.Fatalf("Error in encrypt, %v", err)
|
||||
}
|
||||
err = json.Unmarshal(respJson, &s)
|
||||
if err != nil {
|
||||
t.Fatalf("Error in encrypt, %v", err)
|
||||
}
|
||||
if s.Status != "ok" {
|
||||
t.Fatalf("Error in encrypt, %v", s.Status)
|
||||
}
|
||||
|
||||
respJson, err = Delegate(delegateJson6)
|
||||
if err != nil {
|
||||
t.Fatalf("Error in delegating account, %v", err)
|
||||
}
|
||||
err = json.Unmarshal(respJson, &s)
|
||||
if err != nil {
|
||||
t.Fatalf("Error in delegating account, %v", err)
|
||||
}
|
||||
if s.Status != "ok" {
|
||||
t.Fatalf("Error in delegating account, %v", s.Status)
|
||||
}
|
||||
|
||||
// decrypt file
|
||||
decryptJson3, err := json.Marshal(DecryptRequest{Name: "Alice", Password: "Hello", Data: s.Response})
|
||||
if err != nil {
|
||||
t.Fatalf("Error in marshalling decryption, %v", err)
|
||||
}
|
||||
|
||||
respJson2, err = Decrypt(decryptJson3)
|
||||
if err != nil {
|
||||
t.Fatalf("Error in decrypt, %v", err)
|
||||
}
|
||||
err = json.Unmarshal(respJson2, &s)
|
||||
if err != nil {
|
||||
t.Fatalf("Error in decrypt, %v", err)
|
||||
}
|
||||
if s.Status != "ok" {
|
||||
t.Fatalf("Error in decrypt, %v", s.Status)
|
||||
}
|
||||
|
||||
// Encrypt with "unused" usage
|
||||
respJson, err = Encrypt(encryptJson5)
|
||||
if err != nil {
|
||||
t.Fatalf("Error in encrypt, %v", err)
|
||||
}
|
||||
err = json.Unmarshal(respJson, &s)
|
||||
if err != nil {
|
||||
t.Fatalf("Error in encrypt, %v", err)
|
||||
}
|
||||
if s.Status != "ok" {
|
||||
t.Fatalf("Error in encrypt, %v", s.Status)
|
||||
}
|
||||
|
||||
respJson, err = Delegate(delegateJson6)
|
||||
if err != nil {
|
||||
t.Fatalf("Error in delegating account, %v", err)
|
||||
}
|
||||
err = json.Unmarshal(respJson, &s)
|
||||
if err != nil {
|
||||
t.Fatalf("Error in delegating account, %v", err)
|
||||
}
|
||||
if s.Status != "ok" {
|
||||
t.Fatalf("Error in delegating account, %v", s.Status)
|
||||
}
|
||||
|
||||
// decrypt file
|
||||
decryptJson4, err := json.Marshal(DecryptRequest{Name: "Alice", Password: "Hello", Data: s.Response})
|
||||
if err != nil {
|
||||
t.Fatalf("Error in marshalling decryption, %v", err)
|
||||
}
|
||||
|
||||
respJson2, err = Decrypt(decryptJson4)
|
||||
if err != nil {
|
||||
t.Fatalf("Error in decrypt, %v", err)
|
||||
}
|
||||
err = json.Unmarshal(respJson2, &s)
|
||||
if err != nil {
|
||||
t.Fatalf("Error in decrypt, %v", err)
|
||||
}
|
||||
if s.Status == "ok" {
|
||||
t.Fatalf("Expected error decrypting blob without \"decrypt\" usage")
|
||||
}
|
||||
}
|
||||
|
||||
func TestReEncrypt(t *testing.T) {
|
||||
@@ -1195,6 +1284,142 @@ func TestValidateName(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestSSHSignWith(t *testing.T) {
|
||||
delegateJson := []byte("{\"Name\":\"Alice\",\"Password\":\"Hello\",\"Time\":\"10s\",\"Uses\":10}")
|
||||
cfg := config.New()
|
||||
Init("memory", cfg)
|
||||
|
||||
// check for summary of initialized vault with new member
|
||||
var s ResponseData
|
||||
respJson, err := Create(delegateJson)
|
||||
if err != nil {
|
||||
t.Fatalf("Error in creating account, %v", err)
|
||||
}
|
||||
err = json.Unmarshal(respJson, &s)
|
||||
if err != nil {
|
||||
t.Fatalf("Error in creating account, %v", err)
|
||||
}
|
||||
if s.Status != "ok" {
|
||||
t.Fatalf("Error in creating account, %v", s.Status)
|
||||
}
|
||||
|
||||
respJson, err = Delegate(delegateJson)
|
||||
if err != nil {
|
||||
t.Fatalf("Error in delegating account, %v", err)
|
||||
}
|
||||
err = json.Unmarshal(respJson, &s)
|
||||
if err != nil {
|
||||
t.Fatalf("Error in delegating account, %v", err)
|
||||
}
|
||||
if s.Status != "ok" {
|
||||
t.Fatalf("Error in delegating account, %v", s.Status)
|
||||
}
|
||||
|
||||
sshKey, err := ioutil.ReadFile("../testdata/ssh_key")
|
||||
if err != nil {
|
||||
t.Fatalf("Error loading test SSH key, %v", err)
|
||||
}
|
||||
|
||||
sshPubKeyBytes, err := ioutil.ReadFile("../testdata/ssh_key.pub")
|
||||
if err != nil {
|
||||
t.Fatalf("Error loading test SSH pubkey, %v", err)
|
||||
}
|
||||
|
||||
sshPubKey, _, _, _, err := ssh.ParseAuthorizedKey(sshPubKeyBytes)
|
||||
if err != nil {
|
||||
t.Fatalf("Error loading test SSH pubkey, %v", err)
|
||||
}
|
||||
|
||||
e := EncryptRequest{Name: "Alice", Password: "Hello",
|
||||
Owners: []string{"Alice"}, Minimum: 1, Data: sshKey}
|
||||
|
||||
encryptJson, err := json.Marshal(e)
|
||||
if err != nil {
|
||||
t.Fatalf("Error marshalling encrypt request, %v", err)
|
||||
}
|
||||
|
||||
// Encrypt SSH key
|
||||
respJson, err = Encrypt(encryptJson)
|
||||
if err != nil {
|
||||
t.Fatalf("Error in encrypt, %v", err)
|
||||
}
|
||||
err = json.Unmarshal(respJson, &s)
|
||||
if err != nil {
|
||||
t.Fatalf("Error in encrypt, %v", err)
|
||||
}
|
||||
if s.Status != "ok" {
|
||||
t.Fatalf("Error in encrypt, %v", s.Status)
|
||||
}
|
||||
|
||||
// try to generate a signature
|
||||
sshSignWithJson, err := json.Marshal(SSHSignWithRequest{Name: "Alice", Password: "Hello", Data: s.Response, TBSData: []byte("signme")})
|
||||
if err != nil {
|
||||
t.Fatalf("Error marshalling ssh-sign-with request, %v", err)
|
||||
}
|
||||
|
||||
respJson, err = SSHSignWith(sshSignWithJson)
|
||||
if err != nil {
|
||||
t.Fatalf("Error in ssh-sign-with, %v", err)
|
||||
}
|
||||
err = json.Unmarshal(respJson, &s)
|
||||
if err != nil {
|
||||
t.Fatalf("Error in ssh-sign-with, %v", err)
|
||||
}
|
||||
if s.Status != "cannot sign with this file" {
|
||||
t.Fatalf("Expected error using ssh-sign-with without 'ssh-sign-with' usage, got %v", s.Status)
|
||||
}
|
||||
|
||||
e.Usages = []string{"ssh-sign-with"}
|
||||
encryptJson, err = json.Marshal(e)
|
||||
if err != nil {
|
||||
t.Fatalf("Error marshalling encrypt request, %v", err)
|
||||
}
|
||||
|
||||
respJson, err = Encrypt(encryptJson)
|
||||
if err != nil {
|
||||
t.Fatalf("Error in encrypt, %v", err)
|
||||
}
|
||||
err = json.Unmarshal(respJson, &s)
|
||||
if err != nil {
|
||||
t.Fatalf("Error in encrypt, %v", err)
|
||||
}
|
||||
if s.Status != "ok" {
|
||||
t.Fatalf("Error in encrypt, %v", s.Status)
|
||||
}
|
||||
|
||||
sshSignWithJson, err = json.Marshal(SSHSignWithRequest{Name: "Alice", Password: "Hello", Data: s.Response, TBSData: []byte("signme")})
|
||||
if err != nil {
|
||||
t.Fatalf("Error marshalling ssh-sign-with request, %v", err)
|
||||
}
|
||||
|
||||
respJson, err = SSHSignWith(sshSignWithJson)
|
||||
if err != nil {
|
||||
t.Fatalf("Error in ssh-sign-with, %v", err)
|
||||
}
|
||||
err = json.Unmarshal(respJson, &s)
|
||||
if err != nil {
|
||||
t.Fatalf("Error in ssh-sign-with, %v", err)
|
||||
}
|
||||
if s.Status != "ok" {
|
||||
t.Fatalf("Error in ssh-sign-with, %v", s.Status)
|
||||
}
|
||||
|
||||
var sshSignWithResponse SSHSignatureWithDelegates
|
||||
err = json.Unmarshal(s.Response, &sshSignWithResponse)
|
||||
if err != nil {
|
||||
t.Fatalf("Error unmarshalling ssh-sign-with response, %v", err)
|
||||
}
|
||||
|
||||
sshSignature := ssh.Signature{
|
||||
Format: sshSignWithResponse.SignatureFormat,
|
||||
Blob: sshSignWithResponse.Signature,
|
||||
}
|
||||
err = sshPubKey.Verify([]byte("signme"), &sshSignature)
|
||||
if err != nil {
|
||||
t.Fatalf("Error verifying ssh-sign-with signature, %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Create a vault for the restore tests.
|
||||
func restoreCreateVault(t *testing.T, pstore, file string) {
|
||||
cfg := config.New()
|
||||
|
||||
@@ -223,10 +223,6 @@ func (encrypted *EncryptedData) computeHmac(key []byte) []byte {
|
||||
mac.Write([]byte(usage))
|
||||
}
|
||||
|
||||
for index := range encrypted.Usages {
|
||||
mac.Write([]byte(encrypted.Usages[index]))
|
||||
}
|
||||
|
||||
return mac.Sum(nil)
|
||||
}
|
||||
|
||||
|
||||
15
testdata/ssh_key
vendored
Normal file
15
testdata/ssh_key
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIICWwIBAAKBgQCz2+6OyTyo4Qo/hCtaBLT9gczJPzPhu7CzYWOSqRjbFs2/16y0
|
||||
YOuyPesO/e84ZasMlzFJMogNddnq5uJxcM6+f3XzUs2yIL26cw0rcespNg1UUpZg
|
||||
OSxSluXoJapB/SQhcIuO+uD0snvjNQrAMUz7oK+b6Uv3fYu3DmgI8CrSlwIDAQAB
|
||||
AoGAYs8ci8z6Sjz3iFVwC5AybmL0wkq6kfSu6p1COrwzL4mjlxVBiAcG9XEWxbGz
|
||||
zmPsSIp3RSNBo0NvaKFXHcM/kHRMsZG9FmmQBikoOkMTaEeCdbw/9k3Xzh1aFPo7
|
||||
eCAMbMAO/6nZb8wjARZZ2EHFAo4fXcORwj7dY4/hR3r7KEECQQDdOioQLThTVXXT
|
||||
tV24cE0WVezC8xcnSOE0MIMyFyxjD0aGtzrBKoXewocfRe+zvzoMJzrWM0CIEP5U
|
||||
IbSUTGX5AkEA0CEuJxOpc3yw3I9hy3isqcA9rR6Pa7gvG/H8dLkmhyK6knzuUHU0
|
||||
kW+aTg/LqH22hdCe8SQbUuIWoblSetnhDwJAZOPhyv7UcSzIT4Sm+TY98bG+CCpU
|
||||
pNXX3rVBH9bxpzuQLl/hq7Z41t5gQSLj7lWHY4OAka9N/r/BPR0h/X/aAQJAKbHL
|
||||
9iYZNzqOj9DljYaCSItrj6fkoXbHcTi8E4IX9tB9QeVnNJUWT+BksCi36uwsSYhu
|
||||
nu5VzvfeAs4GePf2/wJATHu5znRyBkegvvn702wodqfhbPd8pmnNT0vXKcD90jsz
|
||||
ZDe0VlX/kmE4fbORozMDRURUGaVDhFIiEsa4gct2mA==
|
||||
-----END RSA PRIVATE KEY-----
|
||||
1
testdata/ssh_key.pub
vendored
Normal file
1
testdata/ssh_key.pub
vendored
Normal file
@@ -0,0 +1 @@
|
||||
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQCz2+6OyTyo4Qo/hCtaBLT9gczJPzPhu7CzYWOSqRjbFs2/16y0YOuyPesO/e84ZasMlzFJMogNddnq5uJxcM6+f3XzUs2yIL26cw0rcespNg1UUpZgOSxSluXoJapB/SQhcIuO+uD0snvjNQrAMUz7oK+b6Uv3fYu3DmgI8CrSlw==
|
||||
Reference in New Issue
Block a user