Rust implementation of OCI Distribution Spec with granular access control
1mod common;
2
3use common::*;
4use serial_test::serial;
5
6#[test]
7#[serial]
8fn test_admin_list_users() {
9 let mut server = TestServer::new();
10 server.start();
11 let client = server.client();
12
13 let resp = client
14 .get("/admin/users")
15 .basic_auth("admin", Some("admin"))
16 .send()
17 .unwrap();
18
19 assert_eq!(resp.status(), 200);
20 let json: serde_json::Value = resp.json().unwrap();
21
22 let users = json["users"].as_array().unwrap();
23 assert!(users.len() >= 4); // admin, reader, writer, limited
24
25 // Verify admin user exists
26 let admin_user = users.iter().find(|u| u["username"] == "admin");
27 assert!(admin_user.is_some());
28}
29
30#[test]
31#[serial]
32fn test_admin_create_user() {
33 let mut server = TestServer::new();
34 server.start();
35 let client = server.client();
36
37 let new_user = serde_json::json!({
38 "username": "newuser",
39 "password": "newpass",
40 "permissions": []
41 });
42
43 let resp = client
44 .post("/admin/users")
45 .basic_auth("admin", Some("admin"))
46 .json(&new_user)
47 .send()
48 .unwrap();
49
50 assert_eq!(resp.status(), 201);
51
52 // Verify user can authenticate
53 let resp = client
54 .get("/v2/")
55 .basic_auth("newuser", Some("newpass"))
56 .send()
57 .unwrap();
58 assert_eq!(resp.status(), 200);
59}
60
61#[test]
62#[serial]
63fn test_admin_create_duplicate_user() {
64 let mut server = TestServer::new();
65 server.start();
66 let client = server.client();
67
68 let duplicate_user = serde_json::json!({
69 "username": "admin",
70 "password": "newpass",
71 "permissions": []
72 });
73
74 let resp = client
75 .post("/admin/users")
76 .basic_auth("admin", Some("admin"))
77 .json(&duplicate_user)
78 .send()
79 .unwrap();
80
81 assert_eq!(resp.status(), 409); // Conflict
82}
83
84#[test]
85#[serial]
86fn test_admin_delete_user() {
87 let mut server = TestServer::new();
88 server.start();
89 let client = server.client();
90
91 // Create user first
92 let new_user = serde_json::json!({
93 "username": "todelete",
94 "password": "pass",
95 "permissions": []
96 });
97
98 client
99 .post("/admin/users")
100 .basic_auth("admin", Some("admin"))
101 .json(&new_user)
102 .send()
103 .unwrap();
104
105 // Delete user
106 let resp = client
107 .delete("/admin/users/todelete")
108 .basic_auth("admin", Some("admin"))
109 .send()
110 .unwrap();
111
112 assert_eq!(resp.status(), 200);
113
114 // Verify user cannot authenticate
115 let resp = client
116 .get("/v2/")
117 .basic_auth("todelete", Some("pass"))
118 .send()
119 .unwrap();
120 assert_eq!(resp.status(), 401);
121}
122
123#[test]
124#[serial]
125fn test_admin_delete_nonexistent_user() {
126 let mut server = TestServer::new();
127 server.start();
128 let client = server.client();
129
130 let resp = client
131 .delete("/admin/users/nonexistent")
132 .basic_auth("admin", Some("admin"))
133 .send()
134 .unwrap();
135
136 assert_eq!(resp.status(), 404);
137}
138
139#[test]
140#[serial]
141fn test_admin_add_permission() {
142 let mut server = TestServer::new();
143 server.start();
144 let client = server.client();
145
146 // Create user with no permissions
147 let new_user = serde_json::json!({
148 "username": "testperm",
149 "password": "pass",
150 "permissions": []
151 });
152
153 client
154 .post("/admin/users")
155 .basic_auth("admin", Some("admin"))
156 .json(&new_user)
157 .send()
158 .unwrap();
159
160 // User should not be able to push
161 let blob = sample_blob();
162 let digest = sample_blob_digest();
163 let resp = client
164 .post(&format!("/v2/test/repo/blobs/uploads/?digest={}", digest))
165 .basic_auth("testperm", Some("pass"))
166 .body(blob.clone())
167 .send()
168 .unwrap();
169 assert_eq!(resp.status(), 403);
170
171 // Add permission
172 let permission = serde_json::json!({
173 "username": "testperm",
174 "repository": "test/*",
175 "tag": "*",
176 "actions": ["pull", "push"]
177 });
178
179 let resp = client
180 .post("/admin/permissions")
181 .basic_auth("admin", Some("admin"))
182 .json(&permission)
183 .send()
184 .unwrap();
185
186 assert_eq!(resp.status(), 200);
187
188 // User should now be able to push
189 let resp = client
190 .post(&format!("/v2/test/repo/blobs/uploads/?digest={}", digest))
191 .basic_auth("testperm", Some("pass"))
192 .body(blob)
193 .send()
194 .unwrap();
195 assert_eq!(resp.status(), 201);
196}
197
198#[test]
199#[serial]
200fn test_admin_requires_admin_permission() {
201 let mut server = TestServer::new();
202 server.start();
203 let client = server.client();
204
205 // Non-admin users should not access admin endpoints
206 let resp = client
207 .get("/admin/users")
208 .basic_auth("reader", Some("reader"))
209 .send()
210 .unwrap();
211 assert_eq!(resp.status(), 403);
212
213 let resp = client
214 .post("/admin/users")
215 .basic_auth("writer", Some("writer"))
216 .json(&serde_json::json!({"username": "test", "password": "test", "permissions": []}))
217 .send()
218 .unwrap();
219 assert_eq!(resp.status(), 403);
220
221 // Admin should have access
222 let resp = client
223 .get("/admin/users")
224 .basic_auth("admin", Some("admin"))
225 .send()
226 .unwrap();
227 assert_eq!(resp.status(), 200);
228}
229
230#[test]
231#[serial]
232fn test_admin_api_requires_authentication() {
233 let mut server = TestServer::new();
234 server.start();
235 let client = server.client();
236
237 // No auth should fail
238 let resp = client.get("/admin/users").send().unwrap();
239 assert_eq!(resp.status(), 401);
240
241 // Invalid credentials should fail
242 let resp = client
243 .get("/admin/users")
244 .basic_auth("invalid", Some("invalid"))
245 .send()
246 .unwrap();
247 assert_eq!(resp.status(), 401);
248}
249
250#[test]
251#[serial]
252fn test_admin_create_user_with_permissions() {
253 let mut server = TestServer::new();
254 server.start();
255 let client = server.client();
256
257 let new_user = serde_json::json!({
258 "username": "fulluser",
259 "password": "pass",
260 "permissions": [
261 {
262 "repository": "myorg/*",
263 "tag": "*",
264 "actions": ["pull", "push"]
265 }
266 ]
267 });
268
269 let resp = client
270 .post("/admin/users")
271 .basic_auth("admin", Some("admin"))
272 .json(&new_user)
273 .send()
274 .unwrap();
275
276 assert_eq!(resp.status(), 201);
277
278 // Verify permissions work
279 let blob = sample_blob();
280 let digest = sample_blob_digest();
281 let resp = client
282 .post(&format!("/v2/myorg/repo/blobs/uploads/?digest={}", digest))
283 .basic_auth("fulluser", Some("pass"))
284 .body(blob)
285 .send()
286 .unwrap();
287 assert_eq!(resp.status(), 201);
288}
289
290#[test]
291#[serial]
292fn test_admin_user_persistence() {
293 let mut server = TestServer::new();
294 server.start();
295 let client = server.client();
296
297 // Create user
298 let new_user = serde_json::json!({
299 "username": "persistent",
300 "password": "pass",
301 "permissions": []
302 });
303
304 client
305 .post("/admin/users")
306 .basic_auth("admin", Some("admin"))
307 .json(&new_user)
308 .send()
309 .unwrap();
310
311 // Verify user exists in list
312 let resp = client
313 .get("/admin/users")
314 .basic_auth("admin", Some("admin"))
315 .send()
316 .unwrap();
317
318 let json: serde_json::Value = resp.json().unwrap();
319 let users = json["users"].as_array().unwrap();
320 let persistent_user = users.iter().find(|u| u["username"] == "persistent");
321 assert!(persistent_user.is_some());
322}