Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
ruanhaishen
redis
Commits
411bcf1a
Commit
411bcf1a
authored
Oct 26, 2020
by
Madelyn Olson
Committed by
Madelyn Olson
Oct 28, 2020
Browse files
Further improved ACL algorithm for picking categories
parent
efd17316
Changes
2
Hide whitespace changes
Inline
Side-by-side
src/acl.c
View file @
411bcf1a
...
@@ -479,36 +479,61 @@ sds ACLDescribeUserCommandRules(user *u) {
...
@@ -479,36 +479,61 @@ sds ACLDescribeUserCommandRules(user *u) {
ACLSetUser
(
fakeuser
,
"-@all"
,
-
1
);
ACLSetUser
(
fakeuser
,
"-@all"
,
-
1
);
}
}
/* Try to add or subtract each category one after the other. Often a
/* Attempt to find a good approximation for categories and commands
* single category will not perfectly match the set of commands into
* based on the current bits used, by looping over the category list
* it, so at the end we do a final pass adding/removing the single commands
* and applying the best fit each time. Often a set of categories will not
* needed to make the bitmap exactly match. A temp user is maintained to
* perfectly match the set of commands into it, so at the end we do a
* keep track of categories already applied. */
* final pass adding/removing the single commands needed to make the bitmap
* exactly match. A temp user is maintained to keep track of categories
* already applied. */
user
tu
=
{
0
};
user
tu
=
{
0
};
user
*
tempuser
=
&
tu
;
user
*
tempuser
=
&
tu
;
memcpy
(
tempuser
->
allowed_commands
,
memcpy
(
tempuser
->
allowed_commands
,
u
->
allowed_commands
,
u
->
allowed_commands
,
sizeof
(
u
->
allowed_commands
));
sizeof
(
u
->
allowed_commands
));
while
(
1
)
{
for
(
int
j
=
0
;
ACLCommandCategories
[
j
].
flag
!=
0
;
j
++
)
{
int
best
=
-
1
;
unsigned
long
on
,
off
;
unsigned
long
mindiff
=
INT_MAX
,
maxsame
=
0
;
ACLCountCategoryBitsForUser
(
tempuser
,
&
on
,
&
off
,
ACLCommandCategories
[
j
].
name
);
for
(
int
j
=
0
;
ACLCommandCategories
[
j
].
flag
!=
0
;
j
++
)
{
if
((
additive
&&
on
>
off
)
||
(
!
additive
&&
off
>
on
))
{
unsigned
long
on
,
off
,
diff
,
same
;
sds
op
=
sdsnewlen
(
additive
?
"+@"
:
"-@"
,
2
);
ACLCountCategoryBitsForUser
(
tempuser
,
&
on
,
&
off
,
ACLCommandCategories
[
j
].
name
);
op
=
sdscat
(
op
,
ACLCommandCategories
[
j
].
name
);
ACLSetUser
(
fakeuser
,
op
,
-
1
);
/* Check if the current category is the best this loop:
* * It has more commands in common with the user than commands
sds
invop
=
sdsnewlen
(
additive
?
"-@"
:
"+@"
,
2
);
* that are different.
invop
=
sdscat
(
invop
,
ACLCommandCategories
[
j
].
name
);
* AND EITHER
ACLSetUser
(
tempuser
,
invop
,
-
1
);
* * It has the fewest number of differences
* than the best match we have found so far.
rules
=
sdscatsds
(
rules
,
op
);
* * OR it matches the fewest number of differences
rules
=
sdscatlen
(
rules
,
" "
,
1
);
* that we've seen but it has more in common. */
sdsfree
(
op
);
diff
=
additive
?
off
:
on
;
sdsfree
(
invop
);
same
=
additive
?
on
:
off
;
if
(
same
>
diff
&&
((
diff
<
mindiff
)
||
(
diff
==
mindiff
&&
same
>
maxsame
)))
{
best
=
j
;
mindiff
=
diff
;
maxsame
=
same
;
}
}
}
/* We didn't find a match */
if
(
best
==
-
1
)
break
;
sds
op
=
sdsnewlen
(
additive
?
"+@"
:
"-@"
,
2
);
op
=
sdscat
(
op
,
ACLCommandCategories
[
best
].
name
);
ACLSetUser
(
fakeuser
,
op
,
-
1
);
sds
invop
=
sdsnewlen
(
additive
?
"-@"
:
"+@"
,
2
);
invop
=
sdscat
(
invop
,
ACLCommandCategories
[
best
].
name
);
ACLSetUser
(
tempuser
,
invop
,
-
1
);
rules
=
sdscatsds
(
rules
,
op
);
rules
=
sdscatlen
(
rules
,
" "
,
1
);
sdsfree
(
op
);
sdsfree
(
invop
);
}
}
/* Fix the final ACLs with single commands differences. */
/* Fix the final ACLs with single commands differences. */
dictIterator
*
di
=
dictGetIterator
(
server
.
orig_commands
);
dictIterator
*
di
=
dictGetIterator
(
server
.
orig_commands
);
dictEntry
*
de
;
dictEntry
*
de
;
...
...
tests/unit/acl.tcl
View file @
411bcf1a
...
@@ -138,15 +138,21 @@ start_server {tags {"acl"}} {
...
@@ -138,15 +138,21 @@ start_server {tags {"acl"}} {
# A regression test make sure that as long as there is a simple
# A regression test make sure that as long as there is a simple
# category defining the commands, that it will be used as is.
# category defining the commands, that it will be used as is.
test
{
ACL GETUSER provides reasonable results
}
{
test
{
ACL GETUSER provides reasonable results
}
{
# Test for future commands where allowed
set categories
[
r ACL CAT
]
r ACL setuser additive reset +@all -@write
set cmdstr
[
dict get
[
r ACL getuser additive
]
commands
]
# Test that adding each single category will
assert_match
{
+@all -@write
}
$cmdstr
# result in just that category with both +@all and -@all
foreach category $categories
{
# Test for future commands are disallowed
# Test for future commands where allowed
r ACL setuser subtractive reset -@all +@read
r ACL setuser additive reset +@all
"-@
$category
"
set cmdstr
[
dict get
[
r ACL getuser subtractive
]
commands
]
set cmdstr
[
dict get
[
r ACL getuser additive
]
commands
]
assert_match
{
-@all +@read
}
$cmdstr
assert_equal
"+@all -@
$category
"
$cmdstr
# Test for future commands where disallowed
r ACL setuser restrictive reset -@all
"+@
$category
"
set cmdstr
[
dict get
[
r ACL getuser restrictive
]
commands
]
assert_equal
"-@all +@
$category
"
$cmdstr
}
}
}
test
{
ACL #5998 regression: memory leaks adding / removing subcommands
}
{
test
{
ACL #5998 regression: memory leaks adding / removing subcommands
}
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment