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