Fossil SCM

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

Keyboard Shortcuts

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