User authentication on Savannah
User account creation
- Anyone can register a Savannah user account using the web interface: https://savannah.gnu.org/account/register.php
- These user accounts are used across all Savannah systems.
- Users can upload ssh public keys using the web interface at: https://savannah.gnu.org/my/admin/editsshkeys.php
- ssh public keys are stored in the MySQL database server on
internal0.savannah.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
In the SQL database, currently internal0.savannah.gnu.org
but
accessible from the collection of hosts, 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.
Users upload their GPG key and this data is stored in this database
record. Some users have uploaded malformed and invalid GPG key
information. Therefore some of these records are invalid due to
having had invalid information uploaded.
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:
vcs0:~# getent passwd agn
agn:x:131035:1003:Assaf Gordon:/srv:/usr/local/bin/sv_membersh
and a unix group for each Savannah registered project:
vcs0:~# 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:
vcs0:~# 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:
vcs0:~# 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 download0:/etc/nsswitch.conf
and vcs0:/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.
download0:~# getent passwd agn
agn:x:131035:1003:Assaf Gordon:/srv:/usr/local/bin/sv_membersh
The sql statements (to extract information from the mysql database on
internal0
) are defined in download0:/etc/libnss-mysql.cfg
and
vcs0:/etc/libnss-mysql.cfg
.
uidNumber
Savannah users have two IDs in the database: user.user_id
and
user.uidNumber
. user_id
is used in the PHP web-frontend alone
(it is the primary key for the user table). uidNumber
is the
user's unix account user id (used by getent
above).
When a new user is registerd on savannah, the user_id
will be
unique but the uidNumber
will be NULL.
A cron job (mgt0:/etc/cron.d/savannah
) calls a script (
sv_assign_uid_gid)
which scans the new users in the database, and creates unix user-ids and
group ids if needed (if a user is not part of any group - they won't need
ssh access and thus won't need user-id).
Search for sv_assign_uid_gid
in SavannahInternals to see
how it is called (but note that the page is out-dated: the script now
runs as a cron job on mgt0
, not internal0
).
ssh authentication
The file /etc/ssh/sshd_config
on download0:
and vcs0:
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 optionAuthorizedKeysCommand
.
This option (and notAuthorizedKeysExec
) is available in most OpenSSH installations.
If Savannah servers are ever upgraded, these configuration files should be updated fromAuthorizedKeysExec
toAuthorizedKeysCommand
.
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:
vcs0:~# /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:
vcs0:~# ~/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)
vcs0:~# ~/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
mgt0.savannah.gnu.org
is the management server (see SavannahArchitecture for
more details).
root access to mgt0
(and from there to the other Savannah servers) is
controlled by mgt0:/root/.ssh/authorized_keys
. This file is updated
manually by existing Savannah administrators, adding ssh public keys
of authorized savannah hackers.
ssh access to mgt0
is only possible from fencepost
(and other
internal FSF machines to which no one outside the FSF has access).
ssh access to vcs0 and download0 is open to all as required by their
respective functions.
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 group:www:rw- FILES
setfacl -m default:group:www:rwx -m group:www:rwx DIRS
To set all of them I think this is needed. Testing it now.
setfacl -m group:www:rw- project/CVSROOT/history
find project/project -type d -exec setfacl -m default:group:www:rwx -m group:www:rwx {} +
find . -name CVSROOT -prune -o -type f -exec setfacl -m group:www:rw- {} +
The Cvs.pm
Savane module apparently installs this access for new gnu
projects and directories.