File: aclcheck.tcl

package info (click to toggle)
redis 5%3A8.0.2-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 22,304 kB
  • sloc: ansic: 216,903; tcl: 51,562; sh: 4,625; perl: 4,214; cpp: 3,568; python: 2,954; makefile: 2,055; ruby: 639; javascript: 30; csh: 7
file content (207 lines) | stat: -rw-r--r-- 10,089 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
set testmodule [file normalize tests/modules/aclcheck.so]

start_server {tags {"modules acl"}} {
    r module load $testmodule

    test {test module check acl for command perm} {
        # by default all commands allowed
        assert_equal [r aclcheck.rm_call.check.cmd set x 5] OK
        # block SET command for user
        r acl setuser default -set
        catch {r aclcheck.rm_call.check.cmd set x 5} e
        assert_match {*DENIED CMD*} $e

        # verify that new log entry added
        set entry [lindex [r ACL LOG] 0]
        assert {[dict get $entry username] eq {default}}
        assert {[dict get $entry context] eq {module}}
        assert {[dict get $entry object] eq {set}}
        assert {[dict get $entry reason] eq {command}}
    }
        
    test {test module check acl for key prefix permission} {
        r acl setuser default +set resetkeys ~CART* %W~ORDER* %R~PRODUCT* ~ESCAPED_STAR\\* ~NON_ESCAPED_STAR\\\\*
        
        # check for key permission of prefix CART* (READ+WRITE)
        catch {r aclcheck.set.check.prefixkey "~" CAR CART_CLOTHES_7 5} e
        assert_match "*DENIED KEY*" $e
        assert_equal [r aclcheck.set.check.prefixkey "~" CART CART 5] OK
        assert_equal [r aclcheck.set.check.prefixkey "W" CART_BOOKS CART_BOOKS_12 5] OK
        assert_equal [r aclcheck.set.check.prefixkey "R" CART_CLOTHES CART_CLOTHES_7 5] OK
        
        # check for key permission of prefix ORDER* (WRITE)
        catch {r aclcheck.set.check.prefixkey "~" ORDE ORDER_2024_155351 5} e
        assert_match "*DENIED KEY*" $e
        assert_equal [r aclcheck.set.check.prefixkey "~" ORDER ORDER 5] OK
        assert_equal [r aclcheck.set.check.prefixkey "W" ORDER_2024 ORDER_2024_564879 5] OK
        assert_equal [r aclcheck.set.check.prefixkey "~" ORDER_2023 ORDER_2023_564879 5] OK
        catch {r aclcheck.set.check.prefixkey "R" ORDER_2023 ORDER_2023_564879 5}
        assert_match "*DENIED KEY*" $e
        
        # check for key permission of prefix PRODUCT* (READ)
        catch {r aclcheck.set.check.prefixkey "~" PRODUC PRODUCT_CLOTHES_753376 5} e
        assert_match "*DENIED KEY*" $e
        assert_equal [r aclcheck.set.check.prefixkey "~" PRODUCT PRODUCT 5] OK
        assert_equal [r aclcheck.set.check.prefixkey "~" PRODUCT_BOOKS PRODUCT_BOOKS_753376 5] OK
        
        # pattern ends with a escaped '*' character should not be counted as a prefix
        catch {r aclcheck.set.check.prefixkey "~" ESCAPED_STAR ESCAPED_STAR_12 5} e
        assert_match "*DENIED KEY*" $e
        catch {r aclcheck.set.check.prefixkey "~" ESCAPED_STAR* ESCAPED_STAR* 5} e
        assert_match "*DENIED KEY*" $e        
        assert_equal [r aclcheck.set.check.prefixkey "~" NON_ESCAPED_STAR\\ NON_ESCAPED_STAR\\clothes 5] OK
    }
    
    test {check ACL permissions versus empty string prefix} {
        # The empty string should should match all keys permissions
        r acl setuser default +set resetkeys %R~* %W~* ~*
        assert_equal [r aclcheck.set.check.prefixkey "~" "" CART_BOOKS_12 5] OK
        assert_equal [r aclcheck.set.check.prefixkey "W" "" ORDER_2024_564879 5] OK
        assert_equal [r aclcheck.set.check.prefixkey "R" "" PRODUCT_BOOKS_753376 5] OK
        
        # The empty string prefix should not match if cannot access all keys 
        r acl setuser default +set resetkeys %R~x* %W~x* ~x*
        catch {r aclcheck.set.check.prefixkey "~" "" CART_BOOKS_12 5} e
        assert_match "*DENIED KEY*" $e
    }

    test {test module check acl for key perm} {
        # give permission for SET and block all keys but x(READ+WRITE), y(WRITE), z(READ)
        r acl setuser default +set resetkeys ~x %W~y %R~z ~ESCAPED_STAR\\*

        assert_equal [r aclcheck.set.check.key "*" x 5] OK
        catch {r aclcheck.set.check.key "*" v 5} e
        assert_match "*DENIED KEY*" $e

        assert_equal [r aclcheck.set.check.key "~" x 5] OK
        assert_equal [r aclcheck.set.check.key "~" y 5] OK
        assert_equal [r aclcheck.set.check.key "~" z 5] OK
        catch {r aclcheck.set.check.key "~" v 5} e
        assert_match "*DENIED KEY*" $e

        assert_equal [r aclcheck.set.check.key "W" y 5] OK
        catch {r aclcheck.set.check.key "W" v 5} e
        assert_match "*DENIED KEY*" $e

        assert_equal [r aclcheck.set.check.key "R" z 5] OK
        catch {r aclcheck.set.check.key "R" v 5} e
        assert_match "*DENIED KEY*" $e
        
        # check pattern ends with escaped '*' character
        assert_equal [r aclcheck.set.check.key "~" ESCAPED_STAR* 5] OK
    }

    test {test module check acl for module user} {
        # the module user has access to all keys
        assert_equal [r aclcheck.rm_call.check.cmd.module.user set y 5] OK
    }

    test {test module check acl for channel perm} {
        # block all channels but ch1
        r acl setuser default resetchannels &ch1
        assert_equal [r aclcheck.publish.check.channel ch1 msg] 0
        catch {r aclcheck.publish.check.channel ch2 msg} e
        set e
    } {*DENIED CHANNEL*}

    test {test module check acl in rm_call} {
        # rm call check for key permission (x: READ + WRITE)
        assert_equal [r aclcheck.rm_call set x 5] OK
        assert_equal [r aclcheck.rm_call set x 6 get] 5

        # rm call check for key permission (y: only WRITE)
        assert_equal [r aclcheck.rm_call set y 5] OK
        assert_error {*NOPERM*} {r aclcheck.rm_call set y 5 get}
        assert_error {*NOPERM*No permissions to access a key*} {r aclcheck.rm_call_with_errors set y 5 get}

        # rm call check for key permission (z: only READ)
        assert_error {*NOPERM*} {r aclcheck.rm_call set z 5}
        catch {r aclcheck.rm_call_with_errors set z 5} e
        assert_match {*NOPERM*No permissions to access a key*} $e
        assert_error {*NOPERM*} {r aclcheck.rm_call set z 6 get}
        assert_error {*NOPERM*No permissions to access a key*} {r aclcheck.rm_call_with_errors set z 6 get}

        # verify that new log entry added
        set entry [lindex [r ACL LOG] 0]
        assert {[dict get $entry username] eq {default}}
        assert {[dict get $entry context] eq {module}}
        assert {[dict get $entry object] eq {z}}
        assert {[dict get $entry reason] eq {key}}

        # rm call check for command permission
        r acl setuser default -set
        assert_error {*NOPERM*} {r aclcheck.rm_call set x 5}
        assert_error {*NOPERM*has no permissions to run the 'set' command*} {r aclcheck.rm_call_with_errors set x 5}

        # verify that new log entry added
        set entry [lindex [r ACL LOG] 0]
        assert {[dict get $entry username] eq {default}}
        assert {[dict get $entry context] eq {module}}
        assert {[dict get $entry object] eq {set}}
        assert {[dict get $entry reason] eq {command}}
    }

    test {test blocking of Commands outside of OnLoad} {
        assert_equal [r block.commands.outside.onload] OK
    }

    test {test users to have access to module commands having acl categories} {
        r acl SETUSER j1 on >password -@all +@WRITE
        r acl SETUSER j2 on >password -@all +@READ
        assert_equal [r acl DRYRUN j1 aclcheck.module.command.aclcategories.write] OK
        assert_equal [r acl DRYRUN j2 aclcheck.module.command.aclcategories.write.function.read.category] OK
        assert_equal [r acl DRYRUN j2 aclcheck.module.command.aclcategories.read.only.category] OK
    }

    test {Unload the module - aclcheck} {
        assert_equal {OK} [r module unload aclcheck]
    }
}

start_server {tags {"modules acl"}} {
    test {test existing users to have access to module commands loaded on runtime} {
        r acl SETUSER j3 on >password -@all +@WRITE
        assert_equal [r module load $testmodule] OK
        assert_equal [r acl DRYRUN j3 aclcheck.module.command.aclcategories.write] OK
        assert_equal {OK} [r module unload aclcheck]
    }
}

start_server {tags {"modules acl"}} {
    test {test existing users without permissions, do not have access to module commands loaded on runtime.} {
        r acl SETUSER j4 on >password -@all +@READ
        r acl SETUSER j5 on >password -@all +@WRITE
        assert_equal [r module load $testmodule] OK
        catch {r acl DRYRUN j4 aclcheck.module.command.aclcategories.write} e
        assert_equal {User j4 has no permissions to run the 'aclcheck.module.command.aclcategories.write' command} $e
        catch {r acl DRYRUN j5 aclcheck.module.command.aclcategories.write.function.read.category} e
        assert_equal {User j5 has no permissions to run the 'aclcheck.module.command.aclcategories.write.function.read.category' command} $e
    }

    test {test users without permissions, do not have access to module commands.} {
        r acl SETUSER j6 on >password -@all +@READ
        catch {r acl DRYRUN j6 aclcheck.module.command.aclcategories.write} e
        assert_equal {User j6 has no permissions to run the 'aclcheck.module.command.aclcategories.write' command} $e
        r acl SETUSER j7 on >password -@all +@WRITE
        catch {r acl DRYRUN j7 aclcheck.module.command.aclcategories.write.function.read.category} e
        assert_equal {User j7 has no permissions to run the 'aclcheck.module.command.aclcategories.write.function.read.category' command} $e
    }

    test {test if foocategory acl categories is added} {
        r acl SETUSER j8 on >password -@all +@foocategory
        assert_equal [r acl DRYRUN j8 aclcheck.module.command.test.add.new.aclcategories] OK
    }

    test {test permission compaction and simplification for categories added by a module} {
        r acl SETUSER j9 on >password -@all +@foocategory -@foocategory
        catch {r ACL GETUSER j9} res
        assert_equal {-@all -@foocategory} [lindex $res 5]
        assert_equal {OK} [r module unload aclcheck]
    }
}

start_server {tags {"modules acl"}} {
    test {test module load fails if exceeds the maximum number of adding acl categories} {
        assert_error {ERR Error loading the extension. Please check the server logs.} {r module load $testmodule 1}
    }
}