[ARVADOS] updated: 35a26ea6b98639a1313a5ece76c78b15964dde1f

git at public.curoverse.com git at public.curoverse.com
Tue Aug 11 10:51:37 EDT 2015


Summary of changes:
 sdk/pam/arvados_pam/__init__.py                    | 102 ++-------------------
 sdk/pam/arvados_pam/{__init__.py => auth_event.py} |  53 +----------
 sdk/pam/tests/mocker.py                            |  59 ++++++++++++
 sdk/pam/tests/{test_pam.py => test_auth_event.py}  |  73 ++-------------
 sdk/pam/tests/test_pam_sm.py                       |  26 ++++++
 5 files changed, 101 insertions(+), 212 deletions(-)
 copy sdk/pam/arvados_pam/{__init__.py => auth_event.py} (71%)
 create mode 100644 sdk/pam/tests/mocker.py
 rename sdk/pam/tests/{test_pam.py => test_auth_event.py} (57%)
 create mode 100644 sdk/pam/tests/test_pam_sm.py

       via  35a26ea6b98639a1313a5ece76c78b15964dde1f (commit)
       via  110f03773d2f1187f173c2615b583969b3baef6e (commit)
      from  982a80e54bef92b3c942a1e7f6924980b74d1ef4 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.


commit 35a26ea6b98639a1313a5ece76c78b15964dde1f
Author: Tom Clegg <tom at curoverse.com>
Date:   Tue Aug 11 10:46:28 2015 -0400

    6934: Add pam_sm tests.

diff --git a/sdk/pam/tests/test_pam_sm.py b/sdk/pam/tests/test_pam_sm.py
new file mode 100644
index 0000000..a967493
--- /dev/null
+++ b/sdk/pam/tests/test_pam_sm.py
@@ -0,0 +1,26 @@
+import arvados_pam
+import mock
+from . import mocker
+
+class PamSMTest(mocker.Mocker):
+    def attempt(self):
+        return arvados_pam.pam_sm_authenticate(self.pamh, 0, self.argv)
+
+    def test_success(self):
+        self.assertEqual(self.pamh.PAM_SUCCESS, self.attempt())
+
+    def test_bad_user(self):
+        self.pamh.get_user = mock.MagicMock(return_value='badusername')
+        self.assertEqual(self.pamh.PAM_AUTH_ERR, self.attempt())
+
+    def test_bad_vm(self):
+        self.argv[2] = 'testvm22.shell'
+        self.assertEqual(self.pamh.PAM_AUTH_ERR, self.attempt())
+
+    def setUp(self):
+        super(PamSMTest, self).setUp()
+        self.pamh = mock.MagicMock()
+        self.pamh.get_user = mock.MagicMock(return_value='active')
+        self.pamh.PAM_SUCCESS = 12345
+        self.pamh.PAM_AUTH_ERR = 54321
+        self.argv = [__file__, 'zzzzz.arvadosapi.com', 'testvm2.shell']

commit 110f03773d2f1187f173c2615b583969b3baef6e
Author: Tom Clegg <tom at curoverse.com>
Date:   Tue Aug 11 10:32:49 2015 -0400

    6934: Split module

diff --git a/sdk/pam/arvados_pam/__init__.py b/sdk/pam/arvados_pam/__init__.py
index 1ec6a3a..087ea2e 100644
--- a/sdk/pam/arvados_pam/__init__.py
+++ b/sdk/pam/arvados_pam/__init__.py
@@ -1,96 +1,7 @@
 import sys
 sys.argv=['']
 
-import arvados
-import os
-import syslog
-
-def auth_log(msg):
-    """Log an authentication result to syslogd"""
-    syslog.openlog(facility=syslog.LOG_AUTH)
-    syslog.syslog('arvados_pam: ' + msg)
-    syslog.closelog()
-
-class AuthEvent(object):
-    def __init__(self, config, service, client_host, username, token):
-        self.config = config
-        self.service = service
-        self.client_host = client_host
-        self.username = username
-        self.token = token
-
-        self.api_host = None
-        self.vm_uuid = None
-        self.user = None
-
-    def can_login(self):
-        """Return truthy IFF credentials should be accepted."""
-        ok = False
-        try:
-            self.api_host = self.config['arvados_api_host']
-            self.arv = arvados.api('v1', host=self.api_host, token=self.token,
-                                   insecure=self.config.get('insecure'),
-                                   cache=False)
-
-            vmname = self.config['virtual_machine_hostname']
-            vms = self.arv.virtual_machines().list(filters=[['hostname','=',vmname]]).execute()
-            if vms['items_available'] > 1:
-                raise Exception("lookup hostname %s returned %d records" % (vmname, vms['items_available']))
-            if vms['items_available'] == 0:
-                raise Exception("lookup hostname %s not found" % vmname)
-            vm = vms['items'][0]
-            if vm['hostname'] != vmname:
-                raise Exception("lookup hostname %s returned hostname %s" % (vmname, vm['hostname']))
-            self.vm_uuid = vm['uuid']
-
-            self.user = self.arv.users().current().execute()
-
-            filters = [
-                ['link_class','=','permission'],
-                ['name','=','can_login'],
-                ['head_uuid','=',self.vm_uuid],
-                ['tail_uuid','=',self.user['uuid']]]
-            for l in self.arv.links().list(filters=filters, limit=10000).execute()['items']:
-                if (l['properties']['username'] == self.username and
-                    l['tail_uuid'] == self.user['uuid'] and
-                    l['head_uuid'] == self.vm_uuid and
-                    l['link_class'] == 'permission' and
-                    l['name'] == 'can_login'):
-                    return self._report(True)
-
-            return self._report(False)
-
-        except Exception as e:
-            return self._report(e)
-
-    def _report(self, result):
-        """Log the result. Return truthy IFF result is True.
-
-        result must be True, False, or an exception.
-        """
-        self.result = result
-        auth_log(self.message())
-        return result == True
-
-    def message(self):
-        """Return a log message describing the event and its outcome."""
-        if isinstance(self.result, Exception):
-            outcome = 'Error: ' + repr(self.result)
-        elif self.result == True:
-            outcome = 'Allow'
-        else:
-            outcome = 'Deny'
-
-        if len(self.token) > 40:
-            log_token = self.token[0:15]
-        else:
-            log_token = '<invalid>'
-
-        log_label = [self.service, self.api_host, self.vm_uuid, self.client_host, self.username, log_token]
-        if self.user:
-            log_label += [self.user.get('uuid'), self.user.get('full_name')]
-        return str(log_label) + ': ' + outcome
-
+from . import auth_event
 
 def pam_sm_authenticate(pamh, flags, argv):
     config = {}
@@ -114,11 +25,12 @@ def pam_sm_authenticate(pamh, flags, argv):
     except pamh.exception as e:
         return e.pam_result
 
-    if AuthEvent(config,
-                 service=pamh.service,
-                 client_host=pamh.rhost,
-                 username=username,
-                 token=token).can_login():
+    if auth_event.AuthEvent(
+            config=config,
+            service=pamh.service,
+            client_host=pamh.rhost,
+            username=username,
+            token=token).can_login():
         return pamh.PAM_SUCCESS
     else:
         return pamh.PAM_AUTH_ERR
diff --git a/sdk/pam/arvados_pam/__init__.py b/sdk/pam/arvados_pam/auth_event.py
similarity index 71%
copy from sdk/pam/arvados_pam/__init__.py
copy to sdk/pam/arvados_pam/auth_event.py
index 1ec6a3a..8abd9c5 100644
--- a/sdk/pam/arvados_pam/__init__.py
+++ b/sdk/pam/arvados_pam/auth_event.py
@@ -1,8 +1,4 @@
-import sys
-sys.argv=['']
-
 import arvados
-import os
 import syslog
 
 def auth_log(msg):
@@ -29,7 +25,7 @@ class AuthEvent(object):
         try:
             self.api_host = self.config['arvados_api_host']
             self.arv = arvados.api('v1', host=self.api_host, token=self.token,
-                                   insecure=self.config.get('insecure'),
+                                   insecure=self.config.get('insecure', False),
                                    cache=False)
 
             vmname = self.config['virtual_machine_hostname']
@@ -90,50 +86,3 @@ class AuthEvent(object):
         if self.user:
             log_label += [self.user.get('uuid'), self.user.get('full_name')]
         return str(log_label) + ': ' + outcome
-
-
-def pam_sm_authenticate(pamh, flags, argv):
-    config = {}
-    config['arvados_api_host'] = argv[1]
-    config['virtual_machine_hostname'] = argv[2]
-    if len(argv) > 3:
-        for k in argv[3:]:
-            config[k] = True
-
-    try:
-        username = pamh.get_user(None)
-    except pamh.exception, e:
-        return e.pam_result
-
-    if not username:
-        return pamh.PAM_USER_UNKNOWN
-
-    try:
-        prompt = '' if config.get('noprompt') else 'Arvados API token: '
-        token = pamh.conversation(pamh.Message(pamh.PAM_PROMPT_ECHO_OFF, prompt)).resp
-    except pamh.exception as e:
-        return e.pam_result
-
-    if AuthEvent(config,
-                 service=pamh.service,
-                 client_host=pamh.rhost,
-                 username=username,
-                 token=token).can_login():
-        return pamh.PAM_SUCCESS
-    else:
-        return pamh.PAM_AUTH_ERR
-
-def pam_sm_setcred(pamh, flags, argv):
-    return pamh.PAM_SUCCESS
-
-def pam_sm_acct_mgmt(pamh, flags, argv):
-    return pamh.PAM_SUCCESS
-
-def pam_sm_open_session(pamh, flags, argv):
-    return pamh.PAM_SUCCESS
-
-def pam_sm_close_session(pamh, flags, argv):
-    return pamh.PAM_SUCCESS
-
-def pam_sm_chauthtok(pamh, flags, argv):
-    return pamh.PAM_SUCCESS
diff --git a/sdk/pam/tests/mocker.py b/sdk/pam/tests/mocker.py
new file mode 100644
index 0000000..76c1ea3
--- /dev/null
+++ b/sdk/pam/tests/mocker.py
@@ -0,0 +1,59 @@
+import mock
+import unittest
+
+class Mocker(unittest.TestCase):
+    ACTIVE_TOKEN = '3kg6k6lzmp9kj5cpkcoxie963cmvjahbt2fod9zru30k1jqdmi'
+
+    default_config = {
+        'arvados_api_host': 'zzzzz.api_host.example',
+        'virtual_machine_hostname': 'testvm2.shell',
+    }
+    default_request = {
+        'client_host': '::1',
+        'token': ACTIVE_TOKEN,
+        'username': 'active',
+    }
+    default_response = {
+        'links': {
+            'items': [{
+                'uuid': 'zzzzz-o0j2j-rah2ya1ohx9xaev',
+                'tail_uuid': 'zzzzz-tpzed-xurymjxw79nv3jz',
+                'head_uuid': 'zzzzz-2x53u-382brsig8rp3065',
+                'link_class': 'permission',
+                'name': 'can_login',
+                'properties': {
+                    'username': 'active',
+                },
+            }],
+        },
+        'users': {
+            'uuid': 'zzzzz-tpzed-xurymjxw79nv3jz',
+            'full_name': 'Active User',
+        },
+        'virtual_machines': {
+            'items': [{
+                'uuid': 'zzzzz-2x53u-382brsig8rp3065',
+                'hostname': 'testvm2.shell',
+            }],
+            'items_available': 1,
+        },
+    }
+
+    def setUp(self):
+        self.config = self.default_config.copy()
+        self.request = self.default_request.copy()
+        self.response = self.default_response.copy()
+        self.api_client = mock.MagicMock(name='api_client')
+        self.api_client.users().current().execute.side_effect = lambda: self.response['users']
+        self.api_client.virtual_machines().list().execute.side_effect = lambda: self.response['virtual_machines']
+        self.api_client.links().list().execute.side_effect = lambda: self.response['links']
+        patcher = mock.patch('arvados.api')
+        self.api = patcher.start()
+        self.addCleanup(patcher.stop)
+        self.api.side_effect = [self.api_client]
+
+        self.syslogged = []
+        patcher = mock.patch('syslog.syslog')
+        self.syslog = patcher.start()
+        self.addCleanup(patcher.stop)
+        self.syslog.side_effect = lambda s: self.syslogged.append(s)
diff --git a/sdk/pam/tests/test_pam.py b/sdk/pam/tests/test_auth_event.py
similarity index 57%
rename from sdk/pam/tests/test_pam.py
rename to sdk/pam/tests/test_auth_event.py
index c9c0c36..3fb6d74 100644
--- a/sdk/pam/tests/test_pam.py
+++ b/sdk/pam/tests/test_auth_event.py
@@ -1,51 +1,10 @@
-import arvados
 import arvados_pam
-import mock
-import os
 import re
-import StringIO
-import unittest
-
-ACTIVE_TOKEN = '3kg6k6lzmp9kj5cpkcoxie963cmvjahbt2fod9zru30k1jqdmi'
-
-class AuthTest(unittest.TestCase):
-    default_config = {
-        'ARVADOS_API_HOST': 'zzzzz.api_host.example',
-        'virtual_machine_hostname': 'testvm2.shell',
-    }
-    default_request = {
-        'client_host': '::1',
-        'token': ACTIVE_TOKEN,
-        'username': 'active',
-    }
-    default_response = {
-        'links': {
-            'items': [{
-                'uuid': 'zzzzz-o0j2j-rah2ya1ohx9xaev',
-                'tail_uuid': 'zzzzz-tpzed-xurymjxw79nv3jz',
-                'head_uuid': 'zzzzz-2x53u-382brsig8rp3065',
-                'link_class': 'permission',
-                'name': 'can_login',
-                'properties': {
-                    'username': 'active',
-                },
-            }],
-        },
-        'users': {
-            'uuid': 'zzzzz-tpzed-xurymjxw79nv3jz',
-            'full_name': 'Active User',
-        },
-        'virtual_machines': {
-            'items': [{
-                'uuid': 'zzzzz-2x53u-382brsig8rp3065',
-                'hostname': 'testvm2.shell',
-            }],
-            'items_available': 1,
-        },
-    }
+from . import mocker
 
+class AuthEventTest(mocker.Mocker):
     def attempt(self):
-        return arvados_pam.AuthEvent(config=self.config, service='test_service', **self.request).can_login()
+        return arvados_pam.auth_event.AuthEvent(config=self.config, service='test_service', **self.request).can_login()
 
     def test_success(self):
         self.assertTrue(self.attempt())
@@ -53,11 +12,14 @@ class AuthTest(unittest.TestCase):
         self.api_client.virtual_machines().list.assert_called_with(
             filters=[['hostname','=',self.config['virtual_machine_hostname']]])
         self.api.assert_called_with(
-            'v1', host=self.config['ARVADOS_API_HOST'], token=self.request['token'], cache=None)
+            'v1',
+            host=self.config['arvados_api_host'], token=self.request['token'],
+            insecure=False,
+            cache=False)
         self.assertEqual(1, len(self.syslogged))
         for i in ['test_service',
                   self.request['username'],
-                  self.config['ARVADOS_API_HOST'],
+                  self.config['arvados_api_host'],
                   self.response['virtual_machines']['items'][0]['uuid']]:
             self.assertRegexpMatches(self.syslogged[0], re.escape(i))
         self.assertRegexpMatches(self.syslogged[0], re.escape(self.request['token'][0:15]), 'token prefix not logged')
@@ -131,22 +93,3 @@ class AuthTest(unittest.TestCase):
             }],
         }
         self.assertFalse(self.attempt())
-
-    def setUp(self):
-        self.config = self.default_config.copy()
-        self.request = self.default_request.copy()
-        self.response = self.default_response.copy()
-        self.api_client = mock.MagicMock(name='api_client')
-        self.api_client.users().current().execute.side_effect = lambda: self.response['users']
-        self.api_client.virtual_machines().list().execute.side_effect = lambda: self.response['virtual_machines']
-        self.api_client.links().list().execute.side_effect = lambda: self.response['links']
-        patcher = mock.patch('arvados.api')
-        self.api = patcher.start()
-        self.addCleanup(patcher.stop)
-        self.api.side_effect = [self.api_client]
-
-        self.syslogged = []
-        patcher = mock.patch('syslog.syslog')
-        self.syslog = patcher.start()
-        self.addCleanup(patcher.stop)
-        self.syslog.side_effect = lambda s: self.syslogged.append(s)

-----------------------------------------------------------------------


hooks/post-receive
-- 




More information about the arvados-commits mailing list