Skip to content

Commit a13be3b

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 71c3c07 commit a13be3b

2 files changed

Lines changed: 219 additions & 0 deletions

File tree

itest/litd_mode_integrated_test.go

Lines changed: 215 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"
@@ -1530,3 +1531,217 @@ func bakeSuperMacaroon(t *testing.T, cfg *LitNodeConfig,
15301531

15311532
return tempFile.Name()
15321533
}
1534+
1535+
// testSuperMacaroonOnStartup tests that the super macaroon is successfully
1536+
// baked on startup if configured.
1537+
func testSuperMacaroonOnStartup(ctx context.Context, net *NetworkHarness,
1538+
t *harnessTest) {
1539+
1540+
superMacPath := filepath.Join(
1541+
net.Alice.Cfg.LitDir, "startup-super.macaroon",
1542+
)
1543+
1544+
verifyMacaroonPermissions := func(path string, expectWrite bool) {
1545+
ctxTimeout, cancel := context.WithTimeout(ctx, defaultTimeout)
1546+
defer cancel()
1547+
1548+
rawConn, err := connectRPC(
1549+
ctxTimeout, net.Alice.Cfg.LitAddr(),
1550+
net.Alice.Cfg.LitTLSCertPath,
1551+
)
1552+
require.NoError(t.t, err)
1553+
defer rawConn.Close()
1554+
1555+
macBytes, err := os.ReadFile(path)
1556+
require.NoError(t.t, err)
1557+
1558+
ctxm := macaroonContext(ctxTimeout, macBytes)
1559+
lnrpcConn := lnrpc.NewLightningClient(rawConn)
1560+
1561+
_, err = lnrpcConn.GetInfo(ctxm, &lnrpc.GetInfoRequest{})
1562+
require.NoError(t.t, err)
1563+
1564+
_, err = lnrpcConn.NewAddress(ctxm, &lnrpc.NewAddressRequest{
1565+
Type: lnrpc.AddressType_WITNESS_PUBKEY_HASH,
1566+
})
1567+
if expectWrite {
1568+
require.NoError(t.t, err)
1569+
} else {
1570+
require.Error(t.t, err)
1571+
require.Contains(t.t, err.Error(), "permission denied")
1572+
}
1573+
}
1574+
1575+
verifyMacaroonSubserverPermissions := func(path string,
1576+
expectSubservers bool) {
1577+
1578+
macBytes, err := os.ReadFile(path)
1579+
require.NoError(t.t, err)
1580+
1581+
mac := &macaroon.Macaroon{}
1582+
err = mac.UnmarshalBinary(macBytes)
1583+
require.NoError(t.t, err)
1584+
1585+
rawID := mac.Id()
1586+
require.NotEmpty(t.t, rawID)
1587+
1588+
decodedID := &lnrpc.MacaroonId{}
1589+
err = proto.Unmarshal(rawID[1:], decodedID)
1590+
require.NoError(t.t, err)
1591+
1592+
hasSubserver := false
1593+
for _, op := range decodedID.Ops {
1594+
if op == nil {
1595+
continue
1596+
}
1597+
if op.Entity == "loop" || op.Entity == "pool" ||
1598+
op.Entity == "faraday" {
1599+
1600+
hasSubserver = true
1601+
}
1602+
}
1603+
1604+
if expectSubservers {
1605+
require.True(
1606+
t.t, hasSubserver,
1607+
"expected macaroon to contain "+
1608+
"subserver permissions",
1609+
)
1610+
} else {
1611+
require.False(
1612+
t.t, hasSubserver,
1613+
"expected macaroon NOT to contain "+
1614+
"subserver permissions",
1615+
)
1616+
}
1617+
}
1618+
1619+
// Ensure any old file is removed first.
1620+
_ = os.Remove(superMacPath)
1621+
1622+
// Test that starting Alice with an invalid super-macaroon-path (not
1623+
// ending with .macaroon) fails.
1624+
invalidMacPath := filepath.Join(
1625+
net.Alice.Cfg.LitDir, "invalid-path.mac",
1626+
)
1627+
err := net.RestartNode(
1628+
net.Alice, nil, []LitArgOption{
1629+
WithLitArg("bake-super-macaroon", "read-only"),
1630+
WithLitArg("super-macaroon-path", invalidMacPath),
1631+
},
1632+
)
1633+
require.Error(t.t, err)
1634+
1635+
// Drain the expected process exit error from the error channel to
1636+
// prevent it from failing the test runner at the end of the test.
1637+
select {
1638+
case <-net.lndErrorChan:
1639+
case <-time.After(defaultTimeout):
1640+
t.t.Fatalf("expected process exit error in lndErrorChan")
1641+
}
1642+
1643+
// Restart Alice with read-only super macaroon baking enabled.
1644+
err = net.RestartNode(
1645+
net.Alice, nil, []LitArgOption{
1646+
WithLitArg("bake-super-macaroon", "read-only"),
1647+
WithLitArg("super-macaroon-path", superMacPath),
1648+
},
1649+
)
1650+
require.NoError(t.t, err)
1651+
1652+
// Verify that the super macaroon was created on startup.
1653+
require.FileExists(t.t, superMacPath)
1654+
1655+
// Verify permissions: write should be blocked.
1656+
verifyMacaroonPermissions(superMacPath, false)
1657+
1658+
// Restart Alice with a read-write super macaroon, WITHOUT
1659+
// deleting the file. This will test the overwrite behavior when
1660+
// permissions differ.
1661+
err = net.RestartNode(
1662+
net.Alice, nil, []LitArgOption{
1663+
WithLitArg("bake-super-macaroon", "read-write"),
1664+
WithLitArg("super-macaroon-path", superMacPath),
1665+
},
1666+
)
1667+
require.NoError(t.t, err)
1668+
1669+
require.FileExists(t.t, superMacPath)
1670+
1671+
// Verify permissions: write should succeed.
1672+
verifyMacaroonPermissions(superMacPath, true)
1673+
1674+
// Restart Alice back with a read-only super macaroon, WITHOUT
1675+
// deleting the file. This will test the overwrite behavior when
1676+
// switching back to read-only.
1677+
err = net.RestartNode(
1678+
net.Alice, nil, []LitArgOption{
1679+
WithLitArg("bake-super-macaroon", "read-only"),
1680+
WithLitArg("super-macaroon-path", superMacPath),
1681+
},
1682+
)
1683+
require.NoError(t.t, err)
1684+
1685+
require.FileExists(t.t, superMacPath)
1686+
1687+
// Verify permissions: write should be blocked again.
1688+
verifyMacaroonPermissions(superMacPath, false)
1689+
1690+
// Restart Alice with a sub-server disabled to bake a super macaroon
1691+
// with a subset of permissions.
1692+
err = net.RestartNode(
1693+
net.Alice, nil, []LitArgOption{
1694+
WithLitArg("bake-super-macaroon", "read-write"),
1695+
WithLitArg("super-macaroon-path", superMacPath),
1696+
WithLitArg("loop-mode", "disable"),
1697+
WithLitArg("pool-mode", "disable"),
1698+
WithLitArg("faraday-mode", "disable"),
1699+
},
1700+
)
1701+
require.NoError(t.t, err)
1702+
1703+
require.FileExists(t.t, superMacPath)
1704+
verifyMacaroonSubserverPermissions(superMacPath, false)
1705+
1706+
// Restart Alice with the sub-servers re-enabled. This will add
1707+
// permissions and trigger macaroon regeneration on startup.
1708+
err = net.RestartNode(
1709+
net.Alice, nil, []LitArgOption{
1710+
WithLitArg("bake-super-macaroon", "read-write"),
1711+
WithLitArg("super-macaroon-path", superMacPath),
1712+
},
1713+
)
1714+
require.NoError(t.t, err)
1715+
1716+
require.FileExists(t.t, superMacPath)
1717+
verifyMacaroonSubserverPermissions(superMacPath, true)
1718+
1719+
// Verify permissions: write should succeed.
1720+
verifyMacaroonPermissions(superMacPath, true)
1721+
1722+
// Clean up the super macaroon file.
1723+
_ = os.Remove(superMacPath)
1724+
1725+
// Restart Alice with super macaroon baking disabled and verify that
1726+
// no super macaroon is created.
1727+
err = net.RestartNode(
1728+
net.Alice, nil, []LitArgOption{
1729+
WithLitArg("bake-super-macaroon", "none"),
1730+
WithLitArg("super-macaroon-path", superMacPath),
1731+
},
1732+
)
1733+
require.NoError(t.t, err)
1734+
1735+
_, err = os.Stat(superMacPath)
1736+
require.True(t.t, os.IsNotExist(err))
1737+
1738+
// Clean up after ourselves.
1739+
err = net.RestartNode(
1740+
net.Alice, nil, []LitArgOption{
1741+
WithoutLitArg("bake-super-macaroon"),
1742+
WithoutLitArg("super-macaroon-path"),
1743+
},
1744+
)
1745+
require.NoError(t.t, err)
1746+
net.ConnectNodes(t.t, net.Alice, net.Bob)
1747+
}

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)