@@ -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.
2331type 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