Fossil SCM

fossil-scm / www / server / any / http-over-ssh.md
1
# Forcing Use of Fossil’s RBAC over SSH
2
3
Andy Bradford posted a [clever solution][sshfc] to the problem of
4
Fossil’s RBAC system [being ignored](../../caps/#webonly) over `ssh://`
5
URLs: use OpenSSH’s `ForceCommand` feature to route the sync transfer
6
protocol data over `fossil http` rather than `fossil test-http`.
7
8
The setup for this is complicated, but it’s a worthy option when you
9
need encrypted communications between the client and server, you already
10
have SSH set up, and [the HTTPS alternative](../../ssl.wiki) is
11
unworkable for some reason.
12
13
14
## 1. Force remote Fossil access through a wrapper script <a id="sshd"></a>
15
16
Put something like the following into the `sshd_config` file on the
17
Fossil repository server:
18
19
``` ssh-config
20
Match Group fossil
21
X11Forwarding no
22
AllowTcpForwarding no
23
AllowAgentForwarding no
24
ForceCommand /home/fossil/bin/wrapper
25
```
26
27
This file is usually found in `/etc/ssh`, but some OSes put it
28
elsewhere.
29
30
The first line presumes that we will put all users who need to use our
31
Fossil repositories into the `fossil` group, as we will do
32
[below](#perms). You could instead say something like:
33
34
``` ssh-config
35
Match User alice,bob,carol,dave
36
```
37
38
You have to list the users allowed to use Fossil in this case because
39
your system likely has a system administrator that uses SSH for remote
40
shell access, so you want to *exclude* that user from the list. For the
41
same reason, you don’t want to put the `ForceCommand` directive outside
42
a `Match` block of some sort.
43
44
You could instead list the exceptions:
45
46
``` ssh-config
47
Match User !evi
48
```
49
50
This would permit only [Evi the System Administrator][evi] to bypass this
51
mechanism.
52
53
[evi]: https://en.wikipedia.org/wiki/Evi_Nemeth
54
55
If you have a user that needs both interactive SSH shell access *and*
56
Fossil access, exclude that user from the `Match` rule and use Fossil’s
57
normal `ssh://` URL scheme for those cases. This user will bypass the
58
Fossil RBAC, but they effectively have Setup capability on those
59
repositories anyway by having full read/write access to the DB files via
60
the shell.
61
62
63
## 2. Rewrite the sync command with that wrapper <a id="wrapper"></a>
64
65
When Fossil syncs over SSH, it attempts to launch a remote Fossil
66
instance with certain parameters in order to set up the HTTP-based sync
67
protocol over that SSH tunnel. We need to preserve some of this command
68
and rewrite other parts to make this work.
69
70
Here is a simpler variant of Andy’s original wrapper script:
71
72
``` sh
73
#!/bin/bash
74
set -- $SSH_ORIGINAL_COMMAND
75
while [ $# -gt 1 ] ; do shift ; done
76
export REMOTE_USER="$USER"
77
ROOT=/home/fossil
78
exec "$ROOT/bin/fossil" http "$ROOT/museum/$(/bin/basename "$1")"
79
```
80
81
The substantive changes are:
82
83
1. Move the command rewriting bits to the start.
84
85
2. Be explicit about executable paths. You might extend this idea by
86
using chroot, BSD jails, Linux containers, etc.
87
88
3. Restrict the Fossil repositories to a single flat subdirectory under
89
the `fossil` user’s home directory. This scheme is easier to secure
90
than one allowing subdirectories, since you’d need to take care of
91
`../` and such to prevent a sandbox escape.
92
93
4. Don’t take the user name via the SSH command; to this author’s mind,
94
the user should not get to override their Fossil user name on the
95
remote server, as that permits impersonation. The identity you
96
present to the SSH server must be the same identity that the Fossil
97
repository you’re working with knows you by. Since the users
98
selected by “`Match`” block above are dedicated to using only Fossil
99
in this setup, this restriction shouldn’t present a practical problem.
100
101
The script’s shebang line assumes `/bin/sh` is POSIX-compliant, but that
102
is not the case everywhere. If the script fails to run on your system,
103
try changing this line to point at `bash`, `dash`, `ksh`, or `zsh`. Also
104
check the absolute paths for local correctness: is `/bin/basename`
105
installed on your system, for example?
106
107
Under this scheme, you clone with a command like:
108
109
$ fossil clone ssh://HOST/repo.fossil
110
111
This will clone the remote `/home/fossil/museum/repo.fossil` repository
112
to your local machine under the same name and open it into a “`repo/`”
113
subdirectory. Notice that we didn’t have to give the `museum/` part of
114
the path: it’s implicit per point #3 above.
115
116
This presumes your local user name matches the remote user name. Unlike
117
with `http[s]://` URLs, you don’t have to provide the `USER@` part to
118
get authenticated access
119
since this scheme doesn’t permit anonymous cloning. Only
120
if these two user names are different do you need to add the `USER@` bit to the
121
URL.
122
123
124
## 3. Set permissions <a id="perms"></a>
125
126
This scheme assumes that the users covered by the `Match` rule can read
127
the wrapper script from where you placed it and execute it, and that
128
they have read/write access on the directory where the Fossil
129
repositories are stored.
130
131
You can achieve all of this on a Linux box with:
132
133
``` shell
134
sudo adduser fossil
135
for u in alice bob carol dave ; do
136
sudo adduser $u
137
sudo gpasswd -a fossil $u
138
done
139
sudo -i -u fossil
140
chmod 710 .
141
mkdir -m 750 bin
142
mkdir -m 770 museum
143
ln -s /usr/local/bin/fossil bin
144
```
145
146
You then need to copy the Fossil repositories into `~fossil/museum` and
147
make them readable and writable by group `fossil`. These repositories
148
presumably already have Fossil users configured, with the necessary
149
[user capabilities](../../caps/), the point of this article being to
150
show you how to make Fossil-over-SSH pay attention to those caps.
151
152
You must also permit use of `REMOTE_USER` on each shared repository.
153
Fossil only pays attention to this environment variable in certain
154
contexts, of which “`fossil http`” is not one. Run this command against
155
each repo to allow that:
156
157
``` shell
158
echo "INSERT OR REPLACE INTO config VALUES ('remote_user_ok',1,strftime('%s','now'));" |
159
fossil sql -R museum/repo.fossil
160
```
161
162
Now you can configure SSH authentication for each user. Since Fossil’s
163
password-saving feature doesn’t work in this case, I suggest setting up
164
SSH keys via `~USER/.ssh/authorized_keys` since the SSH authentication
165
occurs on each sync, which Fossil’s default-enabled autosync setting
166
makes frequent.
167
168
Equivalent commands for other OSes should be readily discerned from the
169
script above.
170
171
[sshfc]: forum:/forumpost/0d7d6c3df41fcdfd
172
173
<div style="height:50em" id="this-space-intentionally-left-blank"></div>
174

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button