[ARVADOS] updated: c249e92657d76221cf3977145a8dfbd79e8f6d9a

git at public.curoverse.com git at public.curoverse.com
Wed Aug 12 12:10:51 EDT 2015


Summary of changes:

  discards  b12d869f304b930374d601a309951bd547394247 (commit)
  discards  3d8b5718dd6e8dbd2ccbd5b940be3c761dcb6bec (commit)
  discards  aa0ead5180147d83fc54e922e78cf76a114b843e (commit)
  discards  48f294f5eb109fbec200ad79b3b525203ad0e873 (commit)
  discards  f95a71310e09803638c6750e6bca285bca2e04d1 (commit)
       via  c249e92657d76221cf3977145a8dfbd79e8f6d9a (commit)
       via  bf23a991e15aa268f98de95e5ebee0564dfb1221 (commit)
       via  4c3860e66b4a4f8108de793ddcfb66b8b5b182aa (commit)
       via  f8daac938f766732ade005aaf8ac239dce1f697f (commit)

This update added new revisions after undoing existing revisions.  That is
to say, the old revision is not a strict subset of the new revision.  This
situation occurs when you --force push a change and generate a repository
containing something like this:

 * -- * -- B -- O -- O -- O (b12d869f304b930374d601a309951bd547394247)
            \
             N -- N -- N (c249e92657d76221cf3977145a8dfbd79e8f6d9a)

When this happens we assume that you've already had alert emails for all
of the O revisions, and so we here report only the revisions in the N
branch from the common base, B.

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 c249e92657d76221cf3977145a8dfbd79e8f6d9a
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 bf23a991e15aa268f98de95e5ebee0564dfb1221
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)

commit 4c3860e66b4a4f8108de793ddcfb66b8b5b182aa
Author: Tom Clegg <tom at curoverse.com>
Date:   Tue Aug 11 02:26:51 2015 -0400

    6934: Put wrapper in /lib/security/ instead of writing dist-packages path in config file. Make integration test work.

diff --git a/sdk/pam/Dockerfile b/sdk/pam/Dockerfile
index c5e83f8..76b08b9 100644
--- a/sdk/pam/Dockerfile
+++ b/sdk/pam/Dockerfile
@@ -1,8 +1,8 @@
 # Manual integration test:
 # 0. python setup.py sdist rotate --keep=1 --match .tar.gz
-# 1. docker build -name arvados:pam_test .
-# 2. docker run -it arvados:pam_test
-# 3. container# edit /etc/pam.d/login  # set api host and shell VM name
+# 1. replace 53015 below with your api server's port number
+# 2. docker build -name arvados:pam_test .
+# 3. docker run -it --add-host zzzzz.arvadosapi.com:"$(hostname -I |awk '{print $1}')" arvados:pam_test
 # 4. container# useradd testusername
 # 5. container# login                  # enter username and token
 
@@ -12,9 +12,28 @@ RUN apt-get -qy dist-upgrade
 RUN apt-get -qy install python python-virtualenv libpam-python rsyslog
 # Packages required by pycurl, ciso8601
 RUN apt-get -qy install libcurl4-gnutls-dev python2.7-dev
+
+# for jessie (which also has other snags)
+# RUN apt-get -qy install python-pip libgnutls28-dev
+
 RUN pip install --upgrade setuptools
 RUN pip install python-pam
 ADD dist /dist
 RUN pip install /dist/arvados-pam-*.tar.gz
+
+# Configure and enable the module (hopefully vendor packages will offer a neater way)
+RUN perl -pi -e 's{api.example}{zzzzz.arvadosapi.com:53015}; s{shell\.example}{testvm2.shell insecure};' /usr/share/pam-configs/arvados
 RUN DEBIAN_FRONTEND=noninteractive pam-auth-update arvados --remove unix
-CMD rsyslogd & tail -F /var/log/auth.log & bash
+
+# Add a user account matching the fixture
+RUN useradd -ms /bin/bash active
+
+# Test with python (SIGSEGV during tests)
+#ADD . /pam
+#WORKDIR /pam
+#CMD rsyslogd & tail -F /var/log/auth.log & python setup.py test
+
+# Test with perl (SIGSEGV when program exits)
+RUN apt-get install -qy libauthen-pam-perl
+ADD tests/integration_test.pl /integration_test.pl
+CMD rsyslogd & tail -F /var/log/auth.log & sleep 1 && /integration_test.pl
diff --git a/sdk/pam/arvados_pam/__init__.py b/sdk/pam/arvados_pam/__init__.py
index 920a364..1ec6a3a 100644
--- a/sdk/pam/arvados_pam/__init__.py
+++ b/sdk/pam/arvados_pam/__init__.py
@@ -28,7 +28,9 @@ class AuthEvent(object):
         ok = False
         try:
             self.api_host = self.config['arvados_api_host']
-            self.arv = arvados.api('v1', host=self.api_host, token=self.token, cache=None)
+            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()
@@ -94,18 +96,20 @@ def pam_sm_authenticate(pamh, flags, argv):
     config = {}
     config['arvados_api_host'] = argv[1]
     config['virtual_machine_hostname'] = argv[2]
-    config['noprompt'] = (len(argv) > 3 and argv[3] == 'noprompt')
+    if len(argv) > 3:
+        for k in argv[3:]:
+            config[k] = True
 
     try:
-        username = pamh.get_user()
-    except pamh.exception as e:
+        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['noprompt'] else 'Arvados API token: '
+        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
diff --git a/sdk/pam/pam-configs/arvados b/sdk/pam/pam-configs/arvados
index 3d245f0..6972a39 100644
--- a/sdk/pam/pam-configs/arvados
+++ b/sdk/pam/pam-configs/arvados
@@ -9,6 +9,6 @@ Default: yes
 Priority: 256
 Auth-Type: Primary
 Auth:
-	[success=end default=ignore]	pam_python.so /usr/local/lib/python2.7/dist-packages/arvados_pam/__init__.py api.example shell.example
+	[success=end default=ignore]	pam_python.so /lib/security/libpam_arvados.py api.example shell.example
 Auth-Initial:
-	[success=end default=ignore]	pam_python.so /usr/local/lib/python2.7/dist-packages/arvados_pam/__init__.py api.example shell.example
+	[success=end default=ignore]	pam_python.so /lib/security/libpam_arvados.py api.example shell.example
diff --git a/sdk/pam/tests/integration_test.pl b/sdk/pam/tests/integration_test.pl
new file mode 100755
index 0000000..e5dff1e
--- /dev/null
+++ b/sdk/pam/tests/integration_test.pl
@@ -0,0 +1,46 @@
+#!/usr/bin/env perl
+
+$ENV{ARVADOS_API_HOST_INSECURE} = 1;
+use Authen::PAM qw(:constants);
+
+for my $case (['good', 1, 'active', '3kg6k6lzmp9kj5cpkcoxie963cmvjahbt2fod9zru30k1jqdmi'],
+              ['badtoken', 0, 'active', 'badtokenmp9kj5cpkcoxie963cmvjahbt2fod9zru30k1jqdmi'],
+              ['badusername', 0, 'baduser', '3kg6k6lzmp9kj5cpkcoxie963cmvjahbt2fod9zru30k1jqdmi']) {
+    dotest(@$case);
+}
+print "=== OK ===\n";
+
+sub dotest {
+    my ($label, $expect_ok, $user, $token) = @_;
+    print "$label: ";
+    my $service_name = 'login';
+    $main::Token = $token;
+    my $pamh = new Authen::PAM($service_name, $user, \&token_conv_func);
+    ref($pamh) || die "Error code $pamh during PAM init!";
+    $pamh->pam_set_item(PAM_RHOST(), '::1');
+    $pamh->pam_set_item(PAM_RUSER(), 'none');
+    $pamh->pam_set_item(PAM_TTY(), '/dev/null');
+    my $flags = PAM_SILENT();
+    $res = $pamh->pam_authenticate($flags);
+    $msg = $pamh->pam_strerror($res);
+    print "Result (code $res): $msg\n";
+    if (($res == 0) != ($expect_ok == 1)) {
+        die "*** FAIL ***\n";
+    }
+}
+
+sub token_conv_func {
+    my @res;
+    while ( @_ ) {
+        my $code = shift;
+        my $msg = shift;
+        my $ans;
+        print "Message (type $code): $msg\n";
+        if ($code == PAM_PROMPT_ECHO_OFF() || $code == PAM_PROMPT_ECHO_ON()) {
+            $ans = $main::Token;
+        }
+        push @res, (0,$ans);
+    }
+    push @res, PAM_SUCCESS();
+    return @res;
+}
diff --git a/sdk/pam/tests/test_integration.py b/sdk/pam/tests/test_integration.py
index 2728bcd..53ef0ea 100644
--- a/sdk/pam/tests/test_integration.py
+++ b/sdk/pam/tests/test_integration.py
@@ -1,8 +1,13 @@
 import os
-if os.path.exists('/etc/pam.d/arvados-pam-test'):
+if os.path.exists('/usr/share/pam-configs/arvados') and os.getuid() == 0:
+    """These tests assume we are running (in a docker container) with
+    arvados_pam configured and a test API server running.
+    """
     import pam
     import unittest
 
+    # From services/api/test/fixtures/api_client_authorizations.yml
+    # because that file is not available during integration tests:
     ACTIVE_TOKEN = '3kg6k6lzmp9kj5cpkcoxie963cmvjahbt2fod9zru30k1jqdmi'
     SPECTATOR_TOKEN = 'zw2f4gwx8hw8cjre7yp6v1zylhrhn3m5gvjq73rtpwhmknrybu'
 
@@ -11,13 +16,13 @@ if os.path.exists('/etc/pam.d/arvados-pam-test'):
             self.p = pam.pam()
 
         def test_allow(self):
-            self.assertTrue(self.p.authenticate('active', ACTIVE_TOKEN, service='arvados-pam-test'))
+            self.assertTrue(self.p.authenticate('active', ACTIVE_TOKEN, service='login'))
 
-        def test_deny_service(self):
-            self.assertFalse(self.p.authenticate('active', ACTIVE_TOKEN, service='login'))
+        def test_deny_bad_token(self):
+            self.assertFalse(self.p.authenticate('active', 'thisisaverybadtoken', service='login'))
 
-        def test_deny_token(self):
-            self.assertFalse(self.p.authenticate('active', 'bogustoken', service='arvados-pam-test'))
+        def test_deny_empty_token(self):
+            self.assertFalse(self.p.authenticate('active', '', service='login'))
 
         def test_deny_permission(self):
-            self.assertFalse(self.p.authenticate('spectator', SPECTATOR_TOKEN, service='arvados-pam-test'))
+            self.assertFalse(self.p.authenticate('spectator', SPECTATOR_TOKEN, service='login'))

commit f8daac938f766732ade005aaf8ac239dce1f697f
Author: Tom Clegg <tom at curoverse.com>
Date:   Mon Aug 10 10:42:17 2015 -0400

    6934: Add packaging instructions

diff --git a/sdk/pam/.dockerignore b/sdk/pam/.dockerignore
index d6778dc..86ec754 100644
--- a/sdk/pam/.dockerignore
+++ b/sdk/pam/.dockerignore
@@ -3,6 +3,4 @@
 .eggs
 *.egg_info
 build
-debian
-dist
 tmp
diff --git a/sdk/pam/Dockerfile b/sdk/pam/Dockerfile
index 7c45607..c5e83f8 100644
--- a/sdk/pam/Dockerfile
+++ b/sdk/pam/Dockerfile
@@ -1,3 +1,11 @@
+# Manual integration test:
+# 0. python setup.py sdist rotate --keep=1 --match .tar.gz
+# 1. docker build -name arvados:pam_test .
+# 2. docker run -it arvados:pam_test
+# 3. container# edit /etc/pam.d/login  # set api host and shell VM name
+# 4. container# useradd testusername
+# 5. container# login                  # enter username and token
+
 FROM debian:wheezy
 RUN apt-get update
 RUN apt-get -qy dist-upgrade
@@ -6,10 +14,7 @@ RUN apt-get -qy install python python-virtualenv libpam-python rsyslog
 RUN apt-get -qy install libcurl4-gnutls-dev python2.7-dev
 RUN pip install --upgrade setuptools
 RUN pip install python-pam
-ADD . /pam
-WORKDIR /pam
-RUN ./setup.py sdist
-RUN pip install dist/arvados-pam-*.tar.gz
-COPY examples/pam-auth-update_arvados /usr/share/pam-configs/arvados
+ADD dist /dist
+RUN pip install /dist/arvados-pam-*.tar.gz
 RUN DEBIAN_FRONTEND=noninteractive pam-auth-update arvados --remove unix
 CMD rsyslogd & tail -F /var/log/auth.log & bash
diff --git a/sdk/pam/MANIFEST.in b/sdk/pam/MANIFEST.in
index 9561fb1..39211b3 100644
--- a/sdk/pam/MANIFEST.in
+++ b/sdk/pam/MANIFEST.in
@@ -1 +1,3 @@
 include README.rst
+include lib/libpam_arvados.py
+include pam-configs/arvados
diff --git a/sdk/pam/fpm-info.sh b/sdk/pam/fpm-info.sh
new file mode 100644
index 0000000..4a81571
--- /dev/null
+++ b/sdk/pam/fpm-info.sh
@@ -0,0 +1,17 @@
+case "$TARGET" in
+    debian* | ubuntu*)
+        fpm_depends+=('libpam-python')
+        ;;
+    *)
+        echo >&2 "ERROR: $PACKAGE: pam_python.so dependency unavailable in $TARGET."
+        return 1
+        ;;
+esac
+
+case "$FORMAT" in
+    deb)
+        fpm_args+=('--deb-recommends=rsyslog')
+        ;;
+esac
+
+fpm_args+=('--config-files=examples/pam-auth-update_arvados')
diff --git a/sdk/pam/lib/libpam_arvados.py b/sdk/pam/lib/libpam_arvados.py
new file mode 100644
index 0000000..deead7e
--- /dev/null
+++ b/sdk/pam/lib/libpam_arvados.py
@@ -0,0 +1 @@
+from arvados_pam import *
diff --git a/sdk/pam/examples/pam-auth-update_arvados b/sdk/pam/pam-configs/arvados
similarity index 59%
rename from sdk/pam/examples/pam-auth-update_arvados
rename to sdk/pam/pam-configs/arvados
index eb58694..3d245f0 100644
--- a/sdk/pam/examples/pam-auth-update_arvados
+++ b/sdk/pam/pam-configs/arvados
@@ -1,5 +1,8 @@
-# 1. Install in /usr/share/pam-configs/arvados
-# 2. Run `pam-auth-update arvados`
+# 1. Change "api.example" to your ARVADOS_API_HOST
+# 2. Change "shell.example" to this host's hostname
+#    (as it appears in the Arvados virtual_machines list)
+# 3. Install in /usr/share/pam-configs/arvados
+# 4. Run `pam-auth-update arvados`
 
 Name: Arvados authentication
 Default: yes
diff --git a/sdk/pam/setup.py b/sdk/pam/setup.py
index f8a0c62..7ab4521 100755
--- a/sdk/pam/setup.py
+++ b/sdk/pam/setup.py
@@ -13,8 +13,7 @@ README = os.path.join(SETUP_DIR, 'README.rst')
 tagger = egg_info_cmd.egg_info
 try:
     import gittaggers
-    if subprocess.check_call(['git', 'log', '-n1']):
-        tagger = gittaggers.EggInfoFromGit
+    tagger = gittaggers.EggInfoFromGit
 except (ImportError, OSError):
     pass
 
@@ -32,6 +31,10 @@ setup(name='arvados-pam',
       ],
       scripts=[
       ],
+      data_files=[
+          ('/usr/share/pam-configs', ['pam-configs/arvados']),
+          ('/lib/security', ['lib/libpam_arvados.py']),
+      ],
       install_requires=[
           'arvados-python-client>=0.1.20150801000000',
       ],
diff --git a/services/nodemanager/bin/arvados-node-manager b/services/nodemanager/bin/arvados-node-manager
old mode 100644
new mode 100755

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


hooks/post-receive
-- 




More information about the arvados-commits mailing list