User authentication on Savannah

User account creation

  1. Anyone can register a Savannah user account using the web interface: https://savannah.gnu.org/account/register.php
  2. These user accounts are used across all Savannah systems.
  3. Users can upload ssh public keys using the web interface at: https://savannah.gnu.org/my/admin/editsshkeys.php
  4. ssh public keys are stored in the MySQL database server on internal.sv.gnu.org (see SavannahServices).

User information can be viewed by anyone on the Savannah web site. Example for user 'agn': https://sv.gnu.org/users/agn/

Database access

On internal.sv.gnu.org, the following sql commands can be used to examine user accounts:

$ echo "select
          user_id, user_name, email, realname,
          uidNumber, authorized_keys
        from user
        where user_name = 'agn'" \
      | mysql savane

+---------+-----------+----------+--------------+-----------+-----------------+
| user_id | user_name | email    | realname     | uidNumber | authorized_keys |
+---------+-----------+----------+--------------+-----------+-----------------+
|   94790 | agn       | [email]  | Assaf Gordon |    131035 | ssh-rsa AAAAB3Nz|
+---------+-----------+----------+--------------+-----------+-----------------+

The authorized_keys field contains all the user's SSH public keys, concatenated with a ### delimiter, as a one-line string. (The database currently contains some malformed/invalid keys - when a user uploaded invalid keys.)

Reactivating a user

It's possible to do this in the web interface: Main page -> Browse Users List -> find user -> [Activate] in the Actions column.

Also possible to do in sql, of course. Check the status, do the update as safely as possible, check again:

mysql> select user_id,user_name,status from user where user_name = 'FOO';
mysql> update user set status='A' where user_id=N and user_name='FOO' limit 1;
mysql> select user_id,user_name,status from user where user_name = 'FOO';

User/group accounts

In Savannah systems, there is a Unix user for each Savannah registered user:

 vcs:~# getent passwd agn
 agn:x:131035:1003:Assaf Gordon:/srv:/usr/local/bin/sv_membersh

and a unix group for each Savannah registered project:

vcs:~# getent group datamash
datamash:x:77800:agn

Access control is based on Unix group membership.

Example:

The gawk (GNU Awk) project (http://sv.gnu.org/p/gawk) has six members as of Nov. 2014 (http://sv.gnu.org/project/memberlist.php?group=gawk).

The git repository on vcs.sv.gnu.org is group-owned by gawk group:

vcs:~# ls -ld /srv/git/gawk.git/
drwxrwsr-x 8 root gawk 4096 Nov  4 01:23 /srv/git/gawk.git/

The members of the gawk group are allowed to push code updates to the gawk repository:

vcs:~# getent group gawk
gawk:x:6731:ajschorr,arnold,eliz,jkahrs,scldad,wb8tyw

Authentication mechanisms

For VCS repositories (git/hg/bzr/svn/cvs on vcs.sv.gnu.org) and download/releases (on dl.sv.gnu.org), users are authenticated using SSH access and their public keys. See SavannahServices for details about the available services on these servers.

Savannah users who are not members of any project (i.e., do not have write access to any repository) do not have ssh login access on vcs even if they have set up their ssh keys. getent passwd USER will return empty results for such users, even if they are valid users in the database (i.e., they exist in the users mysql table).

Technically, this is due to the libnss-mysql (see below) script doing an sql join on the user and user_group tables, and requiring having at least one record in the user_group table. Maybe someday this will be changed.

These servers use the MySQL database in two ways:

  • Unix user management, using nsswitch and libnss-mysql.
  • ssh key authentication, using the custom AuthorizedKeysExec option.

nsswitch and libnss-mysql

The files dl:/etc/nsswitch.conf and vcs:/etc/nsswitch.conf contain the following configuration:

...
passwd:         compat mysql
group:          compat mysql
shadow:         compat mysql
...

Bob Proulx explains:

That is how libc is configured. 'compat' means /etc/passwd in the normal compatible way. 'mysql' means if not found in the first compat section then look it up in mysql. That is what allows libc to find users in the mysql database.

 download:~# getent passwd agn
 agn:x:131035:1003:Assaf Gordon:/srv:/usr/local/bin/sv_membersh

(Notice the uidNumber from the mysql database is the user's Unix uid.)

The sql statements (to extract information from the mysql database on internal) are defined in dl:/etc/libnss-mysql.cfg and vcs:/etc/libnss-mysql.cfg.

ssh authentication

The file /etc/ssh/sshd_config on dl: and vcs: servers have the line: ... AuthorizedKeysExec /usr/local/bin/sv_get_authorized_keys ...

Historical Note:
AuthorizedKeysExec was a patch submitted by GNU Hacker Michael J. Flickinger (http://sv.gnu.org/u/mjflick) to OpenSSH in 2011. It appears the patch was never formally accepted by upstream OpenSSH.
In 2012 a similar patch was accepted from RedHat using a differently named option AuthorizedKeysCommand.
This option (and not AuthorizedKeysExec) is available in most OpenSSH installations.
If Savannah servers are ever upgraded, these configuration files should be updated from AuthorizedKeysExec to AuthorizedKeysCommand.

When users login to Savannah servers using ssh, they specify the user account:

git clone agn@git.sv.gnu.org:/srv/git/datamash.git

The user is therefore known, and OpenSSH needs to find the user's public keys. The /usr/local/bin/sv_get_authorized_keys Perl script simply queries the ssh public keys of the user (splitting them by ### delimiter):

...
my ($authorized_keys) = $dbd->selectrow_array(q[
    SELECT authorized_keys
    FROM user
    WHERE user_name = ?], undef, $user);

print join("\n", split('###', $authorized_keys));
...

Manually invoking sv_get_authorized_keys looks like:

vcs:~# /usr/local/bin/sv_get_authorized_keys agn
ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAvs [...]
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQ [...]

To validate the user's keys on vcs, use the following script:

vcs:~# ~/bin/check-user-pubkeys.sh agn
gordon@host1     2048 fe:61:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx /tmp/pubkey.check.9WvGnA/key.00 (RSA)
gordon@host2     2048 87:21:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx /tmp/pubkey.check.9WvGnA/key.01 (RSA)
gordon@host3     2048 3d:00:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx /tmp/pubkey.check.9WvGnA/key.02 (RSA)

vcs:~# ~/bin/check-user-pubkeys.sh someuser
someuser@host1   4096 6b:36:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx /tmp/pubkey.check.DmNCzP/key.00 (RSA)
someuser@host2   4096 0b:c3:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx /tmp/pubkey.check.DmNCzP/key.01 (RSA)
Invalid key: /tmp/pubkey.check.DmNCzP/key.02
Errors found in ssh pubkeys for user 'someuser'.
to troubleshoot, check files in /tmp/pubkey.check.DmNCzP .

The above script can help with troubleshooting user's SSH login problems.

mgt and root access

mgt.sv.gnu.org is the management server (see SavannahArchitecture for more details).

root access to mgt (and from there to dl/vcs/dl/fe servers) is controlled by mgt:/root/.ssh/authorized_keys. This file is updated manually by existing Savannah administrators, adding ssh public keys of authorized savannah hackers.

ssh access to root@{mgt,vcs,dl,int,fe} is only possible from fencepost (and other internal FSF machines to which no one outside the FSF has access).

A script mgt:/root/bin/push-root-authkeys copies the file mgt:/root/.ssh/authorized_keys to mgt:/root/.ssh/vm_authorized_keys, and also to {dl,fe,vcs,int}:/etc/ssh/authorized_keys/root. (History: the script mgt:/root/maintenance/authorized_keys_replicate.sh, et al., was a previous method of doing that same job, no longer used.)

The files {dl,fe,vcs,int}:/etc/ssh/sshd_config have:

AuthorizedKeysFile      /etc/ssh/authorized_keys/%u

which enables root login based on the propagated authorized_keys file.

fencepost

fencepost.gnu.org is the general-purpose server for GNU hackers (for more information: https://www.gnu.org/software/README.accounts.html).

It is managed by FSF sysadmin, and not managed by Savannah people in any way whatsoever.

Users on fencepost.gnu.org conventionally use the same username as Savannah accounts, and public ssh keys are copied (manually) from Savannah database (i.e., users requesting access to fencepost should setup accounts on Savannah with ssh public keys). Other than that - user management on fencepost is separate from the rest of Savannah servers.

Each user on fencepost has a home directory with ~/.ssh/authorized_keys files, enabling ssh access:

$ getent passwd agn
agn:x:1557:1562:Assaf Gordon,,,:/home/a/agn:/bin/bash

GNU webpages repository access for www members

Members of the www group (= GNU webmasters) have write access to the webpage repository for all gnu (not nongnu) projects. This is accomplished with ACLs. See ChangeLog entries by Beuc for 2006-06-28 and 2006-05-10, recorded in http://lists.gnu.org/archive/html/savannah-hackers-public/2016-05/msg00031.html. The key command is:

setfacl -m default:group:www:rwx -m group:www:rwx DIRS

The Cvs.pm Savane module apparently installs this access for new gnu projects and directories.