示例#1
0
    def test_sync_group_without_moderators(self, mock_add_or_update):
        """Test the synchronisation of the group without active mods."""
        mock_client = mock.MagicMock()
        test_group = mkGroup(test_group_1)
        mock_client.allgroups.modified[1].get.return_value = (200,
                                                              [test_group_1])
        mock_client.vo[test_group.vsc_id].get.side_effect = HTTPError(
            None, 404, 'not found', None, None)

        mock_add_or_update.return_value = UPDATED

        ldapsyncer = LdapSyncer(mock_client)
        groups = ldapsyncer.sync_altered_groups(1)
        self.assertEqual(groups, {
            'error': set([]),
            'new': set([]),
            'updated': set([test_group.vsc_id])
        })

        ldap_attrs = {
            'status': ['inactive'],
            'cn': 'gtestgroup',
            'institute': ['gent'],
            'memberUid': ['vsc40075'],
            'moderator': ['vsc40003'],
            'gidNumber': ['2640011'],
        }
        mock_add_or_update.assert_called_with(VscLdapGroup, test_group.vsc_id,
                                              ldap_attrs, True)
示例#2
0
    def test_sync_altered_groups(self, mock_add_or_update):
        """Test the sync_altered accounts function"""
        mock_client = mock.MagicMock()
        test_group = mkGroup(test_vo_1)
        mock_client.allgroups.modified[1].get.return_value = (200, [test_vo_1])
        mock_client.vo[test_group.vsc_id].get.return_value = (200, test_vo_1)

        mock_add_or_update.return_value = UPDATED
        ldapsyncer = LdapSyncer(mock_client)
        groups = ldapsyncer.sync_altered_groups(1)
        self.assertEqual(groups, {'error': set([]), 'new': set([]), 'updated': set([test_group.vsc_id])})

        ldap_attrs = {'status': ['active'], 'scratchDirectory': ['/user/scratch/gent/gvo000/gvo00003'],
                      'dataDirectory': ['/user/data/gent/gvo000/gvo00003'], 'cn': 'gvo00003', 'institute': ['gent'],
                      'memberUid': ['vsc40075'], 'moderator': ['vsc40075'], 'gidNumber': ['2640010'],
                      'fairshare': ['100'], 'description': ['VO']}
        mock_add_or_update.assert_called_with(VscLdapGroup, test_group.vsc_id, ldap_attrs, True)

        #  raise a 404 error on getting the VO to trigger a non vo group add instead of a vo add as above
        test_group = mkGroup(test_usergroup_1)
        mock_client.allgroups.modified[1].get.return_value = (200, [test_usergroup_1])
        mock_client.vo[test_group.vsc_id].get.side_effect = HTTPError("mock_url", 404, "Not Found", "mock_headers", None)
        groups = ldapsyncer.sync_altered_groups(1)
        self.assertEqual(groups, {'error': set([]), 'new': set([]), 'updated': set([test_group.vsc_id])})
        ldap_attrs =  {'status': ['active'], 'cn': 'vsc40075', 'institute': ['gent'], 'memberUid': ['vsc40075'],
                       'moderator': ['vsc40075'], 'gidNumber': ['2540075']}
        mock_add_or_update.assert_called_with(VscLdapGroup, test_group.vsc_id, ldap_attrs, True)
示例#3
0
    def test_sync_altered_accounts_unicode_pubkey(self, mock_add_or_update):
        """Test the sync_altered accounts function with a pubkey containing unicode"""
        mock_client = mock.MagicMock()
        test_account = mkVscAccount(test_account_1)
        mock_client.account[test_account.vsc_id] = mock.MagicMock()
        mock_client.account.modified[1].get.return_value = (200,
                                                            [test_account_1])
        mock_client.account[test_account.vsc_id].usergroup.get.return_value = (
            200, test_usergroup_1)
        mock_client.get_public_keys.return_value = [
            mkVscAccountPubkey(p) for p in test_unicode_pubkeys
        ]
        mock_client.account[test_account.vsc_id].quota.get.return_value = (
            200, test_quota)

        mock_add_or_update.return_value = UPDATED
        ldapsyncer = LdapSyncer(mock_client)
        accounts = ldapsyncer.sync_altered_accounts(1)
        self.assertEqual(
            accounts, {
                'error': set([]),
                'new': set([]),
                'updated': set([test_account.vsc_id])
            })
        if is_py2():
            expected_key = 'some pubkey \\[email protected]\\u201d'
        else:
            expected_key = 'some pubkey \\xe2\\x80\\[email protected]\\xe2\\x80\\x9d'
        ldap_attrs = {
            'status': ['active'],
            'scratchDirectory': ['/user/scratch/gent/vsc400/vsc40075'],
            'dataDirectory': ['/user/data/gent/vsc400/vsc40075'],
            'cn': 'vsc40075',
            'homeQuota': ['5242880'],
            'institute': ['gent'],
            'loginShell': ['/bin/bash'],
            'uidNumber': ['2540075'],
            'researchField': ['Bollocks'],
            'gidNumber': ['2540075'],
            'gecos': ['Foo Bar'],
            'dataQuota': ['1'],
            'homeDirectory': ['/user/home/gent/vsc400/vsc40075'],
            'mail': ['*****@*****.**'],
            'scratchQuota': ['1'],
            'pubkey': [expected_key],
            'instituteLogin': ['foobar'],
            'uid': ['vsc40075']
        }
        mock_add_or_update.assert_called_with(VscLdapUser, test_account.vsc_id,
                                              ldap_attrs, True)
示例#4
0
    def test_sync_forceinactive_account(self, mock_add_or_update):
        """Test the sync_altered accounts function"""
        mock_client = mock.MagicMock()
        test_account = mkVscAccount(test_account_4)
        mock_client.account[test_account.vsc_id] = mock.MagicMock()
        mock_client.account.modified[1].get.return_value = (200, [test_account_4])
        mock_client.account[test_account.vsc_id].usergroup.get.return_value = (200, test_usergroup_1)
        mock_client.get_public_keys.return_value = [mkVscAccountPubkey(p) for p in test_pubkeys_1]
        mock_client.account[test_account.vsc_id].quota.get.return_value = (200, test_quota)

        mock_add_or_update.return_value = UPDATED
        ldapsyncer = LdapSyncer(mock_client)
        accounts = ldapsyncer.sync_altered_accounts(1)
        self.assertEqual(accounts, {'error': set([]), 'new': set([]), 'updated': set([test_account.vsc_id])})
        ldap_attrs = {'status': ['inactive'], 'scratchDirectory': ['/scratch/brussel/vsc100/vsc10001'], 'dataDirectory': ['/data/brussel/vsc100/vsc10001'], 'cn': 'vsc10004', 'homeQuota': ['5242880'], 'institute': ['brussel'], 'loginShell': ['/bin/bash'], 'uidNumber': ['2510004'], 'researchField': ['Dinges'], 'gidNumber': ['2540075'], 'gecos': ['Foo Bar'], 'dataQuota': ['1'], 'homeDirectory': ['/user/brussel/vsc100/vsc10001'], 'mail': ['*****@*****.**'], 'scratchQuota': ['1'], 'pubkey': ['pubkey1', 'pubkey2'], 'instituteLogin': ['fooby'], 'uid': ['vsc10004']}
        mock_add_or_update.assert_called_with(VscLdapUser, test_account.vsc_id, ldap_attrs, True)
def main():

    options = {
        'nagios-check-interval-threshold':
        NAGIOS_CHECK_INTERVAL_THRESHOLD,
        'start-timestamp':
        ("The timestamp form which to start, otherwise use the cached value",
         None, "store", None),
        'access_token':
        ('OAuth2 token identifying the user with the accountpage', None,
         'store', None),
        'account_page_url': ('url for the account page', None, 'store', None),
        'start_timestamp':
        ('Timestamp to start the sync from', str, 'store', None),
    }
    # get access_token from conf file
    ExtendedSimpleOption.CONFIGFILES_INIT = ['/etc/account_page.conf']
    opts = ExtendedSimpleOption(options)
    stats = {}

    # Creating this here because this is a singleton class
    _ = LdapQuery(VscConfiguration(VSC_CONF_DEFAULT_FILENAME))

    (last_timestamp, start_time) = retrieve_timestamp_with_default(
        SYNC_TIMESTAMP_FILENAME, start_timestamp=opts.options.start_timestamp)
    logging.info("Using timestamp %s", last_timestamp)
    logging.info("Using startime %s", start_time)

    try:
        parent_pid = os.fork()
        logging.info("Forked.")
    except OSError:
        logging.exception("Could not fork")
        parent_pid = 1
    except Exception:
        logging.exception("Oops")
        parent_pid = 1

    if parent_pid == 0:
        try:
            global logger
            logger = fancylogger.getLogger(NAGIOS_HEADER)
            # drop privileges in the child
            try:
                apache_uid = pwd.getpwnam('apache').pw_uid
                apache_gid = grp.getgrnam('apache').gr_gid

                os.setgroups([])
                os.setgid(apache_gid)
                os.setuid(apache_uid)

                logging.info("Now running as %s" % (os.geteuid(), ))
            except OSError:
                logger.raiseException("Could not drop privileges")

            client = AccountpageClient(token=opts.options.access_token,
                                       url=opts.options.account_page_url +
                                       '/api/')
            syncer = LdapSyncer(client)
            last = last_timestamp
            altered_accounts = syncer.sync_altered_accounts(
                last, opts.options.dry_run)

            logging.debug("Altered accounts: %s", altered_accounts)

            altered_groups = syncer.sync_altered_groups(
                last, opts.options.dry_run)

            logging.debug("Altered groups: %s" % altered_groups)

            if not altered_accounts[ERROR] \
                    and not altered_groups[ERROR]:
                logging.info("Child process exiting correctly")
                sys.exit(0)
            else:
                logging.info("Child process exiting with status -1")
                logging.warning("Error occured in %s" % ([
                    "%s: %s\n" % (k, v) for (k, v) in [
                        ("altered accounts", altered_accounts[ERROR]),
                        ("altered groups", altered_groups[ERROR]),
                    ]
                ]))
                sys.exit(-1)
        except Exception:
            logging.exception("Child caught an exception")
            sys.exit(-1)

    else:
        # parent
        (_, result) = os.waitpid(parent_pid, 0)
        logging.info("Child exited with exit code %d" % (result, ))

        if not result and not opts.options.dry_run:
            (_, ldap_timestamp) = convert_timestamp(start_time)
            write_timestamp(SYNC_TIMESTAMP_FILENAME, ldap_timestamp)
            opts.epilogue("Synchronised LDAP users to the Django DB", stats)
        else:
            sys.exit(NAGIOS_EXIT_CRITICAL)
def main():

    options = {
        'nagios-check-interval-threshold':
        NAGIOS_CHECK_INTERVAL_THRESHOLD,
        'start-timestamp':
        ("The timestamp form which to start, otherwise use the cached value",
         None, "store", None),
        'access_token':
        ('OAuth2 token identifying the user with the accountpage', None,
         'store', None),
        'account_page_url': ('url for the account page', None, 'store', None),
    }
    # get access_token from conf file
    ExtendedSimpleOption.CONFIGFILES_INIT = ['/etc/account_page.conf']
    opts = ExtendedSimpleOption(options)
    stats = {}

    # Creating this here because this is a singleton class
    _ = LdapQuery(VscConfiguration(VSC_CONF_DEFAULT_FILENAME))

    last_timestamp = opts.options.start_timestamp
    if not last_timestamp:
        try:
            last_timestamp = read_timestamp(SYNC_TIMESTAMP_FILENAME)
        except Exception:
            _log.warning("Something broke reading the timestamp from %s",
                         SYNC_TIMESTAMP_FILENAME)
            last_timestamp = "201710230000Z"
            _log.warning(
                "We will resync from a hardcoded know working sync a while back : %s",
                last_timestamp)

    _log.info("Using timestamp %s", last_timestamp)
    # record starttime before starting, and take a 10 sec safety buffer so we don't get gaps where users are approved
    # in between the requesting of modified users and writing out the start time
    start_time = datetime.datetime.now() + datetime.timedelta(seconds=-10)
    _log.info("startime %s", start_time)

    try:
        parent_pid = os.fork()
        _log.info("Forked.")
    except OSError:
        _log.exception("Could not fork")
        parent_pid = 1
    except Exception:
        _log.exception("Oops")
        parent_pid = 1

    if parent_pid == 0:
        try:
            global _log
            _log = fancylogger.getLogger(NAGIOS_HEADER)
            # drop privileges in the child
            try:
                apache_uid = pwd.getpwnam('apache').pw_uid
                apache_gid = grp.getgrnam('apache').gr_gid

                os.setgroups([])
                os.setgid(apache_gid)
                os.setuid(apache_uid)

                _log.info("Now running as %s" % (os.geteuid(), ))
            except OSError:
                _log.raiseException("Could not drop privileges")

            client = AccountpageClient(token=opts.options.access_token,
                                       url=opts.options.account_page_url +
                                       '/api/')
            syncer = LdapSyncer(client)
            last = int(
                (datetime.datetime.strptime(last_timestamp, "%Y%m%d%H%M%SZ") -
                 datetime.datetime(1970, 1, 1)).total_seconds())
            altered_accounts = syncer.sync_altered_accounts(
                last, opts.options.dry_run)

            _log.debug("Altered accounts: %s", altered_accounts)

            altered_groups = syncer.sync_altered_groups(
                last, opts.options.dry_run)

            _log.debug("Altered groups: %s" % altered_groups)

            if not altered_accounts[ERROR] \
                    and not altered_groups[ERROR]:
                _log.info("Child process exiting correctly")
                sys.exit(0)
            else:
                _log.info("Child process exiting with status -1")
                _log.warning("Error occured in %s" % ([
                    "%s: %s\n" % (k, v) for (k, v) in [
                        ("altered accounts", altered_accounts[ERROR]),
                        ("altered groups", altered_groups[ERROR]),
                    ]
                ]))
                sys.exit(-1)
        except Exception:
            _log.exception("Child caught an exception")
            sys.exit(-1)

    else:
        # parent
        (_, result) = os.waitpid(parent_pid, 0)
        _log.info("Child exited with exit code %d" % (result, ))

        if not result:
            if not opts.options.start_timestamp:
                (_, ldap_timestamp) = convert_timestamp(start_time)
                if not opts.options.dry_run:
                    write_timestamp(SYNC_TIMESTAMP_FILENAME, ldap_timestamp)
            else:
                _log.info(
                    "Not updating the timestamp, since one was provided on the command line"
                )
            opts.epilogue("Synchronised LDAP users to the Django DB", stats)
        else:
            _log.info(
                "Not updating the timestamp, since it was given on the command line for this run"
            )
            sys.exit(NAGIOS_EXIT_CRITICAL)