Skip to content

Commit b9cc180

Browse files
authored
Merge pull request #457 from ellemouton/customPlusReadOnlyPerms
session_rpcserver+litrpc: allow custom session with all read-only perms
2 parents ce2cf12 + 00357fd commit b9cc180

File tree

4 files changed

+80
-20
lines changed

4 files changed

+80
-20
lines changed

litrpc/lit-sessions.pb.go

Lines changed: 10 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

litrpc/lit-sessions.proto

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,18 @@ message AddSessionRequest {
3636
}
3737

3838
message MacaroonPermission {
39-
// The entity a permission grants access to.
39+
// The entity a permission grants access to. If a entity is set to the
40+
// "uri" keyword then the action entry should be one of the special cases
41+
// described in the comment for action.
4042
string entity = 1;
4143

42-
// The action that is granted.
44+
// The action that is granted. If entity is set to "uri", then action must
45+
// be set to either:
46+
// - a particular URI to which access should be granted.
47+
// - a URI regex, in which case access will be granted to each URI that
48+
// matches the regex.
49+
// - the "***readonly***" keyword. This will result in the access being
50+
// granted to all read-only endpoints.
4351
string action = 2;
4452
}
4553

perms/permissions_test.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,4 +78,10 @@ func TestMatchRegexURI(t *testing.T) {
7878
uris, isRegex = m.MatchRegexURI("/poolrpc.Trader/.*")
7979
require.True(t, isRegex)
8080
require.Empty(t, uris)
81+
82+
// Assert that the read-only permission's keyword is not seen as a valid
83+
// regex.
84+
uris, isRegex = m.MatchRegexURI("***readonly***")
85+
require.False(t, isRegex)
86+
require.Empty(t, uris)
8187
}

session_rpcserver.go

Lines changed: 54 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,14 @@ import (
1919
"gopkg.in/macaroon.v2"
2020
)
2121

22+
// readOnlyAction defines the keyword that a permission action should be set to
23+
// when the entity is set to "uri" in order to activate the special case that
24+
// will result in all read-only permissions known to lit to be added to a
25+
// session's macaroon. The purpose of the three '*'s is to make this keyword
26+
// an invalid URI and an invalid regex so that it does not ever clash with the
27+
// other special cases.
28+
const readOnlyAction = "***readonly***"
29+
2230
// sessionRpcServer is the gRPC server for the Session RPC interface.
2331
type sessionRpcServer struct {
2432
litrpc.UnimplementedSessionsServer
@@ -126,7 +134,21 @@ func (s *sessionRpcServer) AddSession(_ context.Context,
126134
return nil, err
127135
}
128136

129-
var permissions []bakery.Op
137+
// Store the entity-action permission pairs in a map in order to
138+
// de-dup any repeat perms.
139+
permissions := make(map[string]map[string]struct{})
140+
141+
// addPerm is a closure that can be used to add entity-action pairs to
142+
// the permissions map.
143+
addPerm := func(entity, action string) {
144+
_, ok := permissions[entity]
145+
if !ok {
146+
permissions[entity] = make(map[string]struct{})
147+
}
148+
149+
permissions[entity][action] = struct{}{}
150+
}
151+
130152
switch typ {
131153
// For the default session types we use empty caveats and permissions,
132154
// the macaroons are baked correctly when creating the session.
@@ -144,10 +166,23 @@ func (s *sessionRpcServer) AddSession(_ context.Context,
144166

145167
for _, op := range req.MacaroonCustomPermissions {
146168
if op.Entity != macaroons.PermissionEntityCustomURI {
147-
permissions = append(permissions, bakery.Op{
148-
Entity: op.Entity,
149-
Action: op.Action,
150-
})
169+
addPerm(op.Entity, op.Action)
170+
171+
continue
172+
}
173+
174+
// If the action specified was equal to the
175+
// readOnlyAction keyword, then this is taken to mean
176+
// that the permissions for all read-only URIs should be
177+
// granted.
178+
if op.Action == readOnlyAction {
179+
readPerms := s.cfg.permMgr.ActivePermissions(
180+
true,
181+
)
182+
183+
for _, p := range readPerms {
184+
addPerm(p.Entity, p.Action)
185+
}
151186

152187
continue
153188
}
@@ -159,12 +194,7 @@ func (s *sessionRpcServer) AddSession(_ context.Context,
159194
// the matching URIs returned from the
160195
// permissions' manager.
161196
for _, uri := range uris {
162-
permissions = append(
163-
permissions, bakery.Op{
164-
Entity: op.Entity,
165-
Action: uri,
166-
},
167-
)
197+
addPerm(op.Entity, uri)
168198
}
169199
continue
170200
}
@@ -177,10 +207,7 @@ func (s *sessionRpcServer) AddSession(_ context.Context,
177207
"LiT", op.Action)
178208
}
179209

180-
permissions = append(permissions, bakery.Op{
181-
Entity: op.Entity,
182-
Action: op.Action,
183-
})
210+
addPerm(op.Entity, op.Action)
184211
}
185212

186213
// No other types are currently supported.
@@ -189,9 +216,20 @@ func (s *sessionRpcServer) AddSession(_ context.Context,
189216
"readonly and custom macaroon types supported in LiT")
190217
}
191218

219+
// Collect the de-duped permissions.
220+
var perms []bakery.Op
221+
for entity, actions := range permissions {
222+
for action := range actions {
223+
perms = append(perms, bakery.Op{
224+
Entity: entity,
225+
Action: action,
226+
})
227+
}
228+
}
229+
192230
sess, err := session.NewSession(
193231
req.Label, typ, expiry, req.MailboxServerAddr, req.DevServer,
194-
permissions, nil,
232+
perms, nil,
195233
)
196234
if err != nil {
197235
return nil, fmt.Errorf("error creating new session: %v", err)

0 commit comments

Comments
 (0)