c34732af3d
With this commit we add a simple macaroon jar that can encrypt its content with a user-provided password when being serialized to JSON.
103 lines
3.1 KiB
Go
103 lines
3.1 KiB
Go
package main
|
|
|
|
import (
|
|
"encoding/hex"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
"gopkg.in/macaroon.v2"
|
|
)
|
|
|
|
var (
|
|
dummyMacStr = "0201047465737402067788991234560000062052d26ed139ea5af8" +
|
|
"3e675500c4ccb2471f62191b745bab820f129e5588a255d2"
|
|
dummyMac, _ = hex.DecodeString(dummyMacStr)
|
|
encryptedEntry = &macaroonEntry{
|
|
Name: "encryptedMac",
|
|
Data: "snacl:exX8xbUOb6Gih88ybL2jZGo+DBDPU2tYKkvo0eVVmbDGDoFP" +
|
|
"zlv5xvqNK5eml0LKLcB8LdZRw43qXK1W2OLs/gBAAAAAAAAACAAA" +
|
|
"AAAAAAABAAAAAAAAAA==:C8TN/aDOvSLiBCX+IdoPTx+UUWhVdGj" +
|
|
"NQvbcaWp+KXQWqPfpRZpjJQ6B2PDx5mJxImcezJGPx8ShAqMdxWe" +
|
|
"l2precU+1cOjk7HQFkYuu943eJ00s6JerAY+ssg==",
|
|
}
|
|
plaintextEntry = &macaroonEntry{
|
|
Name: "plaintextMac",
|
|
Data: dummyMacStr,
|
|
}
|
|
|
|
testPassword = []byte("S3curePazzw0rd")
|
|
pwCallback = func(string) ([]byte, error) {
|
|
return testPassword, nil
|
|
}
|
|
noPwCallback = func(string) ([]byte, error) {
|
|
return nil, nil
|
|
}
|
|
)
|
|
|
|
// TestMacaroonJarEncrypted tests that a macaroon can be stored and retrieved
|
|
// safely by encrypting/decrypting it with a password.
|
|
func TestMacaroonJarEncrypted(t *testing.T) {
|
|
// Create a new macaroon entry from the dummy macaroon and encrypt it
|
|
// with the test password.
|
|
newEntry := &macaroonEntry{
|
|
Name: "encryptedMac",
|
|
}
|
|
err := newEntry.storeMacaroon(toMacaroon(t, dummyMac), testPassword)
|
|
require.NoError(t, err)
|
|
|
|
// Now decrypt it again and make sure we get the same content back.
|
|
mac, err := newEntry.loadMacaroon(pwCallback)
|
|
require.NoError(t, err)
|
|
macBytes, err := mac.MarshalBinary()
|
|
require.NoError(t, err)
|
|
require.Equal(t, dummyMac, macBytes)
|
|
|
|
// The encrypted data of the entry we just created shouldn't be the
|
|
// same as our test entry because of the salt snacl uses.
|
|
require.NotEqual(t, encryptedEntry.Data, newEntry.Data)
|
|
|
|
// Decrypt the hard coded test entry and make sure the decrypted content
|
|
// matches our created entry.
|
|
mac, err = encryptedEntry.loadMacaroon(pwCallback)
|
|
require.NoError(t, err)
|
|
macBytes, err = mac.MarshalBinary()
|
|
require.NoError(t, err)
|
|
require.Equal(t, dummyMac, macBytes)
|
|
}
|
|
|
|
// TestMacaroonJarPlaintext tests that a macaroon can be stored and retrieved
|
|
// as plaintext as well.
|
|
func TestMacaroonJarPlaintext(t *testing.T) {
|
|
// Create a new macaroon entry from the dummy macaroon and encrypt it
|
|
// with the test password.
|
|
newEntry := &macaroonEntry{
|
|
Name: "plaintextMac",
|
|
}
|
|
err := newEntry.storeMacaroon(toMacaroon(t, dummyMac), nil)
|
|
require.NoError(t, err)
|
|
|
|
// Now decrypt it again and make sure we get the same content back.
|
|
mac, err := newEntry.loadMacaroon(noPwCallback)
|
|
require.NoError(t, err)
|
|
macBytes, err := mac.MarshalBinary()
|
|
require.NoError(t, err)
|
|
require.Equal(t, dummyMac, macBytes)
|
|
require.Equal(t, plaintextEntry.Data, newEntry.Data)
|
|
|
|
// Load the hard coded plaintext test entry and make sure the loaded
|
|
// content matches our created entry.
|
|
mac, err = plaintextEntry.loadMacaroon(noPwCallback)
|
|
require.NoError(t, err)
|
|
macBytes, err = mac.MarshalBinary()
|
|
require.NoError(t, err)
|
|
require.Equal(t, dummyMac, macBytes)
|
|
}
|
|
|
|
func toMacaroon(t *testing.T, macData []byte) *macaroon.Macaroon {
|
|
mac := &macaroon.Macaroon{}
|
|
err := mac.UnmarshalBinary(macData)
|
|
require.NoError(t, err)
|
|
|
|
return mac
|
|
}
|