scripts: add a standalone script for performing SSH key lookup from LDAP (
bug 1261212); r=fubar, kang
Modern versions of OpenSSH support calling a program that will print SSH
public keys for a user. This script added by this patch is intended to be
used for this purpose.
We go beyond simple key lookup by filtering out DSA keys because they
are insecure and shouldn't be allowed. We stop short of filtering out
RSA keys with a short modulus, however. I don't want to introduce a
BER decoder just yet (we would likely import paramiko's).
MozReview-Commit-ID: 2bYNOsaF76C
new file mode 100644
--- /dev/null
+++ b/hgserver/tests/test-ldap-lookup.t
@@ -0,0 +1,64 @@
+#require hgmodocker
+
+ $ . $TESTDIR/hgserver/tests/helpers.sh
+ $ hgmoenv
+
+ $ alias lookup="hgmo exec hgssh /var/hg/version-control-tools/scripts/ldap-lookup-ssh-key"
+
+No arguments prints error
+
+ $ lookup
+ usage: /var/hg/version-control-tools/scripts/ldap-lookup-ssh-key <user>
+ [1]
+
+Multiple arguments prints failure
+
+ $ lookup me you
+ usage: /var/hg/version-control-tools/scripts/ldap-lookup-ssh-key <user>
+ [1]
+
+Looking up unknown user prints failure
+
+ $ lookup nobody@nowhere.com
+ user not found
+ [1]
+
+User with no SSH key has failure
+
+ $ hgmo create-ldap-user user1@example.com user1 1000 'Some User'
+ $ lookup user1@example.com
+ no SSH keys found for user
+ [1]
+
+User with single SSH key has key printed
+
+ $ ssh-keygen -b 2048 -t rsa -f key1 -N '' > /dev/null
+ $ hgmo add-ssh-key user1@example.com - < key1.pub
+
+ $ lookup user1@example.com
+ ssh-rsa * (glob)
+
+Multiple keys are printed
+
+ $ ssh-keygen -b 2048 -t rsa -f key2 -N '' > /dev/null
+ $ hgmo add-ssh-key user1@example.com - < key2.pub
+
+ $ lookup user1@example.com
+ ssh-rsa * (glob)
+ ssh-rsa * (glob)
+
+DSA keys are filtered
+
+ $ hgmo create-ldap-user dsauser@example.com dsauser 1001 'DSA User'
+ $ ssh-keygen -t dsa -f dsakey -N '' > /dev/null
+ $ hgmo add-ssh-key dsauser@example.com - < dsakey.pub
+
+ $ lookup dsauser@example.com
+ no valid SSH keys found for user
+ [1]
+
+ $ hgmo add-ssh-key dsauser@example.com - < key1.pub
+ $ lookup dsauser@example.com
+ ssh-rsa * (glob)
+
+ $ hgmo clean
new file mode 100755
--- /dev/null
+++ b/scripts/ldap-lookup-ssh-key
@@ -0,0 +1,72 @@
+#!/var/hg/venv_pash/bin/python
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+# This script looks up and prints SSH public keys for the user specified as
+# the command argument.
+
+from __future__ import absolute_import, print_function, unicode_literals
+
+import base64
+import json
+import struct
+import sys
+
+import ldap
+
+
+SETTINGS_PATH = '/etc/mercurial/ldap.json'
+UID_ATTRIBUTE = b'mail'
+SSH_KEY_ATTRIBUTE = b'sshPublicKey'
+
+def main(user):
+ with open(SETTINGS_PATH, 'rb') as fh:
+ settings = json.load(fh)
+
+ conn = ldap.initialize(settings['url'])
+ conn.simple_bind_s(settings['username'], settings['password'])
+
+ result = conn.search_s(b'dc=mozilla', ldap.SCOPE_SUBTREE,
+ b'(%s=%s)' % (UID_ATTRIBUTE, user),
+ [SSH_KEY_ATTRIBUTE])
+
+ if not result:
+ print('user not found', file=sys.stderr)
+ return 1
+
+ if len(result) > 1:
+ print('multiple LDAP entries found; weird', file=sys.stderr)
+ return 1
+
+ result = result[0]
+ if SSH_KEY_ATTRIBUTE not in result[1]:
+ print('no SSH keys found for user', file=sys.stderr)
+ return 1
+
+ keys = result[1][SSH_KEY_ATTRIBUTE]
+
+ # Ignore DSA keys. The server shouldn't support these anyway. Defense
+ # in depth.
+ keys = [k for k in keys if not k.startswith('ssh-dss')]
+
+ if not keys:
+ print('no valid SSH keys found for user', file=sys.stderr)
+ return 1
+
+ for key in keys:
+ print(key)
+
+ return 0
+
+
+if __name__ == '__main__':
+ if len(sys.argv) != 2:
+ print('usage: %s <user>' % sys.argv[0], file=sys.stderr)
+ sys.exit(1)
+
+ try:
+ sys.exit(main(sys.argv[1]))
+ except Exception:
+ print('error', file=sys.stderr)
+ sys.exit(1)