LinuxQuestions.org
Visit Jeremy's Blog.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - General
User Name
Password
Linux - General This Linux forum is for general Linux questions and discussion.
If it is Linux Related and doesn't seem to fit in any other forum then this is the place.

Notices


Reply
  Search this Thread
Old 04-30-2019, 10:06 AM   #1
Ladowny
Member
 
Registered: Oct 2006
Distribution: Debian, OpenBSD, FreeBSD
Posts: 54

Rep: Reputation: 15
CFEngine 3 creating admin and restricted users and setting their groups


I am building CFEngine 3 promise to set up 2 types of system users : admins with sudo permission and developers with no sudo but able to delete each other's files in specific folders

Say we have user dev1
Primary group: developers ( so that other developers can edit/delete the files )
Secondary groups:
adm - to viev logs
www-data - to be able to delete files created by web server
dev1 - unique group to protect home folder

home folder owned by dev1:dev1 so that others cannot look in there

and admin1 user with similar settings, but also added to sudoers

See me promise code below, works fine, adds users, but when I set primary group to developers the unique group for the user is not created and the code perms => og("$(login)","$(login)") fails because there is no such group.

How can I force creation of this unique group if it's not primary for the user ?

Or is there any other way I can be sure files and directories created under /www folder can be deleted and edited by all developers without sudo access. Some of these files are created by web server user and have to be owned by it's user and group

I am setting umask 002 for both shell access and web server so that files are rw for group

Or is there any other solution, maybe I'm stuck on the wrong mountain top ? All I want is to allow developers to update each others code when they take over the project, allow them to clear cache created by web server user but not allow them to run commands as root as they tend to change server configuration to make their code work and do not tell anyone.

The promise code below, works with CFEngine 3.9.1 on Debian 9

And of course I have more admins and developers than in the example below, that's why the code is more complex

Code:
body common control
{
  inputs => { "$(sys.libdir)/users.cf" };
  inputs => { "$(sys.libdir)/files.cf" };
  inputs => { "$(sys.libdir)/stdlib.cf" }; }

# Add "developers" grouup

bundle agent add_groups
{
  classes:
      "group_developers_absent"
        not => groupexists("developers");

  commands:
    linux.group_developers_absent::
      "$(paths.groupadd)"
        args => "developers";
}

# Create users 

bundle agent it_users
{
        vars:
                # Admin users
                "users[john][fullname]" string => "John Doe";
                "users[john][pass_hash]" string => "$................................../";
                "users[john][ssh_key]" string => "ssh-rsa xxxxxxxxxxx" ;

# Additiona example variables
#                "users[winnie][fullname]" string => "Winnie The Pooh ";
#                "users[winnie][uid]" string => "501";
#                "users[winnie][gid]" string => "users";
#                "users[winnie][home]" string => "/home/winnie";
#                "users[winnie][shell]" string => "/bin/bash";
#                "users[winnie][flags]" string => "-m";

	methods:
		 "any" usebundle => add_users ("it_users.users"); }


bundle agent dev_users
{
        vars:
                # Developers  users - only on specific servers 
                "users[winnie][fullname]" string => "Winnie the Pooh";
                "users[winnie][pass_hash]" string => "$...................................../";
                "users[winnie][ssh_key]" string => "ssh-rsa xxxxxxxxxxxxxxxxxxxx ";

        methods:
		dev_users_present::
                 	"any" usebundle => add_users ("dev_users.users"); }


bundle agent add_users (user_array)
{
	vars:	

                "login" slist => getindices("$(user_array)");
                "skel" string => "/etc/skel";
	reports:
                linux::
			"Setting up user $(login) - full name $($(user_array)[$(login)][fullname])" ;
		

        users:
                linux::
                        "$(login)"
                        home_dir => "/home/$(login)",
                        description => "$($(user_array)[$(login)][fullname])",
#   If the below is commented out a group for user is created eg group winnie for user winnie 
#   if I uncomment that the group will not be created and the lines below setting perms for home dir will fail as they would be setting o/g to winnie:winnie 						
#			group_primary => "developers",
                        groups_secondary => { "adm", "developers", "www-data" },
# this also works, provided the group exists
#                         groups_secondary => { "adm", "developers", "www-data", "$(login)"},
						
                        shell => "/bin/bash",
                        policy => "present" ,
                        password => hashed_password( "$($(user_array)[$(login)][pass_hash])" );
        files:
# files promisses get repaired on every run - need to check why 
                linux::
                        "/home/$(login)/."
                                create => "true",

                                perms => og("$(login)","$(login)"),
                                copy_from => seed_cp( $(skel) ),
                                depth_search => recurse( "inf" );
                        "/home/$(login)"
                                perms => og("$(login)","$(login)") ;
                         "/home/$(login)/.ssh/."
                                perms => mog("700","$(login)","$(login)"),
                                create => "true";
                         "/home/$(login)/.ssh/authorized_keys"
                                perms => mog("600","$(login)","$(login)"),
                                edit_line => append_if_no_line("$($(user_array)[$(login)][ssh_key])"),
                                create => "true";

        reports:
                "adding user = $(login) - full  name = $($(user_array)[$(login)][fullname]) hash $($(user_array)[$(login)][pass_hash])";

}


# Users that need to be removed
bundle agent remove_users
{
        vars:
                "login" slist
                        => {
                        "roy",
                        "maurice",
                        "jen",
                 };

        users:
                linux::
                        "$(login)"
                        policy => "absent"; # Remove home directories - need to work on that, content of $HOME removed but the directory stays 
       files:
               linux::
                              "/home/$(login)/."
                               file_select => all,
                               depth_search => recurse("inf"),
                               delete => tidy ;

}

Last edited by Ladowny; 04-30-2019 at 11:53 AM.
 
Old 04-30-2019, 12:02 PM   #2
cmdln
Member
 
Registered: Apr 2009
Location: Lawrence, KS
Distribution: Debian, Centos
Posts: 108
Blog Entries: 1

Rep: Reputation: 25
Quote:
How can I force creation of this unique group if it's not primary for the user ?
Unfortunately, there is currently no groups type promise to just make promises about a groups state. But you can check for the presence of the group and create it using either a commands type promise or a files type promise if you know the GID you want to use. I would look to just make sure the group exists instead of trying to make sure it exists if it's not primary.

Example editing groups directly:
Code:
  bundle agent example
  {
    vars:

        "groups[developers]" string => "developers:x:1010:";
        "groups_file" string => "/tmp/group";

    files:

      # Insert the group if no entry exists, note this doesn't deal with users nor
      # does it handle changing the gid. Those can be done with set_colon_field,
      # and append_user_field from the stdlib

       "$(groups_file)"
         edit_line => append_groups_starting( "$(this.bundle).groups" );

  }
  bundle agent __main__
  {
    methods:
        "example";
  }
Example running groupadd if necessary

Code:
  bundle agent example
  {
    vars:

        "groups_file" string => "/tmp/group";

    commands:
      "/bin/echo groupadd developers"
        unless => regline( "^developers:.*", $(groups_file) );
  }
  bundle agent __main__
  {
    methods:
        "example";
  }
Output:

Code:
:   notice: Q: ".../bin/echo group": groupadd developers
Quote:
Or is there any other way I can be sure files and directories created under /www folder can be deleted and edited by all developers without sudo access. Some of these files are created by web server user and have to be owned by it's user and group
Extended attributes is quite flexible. Have you considered using those?


Quote:
The promise code below, works with CFEngine 3.9.1

And of course I have more admins and developers than in the example below,
that's why the code is more complex
I just made some direct edits to the code:

Code:
  body common control
  {
          inputs => {
                      "$(sys.libdir)/users.cf",
                      "$(sys.libdir)/files.cf",
                      "$(sys.libdir)/stdlib.cf"
          };
  }

  # Add "developers" grouup

  bundle agent add_groups
  {
    classes:
        "group_developers_absent"
          not => groupexists("developers");

    commands:
      linux.group_developers_absent::
        "$(paths.groupadd)"
          args => "developers";
  }

  # Create users

  bundle agent it_users
  {
          vars:
                  # Admin users
                  "users[john][fullname]" string => "John Doe";
                  "users[john][pass_hash]" string => "$................................../";
                  "users[john][ssh_key]" string => "ssh-rsa xxxxxxxxxxx" ;

  # Additiona example variables
  #                "users[winnie][fullname]" string => "Winnie The Pooh ";
  #                "users[winnie][uid]" string => "501";
  #                "users[winnie][gid]" string => "users";
  #                "users[winnie][home]" string => "/home/winnie";
  #                "users[winnie][shell]" string => "/bin/bash";
  #                "users[winnie][flags]" string => "-m";

    methods:
        "any" usebundle => add_users ("it_users.users");
        "any" usebundle => add_groups;
  }

  bundle agent dev_users
  {
          vars:
                  # Developers  users - only on specific servers
                  "users[winnie][fullname]" string => "Winnie the Pooh";
                  "users[winnie][pass_hash]" string => "$...................................../";
                  "users[winnie][ssh_key]" string => "ssh-rsa xxxxxxxxxxxxxxxxxxxx ";

          methods:
      dev_users_present::
                    "any" usebundle => add_groups;
                    "any" usebundle => add_users ("dev_users.users"); }


  bundle agent add_users (user_array)
  {
    vars:

                  "login" slist => getindices("$(user_array)");
                  "skel" string => "/etc/skel";
    reports:
                  linux::
        "Setting up user $(login) - full name $($(user_array)[$(login)][fullname])" ;


          users:
                  linux::
                          "$(login)"
                          home_dir => "/home/$(login)",
                          description => "$($(user_array)[$(login)][fullname])",
  #   If the below is commented out a group for user is created eg group winnie for user winnie
  #   if I uncomment that the group will not be created and the lines below setting perms for home dir will fail as they would be setting o/g to winnie:winnie
  #			group_primary => "developers",
                          groups_secondary => { "adm", "developers", "www-data" },
  # this also works, provided the group exists
  #                         groups_secondary => { "adm", "developers", "www-data", "$(login)"},

                          shell => "/bin/bash",
                          policy => "present" ,
                          password => hashed_password( "$($(user_array)[$(login)][pass_hash])" );
          files:
  # files promisses get repaired on every run - need to check why
                  linux::
                          "/home/$(login)/."
                                  create => "true",

                                  perms => og("$(login)","$(login)"),
                                  copy_from => seed_cp( $(skel) ),
                                  depth_search => recurse( "inf" );
                          "/home/$(login)"
                                  perms => og("$(login)","$(login)") ;
                           "/home/$(login)/.ssh/."
                                  perms => mog("700","$(login)","$(login)"),
                                  create => "true";
                           "/home/$(login)/.ssh/authorized_keys"
                                  perms => mog("600","$(login)","$(login)"),
                                  edit_line => append_if_no_line("$($(user_array)[$(login)][ssh_key])"),
                                  create => "true";

          reports:
                  "adding user = $(login) - full  name = $($(user_array)[$(login)][fullname]) hash $($(user_array)[$(login)][pass_hash])";

  }


  # Users that need to be removed
  bundle agent remove_users
  {
          vars:
                  "login" slist
                          => {
                          "roy",
                          "maurice",
                          "jen",
                   };

          users:
                  linux::
                          "$(login)"
                          policy => "absent"; # Remove home directories - need to work on that, content of $HOME removed but the directory stays
         files:
                 linux::
                                "/home/$(login)/."
                                 file_select => all,
                                 depth_search => recurse("inf"),
                                 delete => tidy ;

  }

- I am surprised that defining inputs multiple times worked. It's a list, it
should be defined just once.

- From the description above, I didn't understand that you already had a
commands promise to groupadd developers. Looking at your policy, I don't
see where add_groups is called. If add_groups is called first, then the
group should exist before perms => mog("700","$(login)","$(login)"), I just
edited it so that add_groups is called before add_users in both the
it_users and dev_users bundles are called. You could instead call it
before it_users and dev_users is called.


Also, the cfengine help list and #cfengine on irc.freenode.net are great resources.
 
Old 05-30-2019, 09:18 PM   #3
Ladowny
Member
 
Registered: Oct 2006
Distribution: Debian, OpenBSD, FreeBSD
Posts: 54

Original Poster
Rep: Reputation: 15
Thanks for the feedback and sorry for not responding earlier. Had to work on another project urgently.

I managed to solve the permission issue by setting the sticky bit on the folder and this seems to work

Code:
chmod g+s /www
As for, 'developers' group, It's created earlier in my promises, no problems with that

However there sill seems to be an issue with the way CFengine3 handles setting each user's primary group called the same as user name. When I set

Code:
                        group_primary => "$(login)",
                        groups_secondary => { "$($(user_array)[$(login)][groups_secondary])"},
in my promise and bootstrap a new machine I get the following error when creating users
Code:
 verbose: Creating user 'winnie'. (command: '/usr/sbin/useradd -c "Winnie the Pooh" -g "winnie" -G "adm,developers,www-data,sudo" -d "/home/winnie" -s "/bin/bash" -M winnie')
   error: Command returned error while creating user 'winnie'. (Command line: '/usr/sbin/useradd -c "Winnie the Pooh" -g "winnie" -G "adm,developers,www-data,sudo" -d "/home/winnie" -s "/bin/bash" -M winnie')
    info: User promise not kept
Groups 'adm,developers,www-data,sudo' exist. Group 'winnie' does not and is not created.

When I comment group_primary promise out and do not promise primary group user 'winnie' gets created fine, with the right primary group 'winnie' which also gets created
Code:
~# groups winnie
winnie : winnie adm sudo www-data developers
but on the consecutive runs of cf-agent I get the following

Code:
 verbose: Getting user 'winnie' password hash from shadow database.
 verbose: Getting user 'winnie' password hash from shadow database.
 verbose: Verifying password hash for user 'winnie': correct.
 verbose: Modifying user 'winnie'. (command: '/usr/sbin/usermod -G "" winnie')
 verbose: Modifying user 'winnie'. (command: '/usr/sbin/usermod -G "adm,developers,www-data,sudo" winnie')
    info: User promise repaired
 verbose: A: Promise REPAIRED

Not sure why it's running
Code:
usr/sbin/usermod -G "" winnie
every time, trying to change secondary groups fro the user


Not sure what you mean by
Quote:
- I am surprised that defining inputs multiple times worked. It's a list, it should be defined just once.
Are you referring to me calling bundle 'add_users' with different user arrays as parameters? I am treating this bundle as a function or a method within a class with parameters passed to it and it seems to work with one exception. That is what I tend to do with any code I write. Try to build reusable classes and methods. I actually have 4 types of users, each type needs to be assigned to different secondary groups and be set up on different servers. These users come and go, and servers are sometimes built per project and need to have set of users created, so looking for a flexible solution.

Thanks

Greg
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
Anything about old PCs, their uses, related OSes and their users rvijay General 1884 07-07-2022 09:29 AM
Creating groups, users, setting passwords gtrrockz84 Linux - Networking 1 01-06-2012 06:39 AM
[SOLVED] samba : how to synchronize AD users & groups with Samba users &groups zelycorn Red Hat 5 05-12-2011 09:15 AM
creating groups, adding users, and setting permissions bowie101 Linux - Newbie 2 11-23-2005 12:42 PM

LinuxQuestions.org > Forums > Linux Forums > Linux - General

All times are GMT -5. The time now is 10:15 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration