0

Currently i am trying to automate the start mode in windows server services. i tried to use puppetlabs registry but realized that the module didn't work as i expected.

Basically i have list of windows services that i need to update on each server but on some servers, the services might not exist, but puppetlabs registry will just create the new key if it's not exist which is not the expected behaviour. By right, it should work as mentioned below:

  1. Check whether the service is in the servers or not
  2. If it does, then update the start mode as mentioned inside the manifest/hiera
  3. If not exist, just do nothing and skip to the next service immediately

Based from what i knew, it seems the only way to check whether the service key exist or not is by using custom function. So i already tried to write some custom function using win32/registry, but was unsuccessful by getting some error such as Win32API not supported. Another way i can think of is using the reg command line to check whether the key exist or not. Here is the puppet code functions:

module Puppet::Parser::Functions
  newfunction(:check_winservice_exist, :type => :rvalue) do |args|

    service_name = args[0]

    unless args.length > 0 then
      raise Puppet::ParseError, ("check_winservice_exist(): wrong number of arguments (#{args.length}; must be > 0)")
    end

    command = "reg query HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\#{service_name} /f DisplayName"
    result = system command

    return result
    #if result == true
    #   return result
    #else
    #   return result
    #end
  end
end

When i run the simplified ruby scripts in command line, it works and return the expected value. But when i used above scripts as puppet custom functions, it always return empty.

This is my first time to write a puppet custom functions so i am not sure what i did wrong here. Please advise whether there are another alternative that i can use to resolve the issue or maybe advise on what i did wrong on the functions script

AlamHo
  • 193
  • 1
  • 3
  • 12
  • This is the classic mistake people make with functions: they run on the master. You need to do a custom fact instead. – Matthew Schuchard Mar 18 '17 at 20:20
  • Thanks for the feedback. Is there another way than using custom fact? Because i have more than hundreds of services to check for security hardening purpose, and creating a list of that services in custom facts would be a bit troublesome. – AlamHo Mar 19 '17 at 00:27
  • You would just create a fact that gathers all of the services in an array. That would be easy. – Matthew Schuchard Mar 19 '17 at 12:53
  • Thanks a lot for the advice. Seems like that's the only way i can do it on puppet for now – AlamHo Mar 19 '17 at 13:44
  • If you get stuck with the custom fact or it seems like that method is causing you to go down a severely unoptimized route, I totally recommend posting a followup with what you have tried and reiterating your goal. – Matthew Schuchard Mar 19 '17 at 19:44
  • Posted on what i did to resolve the issue. Feel free to let me know if there are something wrong on my custom facter scripts. Any feedback is welcomed – AlamHo Mar 21 '17 at 09:49

1 Answers1

0

I managed to resolve this issue by using custom facter as suggested by Matt. Just sharing the custom facter scripts that i used. It might not be perfect as i am still not really proficient in using ruby.

require 'win32/registry'

Facter.add(:winservices) do
  confine :kernel => "windows"
  setcode do
    keyname= 'SYSTEM\CurrentControlSet\Services'
    access = Win32::Registry::KEY_ALL_ACCESS
    arr = []
    winservices_list = []

    Win32::Registry::HKEY_LOCAL_MACHINE.open(keyname, access) do |reg|
      service_lists = (reg.each_key { |key, wtime| arr.push key })
      arr.each do |service|
          service_key = "SYSTEM\\CurrentControlSet\\Services\\#{service}"
          begin
            Win32::Registry::HKEY_LOCAL_MACHINE.open(service_key, access) do |reg|
                value = reg['Start']
              winservices_list.push service
            end
          rescue
          end
      end
      winservices_list
    end

  end
end

And it simply works just by adding simply checking whether the service name is in the array or not

  if $service_name in $facts['winservices'] {
    service { "${service_name}":
      provider  => 'windows',
      enable    => $start_real,
    }
  }
AlamHo
  • 193
  • 1
  • 3
  • 12