[augeas-devel] Help matching a PAM config line

Jennings, Jared L CTR USAF AFMC 96 SK/CCI jared.jennings.ctr at eglin.af.mil
Mon Oct 28 15:26:30 UTC 2013


"Error sending command 'ins' with params ["argument", "after", ".../argument[last()]"]"

In specific: When I added existing arguments to the lines in my test pam config file, "to be sure of what would happen" if they were there, I should have left a line that was just like yours, with no arguments, but I didn't. That's why it worked for me and failed for you. Like Raphaël said, ins only works when it's inserting before or after exactly one node, so I wrote argument[last()]. But you can't get the last() of an empty nodeset, so where there were no arguments, argument[last()] caused an error.

In general: Raphaël is more right than me. I seized upon the details of your problem, but the fact is all the Puppet augeas resources I've written myself to deal with PAM configuration are overly detailed, require explanation of how they work, and still assume too much about the beginning state of the file. I think that's the wrong level of abstraction for Puppet DSL code.

-----Original Message-----
From: Tim Bishop [mailto:tim-lists at bishnet.net] 
Sent: Sunday, October 27, 2013 6:29 PM
To: Jennings, Jared L CTR USAF AFMC 96 SK/CCI
Cc: augeas-devel at redhat.com
Subject: Re: [augeas-devel] Help matching a PAM config line

Hi Jared,

Thanks for your help, and for the pointer to the wiki page. That's useful reading.

I've given what you suggest a go but it didn't work. I get the following error from Puppet:

Debug: Augeas[disableupdates-login](provider=augeas): sending command 'ins' with params ["argument", "after", "/files/etc/pam.d/login/*[module = 'pam_motd.so' and count(argument[. = 'noupdate']) = 0]/argument[last()]"]

Error: /Stage[main]/Motd/Motd::Motd::Disableupdates[login]/Augeas[disableupdates-login]: Could not evaluate: Error sending command 'ins' with params ["argument", "after", "/files/etc/pam.d/login/*[module = 'pam_motd.so' and count(argument[. = 'noupdate']) = 0]/argument[last()]"]/Error sending command 'ins' with params ["argument", "after", "/files/etc/pam.d/login/*[module = 'pam_motd.so' and count(argument[. = 'noupdate']) = 0]/argument[last()]"]

Sadly it's not (to my eye) a particularly helpful error message.

It did give me some ideas though, and I ended up with the code below.
This works, but it doesn't feel quite right. It only matches one at a time, so takes multiple passes to do the job.

    $criterion = "*[module = 'pam_motd.so' and count(argument[. = 'noupdate']) = 0][last()]"
    augeas { "disableupdates-$name":
      context => "/files/etc/pam.d/$name",
      changes => [
        "ins argument after ${criterion}/module",
        "set ${criterion}/argument 'noupdate'",
      ],
      onlyif  => "match *[module = 'pam_motd.so' and count(argument[. = 'noupdate']) = 0] size != 0",
      notify  => Exec['pam-auth-update'],
    }

So it specifically looks for the last one with noupdate and adds noupdate. If there's more than one it'll find them next time.

Any thoughts?

Thanks,
Tim.

On Fri, Oct 25, 2013 at 11:22:04AM -0500, Jennings, Jared L CTR USAF AFMC 96 SK/CCI wrote:
> According to
> https://github.com/hercules-team/augeas/wiki/Path-expressions (Tips & 
> Tricks section), """
>   /files/etc/fstab/*[count(opt[. = "noexec"]) = 0] finds all entries 
> in /etc/fstab that do not have a noexec option."""
> 
> This seems to be parallel to your case. So:
> # match all pam_motd lines lacking a noupdate argument $criterion = 
> "*[module = 'pam_motd.so' and count(argument[. =
> 'noupdate']) = 0]"
> augeas { "disableupdates-$name":
>   context => "/files/etc/pam.d/$name",
>   changes => [
>     "ins argument after ${criterion}/argument[last()]",
>     # now the last argument is the one just inserted
>     "set ${criterion}/argument[last()] noupdate",
>   ],
>   notify => Exec['pam-auth-update'],
> }
> 
> To arrive at this without reconfiguring my system, I wrote /tmp/pambla 
> with these lines:
> session optional pam_motd.so motd=/run/motd.dynamic noupdate session 
> optional pam_motd.so flarble # [1] session optional pam_motd.so zort # 
> [2]
> 
> (I wanted to be sure of what would happen if there happened to be 
> other arguments on a pam_motd line, but no noupdate; and of what would 
> happen if there were multiple pam_motd lines lacking a noupdate 
> argument. These two cases may not happen in the real world, but I've 
> screwed up a lot of config files before by not thinking about enough 
> possibilities.)
> 
> Then I ran augtool and
> set /augeas/load/Pam/incl[last()+1] /tmp/pambla load print 
> /files/tmp/pambla
> 
> (Playing about with the lens includes like this may be obvious to 
> everybody else, but I discovered it just now.)
> 
> If there were other arguments on the line lacking noupdate, set 
> *[...]/argument noupdate, as below, could set all of those arguments 
> to noupdate, which is likely not desirable; the above code would 
> merely insert another argument. In the case of multiple lines matching 
> the criterion, it seems with the above code the last matching line 
> will get a noupdate argument, and next time that line, having a 
> noupdate, will not match the criterion, so another line will be fixed. 
> So this wouldn't fix everything in one pass in that case.
> 
> I tried just set *[...]/argument[last()+1] noupdate, but this put an 
> argument after a #comment in the tree, and then it would not save 
> properly. So the ins followed by set appeared necessary.
> 
> -----Original Message-----
> From: augeas-devel-bounces at redhat.com
> [mailto:augeas-devel-bounces at redhat.com] On Behalf Of Tim Bishop
> Sent: Wednesday, October 23, 2013 4:39 PM
> To: augeas-devel at redhat.com
> Subject: [augeas-devel] Help matching a PAM config line
> 
> Hi,
> 
> I'd like to ask for some Augeas help. I'm trying to match a specific 
> PAM config line so I can append something to it. The relevant lines are:
> 
> session    optional     pam_motd.so  motd=/run/motd.dynamic noupdate
> session    optional     pam_motd.so # [1]
> 
> What I want to do is add "noupdate" to second line.
> 
> I've done something similar previously using Puppet with this block:
> 
>   augeas { "disableupdates-$name":
>     context => "/files/etc/pam.d/$name",
>     changes => [
>       "ins argument after *[module = 'pam_motd.so']/module",
>       "set *[module = 'pam_motd.so']/argument 'noupdate'",
>     ],
>     onlyif  => "match *[module = 'pam_motd.so' and 
> argument='noupdate'] size == 0",
>     notify  => Exec['pam-auth-update'],
>   }
> 
> But at the time the PAM config only contained this line:
> 
> session    optional     pam_motd.so # [1]
> 
> This no longer works because my onlyif statement matches on the new 
> line before it.
> 
> So I'd like some help to modify the above code to only match and 
> modify the second line. Or maybe there's another way that I've not thought of?
> 
> Thank you in advance,
> 
> Tim.
> 
> --
> Tim Bishop
> http://www.bishnet.net/tim/
> PGP Key: 0x6C226B37FDF38D55
> 
> _______________________________________________
> augeas-devel mailing list
> augeas-devel at redhat.com
> https://www.redhat.com/mailman/listinfo/augeas-devel
> 
> _______________________________________________
> augeas-devel mailing list
> augeas-devel at redhat.com
> https://www.redhat.com/mailman/listinfo/augeas-devel


Tim.

--
Tim Bishop
http://www.bishnet.net/tim/
PGP Key: 0x6C226B37FDF38D55





More information about the augeas-devel mailing list