The problem:

        $ cat test.pp
        user { 'test':
                # echo secret | encrypt
                password => 
'$2b$08$ZN1ywlySByQ79VoNNzHT5.riIraLxU/LVfXonHuPimCIyIAcNMArO';
        }

        # puppet apply ./test.pp
        Warning: Facter: Unable to getenv for pid 1, 'uninitialized constant 
Facter::Util::Linux'
        Notice: Compiled catalog for atar in environment production in 0.02 
seconds
        Error: Could not set password on user[test]: No command chpasswd 
defined for provider openbsd
        Error: /Stage[main]/Main/User[test]/password: change from [redacted] to 
[redacted] failed: Could not set password on    user[test]: No command chpasswd 
defined for provider openbsd
        Notice: Applied catalog in 0.01 seconds


We don't have chpasswd, so nothing is executed to change the password.

Current code expects a new value on stdin, so they create a tempfile, etc.

Our usermod(8) -p takes it as argument and, as confimed by ktrace, Puppet
executes the command directly without shell, so use that instead:

        # make update
        # puppet apply ./test.pp
        Warning: Facter: Unable to getenv for pid 1, 'uninitialized constant 
Facter::Util::Linux'
        Notice: Compiled catalog for atar in environment production in 0.02 
seconds
        Notice: /Stage[main]/Main/User[test]/password: changed [redacted] to 
[redacted]
        Notice: Applied catalog in 0.05 seconds

master.passwd(5) now gets updated correctly.

Puppet 7 has the same issue, but is EOL since 2025, so I'd rather remove it.

Feedback? OK?


Index: Makefile
===================================================================
RCS file: /cvs/ports/sysutils/ruby-puppet/8/Makefile,v
diff -u -p -r1.6 Makefile
--- Makefile    28 Jun 2025 00:36:32 -0000      1.6
+++ Makefile    27 Aug 2025 20:33:30 -0000
@@ -1,7 +1,7 @@
 PORTROACH=             limit:^8
 
 VERSION=               8.10.0
-REVISION=              0
+REVISION=              1
 
 RUN_DEPENDS+=          converters/ruby-multi_json,${MODRUBY_FLAVOR}>=1.13,<2 \
                        devel/ruby-concurrent-ruby,${MODRUBY_FLAVOR}>=1,<2 \
Index: patches/patch-lib_puppet_provider_user_useradd_rb
===================================================================
RCS file: patches/patch-lib_puppet_provider_user_useradd_rb
diff -N patches/patch-lib_puppet_provider_user_useradd_rb
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ patches/patch-lib_puppet_provider_user_useradd_rb   28 Aug 2025 22:07:49 
-0000
@@ -0,0 +1,41 @@
+Use usermod(8) -p to update to fix changing a user's password.
+
+Index: lib/puppet/provider/user/useradd.rb
+--- lib/puppet/provider/user/useradd.rb.orig
++++ lib/puppet/provider/user/useradd.rb
+@@ -14,7 +14,7 @@ Puppet::Type.type(:user).provide :useradd, :parent => 
+     To use the `forcelocal` parameter, you need to install the `libuser` 
package (providing
+     `/usr/sbin/lgroupadd` and `/usr/sbin/luseradd`)."
+ 
+-  commands :add => "useradd", :delete => "userdel", :modify => "usermod", 
:password => "chage", :chpasswd => "chpasswd"
++  commands :add => "useradd", :delete => "userdel", :modify => "usermod", 
:password => "chage", :chpasswd => "usermod"
+ 
+   options :home, :flag => "-d", :method => :dir
+   options :comment, :method => :gecos
+@@ -189,25 +189,14 @@ Puppet::Type.type(:user).provide :useradd, :parent => 
+     user = @resource[:name]
+     tempfile = Tempfile.new('puppet', :encoding => Encoding::UTF_8)
+     begin
+-      # Puppet execute does not support strings as input, only files.
+-      # The password is expected to be in an encrypted format given -e is 
specified:
+-      tempfile << "#{user}:#{value}\n"
+-      tempfile.flush
+-
+-      # Options '-e' use encrypted password
+-      # Must receive "user:enc_password" as input
+-      # command, arguments = {:failonfail => true, :combine => true}
+-      cmd = [command(:chpasswd), '-e']
++      cmd = [command(:chpasswd), '-p', value, user]
+       execute_options = {
+         :failonfail => false,
+         :combine => true,
+-        :stdinfile => tempfile.path,
+         :sensitive => has_sensitive_data?
+       }
+       output = execute(cmd, execute_options)
+     rescue => detail
+-      tempfile.close
+-      tempfile.delete
+       raise Puppet::Error, "Could not set password on 
#{@resource.class.name}[#{@resource.name}]: #{detail}", detail.backtrace
+     end
+ 

Reply via email to