hgserver: print LDAP group membership for no-op login (
bug 1372303); r?fubar
This seems like a useful thing to have to help users self-debug
permissions failures.
MozReview-Commit-ID: IMiRGiIowwV
--- a/docs/hgmozilla/auth.rst
+++ b/docs/hgmozilla/auth.rst
@@ -68,16 +68,29 @@ Verify your SSH settings are working by
Your terminal output should resemble the following::
$ ssh hg.mozilla.org
A SSH connection has been successfully established.
Your account (me@example.com) has privileges to access Mercurial over
SSH.
+ You are a member of the following LDAP groups that govern source control
+ access:
+
+ scm_level_1
+
+ This will give you write access to the following repos:
+
+ Try
+
+ You will NOT have write access to the following repos:
+
+ Autoland (integration/autoland), Firefox Repos (mozilla-central, releases/*), ...
+
You did not specify a command to run on the server. This server only
supports running specific commands. Since there is nothing to do, you
are being disconnected.
Connection to hg.mozilla.org closed.
Authenticating with Services
============================
--- a/hgserver/pash/hg_helper.py
+++ b/hgserver/pash/hg_helper.py
@@ -9,16 +9,17 @@ import os
import sys
import re
import shlex
import subprocess
from ldap_helper import (
get_ldap_attribute,
get_ldap_settings,
+ get_scm_groups,
)
import repo_group
from sh_helper import (
prompt_user,
run_command,
)
@@ -43,16 +44,41 @@ are being disconnected.
'''.lstrip()
INVALID_SSH_COMMAND = '''
The command you specified is not allowed on this server.
Goodbye.
'''.lstrip()
+LDAP_GROUP_MEMBERSHIP = """
+You are a member of the following LDAP groups that govern source control
+access:
+
+ {groups}
+
+This will give you write access to the following repos:
+
+ {access}
+
+You will NOT have write access to the following repos:
+
+ {no_access}
+""".lstrip()
+
+NO_LDAP_GROUP_MEMBERSHIP = """
+You are NOT a member of any LDAP groups that govern source control access.
+
+You will NOT be able to push to any repository until you have been granted
+commit access.
+
+See https://www.mozilla.org/about/governance/policies/commit/access-policy/ for
+more information.
+""".lstrip()
+
USER_REPO_EXISTS = """
You already have a repo called %s.
If you think this is wrong, please file a Developer Services :: hg.mozilla.org
bug at
https://bugzilla.mozilla.org/enter_bug.cgi?product=Developer%%20Services&component=Mercurial%%3A%%20hg.mozilla.org
""".strip()
@@ -118,16 +144,64 @@ def is_valid_user(mail):
if account_status == 'TRUE':
return 1
elif account_status == 'FALSE':
return 2
else:
return 0
+GROUP_REPOS = {
+ 'scm_level_1': {
+ 'Try',
+ 'User Repos (users/)',
+ },
+ 'scm_level_2': {
+ 'Project Repos (projects/)',
+ },
+ 'scm_level_3': {
+ 'Firefox Repos (mozilla-central, releases/*)',
+ },
+ 'scm_autoland': {
+ 'Autoland (integration/autoland)',
+ },
+ 'scm_l10n': {
+ 'Localization Repos (releases/l10n/*, others)',
+ }
+}
+
+
+def group_membership_message(mail):
+ """Obtain a message denoting LDAP group membership."""
+ groups = get_scm_groups(mail)
+
+ if groups is None:
+ return 'Unable to determine LDAP group membership.'
+ elif not groups:
+ return NO_LDAP_GROUP_MEMBERSHIP
+ else:
+ access = set()
+ for group in groups:
+ access |= GROUP_REPOS.get(group, set())
+
+ no_access = set()
+ for group, values in GROUP_REPOS.items():
+ if group not in groups:
+ no_access |= values
+
+ if not access:
+ access.add('Unknown')
+ if not no_access:
+ no_access.add('Unknown')
+
+ return LDAP_GROUP_MEMBERSHIP.format(
+ groups=', '.join(sorted(groups)),
+ access=', '.join(sorted(access)),
+ no_access=', '.join(sorted(no_access)))
+
# Please be very careful when you relax/change the regular expressions.
# Being lax can open us up to all kind of security problems.
def is_valid_repo_name(repo_name):
# Trailing slashes can be ignored.
repo_name = repo_name.rstrip('/')
part_re = re.compile(
r'^[a-zA-Z0-9]' # must start with a letter or number
@@ -580,16 +654,18 @@ def mozreview_ldap_associate(args):
def serve(cname, enable_repo_config=False, enable_repo_group=False,
enable_user_repos=False,
enable_mozreview_ldap_associate=False):
ssh_command = os.getenv('SSH_ORIGINAL_COMMAND')
if not ssh_command:
sys.stderr.write(SUCCESSFUL_AUTH % os.environ['USER'])
+ sys.stderr.write(group_membership_message(os.environ['USER']))
+ sys.stderr.write('\n')
sys.stderr.write(NO_SSH_COMMAND)
sys.exit(1)
args = shlex.split(ssh_command)
if args[0] == 'hg':
# SECURITY it is critical that invoked commands be limited to
# `hg -R <path> serve --stdio`. If a user manages to pass arguments
--- a/hgserver/pash/ldap_helper.py
+++ b/hgserver/pash/ldap_helper.py
@@ -86,8 +86,28 @@ def update_access_date(mail, attr, value
'%Y%m%d%H%M%SZ')
# Attribute not yet set.
except KeyError:
# Default to something very old. ~20 years.
last_access = now - datetime.timedelta(days=7300)
if last_access < yesterday:
ldap_conn_write.modify_s(dn, [(ldap.MOD_REPLACE, attr, value)])
+
+
+def get_scm_groups(mail):
+ """Obtain SCM LDAP group membership for a specified user."""
+ settings = get_ldap_settings()
+ conn = ldap_connect(settings['url'])
+ if not conn:
+ return None
+
+ fltr = '(&(cn=scm_*)(memberUid=%s))' % mail
+
+ result = conn.search_s('ou=groups,dc=mozilla', ldap.SCOPE_ONELEVEL,
+ fltr, ['cn'])
+
+ groups = set()
+ for dn, attrs in result:
+ for group in attrs['cn']:
+ groups.add(group)
+
+ return groups
--- a/hgserver/tests/test-auth.t
+++ b/hgserver/tests/test-auth.t
@@ -51,25 +51,34 @@ SSH as a valid user without proper key
# numResponses: 2
# numEntries: 1
$ ssh -T -F ssh_config -i key1 -l user1@example.com -p $HGPORT $SSH_SERVER
Permission denied (publickey).\r (esc)
[255]
-SSH with a valid key gives us warning about no command
+SSH with a valid key gives us warning about no command. Also prints note about
+lack of LDAP group membership.
$ hgmo add-ssh-key user1@example.com - < key1.pub
$ ssh -T -F ssh_config -i key1 -l user1@example.com -p $HGPORT $SSH_SERVER
A SSH connection has been successfully established.
Your account (user1@example.com) has privileges to access Mercurial over
SSH.
+ You are NOT a member of any LDAP groups that govern source control access.
+
+ You will NOT be able to push to any repository until you have been granted
+ commit access.
+
+ See https://www.mozilla.org/about/governance/policies/commit/access-policy/ for
+ more information.
+
You did not specify a command to run on the server. This server only
supports running specific commands. Since there is nothing to do, you
are being disconnected.
[1]
SSH with invalid command prints appropriate error message
$ ssh -T -F ssh_config -i key1 -l user1@example.com -p $HGPORT $SSH_SERVER foobar
@@ -78,16 +87,46 @@ SSH with invalid command prints appropri
Your account (user1@example.com) has privileges to access Mercurial over
SSH.
The command you specified is not allowed on this server.
Goodbye.
[1]
+SCM LDAP group membership is printed with no-op login.
+
+ $ hgmo add-user-to-group user1@example.com scm_autoland
+ $ hgmo add-user-to-group user1@example.com scm_level_1
+ $ hgmo add-user-to-group user1@example.com scm_level_2
+
+ $ ssh -T -F ssh_config -i key1 -l user1@example.com -p $HGPORT $SSH_SERVER
+ A SSH connection has been successfully established.
+
+ Your account (user1@example.com) has privileges to access Mercurial over
+ SSH.
+
+ You are a member of the following LDAP groups that govern source control
+ access:
+
+ scm_autoland, scm_level_1, scm_level_2
+
+ This will give you write access to the following repos:
+
+ Autoland (integration/autoland), Project Repos (projects/), Try, User Repos (users/)
+
+ You will NOT have write access to the following repos:
+
+ Firefox Repos (mozilla-central, releases/*), Localization Repos (releases/l10n/*, others)
+
+ You did not specify a command to run on the server. This server only
+ supports running specific commands. Since there is nothing to do, you
+ are being disconnected.
+ [1]
+
Successful login should set hgAccessDate LDAP attribute
$ hgmo exec hgssh /usr/bin/ldapsearch -b 'dc=mozilla' -s sub -x mail=user1@example.com
# extended LDIF
#
# LDAPv3
# base <dc=mozilla> with scope subtree
# filter: mail=user1@example.com
@@ -191,16 +230,29 @@ No HG access prints helpful error messag
Do another login to verify no pash errors are present
$ ssh -T -F ssh_config -i key1 -l user1@example.com -p $HGPORT $SSH_SERVER
A SSH connection has been successfully established.
Your account (user1@example.com) has privileges to access Mercurial over
SSH.
+ You are a member of the following LDAP groups that govern source control
+ access:
+
+ scm_autoland, scm_level_1, scm_level_2
+
+ This will give you write access to the following repos:
+
+ Autoland (integration/autoland), Project Repos (projects/), Try, User Repos (users/)
+
+ You will NOT have write access to the following repos:
+
+ Firefox Repos (mozilla-central, releases/*), Localization Repos (releases/l10n/*, others)
+
You did not specify a command to run on the server. This server only
supports running specific commands. Since there is nothing to do, you
are being disconnected.
[1]
$ hgmo exec hgssh cat /var/log/pash.log
hgAccountEnabled=FALSE shows account disabled message
@@ -290,16 +342,29 @@ Failure to connect to LDAP master server
$ ssh -T -F ssh_config -i key1 -l user1@example.com -p $HGPORT $SSH_SERVER
Could not connect to the LDAP server at ldap://localhost:6000
A SSH connection has been successfully established.
Your account (user1@example.com) has privileges to access Mercurial over
SSH.
+ You are a member of the following LDAP groups that govern source control
+ access:
+
+ scm_autoland, scm_level_1, scm_level_2
+
+ This will give you write access to the following repos:
+
+ Autoland (integration/autoland), Project Repos (projects/), Try, User Repos (users/)
+
+ You will NOT have write access to the following repos:
+
+ Firefox Repos (mozilla-central, releases/*), Localization Repos (releases/l10n/*, others)
+
You did not specify a command to run on the server. This server only
supports running specific commands. Since there is nothing to do, you
are being disconnected.
[1]
Can pull when LDAP master is not available
$ hgmo create-repo mozilla-central scm_level_3