mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-07-01 19:10:59 +02:00
rpcperms: allow requests to be replaced as well
With this commit we allow a replacement message to be sent by the middleware for a request type as well as the response type. This allows an incoming RPC request to be modified before it is forwarded to lnd.
This commit is contained in:
@ -118,7 +118,7 @@ var (
|
|||||||
// | Macaroon Interceptor |
|
// | Macaroon Interceptor |
|
||||||
// +----------------------------------+--------> +---------------------+
|
// +----------------------------------+--------> +---------------------+
|
||||||
// | RPC Macaroon Middleware Handler |<-------- | External Middleware |
|
// | RPC Macaroon Middleware Handler |<-------- | External Middleware |
|
||||||
// +----------------------------------+ | - approve request |
|
// +----------------------------------+ | - modify request |
|
||||||
// | Prometheus Interceptor | +---------------------+
|
// | Prometheus Interceptor | +---------------------+
|
||||||
// +-+--------------------------------+
|
// +-+--------------------------------+
|
||||||
// | validated gRPC request from client
|
// | validated gRPC request from client
|
||||||
@ -808,15 +808,11 @@ func (r *InterceptorChain) middlewareUnaryServerInterceptor() grpc.UnaryServerIn
|
|||||||
return handler(ctx, req)
|
return handler(ctx, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
msg, err := NewMessageInterceptionRequest(
|
|
||||||
ctx, TypeRequest, false, info.FullMethod, req,
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
requestID := atomic.AddUint64(&r.lastRequestID, 1)
|
requestID := atomic.AddUint64(&r.lastRequestID, 1)
|
||||||
err = r.acceptRequest(requestID, msg)
|
req, err := r.interceptMessage(
|
||||||
|
ctx, TypeRequest, requestID, false, info.FullMethod,
|
||||||
|
req,
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -826,8 +822,9 @@ func (r *InterceptorChain) middlewareUnaryServerInterceptor() grpc.UnaryServerIn
|
|||||||
return resp, respErr
|
return resp, respErr
|
||||||
}
|
}
|
||||||
|
|
||||||
return r.interceptResponse(
|
return r.interceptMessage(
|
||||||
ctx, requestID, false, info.FullMethod, resp,
|
ctx, TypeResponse, requestID, false, info.FullMethod,
|
||||||
|
resp,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -874,7 +871,7 @@ func (r *InterceptorChain) middlewareStreamServerInterceptor() grpc.StreamServer
|
|||||||
}
|
}
|
||||||
|
|
||||||
requestID := atomic.AddUint64(&r.lastRequestID, 1)
|
requestID := atomic.AddUint64(&r.lastRequestID, 1)
|
||||||
err = r.acceptRequest(requestID, msg)
|
err = r.acceptStream(requestID, msg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -926,11 +923,11 @@ func (r *InterceptorChain) middlewareRegistered() bool {
|
|||||||
return len(r.registeredMiddleware) > 0
|
return len(r.registeredMiddleware) > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// acceptRequest sends an intercept request to all middlewares that have
|
// acceptStream sends an intercept request to all middlewares that have
|
||||||
// registered for it. This means either a middleware has requested read-only
|
// registered for it. This means either a middleware has requested read-only
|
||||||
// access or the request actually has a macaroon with a caveat the middleware
|
// access or the request actually has a macaroon with a caveat the middleware
|
||||||
// registered for.
|
// registered for.
|
||||||
func (r *InterceptorChain) acceptRequest(requestID uint64,
|
func (r *InterceptorChain) acceptStream(requestID uint64,
|
||||||
msg *InterceptionRequest) error {
|
msg *InterceptionRequest) error {
|
||||||
|
|
||||||
r.RLock()
|
r.RLock()
|
||||||
@ -967,13 +964,13 @@ func (r *InterceptorChain) acceptRequest(requestID uint64,
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// interceptResponse sends out an intercept request for an RPC response. Since
|
// interceptMessage sends out an intercept request for an RPC response. Since
|
||||||
// middleware that hasn't registered for the read-only mode has the option to
|
// middleware that hasn't registered for the read-only mode has the option to
|
||||||
// overwrite/replace the response, this needs to be handled differently than the
|
// overwrite/replace the message, this needs to be handled differently than the
|
||||||
// request/auth path above.
|
// auth path above.
|
||||||
func (r *InterceptorChain) interceptResponse(ctx context.Context,
|
func (r *InterceptorChain) interceptMessage(ctx context.Context,
|
||||||
requestID uint64, isStream bool, fullMethod string,
|
interceptType InterceptType, requestID uint64, isStream bool,
|
||||||
m interface{}) (interface{}, error) {
|
fullMethod string, m interface{}) (interface{}, error) {
|
||||||
|
|
||||||
r.RLock()
|
r.RLock()
|
||||||
defer r.RUnlock()
|
defer r.RUnlock()
|
||||||
@ -981,7 +978,8 @@ func (r *InterceptorChain) interceptResponse(ctx context.Context,
|
|||||||
currentMessage := m
|
currentMessage := m
|
||||||
for _, middleware := range r.registeredMiddleware {
|
for _, middleware := range r.registeredMiddleware {
|
||||||
msg, err := NewMessageInterceptionRequest(
|
msg, err := NewMessageInterceptionRequest(
|
||||||
ctx, TypeResponse, isStream, fullMethod, currentMessage,
|
ctx, interceptType, isStream, fullMethod,
|
||||||
|
currentMessage,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -1039,8 +1037,9 @@ type serverStreamWrapper struct {
|
|||||||
// SendMsg is called when lnd sends a message to the client. This is wrapped to
|
// SendMsg is called when lnd sends a message to the client. This is wrapped to
|
||||||
// intercept streaming RPC responses.
|
// intercept streaming RPC responses.
|
||||||
func (w *serverStreamWrapper) SendMsg(m interface{}) error {
|
func (w *serverStreamWrapper) SendMsg(m interface{}) error {
|
||||||
newMsg, err := w.interceptor.interceptResponse(
|
newMsg, err := w.interceptor.interceptMessage(
|
||||||
w.ServerStream.Context(), w.requestID, true, w.fullMethod, m,
|
w.ServerStream.Context(), TypeResponse, w.requestID, true,
|
||||||
|
w.fullMethod, m,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -1057,13 +1056,13 @@ func (w *serverStreamWrapper) RecvMsg(m interface{}) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
msg, err := NewMessageInterceptionRequest(
|
req, err := w.interceptor.interceptMessage(
|
||||||
w.ServerStream.Context(), TypeRequest, true, w.fullMethod,
|
w.ServerStream.Context(), TypeRequest, w.requestID, true,
|
||||||
m,
|
w.fullMethod, m,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return w.interceptor.acceptRequest(w.requestID, msg)
|
return replaceProtoMsg(m, req)
|
||||||
}
|
}
|
||||||
|
@ -263,11 +263,9 @@ func (h *MiddlewareHandler) sendInterceptRequests(errChan chan error,
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
// For intercepted responses we also allow the
|
// For intercepted messages we also allow the
|
||||||
// content itself to be overwritten.
|
// content itself to be overwritten.
|
||||||
if requestInfo.request.Type == TypeResponse &&
|
if t.ReplaceResponse {
|
||||||
t.ReplaceResponse {
|
|
||||||
|
|
||||||
response.replace = true
|
response.replace = true
|
||||||
protoMsg, err := parseProto(
|
protoMsg, err := parseProto(
|
||||||
requestInfo.request.ProtoTypeName,
|
requestInfo.request.ProtoTypeName,
|
||||||
@ -322,7 +320,8 @@ const (
|
|||||||
// TypeRequest is the type of intercept message that is sent when an RPC
|
// TypeRequest is the type of intercept message that is sent when an RPC
|
||||||
// request message is sent to lnd. For client-streaming RPCs a new
|
// request message is sent to lnd. For client-streaming RPCs a new
|
||||||
// message of this type is sent for each individual RPC request sent to
|
// message of this type is sent for each individual RPC request sent to
|
||||||
// the stream.
|
// the stream. Middleware has the option to modify a request message
|
||||||
|
// before it is delivered to lnd.
|
||||||
TypeRequest InterceptType = 2
|
TypeRequest InterceptType = 2
|
||||||
|
|
||||||
// TypeResponse is the type of intercept message that is sent when an
|
// TypeResponse is the type of intercept message that is sent when an
|
||||||
|
Reference in New Issue
Block a user