diff --git a/.fixtures.yml b/.fixtures.yml new file mode 100644 index 0000000..61ddd4a --- /dev/null +++ b/.fixtures.yml @@ -0,0 +1,9 @@ +fixtures: + symlinks: + profile: "#{source_dir}" + repositories: + stdlib: "git://github.com/puppetlabs/puppetlabs-stdlib" + apache: "git://github.com/puppetlabs/puppetlabs-apache" + concat: "git://github.com/puppetlabs/puppetlabs-concat" + firewall: "git://github.com/puppetlabs/puppetlabs-firewall" + ntp: "git://github.com/puppetlabs/puppetlabs-ntp" diff --git a/.gitignore b/.gitignore index b9d6bd9..b0ec3e9 100644 --- a/.gitignore +++ b/.gitignore @@ -213,3 +213,5 @@ pip-log.txt #Mr Developer .mr.developer.cfg + +spec/fixtures/ diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..e389d79 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,2 @@ +John Puskar 08/09/17 + - Refactored group_members to group_members for readability and to fix core functionality. \ No newline at end of file diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000..3230009 --- /dev/null +++ b/Gemfile @@ -0,0 +1,8 @@ +# frozen_string_literal: true +source "https://rubygems.org" + +# gem "rails" +gem 'rake' +gem 'rspec-puppet' +gem 'puppet' +gem 'puppetlabs_spec_helper' diff --git a/Gemfile.lock b/Gemfile.lock new file mode 100644 index 0000000..f2dfe4e --- /dev/null +++ b/Gemfile.lock @@ -0,0 +1,62 @@ +GEM + remote: https://rubygems.org/ + specs: + diff-lcs (1.3) + facter (2.4.6) + fast_gettext (1.1.0) + gettext (3.2.2) + locale (>= 2.0.5) + text (>= 1.3.0) + gettext-setup (0.13) + fast_gettext (~> 1.1.0) + gettext (>= 3.0.2) + locale + hiera (3.3.0) + json_pure (1.8.6) + locale (2.1.2) + metaclass (0.0.4) + mocha (1.2.1) + metaclass (~> 0.0.1) + puppet (4.9.2) + facter (> 2.0, < 4) + gettext-setup (>= 0.10, < 1) + hiera (>= 2.0, < 4) + json_pure (~> 1.8) + locale (~> 2.1) + puppet-lint (2.1.1) + puppet-syntax (2.3.0) + rake + puppetlabs_spec_helper (2.0.1) + mocha (~> 1.0) + puppet-lint (~> 2.0) + puppet-syntax (~> 2.0) + rspec-puppet (~> 2.0) + rake (12.0.0) + rspec (3.5.0) + rspec-core (~> 3.5.0) + rspec-expectations (~> 3.5.0) + rspec-mocks (~> 3.5.0) + rspec-core (3.5.4) + rspec-support (~> 3.5.0) + rspec-expectations (3.5.0) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.5.0) + rspec-mocks (3.5.0) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.5.0) + rspec-puppet (2.5.0) + rspec + rspec-support (3.5.0) + text (1.3.1) + +PLATFORMS + ruby + +DEPENDENCIES + puppet + puppetlabs_spec_helper + rake + rspec-puppet + +BUNDLED WITH + 1.14.3 diff --git a/README.md b/README.md index fc18e42..0035609 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ V 0.3.1 : - Fix add user. (dsquery.exe doesn't seem to work anymore) - Works with fullname value - Add Pull Request #8 (fix readme for Group) V 0.3.2 : - - Fix add group and groupmember dsquery.exe doesn't seem to work anymore). + - Fix add group and group member dsquery.exe doesn't seem to work anymore). ##Module Description @@ -209,7 +209,7 @@ For adding a Group : For adding members to a Group : ``` - windows_ad::groupmembers{'Member groupplop': + windows_ad::group_members{'Member groupplop': ensure => present, groupname => 'groupplop', members => '"jre","test2"', diff --git a/Rakefile b/Rakefile index 0a28d84..d1e11f7 100644 --- a/Rakefile +++ b/Rakefile @@ -4,7 +4,7 @@ require 'puppet-lint/tasks/puppet-lint' PuppetLint.configuration.send('disable_80chars') PuppetLint.configuration.ignore_paths = ["spec/**/*.pp", "pkg/**/*.pp"] -desc "Run puppet in noop mode and check for syntax errors." +desc "Validate manifests, templates, and ruby files" task :validate do Dir['manifests/**/*.pp'].each do |manifest| sh "puppet parser validate --noop #{manifest}" diff --git a/checksums.json b/checksums.json index d755a5d..c9a232f 100644 --- a/checksums.json +++ b/checksums.json @@ -6,7 +6,6 @@ "lib/puppet/parser/functions/validate_password.rb": "dc6f2d87967e86882e49a09b9e3e0ca7", "manifests/conf_forest.pp": "2d8de6a9deddaa47711b7684e6c7c43f", "manifests/group.pp": "cf0081d1bba488c62f0eba54fffd52f1", - "manifests/groupmembers.pp": "c50ec54005b12aa3120577e963a61082", "manifests/init.pp": "cbd753ea0b6ceedb14ec94c6fce8abf5", "manifests/install.pp": "02d4dff5c898bf26bf37d25b7bdae2fb", "manifests/organisationalunit.pp": "c1925a20f4cb0da1cf8cb4247a635d4d", diff --git a/manifests/conf_forest.pp b/manifests/conf_forest.pp index 9493035..a84b8eb 100644 --- a/manifests/conf_forest.pp +++ b/manifests/conf_forest.pp @@ -33,34 +33,33 @@ # === Authors # # Jerome RIVIERE (www.jerome-riviere.re) +# Karol Kozakowski # # === Copyright # # Copyright 2014 Jerome RIVIERE. +# Copyright 2017 Karol Kozakowski # class windows_ad::conf_forest ( - #install parameters - $ensure = $ensure, - $domainname = $domainname, - $netbiosdomainname = $netbiosdomainname, - $domainlevel = $domainlevel, - $forestlevel = $forestlevel, - $globalcatalog = $globalcatalog, - $databasepath = $databasepath, - $logpath = $logpath, - $sysvolpath = $sysvolpath, - $dsrmpassword = $dsrmpassword, - $installdns = $installdns, - $kernel_ver = $kernel_ver, - $timeout = 0, - $configureflag = $configureflag, - - #removal parameters - $localadminpassword = $localadminpassword, #admin password required for removal - $force = $force, - $forceremoval = $forceremoval, - $uninstalldnsrole = $uninstalldnsrole, - $demoteoperationmasterrole = $demoteoperationmasterrole, + $ensure, + $domainname, + $netbiosdomainname, + $domainlevel, + $forestlevel, + $globalcatalog, + $databasepath, + $logpath, + $sysvolpath, + $dsrmpassword, + $installdns, + $kernel_ver, + $configureflag, + $localadminpassword, + $force, + $forceremoval, + $uninstalldnsrole, + $demoteoperationmasterrole, + $timeout, ){ validate_bool($configureflag) if ($configureflag == true){ @@ -68,25 +67,35 @@ if $forceremoval { $forceboolremoval = 'true' } else { $forceboolremoval = 'false' } if $demoteoperationmasterrole { $demoteoperationmasterrolebool = 'true' } else { $demoteoperationmasterrolebool = 'false' } - # If the operating is server 2012 then run the appropriate powershell commands if not revert back to the cmd commands + # If the operating is server 2012 or 2016 then run the appropriate powershell commands if not revert back to the cmd commands if ($ensure == 'present') { - if ($kernel_ver =~ /^6\.2|^6\.3/) { + if ($kernel_ver =~ /^6\.2|^6\.3|^10\.0/) { if ($installdns == 'yes'){ - # Deploy Server 2012 Active Directory - exec { 'Config ADDS': - command => "Import-Module ADDSDeployment; Install-ADDSForest -Force -DomainName ${domainname} -DomainMode ${domainlevel} -DomainNetbiosName ${netbiosdomainname} -ForestMode ${forestlevel} -DatabasePath ${databasepath} -LogPath ${logpath} -SysvolPath ${sysvolpath} -SafeModeAdministratorPassword (convertto-securestring '${dsrmpassword}' -asplaintext -force) -InstallDns", - provider => powershell, - onlyif => "if((gwmi WIN32_ComputerSystem).Domain -eq \'${domainname}\'){exit 1}", - timeout => $timeout, + # Deploy Server 2016 Active Directory + class { 'windows_ad::deployments::adds_deployment_powershell': + type => 'ntp', + domainname => $domainname, + domainlevel => $domainlevel, + netbiosdomainname => $netbiosdomainname, + forestlevel => $forestlevel, + databasepath => $databasepath, + logpath => $logpath, + sysvolpath => $sysvolpath, + dsrmpassword => $dsrmpassword, + timeout => $timeout } - } - else{ - # Deploy Server 2012 Active Directory Without DNS - exec { 'Config ADDS': - command => "Import-Module ADDSDeployment; Install-ADDSForest -Force -DomainName ${domainname} -DomainMode ${domainlevel} -DomainNetbiosName ${netbiosdomainname} -ForestMode ${forestlevel} -DatabasePath ${databasepath} -LogPath ${logpath} -SysvolPath ${sysvolpath} -SafeModeAdministratorPassword (convertto-securestring '${dsrmpassword}' -asplaintext -force)", - provider => powershell, - onlyif => "if((gwmi WIN32_ComputerSystem).Domain -eq \'${domainname}\'){exit 1}", - timeout => $timeout, + } else{ + class { 'windows_ad::deployments::adds_deployment_powershell': + type => '', + domainname => $domainname, + domainlevel => $domainlevel, + netbiosdomainname => $netbiosdomainname, + forestlevel => $forestlevel, + databasepath => $databasepath, + logpath => $logpath, + sysvolpath => $sysvolpath, + dsrmpassword => $dsrmpassword, + timeout => $timeout } } }else { @@ -99,7 +108,7 @@ } } }else{ #uninstall AD - if ($kernel_ver =~ /^6\.2|^6\.3/) { + if ($kernel_ver =~ /^6\.2|^6\.3|^10\.0/) { if($localadminpassword != ''){ exec { 'Uninstall ADDS': command => "Import-Module ADDSDeployment;Uninstall-ADDSDomainController -LocalAdministratorPassword (ConvertTo-SecureString \'${localadminpassword}\' -asplaintext -force) -Force:$${forcebool} -ForceRemoval:$${forceboolremoval} -DemoteOperationMasterRole:$${demoteoperationmasterrolebool} -SkipPreChecks", diff --git a/manifests/deployments/adds_deployment_powershell.pp b/manifests/deployments/adds_deployment_powershell.pp new file mode 100644 index 0000000..a7d6c70 --- /dev/null +++ b/manifests/deployments/adds_deployment_powershell.pp @@ -0,0 +1,26 @@ +class windows_ad::deployments::adds_deployment_powershell ( + $type, + $domainname, + $domainlevel, + $netbiosdomainname, + $forestlevel, + $databasepath, + $logpath, + $sysvolpath, + $dsrmpassword, + $timeout, +) { + + if ($type == 'ntp') { + $command = "Import-Module ADDSDeployment; Install-ADDSForest -Force -DomainName ${domainname} -DomainMode ${domainlevel} -DomainNetbiosName ${netbiosdomainname} -ForestMode ${forestlevel} -DatabasePath ${databasepath} -LogPath ${logpath} -SysvolPath ${sysvolpath} -SafeModeAdministratorPassword (convertto-securestring '${dsrmpassword}' -asplaintext -force) -InstallDns" + } else { + $command = "Import-Module ADDSDeployment; Install-ADDSForest -Force -DomainName ${domainname} -DomainMode ${domainlevel} -DomainNetbiosName ${netbiosdomainname} -ForestMode ${forestlevel} -DatabasePath ${databasepath} -LogPath ${logpath} -SysvolPath ${sysvolpath} -SafeModeAdministratorPassword (convertto-securestring '${dsrmpassword}' -asplaintext -force)" + } + + exec { 'Config ADDS': + command => $command, + provider => powershell, + onlyif => "if((gwmi WIN32_ComputerSystem).Domain -eq \'${domainname}\'){exit 1}", + timeout => $timeout, + } +} diff --git a/manifests/group_members.pp b/manifests/group_members.pp new file mode 100644 index 0000000..8c9d825 --- /dev/null +++ b/manifests/group_members.pp @@ -0,0 +1,141 @@ +# == Class: windows_ad::group_members +# +# Manages AD group memberships. +# +# === Authors +# +# John Puskar (johnpuskar@gmail.com) +# Jerome RIVIERE (www.jerome-riviere.re) +# +# === Copyright +# +# Copyright 2014 Jerome RIVIERE. +# +define windows_ad::group_members( + Array[String] $members, + String $group_name = $title, + String $ensure = 'present', +){ + validate_re($ensure, '^(present|absent)$', 'valid values for ensure are \'present\' or \'absent\'') + + $puppet_members_joined = join($members, ',') + $cmd_input_vars = @("END_cmd_input_vars"/$) + \$puppet_group_name = "${group_name}" + \$puppet_members = "${puppet_members_joined}" + | END_cmd_input_vars + + $cmd_ensure_boilerplate_frag_1 = @(END_cmd_ensure_boilerplate) + $ErrorActionPreference = "Stop" + Import-Module activedirectory + + $member_names = $puppet_members.split(',') + $member_names = $member_names | ForEach-Object {$_.replace("""",'').replace("'","").tolower()} + $target_group_name = $puppet_group_name + + Try{ + $target_group = Get-AdGroup $target_group_name + $target_group_members = Get-AdGroupMember $target_group_name + $target_group_members_usernames = $target_group_members | Select-Object "sAMAccountName" -ExpandProperty "sAMAccountName" + $target_group_members_usernames = $target_group_members_usernames | ForEach-Object {$_.ToLower()} + } Catch { + Write-Warning $error[0] + Throw $error[0] + } + | END_cmd_ensure_boilerplate + $cmd_ensure_boilerplate = "\ +${cmd_input_vars} \ +${cmd_ensure_boilerplate_frag_1} \ +" + + $cmd_ensure_present_onlyif_frag_1 = @(END_cmd_ensure_present_onlyif) + $found_missing_members = $false + $member_names | Foreach-Object { + If(!($target_group_members_usernames -contains $_)) { + $found_missing_members = $true + } + } + + If($found_missing_members) { + Exit 1 + } Else { + Exit 0 + } + | END_cmd_ensure_present_onlyif + + $cmd_ensure_present_onlyif = "\ +${cmd_ensure_boilerplate} \ +${cmd_ensure_present_onlyif_frag_1} \ +" + + $cmd_ensure_present_frag_1 = @(END_cmd_ensure_present_frag_1) + $member_names | Foreach-Object { + If(!($target_group_members_usernames -contains $_)) { + $cur_user = $null + Try{ + $cur_user = Get-ADUser $cur_member_name + Add-ADGroupMember $target_group_name -Member $cur_user + } Catch { + Write-Warning $error[0] + Throw $error[0] + } + } + } + | END_cmd_ensure_present_frag_1 + + $cmd_ensure_present = "\ +${cmd_ensure_boilerplate} \ +${cmd_ensure_present_frag_1} \ +" + $cmd_ensure_absent_frag_1 = @(END_cmd_ensure_absent_frag_1) + $member_names | Foreach-Object { + If(!($target_group_members_usernames -contains $_)) { + $cur_user = $null + Try{ + $cur_user = Get-ADUser $cur_member_name + Remove-ADGroupMember $target_group_name -Member $cur_user -Confirm:$False + } Catch { + Write-Warning $error[0] + Throw $error[0] + } + } + } + | END_cmd_ensure_absent_frag_1 + + $cmd_ensure_absent = "\ +${cmd_ensure_boilerplate} \ +${cmd_ensure_absent_frag_1} \ +" + $cmd_ensure_absent_unless_frag_1 = @(END_cmd_ensure_absent_unless) + $found_extra_members = $false + $member_names | Foreach-Object { + If($target_group_members_usernames -contains $_)) { + $found_extra_members = $true + } + } + + If($found_extra_members) { + Exit 1 + } Else { + Exit 0 + } + | END_cmd_ensure_absent_unless + + $cmd_ensure_absent_unless = "\ +${cmd_ensure_boilerplate} \ +${cmd_ensure_absent_unless_frag_1} \ +" + + if($ensure == 'present'){ + exec { "add_ad_group_member_${group_name}": + command => $cmd_ensure_present, + unless => $cmd_ensure_present_onlyif, + provider => 'powershell', + } + } else { + exec { "remove_ad_group_member_${group_name}": + command => $cmd_ensure_absent, + onlyif => $cmd_ensure_absent_unless, + provider => 'powershell', + } + } +} \ No newline at end of file diff --git a/manifests/groupmembers.pp b/manifests/groupmembers.pp deleted file mode 100644 index 52dd2de..0000000 --- a/manifests/groupmembers.pp +++ /dev/null @@ -1,62 +0,0 @@ -# == Class: windows_ad -# -# Full description of windows_ad::groupmembers here. -# -# This resource allow you to add/remove users inside a group of a active directory. -# -# === Parameters -# -# Document parameters here. -# -# [*sample_parameter*] -# === Variables -# -# Here you should define a list of variables that this module would require. -# -# [*sample_variable*] -# Explanation of how this variable affects the funtion of this class and if -# it has a default. e.g. "The parameter enc_ntp_servers must be set by the -# External Node Classifier as a comma separated list of hostnames." (Note, -# global variables should be avoided in favor of class parameters as -# of Puppet 2.6.) -# -# === Examples -# -# windows_ad::groupmembers{'test': -# ensure => present, -# groupname => 'SQLAdmin', -# members => '"jre","test2"', -# } -# -# === Authors -# -# Jerome RIVIERE (www.jerome-riviere.re) -# -# === Copyright -# -# Copyright 2014 Jerome RIVIERE. -# -define windows_ad::groupmembers( - $ensure = present, # add or delete user - $groupname = $groupname, # name of group - $members = $members, # samaccountname of user - -# delete user inside a group - $confirmdeletion = false, # delete wihtout confirmation -){ - validate_re($ensure, '^(present|absent)$', 'valid values for ensure are \'present\' or \'absent\'') - - if($ensure == 'present'){ - exec { "Add Group Member - ${name}": - command => "import-module activedirectory;\$values='${members}';\$split=\$values.split(',');foreach(\$value in \$split){try{\$value = \$value.Replace('\"','');\$user = Get-ADUser \$value;}catch{\$user = \$null};if(\$user -ne \$null){Add-ADGroupMember '${groupname}' -Member \$value}}", - onlyif => "import-module activedirectory;\$member=\$null;\$values='${members}';\$split=\$values.split(',');try{\$group = get-adgroup '${groupname}';}catch{\$group = \$null;};foreach(\$value in \$split){try{\$value = \$value.Replace('\"','');\$user = Get-ADUser \$value}catch{\$user = \$null};if(\$group -ne \$null){if(\$user -ne \$null){foreach(\$allmember in Get-ADGroupMember '${groupname}'){\$one = \$value.tolower() -replace '\"','';if(\$one -eq \$allmember.SamAccountName.tolower()){if(\$member -eq \$null){\$member='\"'+\$allmember.SamAccountName+'\"';}else{\$member+=',\"'+\$allmember.SamAccountName+'\"';}}}if('${members}' -eq \$member){exit 1}}else{if('${members}' -match \$member){exit 1}}}else{exit 1}}", - provider => powershell, - } - }else{ - exec { "Remove Group Member - ${name}": - command => "import-module activedirectory;\$values='${members}';\$split=\$values.split(',');foreach(\$value in \$split){try{\$value = \$value.Replace('\"','');\$user = Get-ADUser \$value}catch{\$user = \$null};if(\$user -ne \$null){Remove-ADGroupMember '${groupname}' -Member \$value -Confirm:\$False}}", - onlyif => "import-module activedirectory;\$member=\$null;\$values=${members};\$split=\$values.split(',');try{\$group = get-adgroup '${groupname}';}catch{\$group = \$null;};foreach(\$value in \$split){if((\$group -ne \$null) -and ((Get-ADGroupMember -Identity ${groupname}) -ne \$null)){foreach(\$allmember in Get-ADGroupMember '${groupname}'){\$one = \$value.tolower();if(\$one -eq \$allmember.SamAccountName.tolower()){if(\$member-eq\$null){\$member='\"'+\$allmember.SamAccountName+'\"';}else{\$member+=',\"'+\$allmember.SamAccountName+'\"';}}};if('${members}' -cmatch \$member){}else{exit 1}}else{exit 1}}", - provider => powershell, - } - } -} \ No newline at end of file diff --git a/manifests/init.pp b/manifests/init.pp index 04118f8..1d95821 100644 --- a/manifests/init.pp +++ b/manifests/init.pp @@ -4,64 +4,67 @@ # === Authors # # Jerome RIVIERE (www.jerome-riviere.re) +# Karol Kozakowski # # === Copyright # # Copyright 2014 Jerome RIVIERE. +# Copyright 2017 Karol Kozakowski # class windows_ad ( ### part install AD - $install = 'present', - $installmanagementtools = true, - $installsubfeatures = false, - $restart = false, - $installflag = true, # Flag to bypass the install of AD if desired + $install = $windows_ad::params::install, + $installmanagementtools = $windows_ad::params::installmanagementtools, + $installsubfeatures = $windows_ad::params::installsubfeatures, + $restart = $windows_ad::params::restart, + $installflag = $windows_ad::params::installflag, # Flag to bypass the install of AD if desired ### Part Configure AD - Global - $configure = 'present', - $domain = 'forest', - $domainname = undef, # FQDN - $netbiosdomainname = undef, # FQDN - $configureflag = true, # Flag to bypass the configuration of AD if desired - + $configure = $windows_ad::params::configure, + $domain = $windows_ad::params::domain, + $domainname = $windows_ad::params::domainname, # FQDN + $netbiosdomainname = $windows_ad::params::netbiosdomainname, # FQDN + $configureflag = $windows_ad::params::configureflag, # Flag to bypass the configuration of AD if desired #level AD - $domainlevel = '6', # Domain level {4 - Server 2008 R2 | 5 - Server 2012 | 6 - Server 2012 R2} - $forestlevel = '6', # Domain level {4 - Server 2008 R2 | 5 - Server 2012 | 6 - Server 2012 R2} + $domainlevel = $windows_ad::params::domainlevel, # Domain level {4 - Server 2008 R2 | 5 - Server 2012 | 6 - Server 2012 R2} + $forestlevel = $windows_ad::params::forestlevel, # Domain level {4 - Server 2008 R2 | 5 - Server 2012 | 6 - Server 2012 R2}, - $installdns = 'yes', # Add DNS Server Role - $globalcatalog = 'yes', # Add Global Catalog functionality - $kernel_ver = $::kernelversion, + $installdns = $windows_ad::params::installdns, # Add DNS Server Role + $globalcatalog = $windows_ad::params::globalcatalog, # Add Global Catalog functionality + $kernel_ver = $windows_ad::params::kernel_ver, # Installation Directories - $databasepath = 'c:\\windows\\ntds', # Active Directory database path - $logpath = 'c:\\windows\\ntds', # Active Directory log path - $sysvolpath = 'c:\\windows\\sysvol', # Active Directory sysvol path + $databasepath = $windows_ad::params::databasepath, # Active Directory database path + $logpath = $windows_ad::params::logpath, # Active Directory log path + $sysvolpath = $windows_ad::params::sysvolpath, # Active Directory sysvol path - $dsrmpassword = undef, + $dsrmpassword = $windows_ad::params::dsrmpassword, ### Part Configure AD - Forest #uninstall forest - $localadminpassword = undef, - $force = true, - $forceremoval = true, - $uninstalldnsrole = 'yes', - $demoteoperationmasterrole = true, + $localadminpassword = $windows_ad::params::localadminpassword, + $force = $windows_ad::params::force, + $forceremoval = $windows_ad::params::forceremoval, + $uninstalldnsrole = $windows_ad::params::uninstalldnsrole, + $demoteoperationmasterrole = $windows_ad::params::demoteoperationmasterrole, ### Part Configure AD - Other - $secure_string_pwd = undef, - $installtype = undef, # New domain or replica of existing domain {replica | domain} - $domaintype = undef, # Type of domain {Tree | Child | Forest} (New domain tree in an existing forest, child domain, or new forest) - $sitename = undef, # Site Name + $secure_string_pwd = $windows_ad::params::secure_string_pwd, + $installtype = $windows_ad::params::installtype, # New domain or replica of existing domain {replica | domain} + $domaintype = $windows_ad::params::domaintype, # Type of domain {Tree | Child | Forest} (New domain tree in an existing forest, child domain, or new forest) + $sitename = $windows_ad::params::sitename, # Site Name ### Define Hiera hashes - $groups = undef, - $groups_hiera_merge = true, - $users = undef, - $users_hiera_merge = true, - $usersingroup = undef, - $usersingroup_hiera_merge = true, -) { + $groups = $windows_ad::params::groups, + $groups_hiera_merge = $windows_ad::params::groups_hiera_merge, + $users = $windows_ad::params::users, + $users_hiera_merge = $windows_ad::params::users_hiera_merge, + $usersingroup = $windows_ad::params::usersingroup, + $usersingroup_hiera_merge = $windows_ad::params::usersingroup_hiera_merge, + + $timeout = $windows_ad::params::timeout +) inherits windows_ad::params { # when present install process will be set. if already install nothing done # when absent uninstall will be launch validate_re($install, '^(present|absent)$', 'valid values for install are \'present\' or \'absent\'') @@ -70,7 +73,7 @@ validate_re($configure, '^(present|absent)$', 'valid values for configure are \'present\' or \'absent\'') validate_bool($configureflag) validate_bool($installflag) - + class{'windows_ad::install': ensure => $install, installmanagementtools => $installmanagementtools, @@ -98,19 +101,20 @@ uninstalldnsrole => $uninstalldnsrole, demoteoperationmasterrole => $demoteoperationmasterrole, configureflag => $configureflag, + timeout => $timeout } if($installflag or $configureflag){ if($install == 'present'){ - anchor{'windows_ad::begin':} -> Class['windows_ad::install'] -> Class['windows_ad::conf_forest'] -> anchor{'windows_ad::end':} -> Windows_ad::Organisationalunit <| |> -> Windows_ad::Group <| |> -> Windows_ad::User <| |> -> Windows_ad::Groupmembers <| |> + anchor{'windows_ad::begin':} -> Class['windows_ad::install'] -> Class['windows_ad::conf_forest'] -> anchor{'windows_ad::end':} -> Windows_ad::Organisationalunit <| |> -> Windows_ad::Group <| |> -> Windows_ad::User <| |> -> Windows_ad::Group_members <| |> }else{ if($configure == present){ fail('You can\'t desactivate the Role ADDS without uninstall ADDSControllerDomain first') }else{ - anchor{'windows_ad::begin':} -> Class['windows_ad::conf_forest'] -> Class['windows_ad::install'] -> anchor{'windows_ad::end':} + anchor{'windows_ad::begin':} -> Class['windows_ad::conf_forest'] -> Class['windows_ad::install'] -> anchor{'windows_ad::end':} } } }else{ - anchor{'windows_ad::begin':} -> Windows_ad::Organisationalunit <| |> -> Windows_ad::Group <| |> -> Windows_ad::User <| |> -> Windows_ad::Groupmembers <| |> -> anchor{'windows_ad::end':} + anchor{'windows_ad::begin':} -> Windows_ad::Organisationalunit <| |> -> Windows_ad::Group <| |> -> Windows_ad::User <| |> -> Windows_ad::Group_members <| |> -> anchor{'windows_ad::end':} } if type($groups_hiera_merge) == 'string' { @@ -161,6 +165,6 @@ $usersingroup_real = $usersingroup } validate_hash($usersingroup_real) - create_resources('windows_ad::groupmembers',$usersingroup_real) + create_resources('windows_ad::group_members',$usersingroup_real) } -} \ No newline at end of file +} diff --git a/manifests/install.pp b/manifests/install.pp index 831ba84..9459b75 100644 --- a/manifests/install.pp +++ b/manifests/install.pp @@ -20,17 +20,19 @@ # === Authors # # Jerome RIVIERE (www.jerome-riviere.re) +# Karol Kozakowski # # === Copyright # # Copyright 2014 Jerome RIVIERE. +# Copyright 2017 Karol Kozakowski # class windows_ad::install ( - $ensure = $ensure, - $installmanagementtools = $installmanagementtools, - $installsubfeatures = $installsubfeatures, - $restart = $restart, - $installflag = $installflag, + $ensure, + $installmanagementtools, + $installsubfeatures, + $restart, + $installflag, ) { validate_re($ensure, '^(present|absent)$', 'valid values for ensure are \'present\' or \'absent\'') @@ -51,7 +53,7 @@ } # Windows 2008 R2 and newer required http://technet.microsoft.com/en-us/library/ee662309.aspx - if $::kernelversion !~ /^(6\.1|6\.2|6\.3)/ { fail ("${module_name} requires Windows 2008 R2 or newer") } + if $::kernelversion !~ /^(6\.1|6\.2|6\.3|10\.0)/ { fail ("${module_name} requires Windows 2008 R2 or newer") } # from Windows 2012 'Add-WindowsFeature' has been replaced with 'Install-WindowsFeature' http://technet.microsoft.com/en-us/library/ee662309.aspx if ($ensure == 'present') { diff --git a/manifests/params.pp b/manifests/params.pp new file mode 100644 index 0000000..3e347aa --- /dev/null +++ b/manifests/params.pp @@ -0,0 +1,41 @@ +class windows_ad::params { + $install = 'present' + $installmanagementtools = true + $installsubfeatures = false + $restart = false + $installflag = true + $configure = 'present' + $domain = 'forest' + $domainname = undef + $netbiosdomainname = undef + $configureflag = true + $domainlevel = '6' + $forestlevel = '6' + $installdns = 'yes' + $globalcatalog = 'yes' + $kernel_ver = $::kernelversion + $databasepath = 'c:\\windows\ntds' + $logpath = 'c:\\windows\ntds' + $sysvolpath = 'c:\\windows\sysvol' + $dsrmpassword = undef + + $localadminpassword = undef + $force = true + $forceremoval = true + $uninstalldnsrole = 'yes' + $demoteoperationmasterrole = true + + $secure_string_pwd = undef + $installtype = undef + $domaintype = undef + $sitename = undef + + $groups = undef + $groups_hiera_merge = true + $users = undef + $users_hiera_merge = true + $usersingroup = undef + $usersingroup_hiera_merge = true + + $timeout = 240 +} diff --git a/manifests/user.pp b/manifests/user.pp index 9f76b38..b868cc5 100644 --- a/manifests/user.pp +++ b/manifests/user.pp @@ -46,16 +46,18 @@ # === Authors # # Jerome RIVIERE (www.jerome-riviere.re) +# Karol Kozakowski (cosaquee.com) # # === Copyright # # Copyright 2014 Jerome RIVIERE. +# Copyright 2017 Karol Kozakowski # define windows_ad::user( + $domainname, + $path, + $accountname, $ensure = present, # add or delete user - $domainname = $domainname, # the domain name like : jre.local - $path = $path, # where is located the account - $accountname = $accountname, # is samaccountname $lastname = '', # is lastname $firstname = '', # is firstname $fullname = '', # is fullname @@ -68,7 +70,6 @@ $writetoxmlflag = true, # Flag that makes writing to the users.xml optional $xmlpath = 'C:\\users.xml', # file where to save user info. Default set to C:\\users.xml -# delete user $confirmdeletion = false, # delete wihtout confirmation ){ validate_re($ensure, '^(present|absent)$', 'valid values for ensure are \'present\' or \'absent\'') @@ -92,26 +93,43 @@ } } } - if($ensure == 'present'){ - if(empty($fullname)){ - if(empty($lastname) and !empty($firstname)){ + if ($ensure == 'present') { + if (empty($fullname)) { + if (empty($lastname) and !empty($firstname)) { $fullnamevalue = $firstname } - if(!empty($lastname) and empty($firstname)){ + + if (!empty($lastname) and empty($firstname)) { $fullnamevalue = $lastname } - if(!empty($lastname) and !empty($firstname)){ + + if (!empty($lastname) and !empty($firstname)) { $fullnamevalue = "${firstname} ${lastname}" } - }else{ + + } else { $fullnamevalue = $fullname } - if(!empty($emailaddress)){$emailaddressparam = "-EmailAddress '$emailaddress'"} - if(!empty($fullnamevalue)){$fullnameparam = "-DisplayName '$fullnamevalue'"} - if(!empty($description)){$descriptionparam = "-Description '${description}'"} - if(!empty($firstname)){$givenparam = "-GivenName '${firstname}'"} - if(!empty($lastname)){$lastnameparam = "-SurName '${lastname}'"} + if (!empty($emailaddress)) { + $emailaddressparam = "-EmailAddress '${emailaddress}'" + } + + if (!empty($fullnamevalue)) { + $fullnameparam = "-DisplayName '${fullnamevalue}'" + } + + if (!empty($description)) { + $descriptionparam = "-Description '${description}'" + } + + if (!empty($firstname)) { + $givenparam = "-GivenName '${firstname}'" + } + + if (!empty($lastname)) { + $lastnameparam = "-SurName '${lastname}'" + } if(empty($password)){ $pwd = get_random_password($passwordlength) @@ -128,6 +146,7 @@ } $userprincipalname = "${accountname}@${domainname}" + exec { "Delete User Desc - ${accountname}": command => "import-module activedirectory;\$user = Get-ADUser -Identity '${accountname}' -Properties Description;Set-ADUser -identity ${accountname} -Remove @{description=\$user.description}", onlyif => "\$user = Get-ADUser -Identity '${accountname}' -Properties *;if((dsquery.exe user -samid ${accountname}) -and ('${description}' -ne \$user.Description -and \$user.Description -ne \$null)){}else{exit 1}", diff --git a/metadata.json b/metadata.json index c55ece7..fbee1ec 100644 --- a/metadata.json +++ b/metadata.json @@ -25,7 +25,6 @@ "lib/puppet/parser/functions/validate_password.rb": "dc6f2d87967e86882e49a09b9e3e0ca7", "manifests/conf_forest.pp": "2d8de6a9deddaa47711b7684e6c7c43f", "manifests/group.pp": "23411b40b610d7d96c9bfcb78b4b38eb", - "manifests/groupmembers.pp": "c0816b35a1fc6df3e9c3ab72216c619a", "manifests/init.pp": "d4d15639d76246871c8c3f6a3196bdff", "manifests/install.pp": "02d4dff5c898bf26bf37d25b7bdae2fb", "manifests/organisationalunit.pp": "c1925a20f4cb0da1cf8cb4247a635d4d", diff --git a/spec/classes/.fixtures.yaml b/spec/classes/.fixtures.yaml new file mode 100644 index 0000000..90924bd --- /dev/null +++ b/spec/classes/.fixtures.yaml @@ -0,0 +1,4 @@ +fixtures: + repositories: + firewall: "git://github.com/puppetlabs/puppetlabs-firewall" + stdlib: "git://github.com/puppetlabs/puppetlabs-stdlib" diff --git a/spec/classes/init_spec.rb b/spec/classes/init_spec.rb new file mode 100644 index 0000000..df03593 --- /dev/null +++ b/spec/classes/init_spec.rb @@ -0,0 +1,19 @@ +require 'spec_helper' + +describe 'windows_ad' do + context 'with default values for all parameters' do + let(:facts) do + { + kernelversion: '6.2', + operatingsystem: 'windows', + } + end + + let(:params) do + { + installsubfeatures: false + } + end + it { should contain_class('windows_ad') } + end +end diff --git a/spec/fixtures/manifests/site.pp b/spec/fixtures/manifests/site.pp new file mode 100644 index 0000000..e69de29 diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 5fda588..421fd71 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,17 +1,9 @@ -dir = File.expand_path(File.dirname(__FILE__)) -$LOAD_PATH.unshift File.join(dir, 'lib') +require 'rspec-puppet' +require 'puppetlabs_spec_helper/module_spec_helper' -require 'mocha' -require 'puppet' -require 'rspec' -require 'spec/autorun' +fixture_path = File.expand_path(File.join(__FILE__, '..', 'fixtures')) -Spec::Runner.configure do |config| - config.mock_with :mocha -end - -# We need this because the RAL uses 'should' as a method. This -# allows us the same behaviour but with a different method name. -class Object - alias :must :should +RSpec.configure do |c| + c.module_path = File.join(fixture_path, 'modules') + c.manifest_dir = File.join(fixture_path, 'manifests') end diff --git a/templates/templates b/templates/templates new file mode 120000 index 0000000..f8a06d1 --- /dev/null +++ b/templates/templates @@ -0,0 +1 @@ +../../../../templates \ No newline at end of file