Skip to content

lnrpc+rpcperms: add ctx metadata pairs to RPCMiddlewareRequest #9739

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Apr 23, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions docs/release-notes/release-notes-0.19.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,10 @@ close transaction.

* [Allow custom lock ID and
duration in FundPsbt](https://github.com/lightningnetwork/lnd/pull/9724) RPC.

* Expand the [lnrpc.RPCMiddlewareRequest](https://github.com/lightningnetwork/lnd/pull/9739)
to include any [gRPC metadata](https://grpc.io/docs/guides/metadata) pairs
that are passed to the initial request via the `context.Context`.

## lncli Updates

Expand Down
42 changes: 36 additions & 6 deletions itest/lnd_rpc_middleware_interceptor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"github.com/lightningnetwork/lnd/macaroons"
"github.com/lightningnetwork/lnd/zpay32"
"github.com/stretchr/testify/require"
"google.golang.org/grpc/metadata"
"google.golang.org/protobuf/proto"
"gopkg.in/macaroon.v2"
)
Expand Down Expand Up @@ -223,6 +224,18 @@ func middlewareInterceptionTest(t *testing.T,
ctxc, cancel := context.WithTimeout(ctxb, defaultTimeout)
defer cancel()

// Add some gRPC metadata pairs to the context that we use for one of
// the calls. This is so that we can test that the interceptor does
// properly receive the pairs via the interceptor request.
requestMetadata := metadata.MD{
"itest-metadata-key": []string{"itest-metadata-value"},
"itest-metadata-key2": []string{
"itest-metadata-value1",
"itest-metadata-value2",
},
}
ctxm := metadata.NewOutgoingContext(ctxc, requestMetadata)

// Create a client connection that we'll use to simulate user requests
// to lnd with.
cleanup, client := macaroonClient(t, node, userMac)
Expand All @@ -234,10 +247,11 @@ func middlewareInterceptionTest(t *testing.T,
req := &lnrpc.ListChannelsRequest{ActiveOnly: true}
go registration.interceptUnary(
"/lnrpc.Lightning/ListChannels", req, nil, readOnly, false,
requestMetadata,
)

// Do the actual call now and wait for the interceptor to do its thing.
resp, err := client.ListChannels(ctxc, req)
resp, err := client.ListChannels(ctxm, req)
require.NoError(t, err)

// Did we receive the correct intercept message?
Expand All @@ -252,7 +266,7 @@ func middlewareInterceptionTest(t *testing.T,
}
go registration.interceptUnary(
"/lnrpc.Lightning/ListChannels", invalidReq, nil, readOnly,
false,
false, nil,
)

// Do the actual call now and wait for the interceptor to do its thing.
Expand Down Expand Up @@ -384,7 +398,7 @@ func middlewareResponseManipulationTest(t *testing.T,
req := &lnrpc.ListChannelsRequest{ActiveOnly: true}
go registration.interceptUnary(
"/lnrpc.Lightning/ListChannels", req, replacementResponse,
readOnly, false,
readOnly, false, nil,
)

// Do the actual call now and wait for the interceptor to do its thing.
Expand All @@ -408,7 +422,7 @@ func middlewareResponseManipulationTest(t *testing.T,
}
go registration.interceptUnary(
"/lnrpc.Lightning/ListChannels", invalidReq, betterError,
readOnly, false,
readOnly, false, nil,
)

// Do the actual call now and wait for the interceptor to do its thing.
Expand Down Expand Up @@ -500,7 +514,7 @@ func middlewareRequestManipulationTest(t *testing.T, node *node.HarnessNode,
}
go registration.interceptUnary(
"/lnrpc.Lightning/AddInvoice", req, replacementRequest,
readOnly, true,
readOnly, true, nil,
)

// Do the actual call now and wait for the interceptor to do its thing.
Expand Down Expand Up @@ -717,12 +731,28 @@ func registerMiddleware(t *testing.T, node *node.HarnessNode,
// read from the response channel.
func (h *middlewareHarness) interceptUnary(methodURI string,
expectedRequest proto.Message, responseReplacement interface{},
readOnly bool, replaceRequest bool) {
readOnly bool, replaceRequest bool, expectedMetadata metadata.MD) {

// Read intercept message and make sure it's for an RPC request.
reqIntercept, err := h.stream.Recv()
require.NoError(h.t, err)

// Check that we have the expected metadata in the request.
if len(expectedMetadata) > 0 {
require.GreaterOrEqual(
h.t, len(reqIntercept.MetadataPairs),
len(expectedMetadata),
)

for key := range expectedMetadata {
require.Contains(h.t, reqIntercept.MetadataPairs, key)
require.Equal(
h.t, expectedMetadata[key],
reqIntercept.MetadataPairs[key].Values,
)
}
}

// Make sure the custom condition is populated correctly (if we're using
// a macaroon with a custom condition).
if !readOnly {
Expand Down
Loading
Loading