def explicit_audit(args): ''' Perform an LDAP audit. Find all users, evaluate how well they match to profiles, and generate a report. ''' configs = config.Config(args.config) ldap_user, ldap_password = ldap_creds(configs) prof = args.profile_dir + '/%s' % args.profile prof = profile.Profile(prof) if args.environment: env = configs.environments.pop(args.environment) ldap_conn = LDAP.LDAP(env, user=ldap_user, password=ldap_password, basedn=configs.basedn) else: ldap_conn = LDAP.LDAP.from_config(configs).next() if args.users: users = args.users else: users = [i for i in ldap_conn.get_all_uids()] audits = defaultdict(list) for user in users: usearch = ldap_conn.user_search(user) the_audit = (prof .audit(usearch, explicit=True, ignore_inherited=args.ignore)) if the_audit['value'] != 3: continue key = the_audit.pop('name') audits[key].append(the_audit) if args.html: print profile.audits2html(audits) else: print yaml.dump(audits, default_flow_style=False)
def test_primary_gid_number(self): ''' Test primary_gid_number property ''' prof = profile.Profile(self.prof_file) # attributes are strings because LDAP self.assertEquals(str(PROFILE['primary-gid-number']), prof.primary_gid_number)
def test_constructor_with_wrong_arg(self): ''' Test that the constructor succeeds with an argument of the correct type but doesn't exist ''' # pylint: disable=no-value-for-parameter with self.assertRaises(IOError): prof = profile.Profile( os.path.join(self.temp_profiles, 'nonexistent.yaml')) prof.run()
def test_bulk_audit_ignore_inherit(self): ''' Test that the bulk_audit class method returns returns different results when ignore_inherited is set to True vs False This assumes there are nested groups in the LDAP directory! ''' prof = profile.Profile(self.prof_file) inherit_audit = profile.Profile.bulk_audit(TEST_USER, profiles=[prof]) no_inherit_audit = profile.Profile.bulk_audit(TEST_USER, profiles=[prof], ignore_inherited=True) self.assertFalse(inherit_audit == no_inherit_audit)
def profile_dumper(args): ''' Dump profiles to stdout. ''' if args.single: profiles = ([profile.Profile(os.path.join(args.profile_dir, args.single))]) else: profiles = [i for i in profile.Profile.from_directory(args.profile_dir)] for prof in profiles: print 'Profile "%s"' % prof.name print prof
def test_bulk_audit_explicit(self): ''' Test that the bulk_audit class method returns returns different results when explicit is set to True vs False Requires a user with disjoint memberships with respect to the profile! ''' prof = profile.Profile(self.prof_file) audit = profile.Profile.bulk_audit(DISJOINT_USER, profiles=[prof]) explicit_audit = profile.Profile.bulk_audit(DISJOINT_USER, profiles=[prof], ignore_inherited=True) self.assertFalse(audit == explicit_audit)
def userenable(args): """ Enable a user; move user out of purgatory at a minimum. """ configs = config.Config(args.config) ldap_user, ldap_password = ldap_creds(configs) prof = args.profile_dir + '/%s' % args.profile prof = profile.Profile(prof) host = configs.environments.pop(args.environment) origin_ldap = LDAP.LDAP(host, user=ldap_user, password=ldap_password, basedn=configs.basedn) user_obj = origin_ldap.get_user(args.user) if not user_obj: raise RuntimeError('%s not found. Please contact PLOPS.' % args.user) origin_ldap.move_user(args.user, LDAP.USERS) user = origin_ldap.user_search(args.user) diff = prof.audit(user, explicit=True, ignore_inherited=True) if not 'profile match' in diff['text'].lower(): print 'Permissions to be changed via "%s" profile:' % prof.name if isinstance(diff['diff'], list): print diff['text'] print yaml.dump(diff['diff'], default_flow_style=False) origin_ldap.enforce_profile(args.user, prof, args.jira) user_obj = origin_ldap.get_user(args.user, LDAP.USERS) for _, host in configs.environments.items(): next_ldap = LDAP.LDAP(host, user=ldap_user, password=ldap_password, basedn=configs.basedn) next_user_obj = next_ldap.get_user(args.user) if not next_user_obj: next_ldap.add_object(user_obj, ignore_attrs=['dn']) modded_user = next_ldap.user_search(args.user) if not modded_user: raise RuntimeError('Adding user object to tree %s failed. \ Please contact PLOPS.' % next_ldap.host) print yaml.dump(modded_user, default_flow_style=False) return next_ldap.move_user(args.user, LDAP.USERS) next_user = next_ldap.user_search(args.user) diff = prof.audit(next_user, explicit=True, ignore_inherited=True) if not 'profile match' in diff['text'].lower(): print 'Permissions to be changed via "%s" profile:' % prof.name if isinstance(diff['diff'], list): print diff['text'] print yaml.dump(diff['diff'], default_flow_style=False) next_ldap.enforce_profile(args.user, prof, args.jira) modded_user = next_ldap.user_search(args.user) if modded_user: print yaml.dump(modded_user, default_flow_style=False)
def useradjust(args): """ Give a user a new profile on all environments """ configs = config.Config(args.config) ldap_user, ldap_password = ldap_creds(configs) prof = args.profile_dir + '/%s' % args.profile prof = profile.Profile(prof) env = configs.environments.pop(args.environment) origin_ldap = LDAP.LDAP(env, user=ldap_user, password=ldap_password, basedn=configs.basedn) user_obj = origin_ldap.get_user(args.user, LDAP.USERS) user = origin_ldap.user_search(args.user) diff = prof.audit(user, explicit=True, ignore_inherited=True) if not 'profile match' in diff['text'].lower(): print 'Permissions to be changed via "%s" profile:' % prof.name if isinstance(diff['diff'], list): print diff['text'] print yaml.dump(diff['diff'], default_flow_style=False) origin_ldap.enforce_profile(args.user, prof) for _, host in configs.environments.items(): next_ldap = LDAP.LDAP(host, user=ldap_user, password=ldap_password, basedn=configs.basedn) next_user = next_ldap.user_search(args.user) if not next_user.found: print ('User %s not found on %s. Full dict: "%s"' % (args.user, next_ldap.host, next_user)) try: next_ldap.add_object(user_obj, ignore_attrs=['dn']) # pylint: disable=no-member except LDAP.ldap.ALREADY_EXISTS: # definitely exists print ('User %s already exists on %s but is also "not found"???' % (args.user, next_ldap.host)) next_user = next_ldap.user_search(args.user) diff = prof.audit(next_user, explicit=True, ignore_inherited=True) if not 'profile match' in diff['text'].lower(): print 'Permissions to be changed via "%s" profile:' % prof.name if isinstance(diff['diff'], list): print diff['text'] print yaml.dump(diff['diff'], default_flow_style=False) next_ldap.enforce_profile(args.user, prof)
def test_getitem(self): ''' Test __getitem__ method ''' prof = profile.Profile(self.prof_file) self.assertEquals(PROFILE['owner'], prof['owner'])
def test_keys(self): ''' Test keys method ''' prof = profile.Profile(self.prof_file) self.assertEquals(sorted(PROFILE.keys()), sorted(prof.keys()))
def test_values(self): ''' Test values method ''' prof = profile.Profile(self.prof_file) self.assertEquals(sorted(PROFILE.values()), sorted(prof.values()))
def test_group_of_unique_names(self): ''' Test group_of_unique_names property ''' prof = profile.Profile(self.prof_file) self.assertEquals(PROFILE['group-of-unique-names'], prof.group_of_unique_names)
def test_samba_group_mapping(self): ''' Test amba_group_mapping property ''' prof = profile.Profile(self.prof_file) self.assertEquals(PROFILE['samba-group-mapping'], prof.samba_group_mapping)
def test_constructor(self): ''' Test that the constructor fails without an argument ''' # pylint: disable=no-value-for-parameter with self.assertRaises(TypeError): profile.Profile()
def test_posix_group(self): ''' Test posix_group property ''' prof = profile.Profile(self.prof_file) self.assertEquals(PROFILE['posix-group'], prof.posix_group)
def test_samba_group_sid(self): ''' Test samba_group_sid property ''' prof = profile.Profile(self.prof_file) self.assertEquals(str(PROFILE['samba-group-sid']), prof.samba_group_sid)
def test_name(self): ''' Test name property ''' prof = profile.Profile(self.prof_file) self.assertEquals(PROF_FILE, prof.name)
def test_constructor_with_arg(self): ''' Test the constructor to create a Profile object with an argument ''' self.assertTrue( isinstance(profile.Profile(self.prof_file), profile.Profile))
def test_constructor_with_bad_arg(self): ''' Test the constructor to fail when given an incorrect argument ''' with self.assertRaises(AttributeError): profile.Profile(1)
def test_bulk_audit_profiles(self): ''' Test bulk_audit class method with the profiles keyword ''' prof = profile.Profile(self.prof_file) audit = profile.Profile.bulk_audit(TEST_USER, profiles=[prof]) self.assertTrue(isinstance(audit, collections.OrderedDict))