├── CHANGELOG.md ├── LICENSE ├── README.md ├── manifests ├── autologon.pp ├── environment.pp ├── firewall_rule.pp ├── iis_express.pp ├── init.pp ├── java.pp ├── nssm.pp ├── params.pp ├── path.pp ├── power_scheme.pp ├── refresh_environment.pp ├── regsvr32.pp ├── screen_saver.pp ├── shortcut.pp ├── unzip.pp └── update.pp ├── metadata.json └── templates ├── download_java.ps1.erb ├── ez_setup.py.erb ├── firewall_rule.erb ├── path_check.ps1.erb ├── path_set.ps1.erb ├── powercfg_check.ps1.erb ├── refresh_environment.ps1.erb ├── regsvr32.ps1.erb ├── screen_saver_check.ps1.erb ├── screen_saver_set.ps1.erb ├── shortcut.ps1.erb └── unzip.ps1.erb /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 1.0.6 (8/13/2017) 2 | 3 | BUG FIXES: 4 | * Fix kernel version comparison (@rogerlz) 5 | 6 | ## 1.0.5 (8/5/2017) 7 | 8 | BUG FIXES: 9 | * Fix regex validation of update time (@makomatic) 10 | * Fix for newer versions of windows update service (@rogerlz) 11 | 12 | ## 1.0.4 (10/15/2016) 13 | 14 | IMPROVEMENTS: 15 | * Allow newer versions of puppetlabs/powershell. 16 | 17 | ## 1.0.3 (06/07/2016) 18 | 19 | IMPROVEMENTS: 20 | * Allow arbitrary shortcut link targets (to support URLs and shell objects) 21 | 22 | ## 1.0.2 (08/28/2015) 23 | 24 | IMPROVEMENTS: 25 | * Updated default Java version to 8u60. 26 | 27 | ## 1.0.1 (08/17/2015) 28 | 29 | IMPROVEMENTS: 30 | * Updated default Java version to 8u51. 31 | 32 | ## 1.0.0 (06/17/2015) 33 | 34 | BUG FIXES: 35 | * Fixed disabling screen saver via @etlweather (GH-4) 36 | * Add support for Java 8 via Aloysius Lim (GH-5) 37 | * Fix linting issues. 38 | 39 | FEATURES: 40 | * Added the `windows::power_scheme` class. 41 | * Added `$windows::java::home` variable. 42 | * Allow customization of icon in `windows::shortcut`. 43 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2013-2015 Counsyl, Inc. 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | windows 2 | ======= 3 | 4 | This module provides Puppet configurations for common Windows administration. 5 | 6 | Windows Classes 7 | --------------- 8 | 9 | ### `windows::autologon` 10 | 11 | Configures automatic logon for the system for the given user. For example: 12 | 13 | ```puppet 14 | class { 'windows::autologon': 15 | user => 'justin', 16 | password => 's3kr1t', 17 | } 18 | ``` 19 | 20 | ### `windows::iis_express` 21 | 22 | Downloads and installs [IIS Express 8](http://www.microsoft.com/en-ca/download/details.aspx?id=34679). 23 | 24 | ### `windows::java` 25 | 26 | Automatically downloads and installs Java from Oracle. Currently, it uses 27 | Java 8 Update 60. Use of this class implies your acceptance of the 28 | [Oracle Binary Code License Agreement for SE Platform Products](http://www.oracle.com/technetwork/java/javase/terms/license/index.html). 29 | 30 | ### `windows::nssm` 31 | 32 | Downloads and installs the [Non-Sucking Service Manager](http://nssm.cc/). 33 | 34 | ### `windows::power_scheme` 35 | 36 | Sets the power scheme for the system, for example: 37 | 38 | ```puppet 39 | class { 'windows::power_scheme': 40 | ensure => 'High performance', 41 | } 42 | ``` 43 | 44 | ### `windows::refresh_environment` 45 | 46 | Contains an `exec` resource that will refresh the current environment -- 47 | used when modifying system variables and having them be reflected 48 | without logging off and/or rebooting. Notify this class after modifying 49 | any system enviornment variable. 50 | 51 | ### `windows::update` 52 | 53 | Configures automatic windows updates, consult its [source](manifests/update.pp) for 54 | more information. 55 | 56 | 57 | Windows Defined Types 58 | --------------------- 59 | 60 | ### `windows::environment` 61 | 62 | Configures a windows environment variable, for example: 63 | 64 | ```puppet 65 | windows::environment { 'PYTHONPATH': 66 | value => 'C:\my_python_path' 67 | } 68 | ``` 69 | 70 | ### `windows::firewall_rule` 71 | 72 | Creates a Windows firewall rule, for a program or a local port. 73 | Some examples: 74 | 75 | ```puppet 76 | # Allow ICMP ping. 77 | windows::firewall_rule { 'ICMP Ping': 78 | protocol => 'icmpv4:8,any', 79 | } 80 | 81 | # Allow Python 2.7. 82 | windows::firewall_rule { 'python2.7': 83 | program => 'C:\Python27\python.exe', 84 | } 85 | ``` 86 | 87 | ### `windows::path` 88 | 89 | Ensures that the given directory is a part of the Windows `%Path%`, e.g.: 90 | 91 | ```puppet 92 | windows::path { 'C:\Python27': } 93 | ``` 94 | 95 | ### `windows::regsvr32` 96 | 97 | Registers a DLL (or other control) specificed by the resource's name as 98 | a component in the registry. 99 | 100 | ### `windows::screen_saver` 101 | 102 | Configures a screen saver (specified by the given user name). For example, 103 | this configures the blank screen saver for the user `justin` to engage after 104 | 10 minutes, and requiring a password to log back in: 105 | 106 | ```puppet 107 | windows::screen_saver { 'justin': 108 | secure => true, 109 | timeout => '10m', 110 | } 111 | ``` 112 | 113 | ### `windows::shortcut` 114 | 115 | Configures a windows shortcut, for example: 116 | 117 | ```puppet 118 | windows::shortcut { 'C:\Users\justin\Desktop\python.lnk': 119 | target => 'C:\Python27\python.exe', 120 | description => 'Python 2.7', 121 | } 122 | ``` 123 | 124 | ### `windows::unzip` 125 | 126 | Unzips a file on Windows using Microsoft native APIs. For example: 127 | 128 | ```puppet 129 | windows::unzip { 'C:\compressed.zip': 130 | destination => 'C:\dest', 131 | creates => 'C:\dest\uncompressed.txt', 132 | } 133 | ``` 134 | 135 | This assumes that the file `uncompressed.txt` exists in `C:\compressed.zip` 136 | 137 | License 138 | ------- 139 | 140 | Apache License, Version 2.0 141 | 142 | Contact 143 | ------- 144 | 145 | Justin Bronn 146 | 147 | Support 148 | ------- 149 | 150 | Please log tickets and issues at https://github.com/counsyl/puppet-windows 151 | -------------------------------------------------------------------------------- /manifests/autologon.pp: -------------------------------------------------------------------------------- 1 | # == Class: windows::autologon 2 | # 3 | # Enable automatic logon to the Windows PC. 4 | # 5 | # === Parameters 6 | # 7 | # [*ensure*] 8 | # Ensure value, defaults to 'enabled'. Set to 'absent' or 'disabled' to 9 | # disable automatic logon. 10 | # 11 | # [*user*] 12 | # Username to enable automatic logon for required when `ensure => 'enabled'`. 13 | # 14 | # [*password*] 15 | # Password to use for automatic logon, required if there's a password set 16 | # for the username. 17 | # 18 | # [*force*] 19 | # Sets the `ForceAutoLogon` key if set, defaults to false. 20 | # 21 | # [*key*] 22 | # Advanced parameter, should not need to change. The base windows registry 23 | # key for automatic logon settings, defaults to: 24 | # 'HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon' 25 | # 26 | class windows::autologon( 27 | $ensure = 'enabled', 28 | $user = undef, 29 | $password = undef, 30 | $domain = undef, 31 | $force = false, 32 | $key = 'HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon', 33 | ) { 34 | case $ensure { 35 | 'enabled', 'present': { 36 | if ! $user { 37 | fail("Must provide a user parameter for windows::autologon.\n") 38 | } 39 | 40 | registry_value { "${key}\\AutoAdminLogon": 41 | ensure => present, 42 | data => '1', 43 | } 44 | 45 | registry_value { "${key}\\DefaultUsername": 46 | ensure => present, 47 | data => $user, 48 | } 49 | 50 | if $password { 51 | registry_value { "${key}\\DefaultPassword": 52 | ensure => present, 53 | data => $password, 54 | } 55 | } 56 | 57 | if $domain { 58 | registry_value { "${key}\\DefaultDomainName": 59 | ensure => present, 60 | data => $domain, 61 | } 62 | } 63 | 64 | if $force { 65 | registry_value { "${key}\\ForceAutoLogon": 66 | ensure => present, 67 | data => '1', 68 | } 69 | } 70 | } 71 | 'disabled', 'absent': { 72 | registry_value { "${key}\\AutoAdminLogon": 73 | ensure => present, 74 | data => '0', 75 | } 76 | 77 | registry_value { ["${key}\\DefaultUsername", "${key}\\DefaultPassword", 78 | "${key}\\DefaultDomainName", "${key}\\ForceAutoLogon"]: 79 | ensure => absent, 80 | } 81 | } 82 | default: { 83 | fail("Invalid ensure value for windows::autologon.\n") 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /manifests/environment.pp: -------------------------------------------------------------------------------- 1 | # == Define: windows::environment 2 | # 3 | # Set Windows environment variable to the given value. 4 | # 5 | # === Parameters 6 | # 7 | # [*value*] 8 | # The value that the environment variable should be, required by default 9 | # (when ensure = 'present'). 10 | # 11 | # [*ensure*] 12 | # The ensure value for the resource, must be 'present' or 'absent'. 13 | # Defaults to 'present'. When set to 'absent', the environment variable 14 | # is removed. 15 | # 16 | # [*variable*] 17 | # The environment variable to set, defaults to the name of the resource. 18 | # 19 | # [*target*] 20 | # The location where an environment variable is stored, must be either 21 | # 'Machine' (the default) or 'User'. 22 | # 23 | define windows::environment( 24 | $value = undef, 25 | $ensure = 'present', 26 | $variable = $name, 27 | $target = 'Machine', 28 | ) { 29 | 30 | # Ensure only valid target parameter. 31 | validate_re($target, '^(Machine|User)$', 'Invalid target parameter') 32 | 33 | case $ensure { 34 | 'present': { 35 | if (! $value) { 36 | fail("Must provide a value to set ${variable} with.\n") 37 | } 38 | $command = "[Environment]::SetEnvironmentVariable(\"${variable}\", \"${value}\", \"${target}\")" 39 | $unless = "if ([Environment]::GetEnvironmentVariable(\"${variable}\", \"${target}\") -ne \"${value}\"){ exit 1 }" 40 | } 41 | 'absent': { 42 | $command = "[Environment]::SetEnvironmentVariable(\"${variable}\", \$null, \"${target}\")" 43 | $unless = "if ([Environment]::GetEnvironmentVariable(\"${variable}\", \"${target}\") -ne \$null){ exit 1 }" 44 | } 45 | default: { 46 | fail("Invalid windows::environment ensure value.\n") 47 | } 48 | } 49 | 50 | # Execute the command that sets or unsets the environment variable, and 51 | # refresh the environment. 52 | include windows::refresh_environment 53 | exec { "env-${name}-${target}": 54 | command => $command, 55 | unless => $unless, 56 | provider => 'powershell', 57 | notify => Class['windows::refresh_environment'], 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /manifests/firewall_rule.pp: -------------------------------------------------------------------------------- 1 | # == Define: windows::firewall_rule 2 | # 3 | # Creates a Windows firewall rule. 4 | # 5 | # == Parameters 6 | # 7 | # For more information on the parameters, please consult: 8 | # http://support.microsoft.com/kb/947709 9 | # 10 | # [*ensure*] 11 | # Defaults to 'present', set to 'absent' to ensure the firewall rule is 12 | # deleted. 13 | # 14 | # [*program*] 15 | # Path to the program to allow through the firewall; either this or the 16 | # `localport` parameter is required. 17 | # 18 | # [*protocol*] 19 | # The network protocol to use, e.g., 'tcp', 'udp', 'icmpv4'. 20 | # 21 | # [*localport*] 22 | # The localport to open up through the firewall, if provided the `protocol` 23 | # parameter must also be specified. 24 | # 25 | define windows::firewall_rule( 26 | $ensure = 'present', 27 | $program = undef, 28 | $protocol = undef, 29 | $localport = undef, 30 | $description = undef, 31 | $remoteport = undef, 32 | $remoteip = undef, 33 | $dir = 'in', 34 | $action = 'allow', 35 | $enable = 'yes', 36 | $profile = undef, 37 | ) { 38 | # Location of netsh executable and the condition command (which only checks if 39 | # the rule exists at this point). The condition command will be used for 40 | # with `onlyif` or `unless`, depending on the ensure value. 41 | $netsh = 'C:\WINDOWS\system32\netsh.exe' 42 | $condition = "${netsh} advfirewall firewall show rule name=\"${title}\"" 43 | 44 | case $ensure { 45 | 'present': { 46 | # Make sure there's at least a program or a localport specified. 47 | if (! $program and ! $localport and ! $protocol) { 48 | fail("Must provide either a program, localport, or protocol for the Windows firewall rule.\n") 49 | } 50 | 51 | if ( $localport and ! $protocol) { 52 | fail("Must provide a protocol when specifying a localport Windows firewall rule.\n") 53 | } 54 | 55 | # The command is constructed from template, which sets the proper 56 | # parameters for the `netsh advfirewall firewall add rule` command. 57 | exec { "windows-firewall-${title}": 58 | command => template('windows/firewall_rule.erb'), 59 | unless => $condition, 60 | } 61 | } 62 | 'absent': { 63 | exec { "windows-firewall-${title}": 64 | command => "${netsh} advfirewall firewall delete rule name=\"${title}\"", 65 | onlyif => $condition, 66 | } 67 | } 68 | default: { 69 | fail("Invalid ensure value for `windows::firewall_rule` must be 'present' or 'absent'.\n") 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /manifests/iis_express.pp: -------------------------------------------------------------------------------- 1 | # == Class: windows::iis_express 2 | # 3 | # Installs IIS Express 8.0. 4 | # 5 | class windows::iis_express( 6 | $base_url = 'http://download.microsoft.com/download/1/6/3/163BBBDE-5523-416D-A293-EA0492020E4A/', 7 | $basename = "iisexpress_8_0_RTM_${::architecture}_en-US.msi", 8 | $package = 'IIS 8.0 Express', 9 | $source = undef, 10 | $path = 'C:\Program Files\IIS Express\iisexpress.exe', 11 | $appcmd = 'C:\Program Files\IIS Express\appcmd.exe', 12 | ) { 13 | # Constructing the $source_uri. 14 | if $source { 15 | $source_uri = $source 16 | } else { 17 | $source_uri = "${base_url}${basename}" 18 | } 19 | 20 | # If a non-UNC URL is used, download the MSI with sys::fetch. 21 | if $source_uri !~ /^[\\]+/ { 22 | include windows 23 | $iis_source = "${windows::installers}\\${basename}" 24 | sys::fetch { 'download-iis': 25 | destination => $iis_source, 26 | source => $source_uri, 27 | before => Package[$package], 28 | } 29 | } else { 30 | $iis_source = $source_uri 31 | } 32 | 33 | # Install IIS Express. 34 | package { $package: 35 | ensure => installed, 36 | source => $iis_source, 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /manifests/init.pp: -------------------------------------------------------------------------------- 1 | # == Class: windows 2 | # 3 | # Creates resources used by other Windows manifests, e.g., the location to 4 | # place downloaded installers. 5 | # 6 | # === Parameters 7 | # 8 | # [*installers*] 9 | # The directory where other manifests place their downloaded installation 10 | # files, defaults to 'C:\ProgramData\installers'. 11 | # 12 | class windows( 13 | $installers = "${windows::params::programdata}\\installers", 14 | ) inherits windows::params { 15 | # Ensure directory to store installers exists. 16 | file { $installers: 17 | ensure => directory, 18 | } 19 | 20 | # Location of commonly-used programs from system32. 21 | $certutil = "${windows::params::system32}\\certutil.exe" 22 | $cmd = "${windows::params::system32}\\cmd.exe" 23 | $regsvr32 = "${windows::params::system32}\\regsvr32.exe" 24 | } 25 | -------------------------------------------------------------------------------- /manifests/java.pp: -------------------------------------------------------------------------------- 1 | # == Class: windows::java 2 | # 3 | # Downloads and installs the Java Runtime Environment. Use of this 4 | # class implies you accept Oracle's Java SE license: 5 | # 6 | # http://www.oracle.com/technetwork/java/javase/terms/license/index.html 7 | # 8 | class windows::java( 9 | $version = '8', 10 | $update = '60', 11 | $build = '27', 12 | $base_url = 'http://download.oracle.com/otn-pub/java/jdk/', 13 | $arch = undef, 14 | $referrer = 'http://edelivery.oracle.com', 15 | ) { 16 | include windows 17 | 18 | # If user passed in architecture parameter, use it for `$java_arch`, 19 | # otherwise use i586 (for x86 systems). 20 | if $arch { 21 | $java_arch = $arch 22 | } else { 23 | case $::architecture { 24 | 'x64': { 25 | $java_arch = 'x64' 26 | } 27 | 'x86': { 28 | $java_arch = 'i586' 29 | } 30 | default: { 31 | fail("Unknown architecture for JRE: ${::architecture}") 32 | } 33 | } 34 | } 35 | 36 | # Determining Java's home depending on the version. 37 | if $version == '7' { 38 | $home = 'C:\Program Files\Java\jre7' 39 | } else { 40 | $home = "C:\\Program Files\\Java\\jre1.${version}.0_${update}" 41 | } 42 | $path = "${home}\\bin" 43 | 44 | # Setting up variables for downloading the JRE. 45 | $jre_basename = "jre-${version}u${update}-windows-${java_arch}.exe" 46 | $jre_installer = "${windows::installers}\\${jre_basename}" 47 | $jre_url = "${base_url}${version}u${update}-b${build}/${jre_basename}" 48 | $cookie = "oraclelicense=accept-securebackup-cookie;gpw_e24=${referrer}" 49 | 50 | # Download the JRE using a PowerShell script that sets the license accepted cookie. 51 | exec { 'download-java': 52 | command => template('windows/download_java.ps1.erb'), 53 | creates => $jre_installer, 54 | provider => 'powershell', 55 | require => File[$windows::installers], 56 | } 57 | 58 | # Determining the Java package name. 59 | if $java_arch == 'x64' { 60 | $java_package = "Java ${version} Update ${update} (64-bit)" 61 | } else { 62 | $java_package = "Java ${version} Update ${update}" 63 | } 64 | 65 | package { $java_package: 66 | ensure => installed, 67 | source => $jre_installer, 68 | install_options => ['/s'], 69 | require => Exec['download-java'], 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /manifests/nssm.pp: -------------------------------------------------------------------------------- 1 | # == Class: windows::nssm 2 | # 3 | # Installs NSSM: the Non-Sucking Service Manager. 4 | # 5 | # === Parameters 6 | # 7 | # [*version*] 8 | # The version of NSSM to install, defaults to '2.24'. 9 | # 10 | # [*base_url*] 11 | # The base URL to download the NSSM ZIP file from, defaults to: 12 | # 'http://nssm.cc/download/'. Must have a trailing slash. 13 | # 14 | # [*destination*] 15 | # The root folder where the NSSM ZIP file is extracted to, defaults 16 | # to 'C:\Program Files'. 17 | # 18 | class windows::nssm( 19 | $version = '2.24', 20 | $base_url = 'http://nssm.cc/download/', 21 | $destination = 'C:\Program Files' 22 | ) { 23 | include windows 24 | $basename = "nssm-${version}.zip" 25 | $nssm_url = "${base_url}${basename}" 26 | $nssm_zip = "${windows::installers}\\${basename}" 27 | 28 | # The root location of NSSM. 29 | $root = "${destination}\\nssm-${version}" 30 | 31 | # Setting the path depending on the system architecture. 32 | if $::architecture == 'x64' { 33 | $path = "${root}\\win64" 34 | } else { 35 | $path = "${root}\\win32" 36 | } 37 | 38 | # Download the NSSM zip archive. 39 | sys::fetch { 'download-nssm': 40 | source => $nssm_url, 41 | destination => $nssm_zip, 42 | require => File[$windows::installers], 43 | } 44 | 45 | # Unzip the NSSM archive into the destination, creating the root folder. 46 | windows::unzip { $nssm_zip: 47 | destination => $destination, 48 | creates => $root, 49 | require => Sys::Fetch['download-nssm'], 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /manifests/params.pp: -------------------------------------------------------------------------------- 1 | # == Class: windows::params 2 | # 3 | # Parameters for Windows. Has one parameter, `$system_root`, which may 4 | # be used to account for when the Windows root drive is not 'C:\'. 5 | # 6 | class windows::params( 7 | $system_root = "C:\\", 8 | ) { 9 | if $::osfamily != 'windows' { 10 | fail('The windows module is only supported on Microsoft Windows.') 11 | } 12 | 13 | # Program Data 14 | $programdata = "${system_root}ProgramData" 15 | 16 | # Windows directory. 17 | $windir = "${system_root}Windows" 18 | 19 | # Windows system directory. 20 | $system32 = "${windir}\\system32" 21 | 22 | # Location of commonly-used programs from system32. 23 | $certutil = "${system32}\\certutil.exe" 24 | $cmd = "${system32}\\cmd.exe" 25 | $regsvr32 = "${system32}\\regsvr32.exe" 26 | } 27 | -------------------------------------------------------------------------------- /manifests/path.pp: -------------------------------------------------------------------------------- 1 | # == Define: windows::path 2 | # 3 | # Ensures the given directory (specified by the resource name or `path` parameter) 4 | # is a part of the Windows System %PATH%. 5 | # 6 | # == Parameters 7 | # 8 | # [*directory*] 9 | # The directory to add the Windows PATH, defaults to the name of the resource. 10 | # 11 | # [*target*] 12 | # The location where the PATH variable is stored, must be either 'Machine' 13 | # (the default) or 'User'. 14 | # 15 | define windows::path( 16 | $ensure = 'present', 17 | $directory = $name, 18 | $target = 'Machine', 19 | ) { 20 | # Ensure only valid parameters. 21 | validate_absolute_path($directory) 22 | validate_re($ensure, '^(present|absent)$', 'Invalid ensure parameter') 23 | validate_re($target, '^(Machine|User)$', 'Invalid target parameter') 24 | 25 | # Set the PATH environment variable, and refresh the environment. 26 | include windows::refresh_environment 27 | exec { "windows-path-${name}": 28 | command => template('windows/path_set.ps1.erb'), 29 | unless => template('windows/path_check.ps1.erb'), 30 | provider => 'powershell', 31 | notify => Class['windows::refresh_environment'], 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /manifests/power_scheme.pp: -------------------------------------------------------------------------------- 1 | # == Class: windows::power_scheme 2 | # 3 | # Configures the power scheme used by Windows. 4 | # 5 | # === Parameters 6 | # 7 | # [*ensure*] 8 | # The power scheme to use, defaults to 'Balanced'. Must correspond to a key in the 9 | # `$guids` parameter. 10 | # 11 | # [*guids*] 12 | # A mapping of power scheme names to their GUID. The default schemes supported are: 13 | # 'Balanced', 'High performance', and 'Power saver'. 14 | # 15 | class windows::power_scheme( 16 | $ensure = 'Balanced', 17 | $guids = { 18 | 'Balanced' => '381b4222-f694-41f0-9685-ff5bb260df2e', 19 | 'High performance' => '8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c', 20 | 'Power saver' => 'a1841308-3541-4fab-bc81-f71556f20b4a', 21 | } 22 | ){ 23 | validate_string($ensure) 24 | validate_hash($guids) 25 | 26 | # Get the GUID for the desired power scheme. 27 | if ! has_key($guids, $ensure) { 28 | fail('There is no GUID for the power scheme.') 29 | } 30 | $guid = $guids[$ensure] 31 | 32 | # Use POWERCFG.EXE to set the desired power scheme. 33 | exec { 'windows-powercfg': 34 | command => "POWERCFG -SETACTIVE ${guid}", 35 | unless => template('windows/powercfg_check.ps1.erb'), 36 | provider => 'powershell', 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /manifests/refresh_environment.pp: -------------------------------------------------------------------------------- 1 | # == Class: windows::refresh_environment 2 | # 3 | # Refresh the Windows Environment. Makes it possible to have updated Windows 4 | # environment variables (e.g., the %Path%) without logging off or restarting. 5 | # 6 | class windows::refresh_environment( 7 | $command_template = 'windows/refresh_environment.ps1.erb', 8 | $refreshonly = true, 9 | $unless = undef, 10 | $onlyif = undef, 11 | $provider = 'powershell', 12 | ){ 13 | exec { 'windows-refresh-environemnt': 14 | command => template($command_template), 15 | refreshonly => $refreshonly, 16 | unless => $unless, 17 | onlyif => $onlyif, 18 | provider => $provider, 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /manifests/regsvr32.pp: -------------------------------------------------------------------------------- 1 | # == Define: regsvr32 2 | # 3 | # Registers a DLL (or other control) specfied by the resources name as a 4 | # component in the registry. 5 | # 6 | # === Parameters 7 | # 8 | # [*clsid*] 9 | # Required, the GUID(s) created in 'HKEY_CLASSES_ROOT\CLSID' when the DLL 10 | # is registered. May be an array or a single string, and each GUID should 11 | # be enclosed in brackets, e.g., '{B125EE95-7C15-4FCA-8D78-1707DD4ECC81}'. 12 | # 13 | # [*dll*] 14 | # The path to the DLL to register, defaults to the resource name. 15 | # 16 | # [*wow64*] 17 | # Are the class GUID(s) located on the Windows 32-bit on Windows 64-bit 18 | # (WoW64) registry node. Defaults to true on 64-bit systems, set to false 19 | # if the class GUID(s) are native 64-bit. 20 | # 21 | define windows::regsvr32( 22 | $clsid, 23 | $ensure = 'present', 24 | $dll = $name, 25 | $wow64 = $::architecture == 'x64', 26 | ) { 27 | include windows 28 | 29 | # Calculating the HKEY_CLASSES_ROOT location, depending on whether we 30 | # are using WoW64 or not. 31 | if $wow64 { 32 | $hkcr = 'Registry::HKEY_CLASSES_ROOT\Wow6432Node\CLSID' 33 | } else { 34 | $hkcr = 'Registry::HKEY_CLASSES_ROOT\CLSID' 35 | } 36 | 37 | case $ensure { 38 | 'present': { 39 | $command = "${windows::regsvr32} \"${dll}\"" 40 | $unless = template('windows/regsvr32.ps1.erb') 41 | } 42 | 'absent': { 43 | $command = "${windows::regsvr32} /u \"${dll}\"" 44 | $onlyif = template('windows/regsvr32.ps1.erb') 45 | } 46 | default: { 47 | fail("Invalid ensure value for windows::regsvr32.\n") 48 | } 49 | } 50 | 51 | exec { "regsvr32-${name}": 52 | command => $command, 53 | unless => $unless, 54 | onlyif => $onlyif, 55 | provider => 'powershell', 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /manifests/screen_saver.pp: -------------------------------------------------------------------------------- 1 | # == Define: windows::screen_saver 2 | # 3 | # Sets up screen saver settings for the user of the given name. 4 | # 5 | # === Parameters 6 | # 7 | # [*ensure*] 8 | # Ensure value for this resource, defaults to 'present'. Set to 'absent' or 9 | # 'disabled' to disable the screen saver for the user. 10 | # 11 | # [*user*] 12 | # The user to set the screen saver for, defaults to the name of the resource. 13 | # 14 | # [*domain*] 15 | # Domain the user belongs, default is undefined. 16 | # 17 | # [*exe*] 18 | # The executable to use for the screen saver, defaults to: 19 | # 'C:\Windows\system32\scrnsave.scr' (the blank screen saver). 20 | # 21 | # [*secure*] 22 | # Whether a password is required to unlock the screen saver, default is false. 23 | # 24 | # [*timeout*] 25 | # How long until the screen saver activates, may be specified as 26 | # seconds ('3600'), minutes ('60m'), or hours ('1h'). Default is 27 | # '300' (5 minutes). 28 | # 29 | define windows::screen_saver( 30 | $ensure = 'present', 31 | $user = $name, 32 | $domain = undef, 33 | $exe = 'C:\Windows\system32\scrnsave.scr', 34 | $secure = false, 35 | $timeout = 300, 36 | ) { 37 | validate_re($ensure, '^(present|enabled|absent|disabled)$') 38 | validate_string($user) 39 | validate_absolute_path($exe) 40 | validate_bool($secure) 41 | validate_re($timeout, '^\d+[mMhH]?$') 42 | 43 | if $ensure in ['present', 'enabled'] { 44 | $active_value = 1 45 | } else { 46 | $active_value = 0 47 | } 48 | 49 | if $secure { 50 | $secure_value = 1 51 | } else { 52 | $secure_value = 0 53 | } 54 | 55 | if $timeout =~ /^(\d+)([MmHh])$/ { 56 | case $2 { 57 | 'm': { 58 | $timeout_minutes = $1 59 | $timeout_seconds = inline_template('<%= Integer(@timeout_minutes) * 60 %>') 60 | } 61 | 'h': { 62 | $timeout_hours = $1 63 | $timeout_seconds = inline_template('<%= Integer(@timeout_hours) * 3600) %>') 64 | } 65 | default: { 66 | fail('Unknown timeout format.') 67 | } 68 | } 69 | } else { 70 | $timeout_seconds = $timeout 71 | } 72 | 73 | exec { "screen-saver-${user}": 74 | command => template('windows/screen_saver_set.ps1.erb'), 75 | unless => template('windows/screen_saver_check.ps1.erb'), 76 | provider => 'powershell', 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /manifests/shortcut.pp: -------------------------------------------------------------------------------- 1 | # == Define: windows::shortcut 2 | # 3 | # Creates a shortcut for the given path (should end in *.lnk) to the given 4 | # target file. 5 | # 6 | define windows::shortcut( 7 | $target, 8 | $path = $title, 9 | $arguments = undef, 10 | $description = undef, 11 | $icon_location = undef, 12 | $working_directory = undef, 13 | ) { 14 | validate_re($path, '\.[lL][nN][kK]$') 15 | validate_absolute_path($path) 16 | validate_string($target) 17 | exec { "windows-shortcut-${path}": 18 | command => template('windows/shortcut.ps1.erb'), 19 | creates => $path, 20 | provider => 'powershell', 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /manifests/unzip.pp: -------------------------------------------------------------------------------- 1 | # == Define: windows::unzip 2 | # 3 | # Extracts a ZIP archive on a Windows system. 4 | # 5 | # === Parameters 6 | # 7 | # [*destination*] 8 | # Required, the destination directory to extract the files into. 9 | # 10 | # [*creates*] 11 | # The `creates` parameter for the exec resource that extracts the ZIP file, 12 | # default is undefined. 13 | # 14 | # [*refreshonly*] 15 | # The `refreshonly` parameter for the exec resource that extracts the ZIP file, 16 | # defaults to false. 17 | # 18 | # [*unless*] 19 | # The `unless` parameter for the exec resource that extracts the ZIP file, 20 | # default is undefined. 21 | # 22 | # [*zipfile*] 23 | # The path to the ZIP file to extract, defaults the name of the resource. 24 | # 25 | # [*provider*] 26 | # Advanced parameter, sets the provider for the exec resource that extracts 27 | # the ZIP file, defaults to 'powershell'. 28 | # 29 | # [*options*] 30 | # Advanced parameter, sets the extraction options for the `Folder.CopyHere` 31 | # method: 32 | # 33 | # http://msdn.microsoft.com/en-us/library/windows/desktop/bb787866. 34 | # 35 | # Defaults to 20, which is sum of: 36 | # * 4: Do not display a progress dialog box. 37 | # * 16: Respond with "Yes to All" for any dialog box that is displayed. 38 | # 39 | # [*command_template*] 40 | # Advanced paramter for generating PowerShell that extracts the ZIP file, 41 | # defaults to 'windows/unzip.ps1.erb'. 42 | # 43 | # [*timeout*] 44 | # Execution timeout in seconds for the unzip command; 0 disables timeout, 45 | # defaults to 300 seconds (5 minutes). 46 | # 47 | define windows::unzip( 48 | $destination, 49 | $creates = undef, 50 | $refreshonly = false, 51 | $unless = undef, 52 | $zipfile = $name, 53 | $provider = 'powershell', 54 | $options = '20', 55 | $command_template = 'windows/unzip.ps1.erb', 56 | $timeout = 300, 57 | ) { 58 | validate_absolute_path($destination) 59 | 60 | if (! $creates and ! $refreshonly and ! $unless){ 61 | fail("Must set one of creates, refreshonly, or unless parameters.\n") 62 | } 63 | 64 | exec { "unzip-${name}": 65 | command => template($command_template), 66 | creates => $creates, 67 | refreshonly => $refreshonly, 68 | unless => $unless, 69 | provider => $provider, 70 | timeout => $timeout, 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /manifests/update.pp: -------------------------------------------------------------------------------- 1 | # == Class: windows::update 2 | # 3 | # Configures settings for automatic Windows Updates. 4 | # 5 | # === Parameters 6 | # For more information on these parameters, consult: 7 | # http://technet.microsoft.com/en-us/library/cc708449%28v=ws.10%29.aspx 8 | # 9 | # [*ensure*] 10 | # Defaults to 'enabled', if set to 'disabled' or 'absent' automatic 11 | # windows updates are disabled. 12 | # 13 | # [*all_users*] 14 | # Whether all users (instead of just Administrators) are allowed to install 15 | # and approve/disapprove updates. Defaults to false. 16 | # 17 | # [*type*] 18 | # How windows updates are installed, defaults to '2': 19 | # 20 | # 2 => Notify before download or installation. 21 | # 3 => Automatically download and notify of installation. 22 | # 4 => Automatic download and scheduled installation. 23 | # 5 => Automatic Updates is required, but end users can configure it. 24 | # 25 | # [*detection_frequency*] 26 | # Time between detection cycles, in hours (1-22). Default is undefined. 27 | # 28 | # [*day*] 29 | # Scheduled install day, 1-7 (Sunday-Monday), or 0 for every day. 30 | # Defaults to 0 (every day). Only valid if options parameter is 4. 31 | # 32 | # [*time*] 33 | # Scheduled install time, 0-23 corresponding to hour (in 24-hour format). 34 | # Defaults to 3 (3:00AM). Only valid if options parameter is 4. 35 | # 36 | # [*reboot_required*] 37 | # Whether any logged-on users get to choose whether or not to restart 38 | # their computer, defaults to true. 39 | # 40 | # [*reboot_warning_time*] 41 | # Length, in minutes, of the restart warning countdown after installing 42 | # updates with a deadline or scheduled updates. Default is undefined. 43 | # 44 | # [*recommended_updates*] 45 | # Give recommended updates the same way as important updates, defaults 46 | # to false. 47 | # 48 | # [*reschedule_wait_time*] 49 | # Time, in minutes, that Automatic Updates should wait at startup before 50 | # applying updates from a missed scheduled installation time. Default 51 | # is undefinded. 52 | # 53 | # [*server*] 54 | # WSUS server to use, default is undefined. 55 | # 56 | # [*status_server*] 57 | # WSUS Status server to use, defaults to value of `server` parameter. 58 | # 59 | # [*key*] 60 | # Advanced use only; registry key for WindowsUpdate settings, defaults to: 61 | # 'HKLM\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate' 62 | # 63 | # [*service*] 64 | # Advanced use only; Windows update service, defaults to 'wuauserv'. 65 | # 66 | class windows::update( 67 | $ensure = 'enabled', 68 | $type = '2', 69 | $all_users = false, 70 | $detection_frequency = undef, 71 | $day = '0', 72 | $time = '3', 73 | $reboot_required = true, 74 | $reboot_relaunch_time = undef, 75 | $reboot_warning_time = undef, 76 | $recommended_updates = false, 77 | $reschedule_wait_time = undef, 78 | $server = undef, 79 | $status_server = undef, 80 | $key = 'HKLM\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate', 81 | $service = 'wuauserv', 82 | ) { 83 | validate_re($ensure, '^(enabled|present|disabled|absent)$') 84 | validate_bool($all_users) 85 | validate_re($type, '^[2-5]$') 86 | validate_re($day, '^[0-7]$') 87 | validate_re($time, '^(\d|1\d|2[0-3])$') 88 | validate_bool($reboot_required) 89 | 90 | # Windows Update service. 91 | # In newer Windows versions the service is started on-demand (Trigger Start) and 92 | # stopped after 10 mins. To workaround it this module won't set ensure => running 93 | # Ref.: https://tickets.puppetlabs.com/browse/MODULES-2420 94 | if (versioncmp($::kernelmajversion, '6.3') >= 0) { 95 | service { $service: 96 | enable => true, 97 | } 98 | } else { 99 | service { $service: 100 | ensure => 'running', 101 | enable => true, 102 | } 103 | } 104 | 105 | # Have any `registry_value` resources here refresh Windows Update service. 106 | Registry_value { 107 | notify => Service[$service], 108 | } 109 | 110 | # AutoUpdate settings registry key, ensure it and it's parent 111 | # are present. 112 | $au_key = "${key}\\AU" 113 | registry_key { [$key, $au_key]: 114 | ensure => present, 115 | } 116 | 117 | # Allow all users to install updates? 118 | if $all_users { 119 | $elevatenonadmins = 1 120 | } else { 121 | $elevatenonadmins = 0 122 | } 123 | registry_value { "${key}\\ElevateNonAdmins": 124 | ensure => present, 125 | type => 'dword', 126 | data => $elevatenonadmins, 127 | } 128 | 129 | # Do we want to set a custom WSUS server? 130 | if $server { 131 | validate_re($server, '^http(s)?') 132 | 133 | registry_value { "${key}\\WUServer": 134 | ensure => present, 135 | type => 'string', 136 | data => $server, 137 | } 138 | 139 | if $status_server { 140 | validate_re($status_server, '^http(s)?') 141 | $status_server_data = $status_server 142 | } else { 143 | $status_server_data = $server 144 | } 145 | 146 | registry_value { "${key}\\WUStatusServer": 147 | ensure => present, 148 | type => 'string', 149 | data => $status_server_data, 150 | } 151 | 152 | registry_value { "${au_key}\\UseWUSServer": 153 | ensure => present, 154 | type => 'string', 155 | data => 1, 156 | } 157 | } else { 158 | registry_value { ["${key}\\WUServer", 159 | "${key}\\WUStatusServer", 160 | "${au_key}\\UseWUServer"]: 161 | ensure => absent, 162 | } 163 | } 164 | 165 | # Whether Windows Update is enabled. 166 | if $ensure in ['enabled', 'present'] { 167 | $noautoupdate = 0 168 | $auoptions = $type 169 | } else { 170 | $noautoupdate = 1 171 | $auoptions = 1 172 | } 173 | 174 | registry_value { "${au_key}\\NoAutoUpdate": 175 | ensure => present, 176 | type => 'dword', 177 | data => $noautoupdate, 178 | } 179 | 180 | registry_value { "${au_key}\\AUOptions": 181 | ensure => present, 182 | type => 'dword', 183 | data => $auoptions, 184 | } 185 | 186 | # Install recommended updates same way as important updates? 187 | if $recommended_updates { 188 | $includerecommendedupates = 1 189 | } else { 190 | $includerecommendedupates = 0 191 | } 192 | 193 | registry_value { "${au_key}\\IncludeRecommendedUpdates": 194 | ensure => present, 195 | type => 'dword', 196 | data => $includerecommendedupates, 197 | } 198 | 199 | if $auoptions == '4' { 200 | registry_value { "${au_key}\\ScheduledInstallDay": 201 | ensure => present, 202 | type => 'dword', 203 | data => $day, 204 | } 205 | 206 | registry_value { "${au_key}\\ScheduledInstallTime": 207 | ensure => present, 208 | type => 'dword', 209 | data => $time, 210 | } 211 | } else { 212 | registry_value { ["${au_key}\\ScheduledInstallDay", 213 | "${au_key}\\ScheduledInstallTime"]: 214 | ensure => absent, 215 | } 216 | } 217 | 218 | if $reboot_required { 219 | # Automatic Updates notifies user computer will restart in 5 minutes. 220 | $reboot_data = 0 221 | } else { 222 | # Logged-on user gets to choose whether or not to restart their computer. 223 | $reboot_data = 1 224 | } 225 | 226 | registry_value { "${au_key}\\NoAutoRebootWithLoggedOnUsers": 227 | ensure => present, 228 | type => 'dword', 229 | data => $reboot_data, 230 | } 231 | 232 | # Detection frequency. 233 | if $detection_frequency { 234 | registry_value { "${au_key}\\DetectionFrequencyEnabled": 235 | ensure => present, 236 | type => 'dword', 237 | data => 1, 238 | } 239 | 240 | registry_value { "${au_key}\\DetectionFrequency": 241 | ensure => present, 242 | type => 'dword', 243 | data => $detection_frequency, 244 | } 245 | } else { 246 | registry_value { "${au_key}\\DetectionFrequencyEnabled": 247 | ensure => present, 248 | type => 'dword', 249 | data => 0, 250 | } 251 | 252 | registry_value { "${au_key}\\DetectionFrequency": 253 | ensure => absent, 254 | } 255 | } 256 | 257 | # Reboot relaunch timeout. 258 | if $reboot_relaunch_time { 259 | registry_value { "${au_key}\\RebootRelaunchTimeoutEnabled": 260 | ensure => present, 261 | type => 'dword', 262 | data => 1, 263 | } 264 | 265 | registry_value { "${au_key}\\RebootRelaunchTimeout": 266 | ensure => present, 267 | type => 'dword', 268 | data => $reboot_relaunch_time, 269 | } 270 | } else { 271 | registry_value { "${au_key}\\RebootRelaunchTimeoutEnabled": 272 | ensure => present, 273 | type => 'dword', 274 | data => 0, 275 | } 276 | 277 | registry_value { "${au_key}\\RebootRelaunchTimeout": 278 | ensure => absent, 279 | } 280 | } 281 | 282 | # Reboot warning timeout. 283 | if $reboot_warning_time { 284 | registry_value { "${au_key}\\RebootWarningTimeoutEnabled": 285 | ensure => present, 286 | type => 'dword', 287 | data => 1, 288 | } 289 | 290 | registry_value { "${au_key}\\RebootWarningTimeout": 291 | ensure => present, 292 | type => 'dword', 293 | data => $reboot_warning_time, 294 | } 295 | } else { 296 | registry_value { "${au_key}\\RebootWarningTimeoutEnabled": 297 | ensure => present, 298 | type => 'dword', 299 | data => 0, 300 | } 301 | 302 | registry_value { "${au_key}\\RebootWarningTimeout": 303 | ensure => absent, 304 | } 305 | } 306 | 307 | # Reschedule wait time. 308 | if $reschedule_wait_time { 309 | registry_value { "${au_key}\\RescheduleWaitTimeEnabled": 310 | ensure => present, 311 | type => 'dword', 312 | data => 1, 313 | } 314 | 315 | registry_value { "${au_key}\\RescheduleWaitTime": 316 | ensure => present, 317 | type => 'dword', 318 | data => $reschedule_wait_time, 319 | } 320 | } else { 321 | registry_value { "${au_key}\\RescheduleWaitTimeEnabled": 322 | ensure => present, 323 | type => 'dword', 324 | data => 0, 325 | } 326 | 327 | registry_value { "${au_key}\\RescheduleWaitTime": 328 | ensure => absent, 329 | } 330 | } 331 | } 332 | -------------------------------------------------------------------------------- /metadata.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "counsyl-windows", 3 | "version": "1.0.6", 4 | "author": "Counsyl, Inc.", 5 | "summary": "Collection of useful Puppet manifests for Windows-based platforms.", 6 | "license": "Apache-2.0", 7 | "source": "git://github.com/counsyl/puppet-windows.git", 8 | "project_page": "https://github.com/counsyl/puppet-windows", 9 | "issues_url": "https://github.com/counsyl/puppet-windows/issues", 10 | "description": "Collection of useful Puppet manifests for Windows-based platforms.", 11 | "dependencies": [ 12 | {"name": "counsyl/sys", "version_requirement": ">= 0.9.18 <2.0.0"}, 13 | {"name": "puppetlabs/powershell", "version_requirement": ">= 1.0.4 <3.0.0"}, 14 | {"name": "puppetlabs/registry", "version_requirement": ">= 1.1.0 <2.0.0"} 15 | ], 16 | "operatingsystem_support": [ 17 | { 18 | "operatingsystem": "windows" 19 | } 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /templates/download_java.ps1.erb: -------------------------------------------------------------------------------- 1 | $wc = New-Object Net.WebClient; 2 | $wc.Headers.Add([System.Net.HttpRequestHeader]::Cookie, "<%= @cookie %>"); 3 | $wc.DownloadFile("<%= @jre_url %>", "<%= @jre_installer %>") -------------------------------------------------------------------------------- /templates/ez_setup.py.erb: -------------------------------------------------------------------------------- 1 | #!python 2 | """Bootstrap setuptools installation 3 | 4 | To use setuptools in your package's setup.py, include this 5 | file in the same directory and add this to the top of your setup.py:: 6 | 7 | from ez_setup import use_setuptools 8 | use_setuptools() 9 | 10 | To require a specific version of setuptools, set a download 11 | mirror, or use an alternate download directory, simply supply 12 | the appropriate options to ``use_setuptools()``. 13 | 14 | This file can also be run as a script to install or upgrade setuptools. 15 | """ 16 | import os 17 | import shutil 18 | import sys 19 | import tempfile 20 | import tarfile 21 | import optparse 22 | import subprocess 23 | import platform 24 | import textwrap 25 | 26 | from distutils import log 27 | 28 | try: 29 | from site import USER_SITE 30 | except ImportError: 31 | USER_SITE = None 32 | 33 | DEFAULT_VERSION = "<%= @version %>" 34 | DEFAULT_URL = "<%= @base_url %>" 35 | 36 | def _python_cmd(*args): 37 | args = (sys.executable,) + args 38 | return subprocess.call(args) == 0 39 | 40 | def _install(tarball, install_args=()): 41 | # extracting the tarball 42 | tmpdir = tempfile.mkdtemp() 43 | log.warn('Extracting in %s', tmpdir) 44 | old_wd = os.getcwd() 45 | try: 46 | os.chdir(tmpdir) 47 | tar = tarfile.open(tarball) 48 | _extractall(tar) 49 | tar.close() 50 | 51 | # going in the directory 52 | subdir = os.path.join(tmpdir, os.listdir(tmpdir)[0]) 53 | os.chdir(subdir) 54 | log.warn('Now working in %s', subdir) 55 | 56 | # installing 57 | log.warn('Installing Setuptools') 58 | if not _python_cmd('setup.py', 'install', *install_args): 59 | log.warn('Something went wrong during the installation.') 60 | log.warn('See the error message above.') 61 | # exitcode will be 2 62 | return 2 63 | finally: 64 | os.chdir(old_wd) 65 | shutil.rmtree(tmpdir) 66 | 67 | 68 | def _build_egg(egg, tarball, to_dir): 69 | # extracting the tarball 70 | tmpdir = tempfile.mkdtemp() 71 | log.warn('Extracting in %s', tmpdir) 72 | old_wd = os.getcwd() 73 | try: 74 | os.chdir(tmpdir) 75 | tar = tarfile.open(tarball) 76 | _extractall(tar) 77 | tar.close() 78 | 79 | # going in the directory 80 | subdir = os.path.join(tmpdir, os.listdir(tmpdir)[0]) 81 | os.chdir(subdir) 82 | log.warn('Now working in %s', subdir) 83 | 84 | # building an egg 85 | log.warn('Building a Setuptools egg in %s', to_dir) 86 | _python_cmd('setup.py', '-q', 'bdist_egg', '--dist-dir', to_dir) 87 | 88 | finally: 89 | os.chdir(old_wd) 90 | shutil.rmtree(tmpdir) 91 | # returning the result 92 | log.warn(egg) 93 | if not os.path.exists(egg): 94 | raise IOError('Could not build the egg.') 95 | 96 | 97 | def _do_download(version, download_base, to_dir, download_delay): 98 | egg = os.path.join(to_dir, 'setuptools-%s-py%d.%d.egg' 99 | % (version, sys.version_info[0], sys.version_info[1])) 100 | if not os.path.exists(egg): 101 | tarball = download_setuptools(version, download_base, 102 | to_dir, download_delay) 103 | _build_egg(egg, tarball, to_dir) 104 | sys.path.insert(0, egg) 105 | 106 | # Remove previously-imported pkg_resources if present (see 107 | # https://bitbucket.org/pypa/setuptools/pull-request/7/ for details). 108 | if 'pkg_resources' in sys.modules: 109 | del sys.modules['pkg_resources'] 110 | 111 | import setuptools 112 | setuptools.bootstrap_install_from = egg 113 | 114 | 115 | def use_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL, 116 | to_dir=os.curdir, download_delay=15): 117 | to_dir = os.path.abspath(to_dir) 118 | rep_modules = 'pkg_resources', 'setuptools' 119 | imported = set(sys.modules).intersection(rep_modules) 120 | try: 121 | import pkg_resources 122 | except ImportError: 123 | return _do_download(version, download_base, to_dir, download_delay) 124 | try: 125 | pkg_resources.require("setuptools>=" + version) 126 | return 127 | except pkg_resources.DistributionNotFound: 128 | return _do_download(version, download_base, to_dir, download_delay) 129 | except pkg_resources.VersionConflict as VC_err: 130 | if imported: 131 | msg = textwrap.dedent(""" 132 | The required version of setuptools (>={version}) is not available, 133 | and can't be installed while this script is running. Please 134 | install a more recent version first, using 135 | 'easy_install -U setuptools'. 136 | 137 | (Currently using {VC_err.args[0]!r}) 138 | """).format(VC_err=VC_err, version=version) 139 | sys.stderr.write(msg) 140 | sys.exit(2) 141 | 142 | # otherwise, reload ok 143 | del pkg_resources, sys.modules['pkg_resources'] 144 | return _do_download(version, download_base, to_dir, download_delay) 145 | 146 | def _clean_check(cmd, target): 147 | """ 148 | Run the command to download target. If the command fails, clean up before 149 | re-raising the error. 150 | """ 151 | try: 152 | subprocess.check_call(cmd) 153 | except subprocess.CalledProcessError: 154 | if os.access(target, os.F_OK): 155 | os.unlink(target) 156 | raise 157 | 158 | def download_file_powershell(url, target): 159 | """ 160 | Download the file at url to target using Powershell (which will validate 161 | trust). Raise an exception if the command cannot complete. 162 | """ 163 | target = os.path.abspath(target) 164 | cmd = [ 165 | 'powershell', 166 | '-Command', 167 | "(new-object System.Net.WebClient).DownloadFile(%(url)r, %(target)r)" % vars(), 168 | ] 169 | _clean_check(cmd, target) 170 | 171 | def has_powershell(): 172 | if platform.system() != 'Windows': 173 | return False 174 | cmd = ['powershell', '-Command', 'echo test'] 175 | devnull = open(os.path.devnull, 'wb') 176 | try: 177 | try: 178 | subprocess.check_call(cmd, stdout=devnull, stderr=devnull) 179 | except: 180 | return False 181 | finally: 182 | devnull.close() 183 | return True 184 | 185 | download_file_powershell.viable = has_powershell 186 | 187 | def download_file_curl(url, target): 188 | cmd = ['curl', url, '--silent', '--output', target] 189 | _clean_check(cmd, target) 190 | 191 | def has_curl(): 192 | cmd = ['curl', '--version'] 193 | devnull = open(os.path.devnull, 'wb') 194 | try: 195 | try: 196 | subprocess.check_call(cmd, stdout=devnull, stderr=devnull) 197 | except: 198 | return False 199 | finally: 200 | devnull.close() 201 | return True 202 | 203 | download_file_curl.viable = has_curl 204 | 205 | def download_file_wget(url, target): 206 | cmd = ['wget', url, '--quiet', '--output-document', target] 207 | _clean_check(cmd, target) 208 | 209 | def has_wget(): 210 | cmd = ['wget', '--version'] 211 | devnull = open(os.path.devnull, 'wb') 212 | try: 213 | try: 214 | subprocess.check_call(cmd, stdout=devnull, stderr=devnull) 215 | except: 216 | return False 217 | finally: 218 | devnull.close() 219 | return True 220 | 221 | download_file_wget.viable = has_wget 222 | 223 | def download_file_insecure(url, target): 224 | """ 225 | Use Python to download the file, even though it cannot authenticate the 226 | connection. 227 | """ 228 | try: 229 | from urllib.request import urlopen 230 | except ImportError: 231 | from urllib2 import urlopen 232 | src = dst = None 233 | try: 234 | src = urlopen(url) 235 | # Read/write all in one block, so we don't create a corrupt file 236 | # if the download is interrupted. 237 | data = src.read() 238 | dst = open(target, "wb") 239 | dst.write(data) 240 | finally: 241 | if src: 242 | src.close() 243 | if dst: 244 | dst.close() 245 | 246 | download_file_insecure.viable = lambda: True 247 | 248 | def get_best_downloader(): 249 | downloaders = [ 250 | download_file_powershell, 251 | download_file_curl, 252 | download_file_wget, 253 | download_file_insecure, 254 | ] 255 | 256 | for dl in downloaders: 257 | if dl.viable(): 258 | return dl 259 | 260 | def download_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL, 261 | to_dir=os.curdir, delay=15, 262 | downloader_factory=get_best_downloader): 263 | """Download setuptools from a specified location and return its filename 264 | 265 | `version` should be a valid setuptools version number that is available 266 | as an egg for download under the `download_base` URL (which should end 267 | with a '/'). `to_dir` is the directory where the egg will be downloaded. 268 | `delay` is the number of seconds to pause before an actual download 269 | attempt. 270 | 271 | ``downloader_factory`` should be a function taking no arguments and 272 | returning a function for downloading a URL to a target. 273 | """ 274 | # making sure we use the absolute path 275 | to_dir = os.path.abspath(to_dir) 276 | tgz_name = "setuptools-%s.tar.gz" % version 277 | url = download_base + tgz_name 278 | saveto = os.path.join(to_dir, tgz_name) 279 | if not os.path.exists(saveto): # Avoid repeated downloads 280 | log.warn("Downloading %s", url) 281 | downloader = downloader_factory() 282 | downloader(url, saveto) 283 | return os.path.realpath(saveto) 284 | 285 | 286 | def _extractall(self, path=".", members=None): 287 | """Extract all members from the archive to the current working 288 | directory and set owner, modification time and permissions on 289 | directories afterwards. `path' specifies a different directory 290 | to extract to. `members' is optional and must be a subset of the 291 | list returned by getmembers(). 292 | """ 293 | import copy 294 | import operator 295 | from tarfile import ExtractError 296 | directories = [] 297 | 298 | if members is None: 299 | members = self 300 | 301 | for tarinfo in members: 302 | if tarinfo.isdir(): 303 | # Extract directories with a safe mode. 304 | directories.append(tarinfo) 305 | tarinfo = copy.copy(tarinfo) 306 | tarinfo.mode = 448 # decimal for oct 0700 307 | self.extract(tarinfo, path) 308 | 309 | # Reverse sort directories. 310 | directories.sort(key=operator.attrgetter('name'), reverse=True) 311 | 312 | # Set correct owner, mtime and filemode on directories. 313 | for tarinfo in directories: 314 | dirpath = os.path.join(path, tarinfo.name) 315 | try: 316 | self.chown(tarinfo, dirpath) 317 | self.utime(tarinfo, dirpath) 318 | self.chmod(tarinfo, dirpath) 319 | except ExtractError as e: 320 | if self.errorlevel > 1: 321 | raise 322 | else: 323 | self._dbg(1, "tarfile: %s" % e) 324 | 325 | 326 | def _build_install_args(options): 327 | """ 328 | Build the arguments to 'python setup.py install' on the setuptools package 329 | """ 330 | return ['--user'] if options.user_install else [] 331 | 332 | def _parse_args(): 333 | """ 334 | Parse the command line for options 335 | """ 336 | parser = optparse.OptionParser() 337 | parser.add_option( 338 | '--user', dest='user_install', action='store_true', default=False, 339 | help='install in user site package (requires Python 2.6 or later)') 340 | parser.add_option( 341 | '--download-base', dest='download_base', metavar="URL", 342 | default=DEFAULT_URL, 343 | help='alternative URL from where to download the setuptools package') 344 | parser.add_option( 345 | '--insecure', dest='downloader_factory', action='store_const', 346 | const=lambda: download_file_insecure, default=get_best_downloader, 347 | help='Use internal, non-validating downloader' 348 | ) 349 | options, args = parser.parse_args() 350 | # positional arguments are ignored 351 | return options 352 | 353 | def main(version=DEFAULT_VERSION): 354 | """Install or upgrade setuptools and EasyInstall""" 355 | options = _parse_args() 356 | tarball = download_setuptools(download_base=options.download_base, 357 | downloader_factory=options.downloader_factory) 358 | return _install(tarball, _build_install_args(options)) 359 | 360 | if __name__ == '__main__': 361 | sys.exit(main()) 362 | -------------------------------------------------------------------------------- /templates/firewall_rule.erb: -------------------------------------------------------------------------------- 1 | <% args = [@netsh, 'advfirewall', 'firewall', 'add', 'rule', "name=\"#{@name}\"", "dir=#{@dir}", "action=#{@action}"] -%> 2 | <% if @description -%> 3 | <% args << "description=\"#{@description}\"" -%> 4 | <% end -%> 5 | <% if @program -%> 6 | <% args << "program=\"#{@program}\"" -%> 7 | <% end -%> 8 | <% if @localport -%> 9 | <% args << "localport=#{@localport}" -%> 10 | <% end -%> 11 | <% if @remoteport -%> 12 | <% args << "remoteport=#{@remoteport}" -%> 13 | <% end -%> 14 | <% if @protocol -%> 15 | <% args << "protocol=#{@protocol}" -%> 16 | <% end -%> 17 | <% if @remoteip -%> 18 | <% args << "remoteip=#{@remoteip}" -%> 19 | <% end -%> 20 | <% if @profile -%> 21 | <% args << "profile=#{@profile}" -%> 22 | <% end -%> 23 | <% if @enable -%> 24 | <% args << "enable=#{@enable}" -%> 25 | <% end -%> 26 | <%= args.join(' ') %> -------------------------------------------------------------------------------- /templates/path_check.ps1.erb: -------------------------------------------------------------------------------- 1 | $curpath = ([Environment]::GetEnvironmentVariable("PATH", "<%= @target %>")).Split(';'); 2 | <% if @ensure == 'present' -%> 3 | foreach($component in $curpath) { if ($component -eq "<%= @directory %>"){ exit 0 } }; 4 | exit 1; 5 | <% else -%> 6 | foreach($component in $curpath) { if ($component -eq "<%= @directory %>"){ exit 1 } }; 7 | exit 0; 8 | <% end -%> 9 | -------------------------------------------------------------------------------- /templates/path_set.ps1.erb: -------------------------------------------------------------------------------- 1 | $curpath = [Environment]::GetEnvironmentVariable("PATH", "<%= @target %>"); 2 | <% if @ensure == 'present' -%> 3 | $newpath = "${curpath};<%= @directory %>"; 4 | <% else -%> 5 | $newpath = @(); 6 | foreach($path in $curpath.Split(';')){ if ($path -ne "<%= @directory %>"){ $newpath = $newpath + $path } }; 7 | $newpath = [String]::Join(';', $newpath) 8 | <% end -%> 9 | [Environment]::SetEnvironmentVariable("PATH", $newpath, "<%= @target %>"); 10 | -------------------------------------------------------------------------------- /templates/powercfg_check.ps1.erb: -------------------------------------------------------------------------------- 1 | if ((POWERCFG -GETACTIVESCHEME).Split()[3] -ne '<%= @guid %>') { exit 1 } 2 | exit 0 3 | -------------------------------------------------------------------------------- /templates/refresh_environment.ps1.erb: -------------------------------------------------------------------------------- 1 | # I remembered this trick from NSIS installers, and found a PowerShell 2 | # implementation from http://poshcode.org/2049. 3 | 4 | # Expose `SendMessageTimeout` from win32 API. 5 | if (-not ("win32.nativemethods" -as [type])) { 6 | Add-Type -Namespace Win32 -Name NativeMethods -MemberDefinition @" 7 | [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)] 8 | public static extern IntPtr SendMessageTimeout( 9 | IntPtr hWnd, uint Msg, UIntPtr wParam, string lParam, 10 | uint fuFlags, uint uTimeout, out UIntPtr lpdwResult); 11 | "@ 12 | }; 13 | 14 | # Setting up variables. 15 | $HWND_BROADCAST = [intptr]0xffff; 16 | $WM_SETTINGCHANGE = 0x1a; 17 | $result = [uintptr]::Zero; 18 | 19 | # Notify all windows of environment block change, if this doesn't return 1, 20 | # exit with an error code. 21 | if ( ([win32.nativemethods]::SendMessageTimeout($HWND_BROADCAST, $WM_SETTINGCHANGE, [uintptr]::Zero, "Environment", 2, 5000, [ref]$result)) -ne 1 ){ exit 1 }; 22 | -------------------------------------------------------------------------------- /templates/regsvr32.ps1.erb: -------------------------------------------------------------------------------- 1 | <% if @clsid.is_a? Array -%> 2 | <% clsids = @clsid.map { |id| "'#{id}'" } -%> 3 | $clsids = @(<%= clsids.join(',') %>); 4 | <% else -%> 5 | $clsids = @('<%= @clsid %>'); 6 | <% end -%> 7 | foreach($clsid in $clsids){ if (! (Test-Path "<%= @hkcr %>\${clsid}") ) { exit 1 } }; 8 | -------------------------------------------------------------------------------- /templates/screen_saver_check.ps1.erb: -------------------------------------------------------------------------------- 1 | <% if @domain -%> 2 | $user = New-Object System.Security.Principal.NTAccount("<%= @domain %>", "<%= @user %>"); 3 | <% else -%> 4 | $user = New-Object System.Security.Principal.NTAccount("<%= @user %>"); 5 | <% end -%> 6 | $sid = ($user.Translate([System.Security.Principal.SecurityIdentifier])).Value; 7 | $regpath = "Registry::HKEY_USERS\${sid}\Control Panel\Desktop"; 8 | $regkey = Get-Item -Path $regpath; 9 | foreach($property in "ScreenSaveActive","SCRNSAVE.EXE","ScreenSaverIsSecure","ScreenSaveTimeOut") { 10 | if ( ! ($regkey.Property -contains $property)) { exit 1; } 11 | } 12 | if ( (Get-ItemProperty -Path $regpath -Name "ScreenSaveActive").ScreenSaveActive -ne <%= @active_value %>) { exit 1; } 13 | <% if @active_value == 1 -%> 14 | if ( (Get-ItemProperty -Path $regpath -Name "SCRNSAVE.EXE")."SCRNSAVE.EXE" -ne "<%= @exe %>") { exit 1; } 15 | <% end -%> 16 | if ( (Get-ItemProperty -Path $regpath -Name "ScreenSaverIsSecure").ScreenSaverIsSecure -ne <%= @secure_value %>) { exit 1; } 17 | if ( (Get-ItemProperty -Path $regpath -Name "ScreenSaveTimeout").ScreenSaveTimeout -ne <%= @timeout_seconds %>) { exit 1; } 18 | exit 0; 19 | -------------------------------------------------------------------------------- /templates/screen_saver_set.ps1.erb: -------------------------------------------------------------------------------- 1 | <% if @domain -%> 2 | $user = New-Object System.Security.Principal.NTAccount("<%= @domain %>", "<%= @user %>"); 3 | <% else -%> 4 | $user = New-Object System.Security.Principal.NTAccount("<%= @user %>"); 5 | <% end -%> 6 | $sid = ($user.Translate([System.Security.Principal.SecurityIdentifier])).Value; 7 | $regpath = "Registry::HKEY_USERS\${sid}\Control Panel\Desktop"; 8 | Set-ItemProperty -Path $regpath -Name "ScreenSaveActive" -Value <%= @active_value %> -Force; 9 | <% if @active_value == 1 -%> 10 | Set-ItemProperty -Path $regpath -Name "SCRNSAVE.EXE" -Value "<%= @exe %>" -Force; 11 | <% else -%> 12 | Remove-ItemProperty -Path $regpath -Name "SCRNSAVE.EXE"; 13 | <% end -%> 14 | Set-ItemProperty -Path $regpath -Name "ScreenSaverIsSecure" -Value <%= @secure_value %> -Force; 15 | Set-ItemProperty -Path $regpath -Name "ScreenSaveTimeOut" -Value <%= @timeout_seconds %> -Force; 16 | -------------------------------------------------------------------------------- /templates/shortcut.ps1.erb: -------------------------------------------------------------------------------- 1 | $shell = New-Object -COMObject WScript.Shell; 2 | $shortcut = $shell.CreateShortcut("<%= @path %>"); 3 | $shortcut.TargetPath = "<%= @target %>"; 4 | <% if @arguments -%> 5 | $shortcut.Arguments = "<%= @arguments %>"; 6 | <% end -%> 7 | <% if @description -%> 8 | $shortcut.Description = "<%= @description %>"; 9 | <% end -%> 10 | <% if @icon_location -%> 11 | $shortcut.IconLocation = "<%= @icon_location %>"; 12 | <% end -%> 13 | <% if @working_directory -%> 14 | $shortcut.WorkingDirectory = "<%= @working_directory %>"; 15 | <% end -%> 16 | $shortcut.Save(); -------------------------------------------------------------------------------- /templates/unzip.ps1.erb: -------------------------------------------------------------------------------- 1 | $shell = New-Object -COMObject Shell.Application; 2 | $zipfile = $shell.NameSpace("<%= @zipfile %>"); 3 | foreach($item in $zipfile.Items()){ $shell.NameSpace("<%= @destination %>").CopyHere($item, <%= @options %>) }; --------------------------------------------------------------------------------