Created
August 28, 2016 13:15
-
-
Save sebug/2ba53d51cc778034af5dbe146109dbfc to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/local/bin/python | |
from subprocess import call | |
from subprocess import Popen | |
from subprocess import PIPE | |
import re | |
import winrm | |
import sys | |
import time | |
settings = { | |
"manage_ovf": "/Users/you/packer-virtualbox-iso-1468762258.ovf", | |
"ad_ovf": "/Users/you/packer-virtualbox-iso-1468684516.ovf", | |
"internal_network_name": "adintnet", | |
"adserver_name": "core-2012r2-active-directory", | |
"manage_name": "server-2012r2-manage-ad", | |
"ad_server_ip": "192.168.0.225", | |
"ad_server_computername": "DC", | |
"domainname": "sandbox.local", | |
"netbiosname": "SANDBOX", | |
"manage_ad_ip": "192.168.0.110", | |
"manage_ad_computername": "ADMANAGE" | |
} | |
def vm_dict(line): | |
vm_line_re = re.compile('"(?P<name>[^"]+)" \\{(?P<id>[^}]+)\\}') | |
p = vm_line_re.match(line) | |
if p == None: | |
return None | |
return { | |
"name": p.group('name'), | |
"id": p.group('id') | |
} | |
def list_vms(): | |
vm_list = Popen(["VBoxManage","list","vms"], stdin=PIPE, stdout=PIPE) | |
out, err = vm_list.communicate(input='\n'.encode()) | |
lines = out.split('\n') | |
return [vm_dict(l) for l in lines if vm_dict(l) != None] | |
def list_running_vms(): | |
vm_list = Popen(["VBoxManage","list","runningvms"], stdin=PIPE, stdout=PIPE) | |
out, err = vm_list.communicate(input='\n'.encode()) | |
lines = out.split('\n') | |
return [vm_dict(l) for l in lines if vm_dict(l) != None] | |
def is_running(vm_name): | |
running_vms = list_running_vms() | |
matching_vms = [vm for vm in running_vms if vm["name"] == vm_name] | |
return any(matching_vms) | |
def start_vm(vm_name): | |
p = Popen(["VBoxManage","startvm",vm_name], stdin=PIPE, stdout=PIPE) | |
out, err = p.communicate(input='\n'.encode()) | |
def vm_exists(vm_name): | |
vms = list_vms() | |
results = [vm for vm in vms if vm["name"] == vm_name] | |
return any(results) | |
def import_vm(ovf_path,name): | |
vm_import = Popen(["VBoxManage","import",ovf_path,"--vsys","0","--vmname",name], stdin=PIPE, stdout=PIPE) | |
out, err = vm_import.communicate(input='\n'.encode()) | |
print out | |
def vm_info(vm_name): | |
info = Popen(["VBoxManage","showvminfo",vm_name], stdin=PIPE, stdout=PIPE) | |
out, err = info.communicate(input='\n'.encode()) | |
setting_re = re.compile('(?P<key>[^:]+):\\s*(?P<value>.+)') | |
lines = out.split('\n') | |
result = {} | |
for line in lines: | |
m = setting_re.match(line) | |
if m: | |
result[m.group('key')] = m.group('value') | |
return result | |
def forward_winrm_port(vm_name,external_port): | |
p = Popen(["VBoxManage","modifyvm",vm_name,"--natpf1","guestwinrm,tcp,127.0.0.1," + str(external_port) + ",,5985"], stdin=PIPE, stdout=PIPE) | |
out, err = p.communicate(input='\n'.encode()) | |
print out | |
def set_up_internal_network(vmname,internal_network_name): | |
create_nic2 = Popen(["VBoxManage","modifyvm",vmname,"--nic2","intnet"], | |
stdin=PIPE, stdout=PIPE) | |
out, err = create_nic2.communicate(input='\n'.encode()) | |
print out | |
set_network_name = Popen(["VBoxManage","modifyvm",vmname,"--intnet2",internal_network_name], stdin=PIPE, stdout=PIPE) | |
out, err = set_network_name.communicate(input='\n'.encode()) | |
print out | |
def session_for_port(server_port, username = '', password = ''): | |
if username == '': | |
username = settings["username"] | |
if password == '': | |
password = settings['password'] | |
return winrm.Session('127.0.0.1:' + str(server_port), auth=(username,password)) | |
def get_windows_features(server_port): | |
s = session_for_port(server_port) | |
r = s.run_ps("Get-WindowsFeature | Select Name, Installed") | |
lines = r.std_out.split('\r\n') | |
feature_re = re.compile('(?P<featurename>\S+)\s+(?P<installed>(False|True))') | |
result = {} | |
for l in lines: | |
m = feature_re.match(l) | |
if m: | |
result[m.group('featurename')] = m.group('installed') == 'True' | |
return result | |
def install_ad(server_port): | |
print "Installing AD features" | |
s = session_for_port(server_port) | |
r = s.run_ps("""Add-WindowsFeature "RSAT-AD-Tools" | |
Start-Job -Name addFeature -ScriptBlock { | |
Add-WindowsFeature "AD-Domain-Services" -IncludeAllSubFeature -IncludeManagementTools | |
Add-WindowsFeature "DNS" -IncludeAllSubFeature -IncludeManagementTools | |
Add-WindowsFeature "GPMC" -IncludeAllSubFeature -IncludeManagementTools | |
} | |
Wait-Job -Name addFeature""") | |
print r.std_out | |
def has_joined_ad_domain(server_port): | |
s = session_for_port(server_port) | |
r = s.run_ps('Get-ADDomain') | |
return r.status_code == 0 | |
def internal_ip_address(server_port): | |
s = session_for_port(server_port) | |
r = s.run_ps('Get-NetIPAddress -AddressFamily IPv4 -InterfaceAlias "Ethernet 2" | Select -ExpandProperty IPAddress') | |
return r.std_out.split('\n')[0] | |
def change_ip_address(server_port, address): | |
print "Changing IP address to " + address | |
s = session_for_port(server_port) | |
r = s.run_ps('$internalAdapter = Get-NetAdapter -Name "Ethernet 2"\r\n' + | |
'$ipaddress = "' + address + '"\r\n' + | |
'$ipprefix = 24\r\n' + | |
'$ipgw = "192.168.0.1"\r\n' + | |
'$ipdns = "' + settings["ad_server_ip"] + '"\r\n' + | |
'$ipif = $internalAdapter.ifIndex\r\n' + | |
'New-NetIPAddress -IPAddress $ipaddress -PrefixLength $ipprefix -InterfaceIndex $ipif -DefaultGateway $ipgw') | |
print r.std_out | |
print r.std_err | |
def get_computer_name(server_port): | |
s = session_for_port(server_port) | |
r = s.run_ps('$env:computername') | |
return r.std_out.strip() | |
def change_computer_name(server_port, computername): | |
print "Changing computer name to " + computername | |
s = session_for_port(server_port) | |
r = s.run_ps('Rename-Computer -NewName ' + computername + ' -force') | |
print r.std_out | |
print r.std_err | |
s.run_ps('Restart-Computer') | |
time.sleep(60) | |
def create_forest(server_port): | |
s = session_for_port(server_port) | |
cmd = '$domainname="' + settings["domainname"] + '"\n' | |
cmd += '$netbiosName="' + settings["netbiosname"] + '"\n' | |
cmd += 'Import-Module ADDSDeployment\n' | |
cmd += '$pwd=ConvertTo-SecureString "' + settings["password"] + '" ' | |
cmd += '-AsPlainText -Force\n' | |
cmd += 'Install-ADDSForest -CreateDnsDelegation:$false ' | |
cmd += '-DatabasePath "C:\Windows\NTDS" ' | |
cmd += '-DomainMode "Win2012" ' | |
cmd += '-DomainName $domainName ' | |
cmd += '-DomainNetbiosName $netbiosName ' | |
cmd += '-ForestMode "Win2012" ' | |
cmd += '-InstallDns:$true ' | |
cmd += '-LogPath "C:\Windows\NTDS" ' | |
cmd += '-NoRebootOnCompletion:$false ' | |
cmd += '-SysvolPath "C:\Windows\SYSVOL" ' | |
cmd += '-Force:$true -SafeModeAdministratorPassword $pwd' | |
print "Installing AD Forest" | |
r = s.run_ps(cmd) | |
print r.std_out | |
print r.std_err | |
def join_domain(server_port): | |
print 'Joining domain ' + settings["netbiosname"] | |
s = session_for_port(server_port) | |
cmd = '$pwd=ConvertTo-SecureString "' + settings["password"] + '" ' | |
cmd += '-AsPlainText -Force\n' | |
cmd += '$credential = New-Object System.Management.Automation.PSCredential("' + settings["netbiosname"] + '\\' + settings["username"] + '", $pwd)\n' | |
cmd += 'Add-Computer -DomainName ' + settings["netbiosname"] + ' -Credential $credential -force\n' | |
r = s.run_ps(cmd) | |
print r.std_out | |
print r.std_err | |
s.run_ps('Restart-Computer') | |
time.sleep(60) | |
def get_dns_client_server_address(server_port): | |
s = session_for_port(server_port) | |
r = s.run_ps('Get-DnsClientServerAddress -AddressFamily IPv4 -InterfaceIndex (Get-NetAdapter -Name "Ethernet 2").InterfaceIndex | Select -ExpandProperty ServerAddresses') | |
return r.std_out.strip() | |
def set_dns_client_server_address(server_port, address): | |
s = session_for_port(server_port) | |
r = s.run_ps('Set-DnsClientServerAddress -InterfaceIndex (Get-NetAdapter -Name "Ethernet 2").InterfaceIndex -ServerAddress ' + address) | |
def main(): | |
print "Setting up Active Directory Lab" | |
ad_server_port = 5986 | |
manage_ad_port = 5987 | |
settings["username"] = sys.argv[1] | |
settings["password"] = sys.argv[2] | |
if (not vm_exists(settings["adserver_name"])): | |
import_vm(settings["ad_ovf"],settings["adserver_name"]) | |
if (not vm_exists(settings["manage_name"])): | |
import_vm(settings["manage_ovf"],settings["manage_name"]) | |
if (vm_info(settings["adserver_name"])["NIC 2"] == "disabled"): | |
set_up_internal_network(settings["adserver_name"],settings["internal_network_name"]) | |
if (vm_info(settings["manage_name"])["NIC 2"] == "disabled"): | |
set_up_internal_network(settings["manage_name"],settings["internal_network_name"]) | |
if ("NIC 1 Rule(1)" not in vm_info(settings["adserver_name"])): | |
forward_winrm_port(settings["adserver_name"],ad_server_port) | |
if (not is_running(settings["adserver_name"])): | |
start_vm(settings["adserver_name"]) | |
time.sleep(60) # I'd say that's about as long as it takes the machine to boot up | |
if (not get_windows_features(ad_server_port)['RSAT-AD-Tools']): | |
install_ad(ad_server_port) | |
time.sleep(60) | |
if (internal_ip_address(ad_server_port).strip() != settings["ad_server_ip"]): | |
change_ip_address(ad_server_port, settings["ad_server_ip"]) | |
if (get_computer_name(ad_server_port) != settings["ad_server_computername"]): | |
change_computer_name(ad_server_port, settings["ad_server_computername"]) | |
if (not has_joined_ad_domain(ad_server_port)): | |
create_forest(ad_server_port) | |
if ("NIC 1 Rule(1)" not in vm_info(settings["manage_name"])): | |
forward_winrm_port(settings["manage_name"],manage_ad_port) | |
if (not is_running(settings["manage_name"])): | |
start_vm(settings["manage_name"]) | |
time.sleep(60) | |
if (internal_ip_address(manage_ad_port).strip() != settings["manage_ad_ip"]): | |
change_ip_address(manage_ad_port, settings["manage_ad_ip"]) | |
if (get_computer_name(manage_ad_port) != settings["manage_ad_computername"]): | |
change_computer_name(manage_ad_port, settings["manage_ad_computername"]) | |
current_address = get_dns_client_server_address(manage_ad_port) | |
if (current_address != settings["ad_server_ip"]): | |
set_dns_client_server_address(manage_ad_port, settings["ad_server_ip"]) | |
if (not has_joined_ad_domain(manage_ad_port)): | |
join_domain(manage_ad_port) | |
if __name__ == "__main__": | |
main() | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment