Skip to content

Commit 4b246d6

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. Also add validation tests verifying that starting with an invalid path suffix or in stateless-init mode with baking enabled fails as expected. 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 d409475 commit 4b246d6

2 files changed

Lines changed: 226 additions & 0 deletions

File tree

itest/litd_mode_integrated_test.go

Lines changed: 222 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,224 @@ 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+
// Test that starting Alice with an invalid super-macaroon-path (not
1574+
// ending with .macaroon) fails.
1575+
invalidMacPath := filepath.Join(
1576+
net.Alice.Cfg.LitDir, "invalid-path.mac",
1577+
)
1578+
err := net.RestartNode(
1579+
net.Alice, nil, []LitArgOption{
1580+
WithLitArg("bake-super-macaroon", "read-only"),
1581+
WithLitArg("super-macaroon-path", invalidMacPath),
1582+
},
1583+
)
1584+
require.Error(t.t, err)
1585+
1586+
// Drain the expected process exit error from the error channel to
1587+
// prevent it from failing the test runner at the end of the test.
1588+
select {
1589+
case <-net.lndErrorChan:
1590+
case <-time.After(defaultTimeout):
1591+
t.t.Fatalf("expected process exit error in lndErrorChan")
1592+
}
1593+
1594+
// Restart Alice with read-only super macaroon baking enabled.
1595+
err = net.RestartNode(
1596+
net.Alice, nil, []LitArgOption{
1597+
WithLitArg("bake-super-macaroon", "read-only"),
1598+
WithLitArg("super-macaroon-path", superMacPath),
1599+
},
1600+
)
1601+
require.NoError(t.t, err)
1602+
1603+
net.ConnectNodes(t.t, net.Alice, net.Bob)
1604+
1605+
// Verify that the super macaroon was created on startup.
1606+
require.FileExists(t.t, superMacPath)
1607+
1608+
// Verify permissions: write should be blocked.
1609+
verifyMacaroonPermissions(superMacPath, false)
1610+
1611+
// Restart Alice with a read-write super macaroon, WITHOUT
1612+
// deleting the file. This will test the overwrite behavior when
1613+
// permissions differ.
1614+
err = net.RestartNode(
1615+
net.Alice, nil, []LitArgOption{
1616+
WithLitArg("bake-super-macaroon", "read-write"),
1617+
WithLitArg("super-macaroon-path", superMacPath),
1618+
},
1619+
)
1620+
require.NoError(t.t, err)
1621+
net.ConnectNodes(t.t, net.Alice, net.Bob)
1622+
1623+
require.FileExists(t.t, superMacPath)
1624+
1625+
// Verify permissions: write should succeed.
1626+
verifyMacaroonPermissions(superMacPath, true)
1627+
1628+
// Restart Alice back with a read-only super macaroon, WITHOUT
1629+
// deleting the file. This will test the overwrite behavior when
1630+
// switching back to read-only.
1631+
err = net.RestartNode(
1632+
net.Alice, nil, []LitArgOption{
1633+
WithLitArg("bake-super-macaroon", "read-only"),
1634+
WithLitArg("super-macaroon-path", superMacPath),
1635+
},
1636+
)
1637+
require.NoError(t.t, err)
1638+
net.ConnectNodes(t.t, net.Alice, net.Bob)
1639+
1640+
require.FileExists(t.t, superMacPath)
1641+
1642+
// Verify permissions: write should be blocked again.
1643+
verifyMacaroonPermissions(superMacPath, false)
1644+
1645+
// Restart Alice with a sub-server disabled to bake a super macaroon
1646+
// with a subset of permissions.
1647+
err = net.RestartNode(
1648+
net.Alice, nil, []LitArgOption{
1649+
WithLitArg("bake-super-macaroon", "read-write"),
1650+
WithLitArg("super-macaroon-path", superMacPath),
1651+
WithLitArg("loop-mode", "disable"),
1652+
WithLitArg("pool-mode", "disable"),
1653+
WithLitArg("faraday-mode", "disable"),
1654+
},
1655+
)
1656+
require.NoError(t.t, err)
1657+
net.ConnectNodes(t.t, net.Alice, net.Bob)
1658+
1659+
require.FileExists(t.t, superMacPath)
1660+
verifyMacaroonSubserverPermissions(superMacPath, false)
1661+
1662+
// Restart Alice with the sub-servers re-enabled. This will add
1663+
// permissions and trigger macaroon regeneration on startup.
1664+
err = net.RestartNode(
1665+
net.Alice, nil, []LitArgOption{
1666+
WithLitArg("bake-super-macaroon", "read-write"),
1667+
WithLitArg("super-macaroon-path", superMacPath),
1668+
},
1669+
)
1670+
require.NoError(t.t, err)
1671+
net.ConnectNodes(t.t, net.Alice, net.Bob)
1672+
1673+
require.FileExists(t.t, superMacPath)
1674+
verifyMacaroonSubserverPermissions(superMacPath, true)
1675+
1676+
// Verify permissions: write should succeed.
1677+
verifyMacaroonPermissions(superMacPath, true)
1678+
1679+
// Clean up the super macaroon file.
1680+
_ = os.Remove(superMacPath)
1681+
1682+
// Restart Alice with super macaroon baking disabled and verify that
1683+
// no super macaroon is created.
1684+
err = net.RestartNode(
1685+
net.Alice, nil, []LitArgOption{
1686+
WithLitArg("bake-super-macaroon", "none"),
1687+
WithLitArg("super-macaroon-path", superMacPath),
1688+
},
1689+
)
1690+
require.NoError(t.t, err)
1691+
net.ConnectNodes(t.t, net.Alice, net.Bob)
1692+
1693+
_, err = os.Stat(superMacPath)
1694+
require.True(t.t, os.IsNotExist(err))
1695+
1696+
// Clean up after ourselves.
1697+
err = net.RestartNode(
1698+
net.Alice, nil, []LitArgOption{
1699+
WithoutLitArg("bake-super-macaroon"),
1700+
WithoutLitArg("super-macaroon-path"),
1701+
},
1702+
)
1703+
require.NoError(t.t, err)
1704+
net.ConnectNodes(t.t, net.Alice, net.Bob)
1705+
}

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)