Fossil Forum

Different way to do fossil over ssh with RBAC
Login

Different way to do fossil over ssh with RBAC

Different way to do fossil over ssh with RBAC

(1) By John Rouillard (rouilj) on 2021-09-26 05:03:09 [link] [source]

This is an alternate way to access fossils over ssh. It does away with the wrapper and changes to sshd_config. Also local user accounts aren't needed. If a user does have local shell access, they have no access to the repos. They have to use fossil to access the repos.

It uses the ~fossil/.ssh/authorized_keys file to specify the forced command and tighten up restrictions.

  1. set up a fossil user and museum same as documented in https://fossil-scm.org/home/doc/trunk/www/server/any/http-over-ssh.md. However, set up the museum to be accessible only to the fossil user.
    • there is no need to create accounts on the server for the users
    • nor is there a need to create a common group for them.
  2. for each user who should use fossil create an entry in ~fossil/.ssh/authorized_keys like:
    command="REMOTE_USER=rou fossil http museum/",no-agent-forwarding,no-port-forwarding,no-pty,no-user-rc,no-x11-forwarding,restrict ssh-rsa AAAAB3NzaC1yc2EAA<more key here>9BoaS0U= rou-fossil
    
  3. note in the command the REMOTE_USER is hardcoded so you can use any name for the fossil user. I haven't tried it but it could be used to define the REMOTE_USER using an email address as a universal identifier. I have only used Unix compatible identifiers.
  4. Only the directory (or a single fossil repo) is specified. If a directory is used, the fossil repo is taken from the http protocol POST command. Note that the trailing / on museum is removed. This is discussed later.
  5. The restrict option alone does the same things that all the other no- options do explicitly. However some sshd servers don't support restrict and the explicit options are needed. So either use no- options or restrict. This set of restrictions prevents:
    • ssh-agent forwarding (same as in the http-over-ssh.md doc)
    • tcp port forwarding (again covered in the doc)
    • requesting a pty. This is not possible using sshd-config and makes sure there is a clean 8-bit path. It can also prevent shenanigans by a user trying to use the ssh key outside of a fossil command
    • running the ~fossil ssh rc file. There shouldn't be one anyway so this is a belt and suspenders no-op
    • X11 forwarding (as covered in the doc)

Also it would be nice to be able to specify:

fossil http museum/ --allow-remote-user
to eliminate the requirement that the remote-user be enabled on the repo. This would allow ssh access (say for users that can check in code). As well as HTTP access to the forum/wiki pages for users/anonymous without enabling REMOTE_USER over the HTTP server path.

As I mentioned above the trailing / on the directory museum/ is stripped. This means that the fossil clone call has to change a bit to:

 fossil clonefossil@ ssh://fossil_host//fossil_repo
to clone museum/fossil_repo.fossil (note the double / after the hostname). It would be nice if it wasn't stripped so the double // before fossil_repo could be just a single /. Without the double /, the HTTP traffic starts with:
POST demo_roundup_child_test HTTP/1.0
that leads to a repo not found. With the double / I get:
POST /demo_roundup_child_test HTTP/1.0
and successful access.

A client side .ssh/config for the ssh://fossil/ URL could be:

host fossil
  hostname my_fossil.server.com
  IdentityFile ~/.ssh/fossil_scm
  IdentitiesOnly yes
  IdentityAgent none
  User fossil
which:

  • sets the ssh identity key file to use for fossil access
  • prevents taking an identity from an ssh-agent or using the default id_rsa etc keys. I assume that the user has other ssh keys used for access to shell accounts, so I want to disable those for efficiency since they won't work.

Alternate forms of the clone: fossil clone ssh://user@fossil_host//fossil_repo can also be used if the user isn't coded into a config.

(2) By Warren Young (wyoung) on 2021-09-26 10:35:13 in reply to 1 [link] [source]

It's an interesting alternative. I'm on another project, so I won't get back to that article for a time, but it does seem worth splitting the article into two alternative solutions.

(3) By John Rouillard (rouilj) on 2021-09-26 13:01:14 in reply to 2 [link] [source]

Hi Warren:

Thanks. Also I was expecting the -U, --user common option would work but in testing it appears only the REMOTE_USER is used. if -U worked it would be even cleaner:

  1. command="fossil -U rouilj http museum/"
  2. No need to enable REMOTE_USER so no need for --allow-remote-user or to enable REMOTE_USER in this context.

Not sure why -U isn't used. I used this same mechanism for remote SSH access to svn repos many years ago (the option for svnserv is --tunnel-user). Maybe a bug in --user support?

(4) By Andy Bradford (andybradford) on 2021-09-26 17:12:21 in reply to 1 [link] [source]

> This is an alternate way to access fossils over ssh.

Yes, in fact, my original suggestions for using Fossil over SSH was very
similar  if  not identical,  and  in  fact,  I've suggested  just  about
every variation  on the  theme (one with  wrappers, one  without, single
account using  keys (ala  git), multiple accounts,  one with  changes to
sshd_config, requiring Fossil Capabilities using ForceCommand, etc.):

https://marc.info/?l=fossil-users&m=144565808636962&w=2

The point  is that  Fossil and SSH  are fairly flexible  in what  can be
accomplished---just depends on the needs and goals.

Also, with  respect to double slash  vs single slash, the  Fossil client
when talking SSH, doesn't think of it as "single slash vs double slash",
but instead parses  a URL. It parses the host  followed by single slash.
Anything that remains is the "path", hence:

ssh://remotehost//path

Fossil  removes everything,  including  a  slash (as  part  of the  URL)
"ssh://remotehost/"  and  what  remains   is  simply  "/path".  For  SSH
specifically, this becomes the difference  between an absolute path, and
a relative path. A relative path  obviously permits the remote server to
interpret  the path  to  a  file as  relative  to  whatever the  working
directory of  the remote  shell is.  This is why  you observe  that when
there is no slash in the path portion of the URL that it fails---the SSH
client  thinks you  want a  relative path  on the  server. However,  the
client isn't aware  that "fossil http directory" is being  run and so it
doesn't know  to treat  the SSH  request as  if it  were really  an HTTP
request, and consquently requests a "relative" repository path.

I'm not  sure that  this should  be changed (just  tell people  to clone
using /repo as  the path), but any change would  probably need to happen
on  the server  side because  the Fossil  client operating  in SSH  mode
cannot easily know that the remote side is forcing commands.


Andy

(5) By John Rouillard (rouilj) on 2021-09-27 00:46:45 in reply to 4 [link] [source]

Hi Andy:

This is an alternate way to access fossils over ssh.

Yes, in fact, my original suggestions for using Fossil over SSH was very similar if not identical,

Doesn't surprise me. My svnserve stuff was done in 2006/2007 or so. I remember reading something similar to what I had done with svnserv for fossil in the mail archives. I tried to find it to give credit but my google-fu wasn't up to the task. Thanks for the URL, that was probably what I remember.

Also, with respect to double slash vs single slash, the Fossil client when talking SSH, doesn't think of it as "single slash vs double slash", but instead parses a URL. It parses the host followed by single slash. Anything that remains is the "path",

However when a browser opens the URL:

https://fossil-scm.org/forum/forumpost/9fd78b751d
the http request starts:
GET /forum/forumpost/9fd78b751d HTTP/1.1
note the leading /. No need to double it in the URL.

Also fossil pull for https://www.fossil-scm.org/home starts with (captured using --httptrace):

POST /home HTTP/1.0
again a leading /. I think the path is supposed to include the / that separates the path and that host part of the URL.

Does this look like a bug in the http rendering inside the ssh support code?

-- rouilj

(6) By Andy Bradford (andybradford) on 2021-09-27 02:33:09 in reply to 5 [link] [source]

> Does this look like a bug in the http rendering inside the ssh support code?

I'm  not yet  convinced  that it  is  a  bug in  the  SSH support  code,
precisely because SSH is not HTTP,  even though Fossil tunnels HTTP over
SSH. As it  was originally designed, SSH uses "fossil  test-http" as the
remote command  and it  never uses  directories as  the target,  but has
always been a direct path (relative  or absolute) to a repository, not a
collection of repositories.

However, I  could certainly  see an enhancement  request on  the "fossil
http" side of  things to enable it  to handle relative paths  as if they
are absolute so that this works:

fossil clone ssh://remoteserver/path

Again,  I'm not  sure it's  necessary since  it's just  as easy  to give
cloning instructions either way.


> However when a browser opens the URL:
>
> https://fossil-scm.org/forum/forumpost/9fd78b751d
>
> the http request starts:
>
> GET /forum/forumpost/9fd78b751d HTTP/1.1

That's  because  that's how  browsers  talking  HTTP work.  They  always
specify  an  absolute  path.  SSH,  on the  other  hand,  can  and  does
distinguish between  "/path" and "path",  the former being  absolute and
the latter relative.

This is similar to the difference between:

scp remoteserver:/path

vs

scp remoteserver:path

Also, keep in mind that Fossil is  using a different URL scheme than SCP
does.  When  one uses  SCP  one  does not  prefix  the  URL with  ssh://
typically, however,  if one  did, how  would SCP  (using a  typical HTTP
scheme  for URLs)  distinguish between  absolute and  relative paths?  I
submit that SSH, if using a full URL scheme like HTTP would in fact have
double slashes as well just to distinguish between absolute and relative
paths. Something like:

scp ssh://remoteserver//path /tmp #absolute
scp ssh://remoteserver/path /tmp  #relative

Unless there  were some  other mechanism  for communicating  relative vs
absolute.

Andy

(7) By Andy Bradford (andybradford) on 2021-09-27 02:59:59 in reply to 5 [source]

> Also  fossil  pull  for  https://www.fossil-scm.org/home  starts  with
> (captured using --httptrace):
>
> POST /home HTTP/1.0

This  is because  the  Fossil  client, when  talking  HTTP, always  uses
absolute paths. It will never send  "POST home HTTP/1.0" and I would bet
that it would result in an error if it tried:

POST home HTTP/1.0
HTTP/1.0 404 Not Found

However,  Fossil,  when  using  SSH as  the  transport  does  understand
relative vs  absolute paths. Please look  at the httptrace when  doing a
"fossil pull" using SSH.

In  the  following  example,  I  have  created  2  Fossil  repositories.
The   first  is   a  relative   path   in  my   user's  home   directory
($HOME/tmp/relative.fossil) and the  second is an absolute  path in /tmp
(/tmp/absolute.fossil).

First the relative (with 0 slashes at beginning of path):

$ fossil pull --httptrace -R clone.fossil
Pull from ssh://localhost/tmp/relative.fossil
Round-trips: 1   Artifacts sent: 0  received: 0
Pull done, wire bytes sent: 376  received: 296  ip: localhost
/***** Subprocess 98205 exit(0) *****/
$ head -1 http-request-1.txt
POST tmp/relative.fossil HTTP/1.0

Next the absolute (with 1 slash at beginning of path):

$ fossil pull --httptrace -R clone.fossil
Pull from ssh://localhost//tmp/absolute.fossil
Round-trips: 1   Artifacts sent: 0  received: 0
Pull done, wire bytes sent: 377  received: 296  ip: localhost
/***** Subprocess 23848 exit(0) *****/
$ head -1 http-request-1.txt
POST /tmp/absolute.fossil HTTP/1.0

So again, what you're observing is  really the difference between an SSH
client that can and does pass in absolute vs relative paths, and an HTTP
server that normally only understands absolute paths.

And the  final question  is... should  "fossil http"  have an  option to
instruct it  to treat all  paths as absolute whether  or not there  is a
leading slash?

Andy