Removed IncludedKeys property on user. Keys that are included in both read and write keys will be considered RW

This commit is contained in:
Kelvin Clement Mwinuka
2024-01-06 22:48:38 +03:00
parent b781a8025c
commit a3c7298b4c
4 changed files with 57 additions and 70 deletions

View File

@@ -341,48 +341,41 @@ func (acl *ACL) AuthorizeConnection(conn *net.Conn, cmd []string, command utils.
return nil return nil
} }
// 7. Check if nokeys is true if len(keys) > 0 {
if len(keys) > 0 && connection.User.NoKeys { // 7. Check if nokeys is true
return errors.New("not authorised to access any keys") if connection.User.NoKeys {
} return errors.New("not authorised to access any keys")
}
// 8. Check if keys are in IncludedKeys // 8. If @read is in the list of categories, check if keys are in IncludedReadKeys
if len(keys) > 0 && !slices.ContainsFunc(keys, func(key string) bool { if slices.Contains(categories, utils.ReadCategory) {
return slices.ContainsFunc(connection.User.IncludedKeys, func(includedKeyGlob string) bool { if !slices.ContainsFunc(keys, func(key string) bool {
if acl.GlobPatterns[includedKeyGlob].Match(key) { return slices.ContainsFunc(connection.User.IncludedReadKeys, func(readKeyGlob string) bool {
return true if acl.GlobPatterns[readKeyGlob].Match(key) {
return true
}
notAllowed = append(notAllowed, fmt.Sprintf("%s~%s", "%R", key))
return false
})
}) {
return fmt.Errorf("not authorised to access the following keys %+v", notAllowed)
} }
notAllowed = append(notAllowed, fmt.Sprintf("%s~%s", "%RW", key)) }
return false
})
}) {
return fmt.Errorf("not authorised to access the following keys %+v", notAllowed)
}
// 9. If @read is in the list of categories, check if keys are in IncludedReadKeys // 9. If @write is in the list of categories, check if keys are in IncludedWriteKeys
if len(keys) > 0 && slices.Contains(categories, utils.ReadCategory) && !slices.ContainsFunc(keys, func(key string) bool { if slices.Contains(categories, utils.WriteCategory) {
return slices.ContainsFunc(connection.User.IncludedReadKeys, func(readKeyGlob string) bool { if !slices.ContainsFunc(keys, func(key string) bool {
if acl.GlobPatterns[readKeyGlob].Match(key) { return slices.ContainsFunc(connection.User.IncludedWriteKeys, func(writeKeyGlob string) bool {
return true if acl.GlobPatterns[writeKeyGlob].Match(key) {
return true
}
notAllowed = append(notAllowed, fmt.Sprintf("%s~%s", "%W", key))
return false
})
}) {
return fmt.Errorf("not authorised to access the following keys %+v", notAllowed)
} }
notAllowed = append(notAllowed, fmt.Sprintf("%s~%s", "%R", key)) }
return false
})
}) {
return fmt.Errorf("not authorised to access the following keys %+v", notAllowed)
}
// 10. If @write is in the list of categories, check if keys are in IncludedWriteKeys
if len(keys) > 0 && slices.Contains(categories, utils.WriteCategory) && !slices.ContainsFunc(keys, func(key string) bool {
return slices.ContainsFunc(connection.User.IncludedWriteKeys, func(writeKeyGlob string) bool {
if acl.GlobPatterns[writeKeyGlob].Match(key) {
return true
}
notAllowed = append(notAllowed, fmt.Sprintf("%s~%s", "%W", key))
return false
})
}) {
return fmt.Errorf("not authorised to access the following keys %+v", notAllowed)
} }
return nil return nil
@@ -395,7 +388,6 @@ func (acl *ACL) CompileGlobs() {
for _, user := range acl.Users { for _, user := range acl.Users {
userGlobs = append(userGlobs, user.IncludedPubSubChannels...) userGlobs = append(userGlobs, user.IncludedPubSubChannels...)
userGlobs = append(userGlobs, user.ExcludedPubSubChannels...) userGlobs = append(userGlobs, user.ExcludedPubSubChannels...)
userGlobs = append(userGlobs, user.IncludedKeys...)
userGlobs = append(userGlobs, user.IncludedReadKeys...) userGlobs = append(userGlobs, user.IncludedReadKeys...)
userGlobs = append(userGlobs, user.IncludedWriteKeys...) userGlobs = append(userGlobs, user.IncludedWriteKeys...)
for _, g := range userGlobs { for _, g := range userGlobs {

View File

@@ -10,6 +10,7 @@ import (
"net" "net"
"os" "os"
"path" "path"
"slices"
"strings" "strings"
) )
@@ -127,16 +128,24 @@ func handleGetUser(ctx context.Context, cmd []string, server utils.Server, conn
} }
// keys // keys
res = res + fmt.Sprintf("\r\n+keys\r\n*%d", allKeys := user.IncludedReadKeys
len(user.IncludedKeys)+len(user.IncludedReadKeys)+len(user.IncludedWriteKeys)) for _, key := range user.IncludedWriteKeys {
for _, key := range user.IncludedKeys { if !slices.Contains(allKeys, key) {
res = res + fmt.Sprintf("\r\n+%s~%s", "%RW", key) allKeys = append(allKeys, key)
}
} }
res = res + fmt.Sprintf("\r\n+keys\r\n*%d", len(allKeys))
for _, key := range user.IncludedReadKeys { for _, key := range user.IncludedReadKeys {
if slices.Contains(user.IncludedWriteKeys, key) {
res = res + fmt.Sprintf("\r\n+%s~%s", "%RW", key)
continue
}
res = res + fmt.Sprintf("\r\n+%s~%s", "%R", key) res = res + fmt.Sprintf("\r\n+%s~%s", "%R", key)
} }
for _, key := range user.IncludedWriteKeys { for _, key := range user.IncludedWriteKeys {
res = res + fmt.Sprintf("\r\n+%s~%s", "%W", key) if !slices.Contains(user.IncludedReadKeys, key) {
res = res + fmt.Sprintf("\r\n+%s~%s", "%W", key)
}
} }
// channels // channels
@@ -149,9 +158,6 @@ func handleGetUser(ctx context.Context, cmd []string, server utils.Server, conn
res = res + fmt.Sprintf("\r\n+-&%s", channel) res = res + fmt.Sprintf("\r\n+-&%s", channel)
} }
// Test arrays to remove later
res = res + fmt.Sprintf("\r\n")
res += "\r\n\r\n" res += "\r\n\r\n"
return []byte(res), nil return []byte(res), nil
@@ -331,17 +337,19 @@ func handleList(ctx context.Context, cmd []string, server utils.Server, conn *ne
} }
s += fmt.Sprintf(" -%s", command) s += fmt.Sprintf(" -%s", command)
} }
// Included keys
for _, key := range user.IncludedKeys {
s += fmt.Sprintf(" %s~%s", "%RW", key)
}
// Included read keys // Included read keys
for _, key := range user.IncludedReadKeys { for _, key := range user.IncludedReadKeys {
if slices.Contains(user.IncludedWriteKeys, key) {
s += fmt.Sprintf(" %s~%s", "%RW", key)
continue
}
s += fmt.Sprintf(" %s~%s", "%R", key) s += fmt.Sprintf(" %s~%s", "%R", key)
} }
// Included write keys // Included write keys
for _, key := range user.IncludedReadKeys { for _, key := range user.IncludedReadKeys {
s += fmt.Sprintf(" %s~%s", "%W", key) if !slices.Contains(user.IncludedReadKeys, key) {
s += fmt.Sprintf(" %s~%s", "%W", key)
}
} }
// Included Pub/Sub channels // Included Pub/Sub channels
for _, channel := range user.IncludedPubSubChannels { for _, channel := range user.IncludedPubSubChannels {

View File

@@ -25,7 +25,6 @@ type User struct {
IncludedCommands []string `json:"IncludedCommands" yaml:"IncludedCommands"` IncludedCommands []string `json:"IncludedCommands" yaml:"IncludedCommands"`
ExcludedCommands []string `json:"ExcludedCommands" yaml:"ExcludedCommands"` ExcludedCommands []string `json:"ExcludedCommands" yaml:"ExcludedCommands"`
IncludedKeys []string `json:"IncludedKeys" yaml:"IncludedKeys"`
IncludedReadKeys []string `json:"IncludedReadKeys" yaml:"IncludedReadKeys"` IncludedReadKeys []string `json:"IncludedReadKeys" yaml:"IncludedReadKeys"`
IncludedWriteKeys []string `json:"IncludedWriteKeys" yaml:"IncludedWriteKeys"` IncludedWriteKeys []string `json:"IncludedWriteKeys" yaml:"IncludedWriteKeys"`
@@ -49,10 +48,6 @@ func (user *User) Normalise() {
user.IncludedCommands = []string{} user.IncludedCommands = []string{}
} }
user.IncludedKeys = RemoveDuplicateEntries(user.IncludedKeys, "allKeys")
if len(user.IncludedKeys) == 0 && !user.NoKeys {
user.IncludedKeys = []string{"*"}
}
user.IncludedReadKeys = RemoveDuplicateEntries(user.IncludedReadKeys, "allKeys") user.IncludedReadKeys = RemoveDuplicateEntries(user.IncludedReadKeys, "allKeys")
if len(user.IncludedReadKeys) == 0 && !user.NoKeys { if len(user.IncludedReadKeys) == 0 && !user.NoKeys {
user.IncludedReadKeys = []string{"*"} user.IncludedReadKeys = []string{"*"}
@@ -149,19 +144,15 @@ func (user *User) UpdateUser(cmd []string) error {
} }
// Parse keys // Parse keys
if strings.EqualFold(str, "allKeys") { if strings.EqualFold(str, "allKeys") {
user.IncludedKeys = []string{"*"}
user.IncludedReadKeys = []string{"*"} user.IncludedReadKeys = []string{"*"}
user.IncludedWriteKeys = []string{"*"} user.IncludedWriteKeys = []string{"*"}
user.NoKeys = false user.NoKeys = false
continue continue
} }
if len(str) > 1 && str[0] == '~' { if (len(str) > 1 && str[0] == '~') || len(str) > 4 && strings.EqualFold(str[0:4], "%RW~") {
user.IncludedKeys = append(user.IncludedKeys, str[1:]) startIndex := strings.Index(str, "~") + 1
user.NoKeys = false user.IncludedReadKeys = append(user.IncludedReadKeys, str[startIndex:])
continue user.IncludedWriteKeys = append(user.IncludedWriteKeys, str[startIndex:])
}
if len(str) > 4 && strings.EqualFold(str[0:4], "%RW~") {
user.IncludedKeys = append(user.IncludedKeys, str[4:])
user.NoKeys = false user.NoKeys = false
continue continue
} }
@@ -226,7 +217,6 @@ func (user *User) UpdateUser(cmd []string) error {
} }
// If resetkeys is provided, reset all keys that the user can access // If resetkeys is provided, reset all keys that the user can access
if strings.EqualFold(str, "resetkeys") { if strings.EqualFold(str, "resetkeys") {
user.IncludedKeys = []string{}
user.IncludedReadKeys = []string{} user.IncludedReadKeys = []string{}
user.IncludedWriteKeys = []string{} user.IncludedWriteKeys = []string{}
user.NoKeys = true user.NoKeys = true
@@ -248,7 +238,6 @@ func (user *User) Merge(new *User) {
user.ExcludedCategories = append(user.ExcludedCategories, new.ExcludedCategories...) user.ExcludedCategories = append(user.ExcludedCategories, new.ExcludedCategories...)
user.IncludedCommands = append(user.IncludedCommands, new.IncludedCommands...) user.IncludedCommands = append(user.IncludedCommands, new.IncludedCommands...)
user.ExcludedCommands = append(user.ExcludedCommands, new.ExcludedCommands...) user.ExcludedCommands = append(user.ExcludedCommands, new.ExcludedCommands...)
user.IncludedKeys = append(user.IncludedKeys, new.IncludedKeys...)
user.IncludedReadKeys = append(user.IncludedReadKeys, new.IncludedReadKeys...) user.IncludedReadKeys = append(user.IncludedReadKeys, new.IncludedReadKeys...)
user.IncludedWriteKeys = append(user.IncludedWriteKeys, new.IncludedWriteKeys...) user.IncludedWriteKeys = append(user.IncludedWriteKeys, new.IncludedWriteKeys...)
user.IncludedPubSubChannels = append(user.IncludedPubSubChannels, new.IncludedPubSubChannels...) user.IncludedPubSubChannels = append(user.IncludedPubSubChannels, new.IncludedPubSubChannels...)
@@ -265,7 +254,6 @@ func (user *User) Replace(new *User) {
user.ExcludedCategories = new.ExcludedCategories user.ExcludedCategories = new.ExcludedCategories
user.IncludedCommands = new.IncludedCommands user.IncludedCommands = new.IncludedCommands
user.ExcludedCommands = new.ExcludedCommands user.ExcludedCommands = new.ExcludedCommands
user.IncludedKeys = new.IncludedKeys
user.IncludedReadKeys = new.IncludedReadKeys user.IncludedReadKeys = new.IncludedReadKeys
user.IncludedWriteKeys = new.IncludedWriteKeys user.IncludedWriteKeys = new.IncludedWriteKeys
user.IncludedPubSubChannels = new.IncludedPubSubChannels user.IncludedPubSubChannels = new.IncludedPubSubChannels
@@ -282,7 +270,6 @@ func CreateUser(username string) *User {
ExcludedCategories: []string{}, ExcludedCategories: []string{},
IncludedCommands: []string{}, IncludedCommands: []string{},
ExcludedCommands: []string{}, ExcludedCommands: []string{},
IncludedKeys: []string{},
IncludedReadKeys: []string{}, IncludedReadKeys: []string{},
IncludedWriteKeys: []string{}, IncludedWriteKeys: []string{},
IncludedPubSubChannels: []string{}, IncludedPubSubChannels: []string{},

View File

@@ -25,6 +25,6 @@ const (
) )
const ( const (
OK_RESPONSE = "+OK\r\n\n" OK_RESPONSE = "+OK\r\n\r\n"
WRONG_ARGS_RESPONSE = "wrong number of arguments" WRONG_ARGS_RESPONSE = "wrong number of arguments"
) )