Skip to content

Commit c3d9338

Browse files
committed
multi: use URIs in session macaroon instead of perms
Also includes an itest to assert that sessions work with very large headers.
1 parent a74ae88 commit c3d9338

File tree

3 files changed

+132
-18
lines changed

3 files changed

+132
-18
lines changed

itest/litd_firewall_test.go

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919
"github.com/lightninglabs/lightning-terminal/litrpc"
2020
"github.com/lightninglabs/lightning-terminal/rules"
2121
"github.com/lightninglabs/lightning-terminal/session"
22+
"github.com/lightningnetwork/lnd"
2223
"github.com/lightningnetwork/lnd/keychain"
2324
"github.com/lightningnetwork/lnd/lnrpc"
2425
"github.com/lightningnetwork/lnd/lntest"
@@ -1137,6 +1138,125 @@ func testPeerAndChannelRestrictRules(net *NetworkHarness, t *harnessTest) {
11371138
require.NoError(t.t, err)
11381139
}
11391140

1141+
func testLargeHttpHeader(net *NetworkHarness, t *harnessTest) {
1142+
ctx := context.Background()
1143+
1144+
// First we add all LND's permissions so that any call we make to LND to
1145+
// test that the connection is working will succeed.
1146+
perms := lnd.MainRPCServerPermissions()
1147+
1148+
// Now we pad the above valid perms with a bunch of junk perms. This is
1149+
// done in order to make the macaroon that will be sent in the header
1150+
// very big.
1151+
for i := 0; i < 800; i++ {
1152+
uniqueString := fmt.Sprintf("unique long string %d", i)
1153+
perms[uniqueString] = []bakery.Op{
1154+
{
1155+
Entity: uniqueString,
1156+
Action: "fake-action",
1157+
},
1158+
}
1159+
}
1160+
1161+
// We first override the autopilots features set. We create a feature
1162+
// with a very large permissions set. This is done so that we can test
1163+
// that a grpc/http header of a certain size does not break things.
1164+
net.autopilotServer.SetFeatures(map[string]*mock.Feature{
1165+
"TestFeature": {
1166+
Rules: map[string]*mock.RuleRanges{},
1167+
Permissions: perms,
1168+
},
1169+
})
1170+
1171+
// We expect a non-empty alias to be returned.
1172+
aliceInfo, err := net.Alice.GetInfo(ctx, &lnrpc.GetInfoRequest{})
1173+
require.NoError(t.t, err)
1174+
require.NotEmpty(t.t, aliceInfo.Alias)
1175+
1176+
// We create a connection to the Alice node's RPC server.
1177+
cfg := net.Alice.Cfg
1178+
rawConn, err := connectRPC(ctx, cfg.LitAddr(), cfg.TLSCertPath)
1179+
require.NoError(t.t, err)
1180+
1181+
macBytes, err := ioutil.ReadFile(cfg.LitMacPath)
1182+
require.NoError(t.t, err)
1183+
ctxm := macaroonContext(ctx, macBytes)
1184+
1185+
// Test that the connection to Alice's rpc server is working and that
1186+
// the autopilot server is returning a non-empty feature list.
1187+
litClient := litrpc.NewAutopilotClient(rawConn)
1188+
featResp, err := litClient.ListAutopilotFeatures(
1189+
ctxm, &litrpc.ListAutopilotFeaturesRequest{},
1190+
)
1191+
require.NoError(t.t, err)
1192+
require.NotEmpty(t.t, featResp)
1193+
1194+
// Add a new Autopilot session that subscribes to a "Test", feature.
1195+
// This call is expected to also result in Litd registering this session
1196+
// with the mock autopilot server.
1197+
sessResp, err := litClient.AddAutopilotSession(
1198+
ctxm, &litrpc.AddAutopilotSessionRequest{
1199+
Label: "integration-test",
1200+
ExpiryTimestampSeconds: uint64(
1201+
time.Now().Add(5 * time.Minute).Unix(),
1202+
),
1203+
MailboxServerAddr: mailboxServerAddr,
1204+
Features: map[string]*litrpc.FeatureConfig{
1205+
"TestFeature": {
1206+
Rules: &litrpc.RulesMap{
1207+
Rules: map[string]*litrpc.RuleValue{},
1208+
},
1209+
},
1210+
},
1211+
// Switch the privacy mapper off for simplicity’s sake.
1212+
NoPrivacyMapper: true,
1213+
},
1214+
)
1215+
require.NoError(t.t, err)
1216+
1217+
// From the response, we can extract Lit's local public key.
1218+
litdPub, err := btcec.ParsePubKey(sessResp.Session.LocalPublicKey)
1219+
require.NoError(t.t, err)
1220+
1221+
// We then query the autopilot server to extract the private key that
1222+
// it will be using for this session.
1223+
pilotPriv, err := net.autopilotServer.GetPrivKey(litdPub)
1224+
require.NoError(t.t, err)
1225+
1226+
// Now we can connect to the mailbox from the PoV of the autopilot
1227+
// server.
1228+
pilotConn, metaDataInjector, err := connectMailboxWithRemoteKey(
1229+
ctx, pilotPriv, litdPub,
1230+
)
1231+
require.NoError(t.t, err)
1232+
defer pilotConn.Close()
1233+
lndConn := lnrpc.NewLightningClient(pilotConn)
1234+
1235+
// The autopilot server is expected to add a MetaInfo caveat to any
1236+
// request that it makes. So we add that now and specify that it is
1237+
// initially making requests on behalf of the HealthCheck feature.
1238+
metaInfo := &firewall.InterceptMetaInfo{
1239+
ActorName: "Autopilot Server",
1240+
Feature: "TestFeature",
1241+
}
1242+
caveat, err := metaInfo.ToCaveat()
1243+
require.NoError(t.t, err)
1244+
caveatCreds := metaDataInjector.addCaveat(caveat)
1245+
1246+
// Now we assert that the size of the macaroon that will go in the
1247+
// request header is larger than a certain threshold.
1248+
meta, err := caveatCreds.Creds.GetRequestMetadata(ctx, "")
1249+
require.NoError(t.t, err)
1250+
require.Greater(t.t, len([]byte(meta[HeaderMacaroon])), 40000)
1251+
1252+
// Assert that requests from the autopilot work with this large header.
1253+
getInfoReq, err := lndConn.GetInfo(
1254+
ctx, &lnrpc.GetInfoRequest{}, caveatCreds,
1255+
)
1256+
require.NoError(t.t, err)
1257+
require.Equal(t.t, aliceInfo.Alias, getInfoReq.Alias)
1258+
}
1259+
11401260
// connectMailboxWithRemoteKey tries to establish a connection through LNC using
11411261
// the given local and remote keys and the test mailbox server.
11421262
func connectMailboxWithRemoteKey(ctx context.Context,

itest/litd_test_list_on_test.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,8 @@ var allTestCases = []*testCase{
1616
name: "test firewall rules",
1717
test: testFirewallRules,
1818
},
19+
{
20+
name: "test large http header",
21+
test: testLargeHttpHeader,
22+
},
1923
}

session_rpcserver.go

Lines changed: 8 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -934,33 +934,23 @@ func (s *sessionRpcServer) AddAutopilotSession(ctx context.Context,
934934

935935
// Gather all the permissions we need to add to the macaroon given the
936936
// feature list.
937-
var dedupedPerms = make(map[string]map[string]bool)
937+
var dedupedPerms = make(map[string]bool)
938938
for name, feature := range autopilotFeatureMap {
939939
if _, ok := req.Features[name]; !ok {
940940
continue
941941
}
942942

943-
for _, ops := range feature.Permissions {
944-
for _, op := range ops {
945-
if dedupedPerms[op.Entity] == nil {
946-
dedupedPerms[op.Entity] = make(
947-
map[string]bool,
948-
)
949-
}
950-
951-
dedupedPerms[op.Entity][op.Action] = true
952-
}
943+
for uri := range feature.Permissions {
944+
dedupedPerms[uri] = true
953945
}
954946
}
955947

956948
var perms []bakery.Op
957-
for entity, actions := range dedupedPerms {
958-
for action := range actions {
959-
perms = append(perms, bakery.Op{
960-
Entity: entity,
961-
Action: action,
962-
})
963-
}
949+
for uri := range dedupedPerms {
950+
perms = append(perms, bakery.Op{
951+
Entity: macaroons.PermissionEntityCustomURI,
952+
Action: uri,
953+
})
964954
}
965955

966956
rulesCaveatStr, err := firewall.RulesToCaveat(interceptRules)

0 commit comments

Comments
 (0)