cloudamatic/mu

View on GitHub
cookbooks/mu-activedirectory/providers/domain.rb

Summary

Maintainability
A
0 mins
Test Coverage
#
# Cookbook Name:: mu-activedirectory
# Provider:: domain
#
# Copyright 2015, eGlobalTech,
#
# All rights reserved - Do Not Redistribute
#

include Chef::Mixin::PowershellOut

def whyrun_supported?
  true
end

action :create do
  case node['platform']
    when "windows"
      install_ad_features
      elevate_remote_access
      set_computer_name(admin_creds)
      create_domain
      configure_network_interface
      configure_domain
    else
      Chef::Log.info("Unsupported platform #{node['platform']}")
  end
end

action :delete do
  case node['platform']
    when "windows"
      delete_domain
    else
      Chef::Log.info("Unsupported platform #{node['platform']}")
  end
end

# def load_current_resource
# @current_resource = @new_resource.dup
# end

def create_domain_admin_user
  unless domain_user_exist?(new_resource.domain_admin_user)
    code =<<-EOH
            New-ADUser -Name #{new_resource.domain_admin_user} -UserPrincipalName #{new_resource.domain_admin_user}@#{new_resource.dns_name} -AccountPassword (ConvertTo-SecureString -AsPlainText '#{new_resource.domain_admin_password}' -force) -Enabled $true -PasswordNeverExpires $true
            Add-ADGroupMember 'Domain Admins' -Members #{new_resource.domain_admin_user}
    EOH
    cmd = powershell_out(code)
    Chef::Log.info("Create Domain Admin User #{new_resource.domain_admin_user}")
    # inspect_exit_status(cmd, "Create Domain Admin User #{new_resource.domain_admin_user}")
  end
end

#This will restart the OS. The OS needs to be restated after creating the domain
# Workaround for a really crappy issue with cygwin/ssh and windows where we need to end all ssh process,
# or Mu's SSH session / chef client run won't disconnect even though the client chef run has finished or the SSH session has closed.
# Running configure_network_interface before creating a domain, and re-running chef-client will cause DNS name resolution to fail if the domain hasn't been created, 
# which is why we add the configure_network_interface code to the domain creation execution itself.
def create_domain
  unless domain_exists?
    require 'chef/win32/version'
    version = Chef::ReservedNames::Win32::Version.new

    Chef::Log.info("Configuring network interface settings and creating domain")
    if version.windows_server_2012?
      code =<<-EOH
#{network_interface_code}
                $DCPromoFile = @"
                [DCINSTALL]
                InstallDNS=yes
                NewDomain=forest
                NewDomainDNSName=#{new_resource.dns_name}
                DomainNetBiosName=#{new_resource.netbios_name}
                SiteName=#{new_resource.site_name}
                ReplicaorNewDomain=domain
                ForestLevel=5
                DomainLevel=5
                ConfirmGC=Yes
                SafeModeAdminPassword="#{new_resource.restore_mode_password}"
                RebootonCompletion=Yes
                "@
                $DCPromoFile | out-file c:/dcpromoanswerfile.txt -Force
                dcpromo.exe /unattend:c:/dcpromoanswerfile.txt
      EOH
    elsif version.windows_server_2012_r2?
      code =<<-EOH
#{network_interface_code}
                Install-ADDSForest -DomainName #{new_resource.dns_name} -SafeModeAdministratorPassword (convertto-securestring '#{new_resource.restore_mode_password}' -asplaintext -force) -DomainMode Win2012R2 -DomainNetbiosName #{new_resource.netbios_name} -ForestMode Win2012R2 -Confirm:$false -Force
                Stop-Process -ProcessName sshd -force -ErrorAction SilentlyContinue
      EOH
      # cmd = powershell_out("Install-ADDSForest -DomainName #{new_resource.dns_name} -SafeModeAdministratorPassword (convertto-securestring '#{new_resource.restore_mode_password}' -asplaintext -force) -DomainMode Win2012R2 -DomainNetbiosName #{new_resource.netbios_name} -ForestMode Win2012R2 -Confirm:$false -Force")
    end
    Chef::Log.info("Creating Active Directory Domain #{new_resource.dns_name}")
    cmd = powershell_out(code)
    kill_ssh
    Chef::Application.fatal!("Failed to create Active Directory Domain #{new_resource.dns_name}") if cmd.exitstatus != 0
    reboot "Active Directory Domain #{new_resource.dns_name} created" do
      action :reboot_now
      reason "Active Directory Domain #{new_resource.dns_name} created"
    end
  end
end

def rename_default_site
  unless default_site_name_set?
    cmd = powershell_out("Get-ADObject -Credential #{admin_creds} -SearchBase (Get-ADRootDSE).ConfigurationNamingContext -filter {Name -eq 'Default-First-Site-Name'} | Rename-ADObject -Credential #{admin_creds} -NewName #{new_resource.site_name}")
    Chef::Log.info("Renamed default site to #{new_resource.site_name}")
    # inspect_exit_status(cmd, "Renamed default site to #{new_resource.site_name}")
  end
end

def configure_replication
  new_resource.sites.each { |site|
    if site[:name] != new_resource.site_name
      powershell_script "Creating AD ReplicationSite #{site[:name]}" do
        guard_interpreter :powershell_script
        code "New-ADReplicationSite #{site[:name]} -Credential #{admin_creds}"
        not_if "(Get-ADObject -Credential #{admin_creds} -SearchBase (Get-ADRootDSE).ConfigurationNamingContext -filter {Name -eq '#{site[:name]}'}).name -eq '#{site[:name]}'"
        sensitive true
      end

      powershell_script "Configure AD Replication between AD sites and" do
        guard_interpreter :powershell_script
        code "Get-ADReplicationSiteLink -Credential #{admin_creds} -Filter * | Set-ADReplicationSiteLink -Credential #{admin_creds} -SitesIncluded @{add='#{site[:name]}'} -ReplicationFrequencyInMinutes 15"
        sensitive true
      end
    end

    powershell_script "Create AD Replication subnet #{site[:ip_block]} for site #{site[:name]}" do
      guard_interpreter :powershell_script
      code "New-ADReplicationSubnet -Credential #{admin_creds} -Name #{site[:ip_block]} -Site #{site[:name]}"
      not_if "(Get-ADReplicationSubnet -Credential #{admin_creds} -Identity #{site[:ip_block]}).name -eq '#{site[:ip_block]}'"
      sensitive true
    end
  }
end

def configure_domain
  # Move these to somewhere that makes sense
  powershell_out("Set-Service NTDS -StartupType Automatic")
  powershell_out("Set-Service ADWS -StartupType Automatic")

  create_domain_admin_user
  rename_default_site
  configure_replication
  set_replication_static_ports
end