#!/usr/share/ucs-test/runner python3
## desc: Tests that Domain Admins members are protected by default
## roles:
##  - domaincontroller_master
##  - domaincontroller_backup
## packages:
##  - univention-admingrp-user-passwordreset
## exposure: dangerous

import time

import univention.testing.strings as uts
from univention.testing.ucr import UCSTestConfigRegistry
from univention.testing.udm import UCSTestUDM
from univention.testing.utils import fail

default_password = 'univention'


class Account:
	def __init__(self, description, dn, name, password=default_password):
		self.description = description
		self.dn = dn
		self.name = name
		self.password = password

	def __str__(self):
		return f'{self.description} "{self.name}"'


with UCSTestConfigRegistry() as ucr:
	with UCSTestUDM() as udm:
		# TODO: Better don't guess DN, use ldapsearch to get DN of "cn=Domain Admins"
		domain_admins_dn = "cn=Domain Admins,cn=groups,%(ldap/base)s" % ucr
		user_password_admins_dn = "cn=User Password Admins,cn=groups,%(ldap/base)s" % ucr

		# create user
		try:
			what = 'Plain user'
			user_dn, user_name = udm.create_user()
			plain_user = Account(what, user_dn, user_name)
		except Exception as exc:
			fail(f'Creating {what} failed: {exc}')
		else:
			print(f'Created {plain_user}')

		# create helpdesk user
		try:
			what = 'Helpdesk user'
			helpdesk_user_dn, helpdesk_user_name = udm.create_user()
			helpdesk_user = Account(what, helpdesk_user_dn, helpdesk_user_name)
		except Exception as exc:
			fail(f'Creating {what} failed: {exc}')
		else:
			print(f'Created {helpdesk_user}')

		# Create domainadmin1
		try:
			what = 'Domain Admin 1'
			domainadmin1_dn, domainadmin1_name = udm.create_user()
			domainadmin1 = Account(what, domainadmin1_dn, domainadmin1_name)
		except Exception as exc:
			fail(f'Creating {what} failed: {exc}')
		else:
			print(f'Created {domainadmin1}')

		# Make domainadmin1 a group member of "Domain Admins"
		try:
			udm.modify_object("users/user", dn=domainadmin1.dn, set={
				'groups': [domain_admins_dn]
			})
		except Exception as exc:
			fail(f'Could not add {domainadmin1} to the group "Domain Admins": {exc}')
		else:
			print(f'Added {domainadmin1} to the group "Domain Admins"')

		# Create domainadmin2
		try:
			what = 'Domain Admin 2'
			domainadmin2_dn, domainadmin2_name = udm.create_user()
			domainadmin2 = Account(what, domainadmin2_dn, domainadmin2_name)
		except Exception as exc:
			fail(f'Creating {what} failed: {exc}')
		else:
			print(f'Created {domainadmin2}')

		# Make domainadmin2 a *primary* member of group "Domain Admins"
		try:
			udm.modify_object("users/user", dn=domainadmin2.dn, set={
				'primaryGroup': [domain_admins_dn]
			})
		except Exception as exc:
			fail(f'Cannot set the  primary group of {domainadmin2} to "Domain Admins": {exc}')
		else:
			print(f'Primary group of {domainadmin2} set to "Domain Admins"')

		# Set group of helpdesk user to User Password Admins
		try:
			udm.modify_object("users/user", dn=helpdesk_user.dn, set={
				"groups": user_password_admins_dn
			})
		except Exception as exc:
			fail(f'Could not add {helpdesk_user} to group "User Password Admins": {exc}')
		else:
			print(f'OK: Added {helpdesk_user} to group "User Password Admins"')

		# It takes a lot of time for this change to take effect unfortunately.. and it seems to take longer and longer ..
		time.sleep(60)

		# Test if Helpdesk user can reset password of admin
		try:
			udm.modify_object('users/user', binddn=helpdesk_user.dn, bindpwd=helpdesk_user.password, dn=domainadmin1.dn, set={
				'password': uts.random_string()
			})
		except Exception:
			print(f'OK: {helpdesk_user} cannot reset password of {domainadmin1}, as expected')
		else:
			fail(f'{helpdesk_user} reset password of {domainadmin1}, but should not be able to')

		# Test if Helpdesk user can reset password of admin2
		try:
			udm.modify_object('users/user', binddn=helpdesk_user.dn, bindpwd=helpdesk_user.password, dn=domainadmin2.dn, set={
				'password': uts.random_string()
			})
		except Exception:
			print(f'OK: {helpdesk_user} cannot reset password of {domainadmin2}')
		else:
			fail(f'{helpdesk_user} reset password of {domainadmin2}, but should not be able to')

		# Test if Helpdesk user can reset password of user
		try:
			udm.modify_object('users/user', binddn=helpdesk_user.dn, bindpwd=helpdesk_user.password, dn=plain_user.dn, set={
				'password': uts.random_string()
			})
		except Exception as exc:
			fail(f'{helpdesk_user} cannot reset password of {plain_user}: {exc}')
		else:
			print(f'OK: {helpdesk_user} reset password of {plain_user}')

# vim: set ft=python ts=4 noexpandtab :
