Forum: Cfengine Help
Subject: Re: 3.0.2 too old?
Author: zzamboni
Link to topic: https://cfengine.com/forum/read.php?3,20392,20419#msg-20419

Fredrik,

I think there may be a logic error in your config, which could explain the 
erratic behavior. When you do:

classes:
 "have_user" expression => userexists("$(users)");

This is being implicitely looped-over for each value of @(users), as it should 
be. However, this looping happens (if I understand the behavior correctly) for 
the whole list before proceeding to the next section (commands: in this case). 
So the "have_user" class will be defined according to the last user tested.

What you can do is define one class for each user to test, and then you can 
loop over the list as many times as you want and get the correct results. This 
is the create_users() bundle I have used successfully (for local accounts on 
Linux at least - the Windows bits are not fully tested):

bundle agent create_users(user)
{
vars:
  "index"        slist => getindices("$(user)");

classes:
  "add_$(index)" not => userexists("$(index)");

commands:
  linux::
    "/usr/sbin/useradd $($(user)[$(index)]) -u $($(user)[$(index)]) 
     -g $($(user)[$(index)]) -d $($(user)[$(index)]) 
     -s $($(user)[$(index)]) -c '$($(user)[$(index)])' $(index)"
      ifvarclass => "add_$(index)";
  windows::
    "c:\Windows\system32\net user $(index) $($(user)[$(index)]) /add 
     \"/fullname:$($(user)[$(index)])\" \"/homedir:$($(user)[$(index)])\""
      ifvarclass => "add_$(index)";
    # Set the password inconditionally in case it has changed.
    "c:/Windows/system32/net user $(index) $($(user)[$(index)])";

files:
  # This is not conditioned to the add_* classes to always check
  # and reset the passwords if needed.
  linux::
    "/etc/shadow"
      edit_line => set_user_field("$(index)", 2, "$($(user)[$(index)])");

reports:
  !linux.!windows::
    "I only know how to create users under Linux and Windows.";
  verbose::
    "Created user $(index)"
      ifvarclass => "add_$(index)";
}


And you use it like this:

bundle agent manage_users
{
vars:
  # Users to create
  "users"     string => "System administrator";
  "users"       string => "0";
  "users"       string => "0";
  "users"      string => "/root";
  "users"     string => "/bin/bash";
  "users"     string => "-o -m";
  "users"  string => "FkDMzhB1WnOp2";

  "users"     string => "Diego Zamboni";
  "users"       string => "501";
  "users"       string => "users";
  "users"      string => "/home/zamboni";
  "users"     string => "/bin/bash";
  "users"     string => "-m";
  "users"  string => "dk52ia209rfuh";

methods:
  "users"   usebundle => create_users("manage_users.users");
}


As you can see, the user-existence classes have the username in them:

classes:
  "add_$(index)" not => userexists("$(index)");

Which makes it clear which users have to be created.

This bundle also sets the password to a fixed value defined in the 
configuration array (the provided value is the hashed password as it should be 
set in /etc/shadow), since it is meant precisely for managing local accounts 
(e.g. for services or applications) that should have a known, fixed password.

Hope this helps,

_______________________________________________
Help-cfengine mailing list
Help-cfengine@cfengine.org
https://cfengine.org/mailman/listinfo/help-cfengine

Reply via email to