@@ -45,6 +45,19 @@ public class StoreAclHandlerTest {
45
45
private boolean [] isSystemStore = { false };
46
46
private boolean [] isFailOpen = { false };
47
47
private boolean [] isMetadata = { false };
48
+ private boolean [] isHealthCheck = { false };
49
+ private boolean [] isBadUri = { false };
50
+
51
+ private void resetAllConditions () {
52
+ hasAccess [0 ] = false ;
53
+ hasAcl [0 ] = false ;
54
+ hasStore [0 ] = false ;
55
+ isSystemStore [0 ] = false ;
56
+ isFailOpen [0 ] = false ;
57
+ isMetadata [0 ] = false ;
58
+ isHealthCheck [0 ] = false ;
59
+ isBadUri [0 ] = false ;
60
+ }
48
61
49
62
@ BeforeMethod
50
63
public void setUp () throws Exception {
@@ -79,28 +92,28 @@ public void setUp() throws Exception {
79
92
@ Test
80
93
public void accessGranted () throws Exception {
81
94
hasAccess [0 ] = true ;
82
- enumerate (hasAcl , hasStore , isSystemStore , isFailOpen , isMetadata );
95
+ enumerate (hasAcl , hasStore , isSystemStore , isFailOpen , isMetadata , isHealthCheck );
83
96
84
97
verify (ctx , never ()).writeAndFlush (argThat (new ContextMatcher (HttpResponseStatus .FORBIDDEN )));
85
98
verify (ctx , never ()).writeAndFlush (argThat (new ContextMatcher (HttpResponseStatus .UNAUTHORIZED )));
86
99
87
100
// Store doesn't exist 8 times
88
101
verify (ctx , times (8 )).writeAndFlush (argThat (new ContextMatcher (HttpResponseStatus .BAD_REQUEST )));
89
102
90
- // No access control 20 times + access control 4 times
91
- verify (ctx , times (24 )).fireChannelRead (req );
103
+ // No access control (METADATA/HEALTH/ADMIN or system store) => 52 times, access control => 4 times
104
+ verify (ctx , times (56 )).fireChannelRead (req );
92
105
}
93
106
94
107
@ Test
95
108
public void accessDenied () throws Exception {
96
109
hasAccess [0 ] = false ;
97
- enumerate (hasAcl , hasStore , isSystemStore , isFailOpen , isMetadata );
110
+ enumerate (hasAcl , hasStore , isSystemStore , isFailOpen , isMetadata , isHealthCheck );
98
111
99
112
// Store doesn't exist 8 times
100
113
verify (ctx , times (8 )).writeAndFlush (argThat (new ContextMatcher (HttpResponseStatus .BAD_REQUEST )));
101
114
102
- // No access control 20 times
103
- verify (ctx , times (20 )).fireChannelRead (req );
115
+ // No access control ((METADATA/HEALTH/ADMIN or system store) => 52 times
116
+ verify (ctx , times (52 )).fireChannelRead (req );
104
117
105
118
// 1 of the 4 rejects is due to internal error
106
119
verify (ctx , times (1 )).writeAndFlush (argThat (new ContextMatcher (HttpResponseStatus .UNAUTHORIZED )));
@@ -112,12 +125,12 @@ public void accessDenied() throws Exception {
112
125
@ Test
113
126
public void storeExists () throws Exception {
114
127
hasStore [0 ] = true ;
115
- enumerate (hasAccess , hasAcl , isFailOpen , isSystemStore , isMetadata );
128
+ enumerate (hasAccess , hasAcl , isFailOpen , isSystemStore , isMetadata , isHealthCheck );
116
129
117
130
verify (ctx , never ()).writeAndFlush (argThat (new ContextMatcher (HttpResponseStatus .BAD_REQUEST )));
118
131
119
- // No access control 24 times, access control 4 times granted
120
- verify (ctx , times (28 )).fireChannelRead (req );
132
+ // No access control (METADATA/HEALTH/ADMIN or system store) => 56 times, access control => 4 times granted
133
+ verify (ctx , times (60 )).fireChannelRead (req );
121
134
122
135
// 1 of the 4 rejects is due to internal error
123
136
verify (ctx , times (1 )).writeAndFlush (argThat (new ContextMatcher (HttpResponseStatus .UNAUTHORIZED )));
@@ -129,9 +142,10 @@ public void storeExists() throws Exception {
129
142
@ Test
130
143
public void storeMissing () throws Exception {
131
144
hasStore [0 ] = false ;
132
- enumerate (hasAccess , hasAcl , isFailOpen , isSystemStore , isMetadata );
145
+ enumerate (hasAccess , hasAcl , isFailOpen , isSystemStore , isMetadata , isHealthCheck );
133
146
134
- verify (ctx , times (16 )).fireChannelRead (req );
147
+ // No access control (METADATA/HEALTH/ADMIN) => 48 times
148
+ verify (ctx , times (48 )).fireChannelRead (req );
135
149
verify (ctx , never ()).writeAndFlush (argThat (new ContextMatcher (HttpResponseStatus .FORBIDDEN )));
136
150
verify (ctx , never ()).writeAndFlush (argThat (new ContextMatcher (HttpResponseStatus .UNAUTHORIZED )));
137
151
verify (ctx , times (16 )).writeAndFlush (argThat (new ContextMatcher (HttpResponseStatus .BAD_REQUEST )));
@@ -141,27 +155,73 @@ public void storeMissing() throws Exception {
141
155
public void aclDisabledForSystemStore () throws Exception {
142
156
isSystemStore [0 ] = true ;
143
157
hasStore [0 ] = true ;
144
- enumerate (hasAccess , hasAcl , isFailOpen , isMetadata );
158
+ enumerate (hasAccess , hasAcl , isFailOpen , isMetadata , isHealthCheck );
145
159
146
160
verify (ctx , never ()).writeAndFlush (any ());
147
- verify (ctx , times (16 )).fireChannelRead (req );
161
+ // No access control (METADATA/HEALTH/ADMIN or system store) => 32 times
162
+ verify (ctx , times (32 )).fireChannelRead (req );
148
163
}
149
164
150
165
@ Test
151
166
public void aclDisabledForMetadataEndpoint () throws Exception {
152
167
isMetadata [0 ] = true ;
153
- enumerate (hasAccess , hasAcl , isSystemStore , isFailOpen );
168
+ enumerate (hasAccess , hasAcl , isSystemStore , isFailOpen , isHealthCheck );
154
169
155
170
verify (ctx , never ()).writeAndFlush (any ());
156
- verify (ctx , times (16 )).fireChannelRead (req );
171
+ // No access control (METADATA) => 32 times
172
+ verify (ctx , times (32 )).fireChannelRead (req );
173
+ }
174
+
175
+ @ Test
176
+ public void aclDisabledForHealthCheckEndpoint () throws Exception {
177
+ isHealthCheck [0 ] = true ;
178
+ enumerate (hasAccess , hasAcl , isSystemStore , isFailOpen , isMetadata );
179
+
180
+ verify (ctx , never ()).writeAndFlush (any ());
181
+ // No access control (HEALTH) => 32 times
182
+ verify (ctx , times (32 )).fireChannelRead (req );
183
+ }
184
+
185
+ @ Test
186
+ public void isBadUri () throws Exception {
187
+ isBadUri [0 ] = true ;
188
+ enumerate (hasAcl , hasStore , hasAccess , isSystemStore , isFailOpen , isMetadata , isHealthCheck );
189
+
190
+ // all 128 times should fail for BAD_REQUEST
191
+ verify (ctx , times (128 )).writeAndFlush (argThat (new ContextMatcher (HttpResponseStatus .BAD_REQUEST )));
157
192
}
158
193
159
194
@ Test
160
195
public void aclMissing () throws Exception {
161
- enumerate (hasStore , hasAcl , hasAccess , isSystemStore , isFailOpen , isMetadata );
196
+ hasAcl [0 ] = false ;
197
+ enumerate (hasStore , hasAccess , isSystemStore , isFailOpen , isMetadata , isHealthCheck );
162
198
199
+ // No access control (METADATA/HEALTH/ADMIN or system store) => 52 times, access control => 2 times granted
200
+ verify (ctx , times (54 )).fireChannelRead (req );
201
+ verify (ctx , times (8 )).writeAndFlush (argThat (new ContextMatcher (HttpResponseStatus .BAD_REQUEST )));
163
202
verify (ctx , times (1 )).writeAndFlush (argThat (new ContextMatcher (HttpResponseStatus .UNAUTHORIZED )));
203
+ verify (ctx , times (1 )).writeAndFlush (argThat (new ContextMatcher (HttpResponseStatus .FORBIDDEN )));
204
+ }
205
+
206
+ @ Test
207
+ public void aclPresent () throws Exception {
208
+ hasAcl [0 ] = true ;
209
+ enumerate (hasStore , hasAccess , isSystemStore , isFailOpen , isMetadata , isHealthCheck );
210
+
211
+ // No access control (METADATA/HEALTH/ADMIN or system store) => 52 times, access control => 2 times granted
212
+ verify (ctx , times (54 )).fireChannelRead (req );
213
+ verify (ctx , times (8 )).writeAndFlush (argThat (new ContextMatcher (HttpResponseStatus .BAD_REQUEST )));
214
+ verify (ctx , never ()).writeAndFlush (argThat (new ContextMatcher (HttpResponseStatus .UNAUTHORIZED )));
215
+ verify (ctx , times (2 )).writeAndFlush (argThat (new ContextMatcher (HttpResponseStatus .FORBIDDEN )));
216
+ }
217
+
218
+ @ Test
219
+ public void testAllCases () throws Exception {
220
+ enumerate (hasAcl , hasStore , hasAccess , isSystemStore , isFailOpen , isMetadata , isHealthCheck , isBadUri );
164
221
222
+ verify (ctx , times (108 )).fireChannelRead (req );
223
+ verify (ctx , times (144 )).writeAndFlush (argThat (new ContextMatcher (HttpResponseStatus .BAD_REQUEST )));
224
+ verify (ctx , times (1 )).writeAndFlush (argThat (new ContextMatcher (HttpResponseStatus .UNAUTHORIZED )));
165
225
// One of the cases is impossible in reality. See StoreAclHandler.java comments
166
226
verify (ctx , times (3 )).writeAndFlush (argThat (new ContextMatcher (HttpResponseStatus .FORBIDDEN )));
167
227
}
@@ -177,26 +237,35 @@ private void update() throws Exception {
177
237
when (metadataRepo .getStoreOrThrow (any ())).thenThrow (new VeniceNoStoreException ("storename" ));
178
238
}
179
239
when (store .isSystemStore ()).thenReturn (isSystemStore [0 ]);
180
- if (isMetadata [0 ]) {
240
+ if (isBadUri [0 ]) {
241
+ when (req .uri ()).thenReturn ("/badUri" );
242
+ } else if (isMetadata [0 ]) {
181
243
when (req .uri ()).thenReturn ("/metadata/storename/random" );
244
+ } else if (isHealthCheck [0 ]) {
245
+ when (req .uri ()).thenReturn ("/health" );
182
246
} else {
183
247
when (req .uri ()).thenReturn ("/storage/storename/random" );
184
248
}
185
249
}
186
250
187
251
/**
188
- * Generate every possible combination for a given list of booleans
252
+ * Generate every possible combination for a given list of booleans based on variables passed
253
+ * to boolean[]... conditions. If all variables (8 in count) are passed, then there will be 256
254
+ * combinations:
189
255
*
190
- * for (int i = 0; i < 32 ; i++) { | i= 0 1 2 3 4 ...
256
+ * for (int i = 0; i < 256 ; i++) { | i= 0 1 2 3 4 ...
191
257
* _hasAccess= (i>>0) % 2 == 1| F T F T F ...
192
258
* _hasAcl= (i>>1) % 2 == 1| F F T T F ...
193
259
* _hasStore= (i>>2) % 2 == 1| F F F F T ...
194
260
* _isAccessControlled= (i>>3) % 2 == 1| F F F F F ...
195
261
* _isFailOpen= (i>>4) % 2 == 1| F F F F F ...
196
262
* _isMetadata= (i>>5) % 2 == 1| F F F F F ...
263
+ * _isHealthCheck= (i>>6) % 2 == 1| F F F F F ...
264
+ * _isBadUri= (i>>7) % 2 == 1| F F F F F ...
197
265
* }
198
266
*/
199
267
private void enumerate (boolean []... conditions ) throws Exception {
268
+ // enumerate for all possible combinations
200
269
int len = conditions .length ;
201
270
for (int i = 0 ; i < Math .pow (2 , len ); i ++) {
202
271
for (int j = 0 ; j < len ; j ++) {
@@ -208,6 +277,9 @@ private void enumerate(boolean[]... conditions) throws Exception {
208
277
update ();
209
278
aclHandler .channelRead0 (ctx , req );
210
279
}
280
+
281
+ // reset all supported conditions to the default to remove changes from this test
282
+ resetAllConditions ();
211
283
}
212
284
213
285
public static class ContextMatcher implements ArgumentMatcher <FullHttpResponse > {
0 commit comments