Skip to content

Commit 5f1b684

Browse files
committed
itest: add test for super macaroon auto-bake
Add testSuperMacaroonOnStartup to verify startup baking logic. The test restarts the node with the auto-baking config flags and asserts the macaroon is baked with read-only or read-write permissions accordingly. Verify permission addition/expansion by starting the node with sub-servers disabled and then restarting with sub-servers re-enabled. Also verify the none config choice, asserting that no super macaroon file is baked/created on startup.
1 parent cf100ba commit 5f1b684

2 files changed

Lines changed: 205 additions & 0 deletions

File tree

itest/litd_mode_integrated_test.go

Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"io/ioutil"
1212
"net/http"
1313
"os"
14+
"path/filepath"
1415
"strings"
1516
"testing"
1617
"time"
@@ -1481,3 +1482,203 @@ func bakeSuperMacaroon(t *testing.T, cfg *LitNodeConfig,
14811482

14821483
return tempFile.Name()
14831484
}
1485+
1486+
// testSuperMacaroonOnStartup tests that the super macaroon is successfully
1487+
// baked on startup if configured.
1488+
func testSuperMacaroonOnStartup(ctx context.Context, net *NetworkHarness,
1489+
t *harnessTest) {
1490+
1491+
superMacPath := filepath.Join(
1492+
net.Alice.Cfg.LitDir, "startup-super.macaroon",
1493+
)
1494+
1495+
verifyMacaroonPermissions := func(path string, expectWrite bool) {
1496+
ctxTimeout, cancel := context.WithTimeout(ctx, defaultTimeout)
1497+
defer cancel()
1498+
1499+
rawConn, err := connectRPC(
1500+
ctxTimeout, net.Alice.Cfg.LitAddr(),
1501+
net.Alice.Cfg.LitTLSCertPath,
1502+
)
1503+
require.NoError(t.t, err)
1504+
defer rawConn.Close()
1505+
1506+
macBytes, err := os.ReadFile(path)
1507+
require.NoError(t.t, err)
1508+
1509+
ctxm := macaroonContext(ctxTimeout, macBytes)
1510+
lnrpcConn := lnrpc.NewLightningClient(rawConn)
1511+
1512+
_, err = lnrpcConn.GetInfo(ctxm, &lnrpc.GetInfoRequest{})
1513+
require.NoError(t.t, err)
1514+
1515+
_, err = lnrpcConn.NewAddress(ctxm, &lnrpc.NewAddressRequest{
1516+
Type: lnrpc.AddressType_WITNESS_PUBKEY_HASH,
1517+
})
1518+
if expectWrite {
1519+
require.NoError(t.t, err)
1520+
} else {
1521+
require.Error(t.t, err)
1522+
require.Contains(t.t, err.Error(), "permission denied")
1523+
}
1524+
}
1525+
1526+
verifyMacaroonSubserverPermissions := func(path string,
1527+
expectSubservers bool) {
1528+
1529+
macBytes, err := os.ReadFile(path)
1530+
require.NoError(t.t, err)
1531+
1532+
mac := &macaroon.Macaroon{}
1533+
err = mac.UnmarshalBinary(macBytes)
1534+
require.NoError(t.t, err)
1535+
1536+
rawID := mac.Id()
1537+
require.NotEmpty(t.t, rawID)
1538+
1539+
decodedID := &lnrpc.MacaroonId{}
1540+
err = proto.Unmarshal(rawID[1:], decodedID)
1541+
require.NoError(t.t, err)
1542+
1543+
hasSubserver := false
1544+
for _, op := range decodedID.Ops {
1545+
if op == nil {
1546+
continue
1547+
}
1548+
if op.Entity == "loop" || op.Entity == "pool" ||
1549+
op.Entity == "faraday" {
1550+
1551+
hasSubserver = true
1552+
}
1553+
}
1554+
1555+
if expectSubservers {
1556+
require.True(
1557+
t.t, hasSubserver,
1558+
"expected macaroon to contain "+
1559+
"subserver permissions",
1560+
)
1561+
} else {
1562+
require.False(
1563+
t.t, hasSubserver,
1564+
"expected macaroon NOT to contain "+
1565+
"subserver permissions",
1566+
)
1567+
}
1568+
}
1569+
1570+
// Ensure any old file is removed first.
1571+
_ = os.Remove(superMacPath)
1572+
1573+
// Restart Alice with read-only super macaroon baking enabled.
1574+
err := net.RestartNode(
1575+
net.Alice, nil, []LitArgOption{
1576+
WithLitArg("bake-super-macaroon", "read-only"),
1577+
WithLitArg("super-macaroon-path", superMacPath),
1578+
},
1579+
)
1580+
require.NoError(t.t, err)
1581+
1582+
net.ConnectNodes(t.t, net.Alice, net.Bob)
1583+
1584+
// Verify that the super macaroon was created on startup.
1585+
require.FileExists(t.t, superMacPath)
1586+
1587+
// Verify permissions: write should be blocked.
1588+
verifyMacaroonPermissions(superMacPath, false)
1589+
1590+
// Restart Alice with a read-write super macaroon, WITHOUT
1591+
// deleting the file. This will test the overwrite behavior when
1592+
// permissions differ.
1593+
err = net.RestartNode(
1594+
net.Alice, nil, []LitArgOption{
1595+
WithLitArg("bake-super-macaroon", "read-write"),
1596+
WithLitArg("super-macaroon-path", superMacPath),
1597+
},
1598+
)
1599+
require.NoError(t.t, err)
1600+
net.ConnectNodes(t.t, net.Alice, net.Bob)
1601+
1602+
require.FileExists(t.t, superMacPath)
1603+
1604+
// Verify permissions: write should succeed.
1605+
verifyMacaroonPermissions(superMacPath, true)
1606+
1607+
// Restart Alice back with a read-only super macaroon, WITHOUT
1608+
// deleting the file. This will test the overwrite behavior when
1609+
// switching back to read-only.
1610+
err = net.RestartNode(
1611+
net.Alice, nil, []LitArgOption{
1612+
WithLitArg("bake-super-macaroon", "read-only"),
1613+
WithLitArg("super-macaroon-path", superMacPath),
1614+
},
1615+
)
1616+
require.NoError(t.t, err)
1617+
net.ConnectNodes(t.t, net.Alice, net.Bob)
1618+
1619+
require.FileExists(t.t, superMacPath)
1620+
1621+
// Verify permissions: write should be blocked again.
1622+
verifyMacaroonPermissions(superMacPath, false)
1623+
1624+
// Restart Alice with a sub-server disabled to bake a super macaroon
1625+
// with a subset of permissions.
1626+
err = net.RestartNode(
1627+
net.Alice, nil, []LitArgOption{
1628+
WithLitArg("bake-super-macaroon", "read-write"),
1629+
WithLitArg("super-macaroon-path", superMacPath),
1630+
WithLitArg("loop-mode", "disable"),
1631+
WithLitArg("pool-mode", "disable"),
1632+
WithLitArg("faraday-mode", "disable"),
1633+
},
1634+
)
1635+
require.NoError(t.t, err)
1636+
net.ConnectNodes(t.t, net.Alice, net.Bob)
1637+
1638+
require.FileExists(t.t, superMacPath)
1639+
verifyMacaroonSubserverPermissions(superMacPath, false)
1640+
1641+
// Restart Alice with the sub-servers re-enabled. This will add
1642+
// permissions and trigger macaroon regeneration on startup.
1643+
err = net.RestartNode(
1644+
net.Alice, nil, []LitArgOption{
1645+
WithLitArg("bake-super-macaroon", "read-write"),
1646+
WithLitArg("super-macaroon-path", superMacPath),
1647+
},
1648+
)
1649+
require.NoError(t.t, err)
1650+
net.ConnectNodes(t.t, net.Alice, net.Bob)
1651+
1652+
require.FileExists(t.t, superMacPath)
1653+
verifyMacaroonSubserverPermissions(superMacPath, true)
1654+
1655+
// Verify permissions: write should succeed.
1656+
verifyMacaroonPermissions(superMacPath, true)
1657+
1658+
// Clean up the super macaroon file.
1659+
_ = os.Remove(superMacPath)
1660+
1661+
// Restart Alice with super macaroon baking disabled and verify that
1662+
// no super macaroon is created.
1663+
err = net.RestartNode(
1664+
net.Alice, nil, []LitArgOption{
1665+
WithLitArg("bake-super-macaroon", "none"),
1666+
WithLitArg("super-macaroon-path", superMacPath),
1667+
},
1668+
)
1669+
require.NoError(t.t, err)
1670+
net.ConnectNodes(t.t, net.Alice, net.Bob)
1671+
1672+
_, err = os.Stat(superMacPath)
1673+
require.True(t.t, os.IsNotExist(err))
1674+
1675+
// Clean up after ourselves.
1676+
err = net.RestartNode(
1677+
net.Alice, nil, []LitArgOption{
1678+
WithoutLitArg("bake-super-macaroon"),
1679+
WithoutLitArg("super-macaroon-path"),
1680+
},
1681+
)
1682+
require.NoError(t.t, err)
1683+
net.ConnectNodes(t.t, net.Alice, net.Bob)
1684+
}

itest/litd_test_list_on_test.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,8 @@ var allTestCases = []*testCase{
3131
name: "kvdb to sql migration",
3232
test: testKvdbSQLMigration,
3333
},
34+
{
35+
name: "terminal super macaroon on startup",
36+
test: testSuperMacaroonOnStartup,
37+
},
3438
}

0 commit comments

Comments
 (0)