mirror of
https://github.com/lightninglabs/lightning-terminal.git
synced 2026-08-13 12:33:36 +02:00
multi: support regex URIs
With this commit, a user can now specify a regex when specifying custom permissions for an LNC session. This regex will be used to select permissions for URIs that match the regex.
This commit is contained in:
parent
d41f796f8e
commit
15cd1bdef9
4 changed files with 152 additions and 6 deletions
|
|
@ -73,7 +73,11 @@ var addSessionCommand = cli.Command{
|
|||
"this flag will only be used if the 'type' " +
|
||||
"flag is set to 'custom'. This flag can be " +
|
||||
"specified multiple times if multiple URIs " +
|
||||
"should be included",
|
||||
"should be included. Note that a regex can " +
|
||||
"also be specified which will then result in " +
|
||||
"all URIs matching the regex to be included. " +
|
||||
"For example, '/lnrpc\\..*' will result in " +
|
||||
"all `lnrpc` permissions being included.",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package perms
|
|||
|
||||
import (
|
||||
"net"
|
||||
"regexp"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
|
|
@ -210,6 +211,40 @@ func (pm *Manager) URIPermissions(uri string) ([]bakery.Op, bool) {
|
|||
return ops, ok
|
||||
}
|
||||
|
||||
// MatchRegexURI first checks that the given URI is in fact a regex. If it is,
|
||||
// then it is used to match on the perms that the manager has. The return values
|
||||
// are a list of URIs that match the regex and the boolean represents whether
|
||||
// the given uri is in fact a regex.
|
||||
func (pm *Manager) MatchRegexURI(uriRegex string) ([]string, bool) {
|
||||
pm.permsMu.RLock()
|
||||
defer pm.permsMu.RUnlock()
|
||||
|
||||
// If the given uri string is one of our permissions, then it is not
|
||||
// a regex.
|
||||
if _, ok := pm.perms[uriRegex]; ok {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
// Construct the regex type from the given string.
|
||||
r, err := regexp.Compile(uriRegex)
|
||||
if err != nil {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
// Iterate over the list of permissions and collect all permissions that
|
||||
// match the given regex.
|
||||
var matches []string
|
||||
for uri := range pm.perms {
|
||||
if !r.MatchString(uri) {
|
||||
continue
|
||||
}
|
||||
|
||||
matches = append(matches, uri)
|
||||
}
|
||||
|
||||
return matches, true
|
||||
}
|
||||
|
||||
// ActivePermissions returns all the available active permissions that the
|
||||
// manager is aware of. Optionally, readOnly can be set to true if only the
|
||||
// read-only permissions should be returned.
|
||||
|
|
|
|||
81
perms/permissions_test.go
Normal file
81
perms/permissions_test.go
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
package perms
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
"gopkg.in/macaroon-bakery.v2/bakery"
|
||||
)
|
||||
|
||||
// TestMatchRegexURI tests the behaviour of the MatchRegexURI method of the
|
||||
// Manager.
|
||||
func TestMatchRegexURI(t *testing.T) {
|
||||
// Construct a new Manager with a predefined list of perms.
|
||||
m := &Manager{
|
||||
perms: map[string][]bakery.Op{
|
||||
"/lnrpc.WalletUnlocker/GenSeed": {},
|
||||
"/lnrpc.WalletUnlocker/InitWallet": {},
|
||||
"/lnrpc.Lightning/SendCoins": {{
|
||||
Entity: "onchain",
|
||||
Action: "write",
|
||||
}},
|
||||
"/litrpc.Sessions/AddSession": {{
|
||||
Entity: "sessions",
|
||||
Action: "write",
|
||||
}},
|
||||
"/litrpc.Sessions/ListSessions": {{
|
||||
Entity: "sessions",
|
||||
Action: "read",
|
||||
}},
|
||||
"/litrpc.Sessions/RevokeSession": {{
|
||||
Entity: "sessions",
|
||||
Action: "write",
|
||||
}},
|
||||
},
|
||||
}
|
||||
|
||||
// Assert that a full URI is not considered a wild card.
|
||||
uris, isRegex := m.MatchRegexURI("/litrpc.Sessions/RevokeSession")
|
||||
require.False(t, isRegex)
|
||||
require.Empty(t, uris)
|
||||
|
||||
// Assert that an invalid URI is also caught as such.
|
||||
uris, isRegex = m.MatchRegexURI("***")
|
||||
require.False(t, isRegex)
|
||||
require.Nil(t, uris)
|
||||
|
||||
// Assert that the function correctly matches on a valid wild card for
|
||||
// litrpc URIs.
|
||||
uris, isRegex = m.MatchRegexURI("/litrpc.Sessions/.*")
|
||||
require.True(t, isRegex)
|
||||
require.ElementsMatch(t, uris, []string{
|
||||
"/litrpc.Sessions/AddSession",
|
||||
"/litrpc.Sessions/ListSessions",
|
||||
"/litrpc.Sessions/RevokeSession",
|
||||
})
|
||||
|
||||
// Assert that the function correctly matches on a valid wild card for
|
||||
// lnd URIs. First we check that we can specify that only the
|
||||
// "WalletUnlocker" methods should be included.
|
||||
uris, isRegex = m.MatchRegexURI("/lnrpc.WalletUnlocker/.*")
|
||||
require.True(t, isRegex)
|
||||
require.ElementsMatch(t, uris, []string{
|
||||
"/lnrpc.WalletUnlocker/GenSeed",
|
||||
"/lnrpc.WalletUnlocker/InitWallet",
|
||||
})
|
||||
|
||||
// Now we check that we can include all the `lnrpc` methods.
|
||||
uris, isRegex = m.MatchRegexURI("/lnrpc\\..*")
|
||||
require.True(t, isRegex)
|
||||
require.ElementsMatch(t, uris, []string{
|
||||
"/lnrpc.WalletUnlocker/GenSeed",
|
||||
"/lnrpc.WalletUnlocker/InitWallet",
|
||||
"/lnrpc.Lightning/SendCoins",
|
||||
})
|
||||
|
||||
// Assert that the function does not return any URIs for a wild card
|
||||
// URI that does not match on any of its perms.
|
||||
uris, isRegex = m.MatchRegexURI("/poolrpc.Trader/.*")
|
||||
require.True(t, isRegex)
|
||||
require.Empty(t, uris)
|
||||
}
|
||||
|
|
@ -143,12 +143,38 @@ func (s *sessionRpcServer) AddSession(_ context.Context,
|
|||
}
|
||||
|
||||
for _, op := range req.MacaroonCustomPermissions {
|
||||
if op.Entity == macaroons.PermissionEntityCustomURI {
|
||||
_, ok := s.cfg.permMgr.URIPermissions(op.Action)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("URI %s is "+
|
||||
"unknown to LiT", op.Action)
|
||||
if op.Entity != macaroons.PermissionEntityCustomURI {
|
||||
permissions = append(permissions, bakery.Op{
|
||||
Entity: op.Entity,
|
||||
Action: op.Action,
|
||||
})
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
// First check if this is a regex URI.
|
||||
uris, isRegex := s.cfg.permMgr.MatchRegexURI(op.Action)
|
||||
if isRegex {
|
||||
// This is a regex URI, and so we add each of
|
||||
// the matching URIs returned from the
|
||||
// permissions' manager.
|
||||
for _, uri := range uris {
|
||||
permissions = append(
|
||||
permissions, bakery.Op{
|
||||
Entity: op.Entity,
|
||||
Action: uri,
|
||||
},
|
||||
)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
// This is not a wild card URI, so just check that the
|
||||
// permissions' manager is aware of this URI.
|
||||
_, ok := s.cfg.permMgr.URIPermissions(op.Action)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("URI %s is unknown to "+
|
||||
"LiT", op.Action)
|
||||
}
|
||||
|
||||
permissions = append(permissions, bakery.Op{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue