Add ListResolvableAliases to the user service (#4609)
* Add ListResolvableAliases to the user service There are a few non common ways this method uses our ACL and grant system. A user is able to list resolvable aliases for another user if they are granted permission to do so. That means we had to load the grants for the user being listed for and not the requester when determining if an alias is able to resolve to a destination for which the requested user has permission. Similarly, the grant hash used for the list pagination is required to be that of the user being listed and not the requester.
This commit is contained in:
26 files changed
+3090
-444
No files matched your search
@@ -5,13 +5,9 @@ package auth
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/binary"
|
||||
stderrors "errors"
|
||||
"fmt"
|
||||
"hash"
|
||||
"hash/fnv"
|
||||
"net/http"
|
||||
"slices"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -102,7 +98,7 @@ type VerifyResults struct {
|
||||
v *verifier
|
||||
|
||||
// Used to generate a hash of all grants
|
||||
grants []perms.GrantTuple
|
||||
grants perms.GrantTuples
|
||||
}
|
||||
|
||||
type verifier struct {
|
||||
@@ -947,49 +943,5 @@ func (r *VerifyResults) ScopesAuthorizedForList(ctx context.Context, rootScopeId
|
||||
|
||||
// GrantsHash returns a stable hash of all the grants in the verify results.
|
||||
func (r *VerifyResults) GrantsHash(ctx context.Context) ([]byte, error) {
|
||||
const op = "auth.GrantsHash"
|
||||
var values []string
|
||||
for _, grant := range r.grants {
|
||||
values = append(values, grant.Grant, grant.RoleId, grant.ScopeId)
|
||||
}
|
||||
// Sort for deterministic output
|
||||
slices.Sort(values)
|
||||
hashVal, err := hashStrings(values...)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op)
|
||||
}
|
||||
return binary.LittleEndian.AppendUint64(make([]byte, 0, 4), hashVal), nil
|
||||
}
|
||||
|
||||
func hashStrings(s ...string) (uint64, error) {
|
||||
hasher := fnv.New64()
|
||||
var h uint64
|
||||
var err error
|
||||
for _, current := range s {
|
||||
hasher.Reset()
|
||||
if _, err = hasher.Write([]byte(current)); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if h, err = hashUpdateOrdered(hasher, h, hasher.Sum64()); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
return h, nil
|
||||
}
|
||||
|
||||
// hashUpdateOrdered is taken directly from
|
||||
// https://github.com/mitchellh/hashstructure
|
||||
func hashUpdateOrdered(h hash.Hash64, a, b uint64) (uint64, error) {
|
||||
// For ordered updates, use a real hash function
|
||||
h.Reset()
|
||||
|
||||
e1 := binary.Write(h, binary.LittleEndian, a)
|
||||
e2 := binary.Write(h, binary.LittleEndian, b)
|
||||
if e1 != nil {
|
||||
return 0, e1
|
||||
}
|
||||
if e2 != nil {
|
||||
return 0, e2
|
||||
}
|
||||
return h.Sum64(), nil
|
||||
return r.grants.GrantHash(ctx)
|
||||
}
|
||||
Reference in new issue
Block a user