71 changes: 71 additions & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
2012-05-04 - Jeff McCune <jeff@puppetlabs.com>
* Add registry::compliance_example class to test compliance (0aa8a68)

2012-05-03 - Jeff McCune <jeff@puppetlabs.com>
* Allow values associated with a registry key to be purged (27eaee3)

2012-05-01 - Jeff McCune <jeff@puppetlabs.com>
* Update README with info about the types provided (b9b2d11)

2012-04-30 - Jeff McCune <jeff@puppetlabs.com>
* Add registry::service defined resource example (57c5b59)

2012-04-25 - Jeff McCune <jeff@puppetlabs.com>
* Add REG_MULTI_SZ (type => array) implementation (1b17c6f)

2012-04-26 - Jeff McCune <jeff@puppetlabs.com>
* Work around #3947, #4248, #14073; load our utility code (a8d9402)

2012-04-24 - Josh Cooper <josh@puppetlabs.com>
* Handle binary registry values (4353642)

2012-04-24 - Josh Cooper <josh@puppetlabs.com>
* Fix puppet resource registry_key (f736cff)

2012-04-23 - Josh Cooper <josh@puppetlabs.com>
* Registry keys and values were autorequiring all ancestors (0de7a0a)

2012-04-24 - Jeff McCune <jeff@puppetlabs.com>
* Add examples of current registry key and value types (bb7e4f4)

2012-04-23 - Josh Cooper <josh@puppetlabs.com>
* Add the ability to manage 32 and 64-bit keys/values (9a16a9b)

2012-04-23 - Josh Cooper <josh@puppetlabs.com>
* Remove rspec deprecation warning (94063d5)

2012-04-23 - Josh Cooper <josh@puppetlabs.com>
* Rename registry-specific util code (cd2aaa1)

2012-04-20 - Josh Cooper <josh@puppetlabs.com>
* Fix autorequiring when using different root key forms (b7a1c39)

2012-04-19 - Josh Cooper <josh@puppetlabs.com>
* Refactor key and value paths (74ebc80)

2012-04-19 - Josh Cooper <josh@puppetlabs.com>
* Encode default-ness in the registry path (64bba67)

2012-04-19 - Josh Cooper <josh@puppetlabs.com>
* Better validation and testing of key paths (d05d1e6)

2012-04-19 - Josh Cooper <josh@puppetlabs.com>
* Maint: Remove more crlf line endings (e9f00c1)

2012-04-19 - Josh Cooper <josh@puppetlabs.com>
* Maint: remove windows cr line endings (0138a1d)

2012-04-18 - Josh Cooper <josh@puppetlabs.com>
* Rename `default` parameter (f45af86)

2012-04-18 - Josh Cooper <josh@puppetlabs.com>
* Fix modifying existing registry values (d06be98)

2012-04-18 - Josh Cooper <josh@puppetlabs.com>
* Remove debugging (8601e92)

2012-04-18 - Josh Cooper <josh@puppetlabs.com>
* Always split the path (de66832)

2012-04-18 - Josh Cooper <josh@puppetlabs.com>
* Initial registry key and value types and providers (065d43d)
8 changes: 4 additions & 4 deletions Modulefile
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
name 'puppetlabs-registry'
version '0.0.1'
source 'UNKNOWN'
source 'git://github.com/puppetlabs/puppetlabs-registry.git'
author 'puppetlabs'
license 'Apache License, Version 2.0'
summary 'UNKNOWN'
description 'UNKNOWN'
project_page 'UNKNOWN'
summary 'This module provides a native type and provider to manage keys and values in the Windows Registry'
description 'This module provides a native type and provider to manage keys and values in the Windows Registry'
project_page 'http://links.puppetlabs.com/registry-module'

## Add dependencies, if any:
# dependency 'username/name', '>= 1.2.0'
16 changes: 0 additions & 16 deletions README

This file was deleted.

132 changes: 132 additions & 0 deletions README.markdown
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
Windows Registry Module
=======================

This module provides the types and providers necessary to manage the Windows
Registry with Puppet.

Installation
------------

The best way to install this module is with the `puppet module` subcommand or
the `puppet-module` Gem.

puppet module install puppetlabs-registry

Make sure your `puppet agent` is configured to synchronize plugins using the
setting:

[main]
pluginsync = true

This is the default behavior of the Puppet Agent on Microsoft Windows
platforms. This setting will ensure the types and providers are synchronized
and available on the agent before the configuration run takes place.


Installation from source
------------------------

If you'd like to install this module from source, please simply clone a copy
into your puppet master's `modulepath`. Here is an example of how to do so for
Puppet Enterprise:

$ cd /etc/puppetlabs/puppet/modules
$ git clone git://github.com/puppetlabs/puppetlabs-registry.git registry

Examples
--------

The `registry_key` and `registry_value` types are provided by this module.

registry_key { 'HKLM\System\CurrentControlSet\Services\Puppet':
ensure => present,
}
registry_value { 'HKLM\System\CurrentControlSet\Services\Puppet\Description':
ensure => present,
type => string,
data => "The Puppet Agent service periodically manages your configuration",
}

Purge Values Example
--------------------

If you want to make sure only the values specified in Puppet are associated
with a particular key, you can use the `purge_values => true` parameter of the
`registry_key` resource to delete any values not explicitly managed by Puppet.
The `registry::example_purge` class shows how this is accomplished:

Make sure the `registry::example_purge` class is included in the node catalog,
then setup a registry key that contains six values:

PS C:\> $env:FACTER_PURGE_EXAMPLE_MODE = 'setup'
PS C:\> puppet agent --test
notice: /Stage[main]/Registry::Purge_example/Registry_key[HKLM\Software\Vendor\Puppet Labs\Examples\KeyPurge]/ensure: created
notice: /Stage[main]/Registry::Purge_example/Registry_value[HKLM\Software\Vendor\Puppet Labs\Examples\KeyPurge\Value3]/ensure: created
notice: /Stage[main]/Registry::Purge_example/Registry_value[HKLM\Software\Vendor\Puppet Labs\Examples\KeyPurge\Value2]/ensure: created
notice: /Stage[main]/Registry::Purge_example/Registry_key[HKLM\Software\Vendor\Puppet Labs\Examples\KeyPurge\SubKey]/ensure: created
notice: /Stage[main]/Registry::Purge_example/Registry_value[HKLM\Software\Vendor\Puppet Labs\Examples\KeyPurge\Value5]/ensure: created
notice: /Stage[main]/Registry::Purge_example/Registry_value[HKLM\Software\Vendor\Puppet Labs\Examples\KeyPurge\Value6]/ensure: created
notice: /Stage[main]/Registry::Purge_example/Registry_value[HKLM\Software\Vendor\Puppet Labs\Examples\KeyPurge\SubKey\Value1]/ensure: created
notice: /Stage[main]/Registry::Purge_example/Registry_value[HKLM\Software\Vendor\Puppet Labs\Examples\KeyPurge\Value1]/ensure: created
notice: /Stage[main]/Registry::Purge_example/Registry_value[HKLM\Software\Vendor\Puppet Labs\Examples\KeyPurge\SubKey\Value2]/ensure: created
notice: /Stage[main]/Registry::Purge_example/Registry_value[HKLM\Software\Vendor\Puppet Labs\Examples\KeyPurge\Value4]/ensure: created
notice: Finished catalog run in 0.14 seconds

Switching the mode to 'purge' will cause the class to only manage three of the
six `registry_value` resources. The other three will be purged since the
`registry_key` resource has `purge_values => true` specified in the manifest.
Notice how Value4, Value5 and Value6 are being removed.

PS C:\> $env:FACTER_PURGE_EXAMPLE_MODE = 'purge'
PS C:\> puppet agent --test
notice: /Registry_value[hklm\Software\Vendor\Puppet Labs\Examples\KeyPurge\Value4]/ensure: removed
notice: /Registry_value[hklm\Software\Vendor\Puppet Labs\Examples\KeyPurge\Value6]/ensure: removed
notice: /Registry_value[hklm\Software\Vendor\Puppet Labs\Examples\KeyPurge\Value5]/ensure: removed
notice: /Stage[main]/Registry::Purge_example/Registry_value[HKLM\Software\Vendor\Puppet Labs\Examples\KeyPurge\Value3]/data: data changed 'key3' to 'should not be purged'
notice: /Stage[main]/Registry::Purge_example/Registry_value[HKLM\Software\Vendor\Puppet Labs\Examples\KeyPurge\Value2]/data: data changed '2' to '0'
notice: /Stage[main]/Registry::Purge_example/Registry_value[HKLM\Software\Vendor\Puppet Labs\Examples\KeyPurge\Value1]/data: data changed '1' to '0'
notice: Finished catalog run in 0.16 seconds

Compliance Example
------------------

In order to use the Registry module with the Compliance feature of Puppet
Enterprise, the `audit` metaparameter should be used with specific
`registry_value` resources. An example of this is provided in the
`registry::compliance_example` class.

To get started:

1. First, add the `registry::compliance_example` class to a node.
2. Then, run `puppet agent --test` on the Windows node to setup a hierarchy of
keys in `HKLM\Software\Vendor\Puppet Labs\Examples\Compliance`
3. Switch the `registry::compliance_example` class into audit mode by setting
a Facter fact: `$env:FACTER_REGISTRY_COMPLIANCE_EXAMPLE_MODE='audit'`.
4. Get the new catalog containing the audit resources using: `puppet agent
--test`.
5. Manually change a registry value inside of `HKLM\Software\Vendor\Puppet
Labs\Examples\Compliance`.
6. Run `puppet inspect` and notice that Puppet has picked up the manual change
and set it to the Puppet Enterprise Console as an inspect report.

![Registry Value Inspect Report](http://links.puppetlabs.com/screen_shot_registry_value_audit_01.png)

License
-------

[Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.html)


Contact
-------

* Puppet Labs <support@puppetlabs.com>
* Jeff McCune <jeff@puppetlabs.com>
* Josh Cooper <josh@puppetlabs.com>


Support
-------

Please log tickets and issues at our [Module Issue
Tracker](http://projects.puppetlabs.com/projects/modules)
32 changes: 16 additions & 16 deletions Rakefile
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
require 'rake'
require 'rspec/core/rake_task'

task :default => [:test]

desc 'Run RSpec'
RSpec::Core::RakeTask.new(:test) do |t|
t.pattern = 'spec/{unit}/**/*.rb'
# t.rspec_opts = ['--color']
end

desc 'Generate code coverage'
RSpec::Core::RakeTask.new(:coverage) do |t|
t.rcov = true
t.rcov_opts = ['--exclude', 'spec']
end
require 'rake'
require 'rspec/core/rake_task'

task :default => [:test]

desc 'Run RSpec'
RSpec::Core::RakeTask.new(:test) do |t|
t.pattern = 'spec/{unit}/**/*.rb'
# t.rspec_opts = ['--color']
end

desc 'Generate code coverage'
RSpec::Core::RakeTask.new(:coverage) do |t|
t.rcov = true
t.rcov_opts = ['--exclude', 'spec']
end
8 changes: 8 additions & 0 deletions lib/puppet/modules.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Open up the Puppet::Modules namespace for use by the registry module utility
# methods. This will throw an error if there is a Puppet::Modules constant
# that is not itself a module. (e.g. it may be a class as was the case with
# Puppet::Module and the puppet-module tool.
module Puppet
module Modules
end
end
12 changes: 12 additions & 0 deletions lib/puppet/modules/registry.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
require 'pathname'
# JJM WORK_AROUND
# explicitly require files without relying on $LOAD_PATH until #14073 is fixed.
# https://projects.puppetlabs.com/issues/14073 is fixed.
require Pathname.new(__FILE__).dirname.expand_path

module Puppet::Modules::Registry
# For 64-bit OS, use 64-bit view. Ignored on 32-bit OS
KEY_WOW64_64KEY = 0x100 unless defined? KEY_WOW64_64KEY
# For 64-bit OS, use 32-bit view. Ignored on 32-bit OS
KEY_WOW64_32KEY = 0x200 unless defined? KEY_WOW64_32KEY
end
66 changes: 66 additions & 0 deletions lib/puppet/modules/registry/key_path.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
require 'puppet/parameter'
require 'pathname'
# JJM WORK_AROUND
# explicitly require files without relying on $LOAD_PATH until #14073 is fixed.
# https://projects.puppetlabs.com/issues/14073 is fixed.
require Pathname.new(__FILE__).dirname
require Pathname.new(__FILE__).dirname + 'registry_base'

class Puppet::Modules::Registry::KeyPath < Puppet::Parameter
include Puppet::Modules::Registry::RegistryBase

attr_reader :root, :hkey, :subkey, :access

def munge(path)
unless captures = /^(32:)?([h|H][^\\]*)((?:\\[^\\]{1,255})*)$/.match(path)
raise ArgumentError, "Invalid registry key: #{path}"
end

@access = if captures[1] == '32:'
Puppet::Modules::Registry::KEY_WOW64_32KEY
else
Puppet::Modules::Registry::KEY_WOW64_64KEY
end

# canonical root key symbol
@root = case captures[2].to_s.downcase
when /hkey_local_machine/, /hklm/
:hklm
when /hkey_classes_root/, /hkcr/
:hkcr
when /hkey_current_user/, /hkcu/,
/hkey_users/, /hku/,
/hkey_current_config/, /hkcc/,
/hkey_performance_data/,
/hkey_performance_text/,
/hkey_performance_nlstext/,
/hkey_dyn_data/
raise ArgumentError, "Unsupported prefined key: #{path}"
else
raise ArgumentError, "Invalid registry key: #{path}"
end

# the hkey object for the root key
@hkey = hkeys[root]

@subkey = captures[3]
if @subkey.empty?
canonical = root.to_s
else
# Leading backslash is not part of the subkey name
@subkey.sub!(/^\\(.*)$/, '\1')
canonical = "#{root.to_s}\\#{subkey}"
end

canonical
end

def ascend(&block)
p = self.value

while idx = p.rindex('\\')
p = p[0, idx]
yield p
end
end
end
Loading