2

I have this class that, when run, should let a user change their password. However, when I run it with puppet agent --test, it gives a syntax error at line 9, where it's setting the password, but I don't know what's wrong with that line. Here is the code I have so far. The "$6" is because it's SHA-512 hashed, as opposed to $1 for MD5, which is the default.

class pwdchange ($newpwd = '', $targetuser = $::id) {
   $hash  = inline_template("<%
     require 'digest'
     Digest::SHA1.hexdigest(newpwd)
   %>")
   $encryptedpwd = '$6'+template($hash)
   user {"$targetuser":
     ensure   => present
     password => $encryptedpwd
  }
}

Could anyone tell me what I'm doing wrong?

Seri
  • 133
  • 1
  • 7
  • To give a few hints: You wouldn't use a class for this kind of work, but a define (See Puppet documentation for classes and defines). Also, Puppet is a very bad tool for this kind of job, especially if you have a large number of users. It's practically impossible to allow regular users to change their own passwords using Puppet, both in security and practicality point of view – Mikko Jul 23 '13 at 13:27
  • Most of the advice I've gotten has been along the lines of "Are there really people who use Puppet instead of LDAP for that?!", but I've been specifically told to use Puppet. – Seri Jul 23 '13 at 13:37
  • I'm looking into defined types now - perhaps use of a defined type could solve [a related issue with this code](http://serverfault.com/questions/525644/user-cant-log-in-after-i-manually-set-md5-hash) I'm having. – Seri Jul 23 '13 at 14:08
  • I actually manage users and passwords with Puppet, but only a handful of administrator accounts. This is to ensure admin access even if LDAP server is not available. Do you have any background why Puppet is selected for this task and using no other tool is possible? – Mikko Jul 23 '13 at 15:38
  • I was told that it was because the ops team is very small relative to the company size, and that it would take prohibitively long to set up an LDAP infrastructure. – Seri Jul 23 '13 at 15:40

2 Answers2

2

You need to terminate lines with commas in the resource definition, also quoting variables is recommended:

class pwdchange ($newpwd = '', $targetuser = $::id) {
   $hash  = inline_template("<%
     require 'digest'
     Digest::SHA1.hexdigest(newpwd)
   %>")
   $encryptedpwd = '$6'+template($hash)
   user {"$targetuser":
     ensure   => present,
     password => "$encryptedpwd",
  }
}
dawud
  • 15,096
  • 3
  • 42
  • 61
  • That helped, but I realized I'm also doing the concatenation wrong. I want to put the literal '$6' in front of the template's output, but the other [questions](http://stackoverflow.com/questions/14885263/how-do-you-concatenate-strings-in-a-puppet-pp-file) on puppet concatenation only refer to variables. How do I escape the '$6' to treat it literally? I've tried various permutations of "${$6}${template($hash)}", and tossing in backslashes, but no luck. – Seri Jul 22 '13 at 14:12
  • any reason not to put the encrypted password directly in the `password` key? – dawud Jul 22 '13 at 15:59
  • Backslashes have always worked for me. What syntax are you using with them? Here's a line from one of my manifests: `$key_pkg_cmd = "/usr/bin/gpg --with-colons --fixed-list-mode /etc/pki/rpm-gpg/${keyfile} | perl -an -F: -e '/^pub/ and printf(\"gpg-pubkey-%s-%x\\n\", lc(substr(\$F[4], 8)), \$F[5])'"`. (It's due to be turned into a type when I have time, but it is an example of escaping dollar signs in Puppet strings.) – asciiphil Jul 23 '13 at 12:44
  • I must disagree, quoting plain variables like `"$encryptedpwd"` is not recommended. This mixes them up with literal strings for no reason. Let variables be variables, so just `$targetuser` and `$encryptedpwd`. – Mikko Jul 23 '13 at 13:02
0

When you are already using inline_template, there is no need for the template function. Also, use a backslash to escape the literal dollar sign.

$hash = inline_template(...)
$encryptedpwd = "\$6${hash}"
user {$targetuser:
    ensure  => present,
    password => $encryptedpwd,
}

Another possibility to build the complex string is to place the prefix in different variable. Using single quotes preserves dollar sing as a literal character:

$hash = inline_template(...)
$prefix = '$6'
$encryptedpwd = "${prefix}${hash}"
Mikko
  • 955
  • 8
  • 14
  • According to the meta, it should be its own question, [which it is](http://serverfault.com/questions/525644/user-cant-log-in-after-i-manually-set-md5-hash). I placed the prefix in a different variable, removed the template function, and realized I could compress the inline template to a single line. It sets a password successfully now, but a user can't log in. For more details (and possibly an answer), see my other question. – Seri Jul 23 '13 at 14:11