mirror of
https://github.com/lightninglabs/lightning-terminal.git
synced 2026-08-13 12:33:36 +02:00
Introduce helper functions in the macaroons package to manage super macaroon files and permissions. Add SuperMacaroonExists, MacaroonMatchesPermissions, and BakeAndWriteSuperMacaroon.
167 lines
4.8 KiB
Go
167 lines
4.8 KiB
Go
package macaroons
|
|
|
|
import (
|
|
"encoding/hex"
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
"gopkg.in/macaroon-bakery.v2/bakery"
|
|
)
|
|
|
|
var (
|
|
// testMacHex is a read-only supermacaroon.
|
|
testMacHex = "0201036c6e6402f802030a1011540404373b4d0b3682b15ea7af60c" +
|
|
"c121431383434313932313339323432393138343738341a0f0a076163636" +
|
|
"f756e741204726561641a0f0a0761756374696f6e1204726561641a0d0a0" +
|
|
"561756469741204726561641a0c0a04617574681204726561641a0c0a046" +
|
|
"96e666f1204726561641a100a08696e7369676874731204726561641a100" +
|
|
"a08696e766f696365731204726561641a0f0a046c6f6f701202696e12036" +
|
|
"f75741a100a086d616361726f6f6e1204726561641a0f0a076d657373616" +
|
|
"7651204726561641a100a086f6666636861696e1204726561641a0f0a076" +
|
|
"f6e636861696e1204726561641a0d0a056f726465721204726561641a0d0" +
|
|
"a0570656572731204726561641a0d0a0572617465731204726561641a160" +
|
|
"a0e7265636f6d6d656e646174696f6e1204726561641a0e0a067265706f7" +
|
|
"2741204726561641a130a0b73756767657374696f6e731204726561641a0" +
|
|
"c0a04737761701204726561641a0d0a057465726d7312047265616400000" +
|
|
"6202362c91888e95dfbbf1eb995bd0fef2b549e2de7f4e9fa11aff445273" +
|
|
"60a6caf"
|
|
)
|
|
|
|
// TestSuperMacaroonRootKeyID tests that adding the super macaroon prefix to
|
|
// a root key ID results in a valid super macaroon root key ID.
|
|
func TestSuperMacaroonRootKeyID(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
someBytes := [4]byte{02, 03, 44, 88}
|
|
rootKeyID := NewSuperMacaroonRootKeyID(someBytes)
|
|
require.True(t, isSuperMacaroonRootKeyID(rootKeyID))
|
|
require.False(t, isSuperMacaroonRootKeyID(123))
|
|
}
|
|
|
|
// TestIsSuperMacaroon tests that we can correctly identify an example super
|
|
// macaroon.
|
|
func TestIsSuperMacaroon(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
require.True(t, IsSuperMacaroon(testMacHex))
|
|
}
|
|
|
|
// TestSuperMacaroonHelpers tests that SuperMacaroonExists and
|
|
// MacaroonMatchesPermissions behave correctly.
|
|
func TestSuperMacaroonHelpers(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
tempDir := t.TempDir()
|
|
path := filepath.Join(tempDir, "test.macaroon")
|
|
|
|
// Verify that it doesn't exist yet.
|
|
require.False(t, SuperMacaroonExists(path))
|
|
|
|
// Write the test macaroon.
|
|
macBytes, err := hex.DecodeString(testMacHex)
|
|
require.NoError(t, err)
|
|
err = os.WriteFile(path, macBytes, 0600)
|
|
require.NoError(t, err)
|
|
|
|
// Now it should exist.
|
|
require.True(t, SuperMacaroonExists(path))
|
|
|
|
// The macaroon matches this expected list of permissions.
|
|
expectedPerms := []bakery.Op{
|
|
{Entity: "account", Action: "read"},
|
|
{Entity: "auction", Action: "read"},
|
|
{Entity: "audit", Action: "read"},
|
|
{Entity: "auth", Action: "read"},
|
|
{Entity: "info", Action: "read"},
|
|
{Entity: "insights", Action: "read"},
|
|
{Entity: "invoices", Action: "read"},
|
|
{Entity: "loop", Action: "in"},
|
|
{Entity: "loop", Action: "out"},
|
|
{Entity: "macaroon", Action: "read"},
|
|
{Entity: "message", Action: "read"},
|
|
{Entity: "offchain", Action: "read"},
|
|
{Entity: "onchain", Action: "read"},
|
|
{Entity: "order", Action: "read"},
|
|
{Entity: "peers", Action: "read"},
|
|
{Entity: "rates", Action: "read"},
|
|
{Entity: "recommendation", Action: "read"},
|
|
{Entity: "report", Action: "read"},
|
|
{Entity: "suggestions", Action: "read"},
|
|
{Entity: "swap", Action: "read"},
|
|
{Entity: "terms", Action: "read"},
|
|
}
|
|
|
|
matches, err := MacaroonMatchesPermissions(path, expectedPerms)
|
|
require.NoError(t, err)
|
|
require.True(t, matches)
|
|
|
|
// A subset of permissions should NOT match exactly.
|
|
matches, err = MacaroonMatchesPermissions(path, expectedPerms[:5])
|
|
require.NoError(t, err)
|
|
require.False(t, matches)
|
|
|
|
// Extra/different permissions should NOT match exactly.
|
|
differentPerms := append(
|
|
expectedPerms,
|
|
bakery.Op{Entity: "invalid", Action: "write"},
|
|
)
|
|
matches, err = MacaroonMatchesPermissions(path, differentPerms)
|
|
require.NoError(t, err)
|
|
require.False(t, matches)
|
|
}
|
|
|
|
// TestHasMacaroonSuffix tests that HasMacaroonSuffix correctly
|
|
// checks the suffix of the super macaroon path.
|
|
func TestHasMacaroonSuffix(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
tests := []struct {
|
|
name string
|
|
path string
|
|
wantErr bool
|
|
errStr string
|
|
}{
|
|
{
|
|
name: "empty path",
|
|
path: "",
|
|
wantErr: true,
|
|
errStr: "super-macaroon-path cannot be empty",
|
|
},
|
|
{
|
|
name: "valid path",
|
|
path: "/tmp/test.macaroon",
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "invalid path - missing suffix",
|
|
path: "/tmp/test.mac",
|
|
wantErr: true,
|
|
errStr: "super-macaroon-path must end " +
|
|
"with the .macaroon suffix",
|
|
},
|
|
{
|
|
name: "invalid path - wrong suffix",
|
|
path: "/tmp/test.macaroon.tmp",
|
|
wantErr: true,
|
|
errStr: "super-macaroon-path must end " +
|
|
"with the .macaroon suffix",
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
tt := tt
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
err := HasMacaroonSuffix(tt.path)
|
|
if tt.wantErr {
|
|
require.Error(t, err)
|
|
require.Contains(t, err.Error(), tt.errStr)
|
|
} else {
|
|
require.NoError(t, err)
|
|
}
|
|
})
|
|
}
|
|
}
|