1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-23 17:34:34 +03:00
samba-mirror/wintest/test-s4-howto.py
Andrew Bartlett a565eff969 wintest Allow 'samba-tool newuser' to run a few times waiting for the RID Set
Pair-Programmed-With: Andrew Tridgell <tridge@samba.org>
2010-12-01 16:09:59 +11:00

868 lines
34 KiB
Python
Executable File
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python
'''automated testing of the steps of the Samba4 HOWTO'''
import sys, os
import optparse
import wintest, pexpect
def check_prerequesites(t):
t.info("Checking prerequesites")
t.setvar('HOSTNAME', t.cmd_output("hostname -s").strip())
if os.getuid() != 0:
raise Exception("You must run this script as root")
t.putenv("KRB5_CONFIG", '${PREFIX}/private/krb5.conf')
t.run_cmd('ifconfig ${INTERFACE} ${INTERFACE_NET} up')
if t.getvar('INTERFACE_IPV6'):
t.run_cmd('ifconfig ${INTERFACE} inet6 del ${INTERFACE_IPV6}/64', checkfail=False)
t.run_cmd('ifconfig ${INTERFACE} inet6 add ${INTERFACE_IPV6}/64 up')
def build_s4(t):
'''build samba4'''
t.info('Building s4')
t.chdir('${SOURCETREE}/source4')
t.putenv('CC', 'ccache gcc')
t.run_cmd('make reconfigure || ./configure --enable-auto-reconfigure --enable-developer --prefix=${PREFIX} -C')
t.run_cmd('make -j')
t.run_cmd('rm -rf ${PREFIX}')
t.run_cmd('make -j install')
def provision_s4(t, func_level="2008"):
'''provision s4 as a DC'''
t.info('Provisioning s4')
t.chdir('${PREFIX}')
t.del_files(["var", "private"])
t.run_cmd("rm -f etc/smb.conf")
provision=['sbin/provision',
'--realm=${LCREALM}',
'--domain=${DOMAIN}',
'--adminpass=${PASSWORD1}',
'--server-role=domain controller',
'--function-level=%s' % func_level,
'-d${DEBUGLEVEL}',
'--option=interfaces=${INTERFACE}',
'--host-ip=${INTERFACE_IP}',
'--option=bind interfaces only=yes',
'--option=rndc command=${RNDC} -c${PREFIX}/etc/rndc.conf']
if t.getvar('INTERFACE_IPV6'):
provision.append('--host-ip6=${INTERFACE_IPV6}')
t.run_cmd(provision)
t.run_cmd('bin/samba-tool newuser testallowed ${PASSWORD1}')
t.run_cmd('bin/samba-tool newuser testdenied ${PASSWORD1}')
t.run_cmd('bin/samba-tool group addmembers "Allowed RODC Password Replication Group" testallowed')
def start_s4(t):
'''startup samba4'''
t.info('Starting Samba4')
t.chdir("${PREFIX}")
t.run_cmd('killall -9 -q samba smbd nmbd winbindd', checkfail=False)
t.run_cmd(['sbin/samba',
'--option', 'panic action=gnome-terminal -e "gdb --pid %PID%"'])
t.port_wait("${INTERFACE_IP}", 139)
def stop_vms(t):
'''Shut down any existing alive VMs, so they don't collide with what we are doing'''
t.info('Shutting down any of our VMs already running')
vms = t.get_vms()
for v in vms:
t.vm_poweroff(v, checkfail=False)
def test_smbclient(t):
'''test smbclient'''
t.info('Testing smbclient')
t.chdir('${PREFIX}')
t.cmd_contains("bin/smbclient --version", ["Version 4.0"])
t.retry_cmd('bin/smbclient -L ${INTERFACE_IP} -U%', ["netlogon", "sysvol", "IPC Service"])
child = t.pexpect_spawn('bin/smbclient //${INTERFACE_IP}/netlogon -Uadministrator%${PASSWORD1}')
child.expect("smb:")
child.sendline("dir")
child.expect("blocks available")
child.sendline("mkdir testdir")
child.expect("smb:")
child.sendline("cd testdir")
child.expect('testdir')
child.sendline("cd ..")
child.sendline("rmdir testdir")
def create_shares(t):
'''create some test shares'''
t.info("Adding test shares")
t.chdir('${PREFIX}')
t.write_file("etc/smb.conf", '''
[test]
path = ${PREFIX}/test
read only = no
[profiles]
path = ${PREFIX}/var/profiles
read only = no
''',
mode='a')
t.run_cmd("mkdir -p test")
t.run_cmd("mkdir -p var/profiles")
def set_nameserver(t, nameserver):
'''set the nameserver in resolv.conf'''
t.write_file("/etc/resolv.conf.wintest", '''
# Generated by wintest, the Samba v Windows automated testing system
nameserver %s
# your original resolv.conf appears below:
''' % t.substitute(nameserver))
child = t.pexpect_spawn("cat /etc/resolv.conf", crlf=False)
i = child.expect(['your original resolv.conf appears below:', pexpect.EOF])
if i == 0:
child.expect(pexpect.EOF)
contents = child.before.lstrip().replace('\r', '')
t.write_file('/etc/resolv.conf.wintest', contents, mode='a')
t.write_file('/etc/resolv.conf.wintest-bak', contents)
t.run_cmd("mv -f /etc/resolv.conf.wintest /etc/resolv.conf")
t.resolv_conf_backup = '/etc/resolv.conf.wintest-bak';
def restore_resolv_conf(t):
'''restore the /etc/resolv.conf after testing is complete'''
if getattr(t, 'resolv_conf_backup', False):
t.info("restoring /etc/resolv.conf")
t.run_cmd("mv -f %s /etc/resolv.conf" % t.resolv_conf_backup)
def rndc_cmd(t, cmd, checkfail=True):
'''run a rndc command'''
t.run_cmd("${RNDC} -c ${PREFIX}/etc/rndc.conf %s" % cmd, checkfail=checkfail)
def restart_bind(t):
'''restart the test environment version of bind'''
t.info("Restarting bind9")
t.putenv('KEYTAB_FILE', '${PREFIX}/private/dns.keytab')
t.putenv('KRB5_KTNAME', '${PREFIX}/private/dns.keytab')
t.chdir('${PREFIX}')
t.run_cmd("mkdir -p var/named/data")
t.run_cmd("chown -R ${BIND_USER} var/named")
nameserver = t.get_nameserver()
if nameserver == t.getvar('INTERFACE_IP'):
raise RuntimeError("old /etc/resolv.conf must not contain %s as a nameserver, this will create loops with the generated dns configuration" % nameserver)
t.setvar('DNSSERVER', nameserver)
if t.getvar('INTERFACE_IPV6'):
ipv6_listen = 'listen-on-v6 port 53 { ${INTERFACE_IPV6}; };'
else:
ipv6_listen = ''
t.setvar('BIND_LISTEN_IPV6', ipv6_listen)
t.write_file("etc/named.conf", '''
options {
listen-on port 53 { ${INTERFACE_IP}; };
${BIND_LISTEN_IPV6}
directory "${PREFIX}/var/named";
dump-file "${PREFIX}/var/named/data/cache_dump.db";
pid-file "${PREFIX}/var/named/named.pid";
statistics-file "${PREFIX}/var/named/data/named_stats.txt";
memstatistics-file "${PREFIX}/var/named/data/named_mem_stats.txt";
allow-query { any; };
recursion yes;
tkey-gssapi-credential "DNS/${HOSTNAME}.${LCREALM}";
tkey-domain "${REALM}";
max-cache-ttl 10;
max-ncache-ttl 10;
forward only;
forwarders {
${DNSSERVER};
};
};
key "rndc-key" {
algorithm hmac-md5;
secret "lA/cTrno03mt5Ju17ybEYw==";
};
controls {
inet ${INTERFACE_IP} port 953
allow { any; } keys { "rndc-key"; };
};
include "${PREFIX}/private/named.conf";
''')
# add forwarding for the windows domains
domains = t.get_domains()
for d in domains:
t.write_file('etc/named.conf',
'''
zone "%s" IN {
type forward;
forward only;
forwarders {
%s;
};
};
''' % (d, domains[d]),
mode='a')
t.write_file("etc/rndc.conf", '''
# Start of rndc.conf
key "rndc-key" {
algorithm hmac-md5;
secret "lA/cTrno03mt5Ju17ybEYw==";
};
options {
default-key "rndc-key";
default-server ${INTERFACE_IP};
default-port 953;
};
''')
set_nameserver(t, t.getvar('INTERFACE_IP'))
rndc_cmd(t, "stop", checkfail=False)
t.port_wait("${INTERFACE_IP}", 53, wait_for_fail=True)
t.bind_child = t.run_child("${BIND9} -u ${BIND_USER} -n 1 -c ${PREFIX}/etc/named.conf -g")
t.port_wait("${INTERFACE_IP}", 53)
rndc_cmd(t, "flush")
def test_dns(t):
'''test that DNS is OK'''
t.info("Testing DNS")
t.cmd_contains("host -t SRV _ldap._tcp.${LCREALM}.",
['_ldap._tcp.${LCREALM} has SRV record 0 100 389 ${HOSTNAME}.${LCREALM}'])
t.cmd_contains("host -t SRV _kerberos._udp.${LCREALM}.",
['_kerberos._udp.${LCREALM} has SRV record 0 100 88 ${HOSTNAME}.${LCREALM}'])
t.cmd_contains("host -t A ${HOSTNAME}.${LCREALM}",
['${HOSTNAME}.${LCREALM} has address'])
def test_kerberos(t):
'''test that kerberos is OK'''
t.info("Testing kerberos")
t.run_cmd("kdestroy")
t.kinit("administrator@${REALM}", "${PASSWORD1}")
# this copes with the differences between MIT and Heimdal klist
t.cmd_contains("klist", ["rincipal", "administrator@${REALM}"])
def test_dyndns(t):
'''test that dynamic DNS is working'''
t.chdir('${PREFIX}')
t.run_cmd("sbin/samba_dnsupdate --fail-immediately")
rndc_cmd(t, "flush")
def run_winjoin(t, vm):
'''join a windows box to our domain'''
t.setwinvars(vm)
t.info("Joining a windows box to the domain")
t.vm_poweroff("${WIN_VM}", checkfail=False)
t.vm_restore("${WIN_VM}", "${WIN_SNAPSHOT}")
child = t.open_telnet("${WIN_HOSTNAME}", "${WIN_USER}", "${WIN_PASS}", set_time=True, set_ip=True)
child.sendline("netdom join ${WIN_HOSTNAME} /Domain:${LCREALM} /PasswordD:${PASSWORD1} /UserD:administrator")
child.expect("The command completed successfully")
child.expect("C:")
child.sendline("shutdown /r -t 0")
t.wait_reboot()
child = t.open_telnet("${WIN_HOSTNAME}", "${WIN_USER}", "${WIN_PASS}", set_time=True, set_ip=True)
child.sendline("ipconfig /registerdns")
child.expect("Registration of the DNS resource records for all adapters of this computer has been initiated. Any errors will be reported in the Event Viewer")
child.expect("C:")
def test_winjoin(t, vm):
t.info("Checking the windows join is OK")
t.chdir('${PREFIX}')
t.port_wait("${WIN_IP}", 139)
t.retry_cmd('bin/smbclient -L ${WIN_HOSTNAME}.${LCREALM} -Uadministrator@${LCREALM}%${PASSWORD1}', ["C$", "IPC$", "Sharename"], retries=100)
t.cmd_contains("host -t A ${WIN_HOSTNAME}.${LCREALM}.", ['has address'])
t.cmd_contains('bin/smbclient -L ${WIN_HOSTNAME}.${LCREALM} -Utestallowed@${LCREALM}%${PASSWORD1}', ["C$", "IPC$", "Sharename"])
t.cmd_contains('bin/smbclient -L ${WIN_HOSTNAME}.${LCREALM} -k no -Utestallowed@${LCREALM}%${PASSWORD1}', ["C$", "IPC$", "Sharename"])
t.cmd_contains('bin/smbclient -L ${WIN_HOSTNAME}.${LCREALM} -k yes -Utestallowed@${LCREALM}%${PASSWORD1}', ["C$", "IPC$", "Sharename"])
child = t.open_telnet("${WIN_HOSTNAME}", "${DOMAIN}\\administrator", "${PASSWORD1}")
child.sendline("net use t: \\\\${HOSTNAME}.${LCREALM}\\test")
child.expect("The command completed successfully")
t.vm_poweroff("${WIN_VM}")
def run_dcpromo(t, vm):
'''run a dcpromo on windows'''
t.setwinvars(vm)
t.info("Joining a windows VM ${WIN_VM} to the domain as a DC using dcpromo")
t.vm_poweroff("${WIN_VM}", checkfail=False)
t.vm_restore("${WIN_VM}", "${WIN_SNAPSHOT}")
child = t.open_telnet("${WIN_HOSTNAME}", "administrator", "${WIN_PASS}", set_ip=True)
child.sendline("copy /Y con answers.txt")
child.sendline('''
[DCINSTALL]
RebootOnSuccess=Yes
RebootOnCompletion=Yes
ReplicaOrNewDomain=Replica
ReplicaDomainDNSName=${LCREALM}
SiteName=Default-First-Site-Name
InstallDNS=No
ConfirmGc=Yes
CreateDNSDelegation=No
UserDomain=${LCREALM}
UserName=${LCREALM}\\administrator
Password=${PASSWORD1}
DatabasePath="C:\Windows\NTDS"
LogPath="C:\Windows\NTDS"
SYSVOLPath="C:\Windows\SYSVOL"
SafeModeAdminPassword=${PASSWORD1}

''')
child.expect("copied.")
child.expect("C:")
child.expect("C:")
child.sendline("dcpromo /answer:answers.txt")
i = child.expect(["You must restart this computer", "failed", "Active Directory Domain Services was not installed", "C:"], timeout=120)
if i == 1 or i == 2:
raise Exception("dcpromo failed")
t.wait_reboot()
def test_dcpromo(t, vm):
'''test that dcpromo worked'''
t.info("Checking the dcpromo join is OK")
t.chdir('${PREFIX}')
t.port_wait("${WIN_IP}", 139)
t.retry_cmd("host -t A ${WIN_HOSTNAME}.${LCREALM}. ${INTERFACE_IP}",
['${WIN_HOSTNAME}.${LCREALM} has address'],
retries=30, delay=10, casefold=True)
t.retry_cmd('bin/smbclient -L ${WIN_HOSTNAME}.${LCREALM} -Uadministrator@${LCREALM}%${PASSWORD1}', ["C$", "IPC$", "Sharename"])
t.cmd_contains("host -t A ${WIN_HOSTNAME}.${LCREALM}.", ['has address'])
t.cmd_contains('bin/smbclient -L ${WIN_HOSTNAME}.${LCREALM} -Utestallowed@${LCREALM}%${PASSWORD1}', ["C$", "IPC$", "Sharename"])
t.cmd_contains("bin/samba-tool drs kcc ${HOSTNAME}.${LCREALM} -Uadministrator@${LCREALM}%${PASSWORD1}", ['Consistency check', 'successful'])
t.retry_cmd("bin/samba-tool drs kcc ${WIN_HOSTNAME}.${LCREALM} -Uadministrator@${LCREALM}%${PASSWORD1}", ['Consistency check', 'successful'])
t.kinit("administrator@${REALM}", "${PASSWORD1}")
# the first replication will transfer the dnsHostname attribute
t.cmd_contains("bin/samba-tool drs replicate ${HOSTNAME}.${LCREALM} ${WIN_HOSTNAME} CN=Configuration,${BASEDN} -k yes", ["was successful"])
for nc in [ '${BASEDN}', 'CN=Configuration,${BASEDN}', 'CN=Schema,CN=Configuration,${BASEDN}' ]:
t.cmd_contains("bin/samba-tool drs replicate ${HOSTNAME}.${LCREALM} ${WIN_HOSTNAME}.${LCREALM} %s -k yes" % nc, ["was successful"])
t.cmd_contains("bin/samba-tool drs replicate ${WIN_HOSTNAME}.${LCREALM} ${HOSTNAME}.${LCREALM} %s -k yes" % nc, ["was successful"])
t.cmd_contains("bin/samba-tool drs showrepl ${HOSTNAME}.${LCREALM} -k yes",
[ "INBOUND NEIGHBORS",
"${BASEDN}",
"Last attempt .* was successful",
"CN=Configuration,${BASEDN}",
"Last attempt .* was successful",
"CN=Configuration,${BASEDN}", # cope with either order
"Last attempt .* was successful",
"OUTBOUND NEIGHBORS",
"${BASEDN}",
"Last success",
"CN=Configuration,${BASEDN}",
"Last success",
"CN=Configuration,${BASEDN}",
"Last success"],
ordered=True,
regex=True)
t.cmd_contains("bin/samba-tool drs showrepl ${WIN_HOSTNAME}.${LCREALM} -k yes",
[ "INBOUND NEIGHBORS",
"${BASEDN}",
"Last attempt .* was successful",
"CN=Configuration,${BASEDN}",
"Last attempt .* was successful",
"CN=Configuration,${BASEDN}",
"Last attempt .* was successful",
"OUTBOUND NEIGHBORS",
"${BASEDN}",
"Last success",
"CN=Configuration,${BASEDN}",
"Last success",
"CN=Configuration,${BASEDN}",
"Last success" ],
ordered=True,
regex=True)
child = t.open_telnet("${WIN_HOSTNAME}", "${DOMAIN}\\administrator", "${PASSWORD1}", set_time=True)
child.sendline("net use t: \\\\${HOSTNAME}.${LCREALM}\\test")
child.expect("The command completed successfully")
t.run_net_time(child)
t.info("Checking if showrepl is happy")
child.sendline("repadmin /showrepl")
child.expect("${BASEDN}")
child.expect("was successful")
child.expect("CN=Configuration,${BASEDN}")
child.expect("was successful")
child.expect("CN=Schema,CN=Configuration,${BASEDN}")
child.expect("was successful")
t.info("Checking if new users propogate to windows")
t.retry_cmd('bin/samba-tool newuser test2 ${PASSWORD2}', ["created successfully"])
t.retry_cmd("bin/smbclient -L ${WIN_HOSTNAME}.${LCREALM} -Utest2%${PASSWORD2} -k no", ['Sharename', 'Remote IPC'])
t.retry_cmd("bin/smbclient -L ${WIN_HOSTNAME}.${LCREALM} -Utest2%${PASSWORD2} -k yes", ['Sharename', 'Remote IPC'])
t.info("Checking if new users on windows propogate to samba")
child.sendline("net user test3 ${PASSWORD3} /add")
while True:
i = child.expect(["The command completed successfully",
"The directory service was unable to allocate a relative identifier"])
if i == 0:
break
time.sleep(2)
t.retry_cmd("bin/smbclient -L ${HOSTNAME}.${LCREALM} -Utest3%${PASSWORD3} -k no", ['Sharename', 'IPC'])
t.retry_cmd("bin/smbclient -L ${HOSTNAME}.${LCREALM} -Utest3%${PASSWORD3} -k yes", ['Sharename', 'IPC'])
t.info("Checking propogation of user deletion")
t.run_cmd('bin/samba-tool user delete test2 -Uadministrator@${LCREALM}%${PASSWORD1}')
child.sendline("net user test3 /del")
child.expect("The command completed successfully")
t.retry_cmd("bin/smbclient -L ${WIN_HOSTNAME}.${LCREALM} -Utest2%${PASSWORD2} -k no", ['LOGON_FAILURE'])
t.retry_cmd("bin/smbclient -L ${HOSTNAME}.${LCREALM} -Utest3%${PASSWORD3} -k no", ['LOGON_FAILURE'])
t.retry_cmd("bin/smbclient -L ${WIN_HOSTNAME}.${LCREALM} -Utest2%${PASSWORD2} -k yes", ['LOGON_FAILURE'])
t.retry_cmd("bin/smbclient -L ${HOSTNAME}.${LCREALM} -Utest3%${PASSWORD3} -k yes", ['LOGON_FAILURE'])
t.vm_poweroff("${WIN_VM}")
def run_dcpromo_rodc(t, vm):
'''run a RODC dcpromo to join a windows DC to the samba domain'''
t.setwinvars(vm)
t.info("Joining a w2k8 box to the domain as a RODC")
t.vm_poweroff("${WIN_VM}", checkfail=False)
t.vm_restore("${WIN_VM}", "${WIN_SNAPSHOT}")
child = t.open_telnet("${WIN_HOSTNAME}", "administrator", "${WIN_PASS}", set_ip=True)
child.sendline("copy /Y con answers.txt")
child.sendline('''
[DCInstall]
ReplicaOrNewDomain=ReadOnlyReplica
ReplicaDomainDNSName=${LCREALM}
PasswordReplicationDenied="BUILTIN\Administrators"
PasswordReplicationDenied="BUILTIN\Server Operators"
PasswordReplicationDenied="BUILTIN\Backup Operators"
PasswordReplicationDenied="BUILTIN\Account Operators"
PasswordReplicationDenied="${DOMAIN}\Denied RODC Password Replication Group"
PasswordReplicationAllowed="${DOMAIN}\Allowed RODC Password Replication Group"
DelegatedAdmin="${DOMAIN}\\Administrator"
SiteName=Default-First-Site-Name
InstallDNS=No
ConfirmGc=Yes
CreateDNSDelegation=No
UserDomain=${LCREALM}
UserName=${LCREALM}\\administrator
Password=${PASSWORD1}
DatabasePath="C:\Windows\NTDS"
LogPath="C:\Windows\NTDS"
SYSVOLPath="C:\Windows\SYSVOL"
SafeModeAdminPassword=${PASSWORD1}
RebootOnCompletion=No

''')
child.expect("copied.")
child.sendline("dcpromo /answer:answers.txt")
i = child.expect(["You must restart this computer", "failed"], timeout=120)
if i != 0:
raise Exception("dcpromo failed")
child.sendline("shutdown -r -t 0")
t.wait_reboot()
def test_dcpromo_rodc(t, vm):
'''test the RODC dcpromo worked'''
t.info("Checking the w2k8 RODC join is OK")
t.chdir('${PREFIX}')
t.port_wait("${WIN_IP}", 139)
t.retry_cmd('bin/smbclient -L ${WIN_HOSTNAME}.${LCREALM} -Uadministrator@${LCREALM}%${PASSWORD1}', ["C$", "IPC$", "Sharename"])
t.cmd_contains("host -t A ${WIN_HOSTNAME}.${LCREALM}.", ['has address'])
t.cmd_contains('bin/smbclient -L ${WIN_HOSTNAME}.${LCREALM} -Utestallowed@${LCREALM}%${PASSWORD1}', ["C$", "IPC$", "Sharename"])
child = t.open_telnet("${WIN_HOSTNAME}", "${DOMAIN}\\administrator", "${PASSWORD1}", set_time=True)
child.sendline("net use t: \\\\${HOSTNAME}.${LCREALM}\\test")
child.expect("The command completed successfully")
t.info("Checking if showrepl is happy")
child.sendline("repadmin /showrepl")
child.expect("${BASEDN}")
child.expect("was successful")
child.expect("CN=Configuration,${BASEDN}")
child.expect("was successful")
child.expect("CN=Configuration,${BASEDN}")
child.expect("was successful")
t.info("Checking if new users are available on windows")
t.run_cmd('bin/samba-tool newuser test2 ${PASSWORD2}')
t.retry_cmd("bin/smbclient -L ${WIN_HOSTNAME}.${LCREALM} -Utest2%${PASSWORD2} -k yes", ['Sharename', 'Remote IPC'])
t.retry_cmd("bin/smbclient -L ${WIN_HOSTNAME}.${LCREALM} -Utest2%${PASSWORD2} -k no", ['LOGON_FAILURE'])
t.retry_cmd("bin/samba-tool drs replicate ${WIN_HOSTNAME}.${LCREALM} ${HOSTNAME}.${LCREALM} ${BASEDN} -k yes", ["was successful"])
t.retry_cmd("bin/smbclient -L ${WIN_HOSTNAME}.${LCREALM} -Utest2%${PASSWORD2} -k no", ['Sharename', 'Remote IPC'])
t.run_cmd('bin/samba-tool user delete test2 -Uadministrator@${LCREALM}%${PASSWORD1}')
t.retry_cmd("bin/smbclient -L ${WIN_HOSTNAME}.${LCREALM} -Utest2%${PASSWORD2} -k yes", ['LOGON_FAILURE'])
t.retry_cmd("bin/smbclient -L ${WIN_HOSTNAME}.${LCREALM} -Utest2%${PASSWORD2} -k no", ['LOGON_FAILURE'])
t.vm_poweroff("${WIN_VM}")
def prep_join_as_dc(t, vm):
'''start VM and shutdown Samba in preperation to join a windows domain as a DC'''
t.setwinvars(vm)
t.info("Starting VMs for joining ${WIN_VM} as a second DC using samba-tool join DC")
t.chdir('${PREFIX}')
t.run_cmd('killall -9 -q samba smbd nmbd winbindd', checkfail=False)
t.vm_poweroff("${WIN_VM}", checkfail=False)
t.vm_restore("${WIN_VM}", "${WIN_SNAPSHOT}")
rndc_cmd(t, 'flush')
t.run_cmd("rm -rf etc/smb.conf private")
child = t.open_telnet("${WIN_HOSTNAME}", "${WIN_DOMAIN}\\administrator", "${WIN_PASS}", set_time=True)
t.get_ipconfig(child)
def join_as_dc(t, vm):
'''join a windows domain as a DC'''
t.setwinvars(vm)
t.info("Joining ${WIN_VM} as a second DC using samba-tool join DC")
t.retry_cmd("bin/samba-tool drs showrepl ${WIN_HOSTNAME}.${WIN_REALM} -Uadministrator%${WIN_PASS}", ['INBOUND NEIGHBORS'] )
t.run_cmd('bin/samba-tool join ${WIN_REALM} DC -Uadministrator%${WIN_PASS} -d${DEBUGLEVEL} --option=interfaces=${INTERFACE}')
t.run_cmd('bin/samba-tool drs kcc ${WIN_HOSTNAME}.${WIN_REALM} -Uadministrator@${WIN_REALM}%${WIN_PASS}')
def test_join_as_dc(t, vm):
'''test the join of a windows domain as a DC'''
t.info("Checking the DC join is OK")
t.chdir('${PREFIX}')
t.retry_cmd('bin/smbclient -L ${HOSTNAME}.${WIN_REALM} -Uadministrator@${WIN_REALM}%${WIN_PASS}', ["C$", "IPC$", "Sharename"])
t.cmd_contains("host -t A ${HOSTNAME}.${WIN_REALM}.", ['has address'])
child = t.open_telnet("${WIN_HOSTNAME}", "${WIN_DOMAIN}\\administrator", "${WIN_PASS}", set_time=True)
t.info("Forcing kcc runs, and replication")
t.run_cmd('bin/samba-tool drs kcc ${WIN_HOSTNAME}.${WIN_REALM} -Uadministrator@${WIN_REALM}%${WIN_PASS}')
t.run_cmd('bin/samba-tool drs kcc ${HOSTNAME}.${WIN_REALM} -Uadministrator@${WIN_REALM}%${WIN_PASS}')
t.kinit("administrator@${WIN_REALM}", "${WIN_PASS}")
for nc in [ '${WIN_BASEDN}', 'CN=Configuration,${WIN_BASEDN}', 'CN=Schema,CN=Configuration,${WIN_BASEDN}' ]:
t.cmd_contains("bin/samba-tool drs replicate ${HOSTNAME}.${WIN_REALM} ${WIN_HOSTNAME}.${WIN_REALM} %s -k yes" % nc, ["was successful"])
t.cmd_contains("bin/samba-tool drs replicate ${WIN_HOSTNAME}.${WIN_REALM} ${HOSTNAME}.${WIN_REALM} %s -k yes" % nc, ["was successful"])
child.sendline("net use t: \\\\${HOSTNAME}.${WIN_REALM}\\test")
child.expect("The command completed successfully")
t.info("Checking if showrepl is happy")
child.sendline("repadmin /showrepl")
child.expect("${WIN_BASEDN}")
child.expect("was successful")
child.expect("CN=Configuration,${WIN_BASEDN}")
child.expect("was successful")
child.expect("CN=Configuration,${WIN_BASEDN}")
child.expect("was successful")
t.info("Checking if new users propogate to windows")
t.run_cmd('bin/samba-tool newuser test2 ${PASSWORD2}')
t.retry_cmd("bin/smbclient -L ${WIN_HOSTNAME}.${WIN_REALM} -Utest2%${PASSWORD2} -k no", ['Sharename', 'Remote IPC'])
t.retry_cmd("bin/smbclient -L ${WIN_HOSTNAME}.${WIN_REALM} -Utest2%${PASSWORD2} -k yes", ['Sharename', 'Remote IPC'])
t.info("Checking if new users on windows propogate to samba")
child.sendline("net user test3 ${PASSWORD3} /add")
child.expect("The command completed successfully")
t.retry_cmd("bin/smbclient -L ${HOSTNAME}.${WIN_REALM} -Utest3%${PASSWORD3} -k no", ['Sharename', 'IPC'])
t.retry_cmd("bin/smbclient -L ${HOSTNAME}.${WIN_REALM} -Utest3%${PASSWORD3} -k yes", ['Sharename', 'IPC'])
t.info("Checking propogation of user deletion")
t.run_cmd('bin/samba-tool user delete test2 -Uadministrator@${WIN_REALM}%${WIN_PASS}')
child.sendline("net user test3 /del")
child.expect("The command completed successfully")
t.retry_cmd("bin/smbclient -L ${WIN_HOSTNAME}.${WIN_REALM} -Utest2%${PASSWORD2} -k no", ['LOGON_FAILURE'])
t.retry_cmd("bin/smbclient -L ${HOSTNAME}.${WIN_REALM} -Utest3%${PASSWORD3} -k no", ['LOGON_FAILURE'])
t.retry_cmd("bin/smbclient -L ${WIN_HOSTNAME}.${WIN_REALM} -Utest2%${PASSWORD2} -k yes", ['LOGON_FAILURE'])
t.retry_cmd("bin/smbclient -L ${HOSTNAME}.${WIN_REALM} -Utest3%${PASSWORD3} -k yes", ['LOGON_FAILURE'])
t.vm_poweroff("${WIN_VM}")
def join_as_rodc(t, vm):
'''join a windows domain as a RODC'''
t.setwinvars(vm)
t.info("Joining ${WIN_VM} as a RODC using samba-tool join DC")
t.chdir('${PREFIX}')
t.run_cmd('killall -9 -q samba smbd nmbd winbindd', checkfail=False)
t.vm_poweroff("${WIN_VM}", checkfail=False)
t.vm_restore("${WIN_VM}", "${WIN_SNAPSHOT}")
rndc_cmd(t, 'flush')
t.run_cmd("rm -rf etc/smb.conf private")
child = t.open_telnet("${WIN_HOSTNAME}", "${WIN_DOMAIN}\\administrator", "${WIN_PASS}", set_time=True)
t.get_ipconfig(child)
t.retry_cmd("bin/samba-tool drs showrepl ${WIN_HOSTNAME}.${WIN_REALM} -Uadministrator%${WIN_PASS}", ['INBOUND NEIGHBORS'] )
t.run_cmd('bin/samba-tool join ${WIN_REALM} RODC -Uadministrator%${WIN_PASS} -d${DEBUGLEVEL} --option=interfaces=${INTERFACE}')
t.run_cmd('bin/samba-tool drs kcc ${WIN_HOSTNAME}.${WIN_REALM} -Uadministrator@${WIN_REALM}%${WIN_PASS}')
def test_join_as_rodc(t, vm):
'''test a windows domain RODC join'''
t.info("Checking the RODC join is OK")
t.chdir('${PREFIX}')
t.retry_cmd('bin/smbclient -L ${HOSTNAME}.${WIN_REALM} -Uadministrator@${WIN_REALM}%${WIN_PASS}', ["C$", "IPC$", "Sharename"])
t.cmd_contains("host -t A ${HOSTNAME}.${WIN_REALM}.", ['has address'])
child = t.open_telnet("${WIN_HOSTNAME}", "${WIN_DOMAIN}\\administrator", "${WIN_PASS}", set_time=True)
t.info("Forcing kcc runs, and replication")
t.run_cmd('bin/samba-tool drs kcc ${HOSTNAME}.${WIN_REALM} -Uadministrator@${WIN_REALM}%${WIN_PASS}')
t.run_cmd('bin/samba-tool drs kcc ${WIN_HOSTNAME}.${WIN_REALM} -Uadministrator@${WIN_REALM}%${WIN_PASS}')
t.kinit("administrator@${WIN_REALM}", "${WIN_PASS}")
for nc in [ '${WIN_BASEDN}', 'CN=Configuration,${WIN_BASEDN}', 'CN=Schema,CN=Configuration,${WIN_BASEDN}' ]:
t.cmd_contains("bin/samba-tool drs replicate ${HOSTNAME}.${WIN_REALM} ${WIN_HOSTNAME}.${WIN_REALM} %s -k yes" % nc, ["was successful"])
child.sendline("net use t: \\\\${HOSTNAME}.${WIN_REALM}\\test")
child.expect("The command completed successfully")
t.info("Checking if showrepl is happy")
child.sendline("repadmin /showrepl")
child.expect("DSA invocationID")
t.cmd_contains("bin/samba-tool drs showrepl ${WIN_HOSTNAME}.${WIN_REALM} -k yes",
[ "INBOUND NEIGHBORS",
"OUTBOUND NEIGHBORS",
"${WIN_BASEDN}",
"Last attempt .* was successful",
"CN=Configuration,${WIN_BASEDN}",
"Last attempt .* was successful",
"CN=Configuration,${WIN_BASEDN}",
"Last attempt .* was successful" ],
ordered=True,
regex=True)
t.info("Checking if new users on windows propogate to samba")
child.sendline("net user test3 ${PASSWORD3} /add")
child.expect("The command completed successfully")
t.retry_cmd("bin/smbclient -L ${HOSTNAME}.${WIN_REALM} -Utest3%${PASSWORD3} -k no", ['Sharename', 'IPC'])
t.retry_cmd("bin/smbclient -L ${HOSTNAME}.${WIN_REALM} -Utest3%${PASSWORD3} -k yes", ['Sharename', 'IPC'])
# should this work?
t.info("Checking if new users propogate to windows")
t.cmd_contains('bin/samba-tool newuser test2 ${PASSWORD2}', ['No RID Set DN'])
t.info("Checking propogation of user deletion")
child.sendline("net user test3 /del")
child.expect("The command completed successfully")
t.retry_cmd("bin/smbclient -L ${HOSTNAME}.${WIN_REALM} -Utest3%${PASSWORD3} -k no", ['LOGON_FAILURE'])
t.retry_cmd("bin/smbclient -L ${HOSTNAME}.${WIN_REALM} -Utest3%${PASSWORD3} -k yes", ['LOGON_FAILURE'])
t.vm_poweroff("${WIN_VM}")
def run_dcpromo_as_first_dc(t, vm, func_level=None):
t.setwinvars(vm)
t.info("Configuring a windows VM ${WIN_VM} at the first DC in the domain using dcpromo")
child = t.open_telnet("${WIN_HOSTNAME}", "administrator", "${WIN_PASS}", set_time=True)
child.sendline("dcdiag");
if t.get_is_dc(child):
return
if func_level == '2008r2':
t.setvar("FUNCTION_LEVEL_INT", str(4))
elif func_level == '2003':
t.setvar("FUNCTION_LEVEL_INT", str(1))
else:
t.setvar("FUNCTION_LEVEL_INT", str(0))
child = t.open_telnet("${WIN_HOSTNAME}", "administrator", "${WIN_PASS}", set_ip=True)
child.sendline("dcdiag");
"""This server must therefore not yet be a directory server, so we must promote it"""
child.sendline("copy /Y con answers.txt")
child.sendline('''
[DCInstall]
; New forest promotion
ReplicaOrNewDomain=Domain
NewDomain=Forest
NewDomainDNSName=${WIN_REALM}
ForestLevel=${FUNCTION_LEVEL_INT}
DomainNetbiosName=${WIN_DOMAIN}
DomainLevel=${FUNCTION_LEVEL_INT}
InstallDNS=Yes
ConfirmGc=Yes
CreateDNSDelegation=No
DatabasePath="C:\Windows\NTDS"
LogPath="C:\Windows\NTDS"
SYSVOLPath="C:\Windows\SYSVOL"
; Set SafeModeAdminPassword to the correct value prior to using the unattend file
SafeModeAdminPassword=${WIN_PASS}
; Run-time flags (optional)
RebootOnCompletion=No

''')
child.expect("copied.")
child.expect("C:")
child.expect("C:")
child.sendline("dcpromo /answer:answers.txt")
i = child.expect(["You must restart this computer", "failed", "Active Directory Domain Services was not installed", "C:"], timeout=120)
if i == 1 or i == 2:
raise Exception("dcpromo failed")
child.sendline("shutdown -r -t 0")
t.port_wait("${WIN_IP}", 139, wait_for_fail=True)
t.port_wait("${WIN_IP}", 139)
def test_howto(t):
'''test the Samba4 howto'''
check_prerequesites(t)
# we don't need fsync safety in these tests
t.putenv('TDB_NO_FSYNC', '1')
if not t.skip("build"):
build_s4(t)
if not t.skip("provision"):
provision_s4(t)
if not t.skip("create-shares"):
create_shares(t)
if not t.skip("starts4"):
start_s4(t)
if not t.skip("stop_vms"):
stop_vms(t)
if not t.skip("smbclient"):
test_smbclient(t)
if not t.skip("startbind"):
restart_bind(t)
if not t.skip("dns"):
test_dns(t)
if not t.skip("kerberos"):
test_kerberos(t)
if not t.skip("dyndns"):
test_dyndns(t)
if t.have_vm('WINDOWS7') and not t.skip("windows7"):
run_winjoin(t, "WINDOWS7")
test_winjoin(t, "WINDOWS7")
if t.have_vm('WINXP') and not t.skip("winxp"):
run_winjoin(t, "WINXP")
test_winjoin(t, "WINXP")
if t.have_vm('W2K8R2C') and not t.skip("dcpromo_rodc"):
t.info("Testing w2k8r2 RODC dcpromo")
run_dcpromo_rodc(t, "W2K8R2C")
test_dcpromo_rodc(t, "W2K8R2C")
if t.have_vm('W2K8R2B') and not t.skip("dcpromo_w2k8r2"):
t.info("Testing w2k8r2 dcpromo")
run_dcpromo(t, "W2K8R2B")
test_dcpromo(t, "W2K8R2B")
if t.have_vm('W2K8B') and not t.skip("dcpromo_w2k8"):
t.info("Testing w2k8 dcpromo")
run_dcpromo(t, "W2K8B")
test_dcpromo(t, "W2K8B")
if t.have_vm('W2K3B') and not t.skip("dcpromo_w2k3"):
t.info("Testing w2k3 dcpromo")
t.info("Changing to 2003 functional level")
provision_s4(t, func_level='2003')
create_shares(t)
start_s4(t)
test_smbclient(t)
restart_bind(t)
test_dns(t)
test_kerberos(t)
test_dyndns(t)
run_dcpromo(t, "W2K3B")
test_dcpromo(t, "W2K3B")
if t.have_vm('W2K8R2A') and not t.skip("join_w2k8r2"):
prep_join_as_dc(t, "W2K8R2A")
run_dcpromo_as_first_dc(t, "W2K8R2A", func_level='2008r2')
join_as_dc(t, "W2K8R2A")
create_shares(t)
start_s4(t)
test_dyndns(t)
test_join_as_dc(t, "W2K8R2A")
if t.have_vm('W2K8R2A') and not t.skip("join_rodc"):
prep_join_as_rodc(t, "W2K8R2A")
run_dcpromo_as_first_dc(t, "W2K8R2A", func_level='2008r2')
join_as_rodc(t, "W2K8R2A")
create_shares(t)
start_s4(t)
test_dyndns(t)
test_join_as_rodc(t, "W2K8R2A")
if t.have_vm('W2K3A') and not t.skip("join_w2k3"):
prep_join_as_dc(t, "W2K3A")
run_dcpromo_as_first_dc(t, "W2K3A", func_level='2003')
join_as_dc(t, "W2K3A")
create_shares(t)
start_s4(t)
test_dyndns(t)
test_join_as_dc(t, "W2K3A")
t.info("Howto test: All OK")
def test_cleanup(t):
'''cleanup after tests'''
t.info("Cleaning up ...")
restore_resolv_conf(t)
if getattr(t, 'bind_child', False):
t.bind_child.kill()
if __name__ == '__main__':
parser = optparse.OptionParser("test-howto.py")
parser.add_option("--conf", type='string', default='', help='config file')
parser.add_option("--skip", type='string', default='', help='list of steps to skip (comma separated)')
parser.add_option("--vms", type='string', default=None, help='list of VMs to use (comma separated)')
parser.add_option("--list", action='store_true', default=False, help='list the available steps')
parser.add_option("--rebase", action='store_true', default=False, help='do a git pull --rebase')
parser.add_option("--clean", action='store_true', default=False, help='clean the tree')
parser.add_option("--prefix", type='string', default=None, help='override install prefix')
parser.add_option("--sourcetree", type='string', default=None, help='override sourcetree location')
parser.add_option("--nocleanup", action='store_true', default=False, help='disable cleanup code')
opts, args = parser.parse_args()
if not opts.conf:
print("Please specify a config file with --conf")
sys.exit(1)
t = wintest.wintest()
t.load_config(opts.conf)
t.set_skip(opts.skip)
t.set_vms(opts.vms)
if opts.list:
t.list_steps_mode()
if opts.prefix:
t.setvar('PREFIX', opts.prefix)
if opts.sourcetree:
t.setvar('SOURCETREE', opts.sourcetree)
if opts.rebase:
t.info('rebasing')
t.chdir('${SOURCETREE}')
t.run_cmd('git pull --rebase')
if opts.clean:
t.info('rebasing')
t.chdir('${SOURCETREE}/source4')
t.run_cmd('rm -rf bin')
try:
test_howto(t)
except:
if not opts.nocleanup:
test_cleanup(t)
raise
if not opts.nocleanup:
test_cleanup(t)
t.info("S4 howto test: All OK")