summaryrefslogtreecommitdiff
path: root/git.liw.fi.yarn
blob: cfa1c747bba374e65d142d3c4959d267b38dcf8d (plain)
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
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
% Test suite for ACL on git.liw.fi

Introduction
============

This is a test suite for my Gitano ACL setup on git.liw.fi. It is run
against either the real or a test instance of the setup. It requires
the person running it to have admin access on the Gitano instance,
so the tests can create and remove users and repositories.

Pre-requisites
==============

Yarn must be run with `--env` used to set the environment variables
`GITANO` and `GITHOST`. `GITANO` must be the Unix user for the
Gitano instance (typically `git`), and `GITHOST` must be the address
of the host (IP address or domain name).

The person running this test suite must be able to log in to the
Gitano instance using their normal ssh key. In other words,
`ssh "$GITANO@$GITHOST" whoami` must work.

See the `check` script for details on how to invoke yarn for this test
suite.

The test suite will create a user called `tstusr` and `tstusr2`, and
remove them after the test suite. The users may get created and
removed multiple times.

Scenarios
=========

User creation
-------------

The admin must be able to create and remove a user.

	SCENARIO admin can create and remove a user
	ASSUMING no tstusr user exists on server
	GIVEN an ssh key for tstusr
	WHEN admin creates user tstusr
	THEN user tstusr exists
	AND user tstusr can access gitano
	WHEN admin removes user tstusr
	THEN user tstusr doesn't exist
	FINALLY remove user tstusr on server

A non-admin mustn't be able to create or remove users.

	SCENARIO non-admin attempts to create or remove users
	ASSUMING no tstusr user exists on server
	AND no tstusr2 user exists on server

	GIVEN an ssh key for tstusr
	AND an ssh key for tstusr2
	WHEN admin creates user tstusr
	AND tstusr attempts to create user tstusr2
	THEN attempt failed with error matching "You may not perform site administration"

	WHEN admin creates user tstusr2
	AND tstusr attempts to remove user tstusr2
	THEN attempt failed with error matching "You may not perform site administration"

	FINALLY remove user tstusr on server
	AND remove user tstusr2 on server

Public repository creation, access, and removal
-----------------------------------------------

The ruleset is meant to make all repositories public.

Admin should be able to create a public repository. That repository
should then be accessible to both the admin and a non-admin via both
git and ssh protocols. Finally, the admin, but not a non-admin, should
be able to remove the repository.

	SCENARIO public repositories
	ASSUMING no tstusr user exists on server
	GIVEN an ssh key for tstusr

	WHEN admin creates user tstusr
	AND admin creates repository tstrepo
	THEN admin can see repository tstrepo
	AND admin can clone tstrepo using git
	AND admin can clone tstrepo using ssh
	AND tstusr can see repository tstrepo
	AND tstusr can clone tstrepo using ssh
	AND cgit shows repository tstrepo

	WHEN tstusr attempts to remove repository tstrepo
	THEN attempt failed with error matching "You may not destroy repositories you do not own"
	
	WHEN admin removes repository tstrepo
	THEN admin can't see repository tstrepo
	AND admin can't clone tstrepo using git
	AND admin can't clone tstrepo using ssh
	AND tstusr can't see repository tstrepo
	AND tstusr can't clone tstrepo using ssh
	AND cgit doesn't show repository tstrepo

	FINALLY remove repository tstrepo on server
	AND remove user tstusr on server

The admin should should be able to push to any branch in a public
repo.

	SCENARIO admin can push to public repository
	
	WHEN admin creates repository tstrepo
	AND admin clones tstrepo over ssh
	AND admin makes change to master in tstrepo
	THEN admin can push master in tstrepo
	
	WHEN admin makes change to foo in tstrepo
	THEN admin can push foo in tstrepo
	
	WHEN admin tags foo branch in tstrepo
	THEN admin can push foo with tags in tstrepo

	FINALLY remove repository tstrepo on server

Non-admin, however, shouldn't be able to push to master, but should be
able to push to a branch prefixed by their username.

	SCENARIO non-admin cannot push to master
	ASSUMING no tstusr user exists on server
	GIVEN an ssh key for tstusr

	WHEN admin creates user tstusr
	AND admin creates repository tstrepo
	AND tstusr clones tstrepo over ssh
	AND tstusr makes change to master in tstrepo
	AND tstusr attempts to push master in tstrepo
	THEN attempt failed with error matching "Rules refused update"

	WHEN tstusr makes change to tstusr/foo in tstrepo
	THEN tstusr can push tstusr/foo in tstrepo
	
	FINALLY remove repository tstrepo on server
	AND remove user tstusr on server

Implementation sections
=======================


Check results of attempted operation
------------------------------------

Some scenario steps attempt to do something which may (or should)
fail. This step verifies the result of such an attempt. It is
intentionally named to be quite generic so we don't need to have
multiple "foo failed with error..." steps.

	IMPLEMENTS THEN attempt failed with error matching "(.*)"
	echo "stderr of attempted command:"
	cat "$DATADIR/attempt.stderr"
	grep "$MATCH_1" "$DATADIR/attempt.stderr"

ssh key generation
------------------

Our test users need ssh keys. We generate these on the fly rather than
storing them in git, so that if someone gets a copy of this test
suite, they don't have keys that can, at least temporarily, access the
gitano instance.

The key is stored as `$DATADIR/$USERNAME.key` (for the secret key;
public key adds `.pub` to the end of the pathname).

We run `ssh-keygen` with `-N` to set an empty passphrase. This is OK
for test keys that never leave the local system, because our shell
library makes sure `$DATADIR` is inaccessible to anyone else.

	IMPLEMENTS GIVEN an ssh key for (\S+)
	ssh-keygen -f "$DATADIR/$MATCH_1.key" -N ''

Check for users on server
-------------------------

We check for users on the server at various stages. Those tests are
collected here, since they're all quite similar. Since we do it in
several IMPLEMENTS sections, we have a shell function in the shell
library to contain the actual code.

First of all, we need to verify that there are no test related users
on the server. If there is, something's gone wrong in a previous run,
and things should be cleaned up manually. Or another run of the test
suite is going on, and we shouldn't interfere with that.

	IMPLEMENTS ASSUMING no (\S+) user exists on server
	if user_exists "$MATCH_1"
	then
		die "User $MATCH_1 exists on server, but shouldn't"
	fi

Verify a user exists on the server.

	IMPLEMENTS THEN user (\S+) exists
	user_exists "$MATCH_1"

Verify a user doesn't exist on the server.

	IMPLEMENTS THEN user (\S+) doesn't exist
	if user_exists "$MATCH_1"
	then
		die "User $MATCH_1 exists on server, but shouldn't"
	fi

Verify a user can actually access gitano (by invoking whoami). This is
necessary to make sure that user creation added the user's ssh key;
otherwise other test steps may fail for unrelated reasons and the test
suite may interpret that wrongly. Further, we make sure the user's ssh
key can access their account and not some other account.

	IMPLEMENTS THEN user (\S+) can access gitano
	run_gitano_as "$MATCH_1" whoami | grep "User name: $MATCH_1\$"

User creation
-------------

An admin creates a user on the server. Since we need to have a
separate step for when a non-admin attempts the same, we have a shell
function to do the actual work. The shell function also sets the ssh
key for the user.

	IMPLEMENTS WHEN admin creates user (\S+)
	user_add admin "$MATCH_1"

Attempt to create a user; check later if it worked.

	IMPLEMENTS WHEN (\S+) attempts to create user (\S+)
	attempt user_add "$MATCH_1" "$MATCH_2"

User removal
------------

Admin removes a user.

	IMPLEMENTS WHEN admin removes user (\S+)
	user_del admin "$MATCH_1"

Non-admin attempts to remove a user.

	IMPLEMENTS WHEN (\S+) attempts to remove user (\S+)
	attempt user_del "$MATCH_1" "$MATCH_2"

Admin clean up user at end of scenario.

	IMPLEMENTS FINALLY remove user (\S+) on server
	if user_exists "$MATCH_1"
	then
		user_del admin "$MATCH_1"
	fi

Repository creation
-------------------

Repositories can only be created by the admin.

	IMPLEMENTS WHEN admin creates repository (\S+)
	run_gitano_as admin create "$MATCH_1"

Repository listing
------------------

Can a user see the desired repository in the `gitano ls` output?

	IMPLEMENTS THEN (\S+) can see repository (\S+)
	repo_exists "$MATCH_1" "$MATCH_2"

And sometimes they shouldn't see it anymore.

	IMPLEMENTS THEN (\S+) can't see repository (\S+)
	if repo_exists "$MATCH_1" "$MATCH_2"
	then
		die "$MATCH_1 can see repository $MATCH_2 but shouldn't"
	fi

Repository cloning
------------------

Repositories can be cloned using git or ssh protocols, and they
may be cloned by various users. We store the clone repositories
as `$DATADIR/$USER/$REPO`. If the same user clones the same
repository more than once, we only keep the last one.

It doesn't matter who clones over git, since git is open to everyone.
So we only have a variant for admin, for simplicity.

	IMPLEMENTS THEN admin can clone (\S+) using git
	localdir="$DATADIR/admin/$MATCH_1"
	rm -rf "$localdir"
	mkdir -p "$localdir"
	git clone "git://$GITHOST/$MATCH_1" "$localdir"

However, cloning over ssh is serious business, for ACL. The tricky bit
here is to get git to use the right ssh key. We do this by having
a ./ssh script that runs the real ssh, but adds a `-i` option to the
desired keyfile. But we only do that for non-admin users.

	IMPLEMENTS THEN (\S+) can clone (\S+) using ssh
	clone_with_ssh "$MATCH_1" "$MATCH_2"

We also need to be able to check we can't clone.

	IMPLEMENTS THEN admin can't clone (\S+) using git
	localdir="$DATADIR/meh"
	rm -rf "$localdir"
	if git clone "git://$GITHOST/$MATCH_1" "$localdir"
	then
		die "repository $MATCH_1 can be cloned over git, but shouldn't"
	fi

	IMPLEMENTS THEN (\S+) can't clone (\S+) using ssh
	if clone_with_ssh "$MATCH_1" "$MATCH_2"
	then
		die "$MATCH_1 can clone $MATCH_2 over ssh, but shouldn't"
	fi

More variants of cloning: this is a WHEN rather than THEN.

	IMPLEMENTS WHEN (\S+) clones (\S+) over ssh
	clone_with_ssh "$MATCH_1" "$MATCH_2"

Repository removal
------------------

At the end, we need to clean up repositories.

	IMPLEMENTS FINALLY remove repository (\S+) on server
	if repo_exists admin "$MATCH_1"
	then
		destroy_repo admin "$MATCH_1"
	fi

An admin can remove a repository.

	IMPLEMENTS WHEN admin removes repository (\S+)
	destroy_repo admin "$MATCH_1"

A non-admin may try to remove a repository. It should fail, but they
can try.

	IMPLEMENTS WHEN (\S+) attempts to remove repository (\S+)
	attempt destroy_repo "$MATCH_1" "$MATCH_2"

Repository changes
------------------

Make a change to a given branch, in a repository cloned by a specific
user. We don't really care about what the change is, just that it's
there. We also commit the change. If the branch doesn't exist yet, we
create it (dealing with empty repos without branches while doing so).

	IMPLEMENTS WHEN (\S+) makes change to (\S+) in (\S+)
	cd "$DATADIR/$MATCH_1/$MATCH_3"
	
	# Create master if it doesn't exist.
	if ! git branch | grep .
	then
		touch file.txt
		git add file.txt
		git commit -m "Initial commit"
	fi

	# Create wanted branch, if missing, and change to it.
	if ! git checkout "$MATCH_2"
	then
		git checkout -b "$MATCH_2"
	fi

	date >> file.txt
	git add file.txt
	git commit -m "A change to file.txt"

Make a tag change in a repo.

	IMPLEMENTS WHEN (\S+) tags (\S+) branch in (\S+)
	cd "$DATADIR/$MATCH_1/$MATCH_3"
	git checkout "$MATCH_2"
	git tag -a -m "a tag" "$MATCH_1.$(date +%s)"

Repository pushing
------------------

A named user pushes a branch to a repository.

	IMPLEMENTS THEN (\S+) can push (\S+) in (\S+)
	cd "$DATADIR/$MATCH_1/$MATCH_3"
	git checkout "$MATCH_2"
	push_with_ssh "$MATCH_1" origin HEAD

Push with tags.

	IMPLEMENTS THEN (\S+) can push (\S+) with tags in (\S+)
	cd "$DATADIR/$MATCH_1/$MATCH_3"
	git checkout "$MATCH_2"
	push_with_ssh "$MATCH_1" --tags origin HEAD

Attempt to push, when the outcome may be uncertain.

	IMPLEMENTS WHEN (\S+) attempts to push (\S+) in (\S+)
	cd "$DATADIR/$MATCH_1/$MATCH_3"
	git checkout "$MATCH_2"
	attempt push_with_ssh "$MATCH_1" origin HEAD

Cgit access
-----------

Verify that cgit shows a repository.

	IMPLEMENTS THEN cgit shows repository (\S+)
	cgit_shows "$MATCH_1"

Verify cgit doesn't show a repository.

	IMPLEMENTS THEN cgit doesn't show repository (\S+)
	if cgit_shows "$MATCH_1"
	then
		die "cgi shows $MATCH_1 but shouldn't"
	fi