I have puppet 6 installed in my environment and would like to ensure that the user centos cannot sudo on all of my agents. I can create somethings like this:
modules/sudoer/manifests/disable_sudo.pp
# Manage the sudoers file
class sudoers {
file { '/etc/sudoers':
source => 'puppet:///modules/sudoers/sudoers',
mode => '0440',
owner => 'root',
group => 'root',
}
}
And then create a modules/sudoers/files/sudoers file and put the content I like in there and make sure the centos line is commented out:
#centos ALL=(ALL) NOPASSWD: ALL
But this is very lengthy and in puppet 3, I could only use sudo::disable_centos: true in the hiera. Is there a better way for letting puppet prevent the user centos from sudo? Thank you
Related
We have RedHat 7.2 Linux OS and use puppet to perform our tasks. I am using puppet to install some software, which has worked fine and now the final step is to create an OS level service. In earlier versions of RHEL, we used chkconfig but that has been replaced with systemctl. Of course, the recommended way of performing this task is using a service. Since this is a custom software, I have my own startup script that I usually copy over to /etc/init.d, run chkconfig and then startup the service. How do I perform these tasks via Puppet for RedHat 7.2 OS ? I only want to create the service (not start it up or anything). This way, when the server reboots, the service will startup the app.
EDIT :
#redstonemercury for RHEL 7 I would think the following would be required. But your suggestion definitely helps as I was thinking along the same lines.
https://serverfault.com/questions/814611/puppet-generated-systemd-unit-files
file { '/lib/systemd/system/myservice.service':
mode => '0644',
owner => 'root',
group => 'root',
content => template('modulename/myservice.systemd.erb'),
}~>
exec { 'myservice-systemd-reload':
command => 'systemctl daemon-reload',
path => [ '/usr/bin', '/bin', '/usr/sbin' ],
refreshonly => true,
}
In puppet, use a package resource to install the package (assuming it's in repos that you're declaring already), then use a file resource to declare the /etc/init.d file, and put require => Package[<package_resource_name>] as a parameter in the file declaration to ensure the custom file gets created after the package has installed (so doesn't potentially get overwritten by the package's /etc/init.d file). E.g.:
package { 'mypackage':
ensure => present,
}
file { '/etc/init.d/mypackage':
ensure => present,
content => template('mypackage/myinitd'),
require => Package['mypackage'],
}
This is if you want to use a template. For a file, instead of content use source: source => puppet://modules/mypackage/myinitd
Some disclosure:
I'm using a master/agent setup in which I own the agent but do not have permission to the master console. The puppetmaster is git-backed, and I control the source for the module(s) in question.
I have 2 relevant modules for my question. One of them, which appears to work just fine, ensures autofs is installed and has 2 file resources for auto.master and a custom auto.home to mount home directories.
#auto.home
#this file is used by auto.master to automount home directories
#from the nfs cluster when a user logs in.
* -fstype=nfs,rw,nosuid,soft <IPaddress>:/homedirs/&
In the module to add home directories, I'm creating users and deploying their public ssh keys via a file resource. This module "works" on systems when I comment out the Class dependency and I'm not mounting /home to NFS, and it *sometimes works when I'm deploying it as-is over NFS.
define local_user(
$fullname,
$username = $title,
$userid,
$gid = 9999,
$homedir_mode = 0700
) {
$white_gid = $gid
user { $username:
ensure => present,
comment => $fullname,
gid => $white_gid,
uid => $userid,
home => $homedir,
require => Group[ "white" ],
}
exec { "chage -M 99999 ${username}":
command => "chage -M 99999 ${username}",
path => "/bin:/sbin:/usr/bin:/usr/sbin",
# chage(1) only works on local users, not on LDAP users,
# so make sure this is a local user before we try to
# change their password expiration.
onlyif => "grep -q '^${username}:' /etc/passwd",
subscribe => User[ $username ],
refreshonly => true,
}
file { $homedir:
ensure => directory,
owner => $username,
group => $white_gid,
mode => $homedir_mode,
require => User[ $username ],
}
file { "$homedir/.ssh":
ensure => directory,
owner => $username,
group => $white_gid,
mode => 0700,
require => File[ "$homedir" ],
}
file { "$homedir/.ssh/authorized_keys":
ensure => present,
owner => $username,
group => $white_gid,
mode => 0600,
source => "puppet:///modules/ssh_keys/${username}_authorized_keys",
require => File["$homedir/.ssh"],
}
}
class ssh_keys {
group { "white":
ensure => present,
gid => 9999,
require => Class["nfs_homedirs"],
}
#### add users below this line
local_user { "userA" : fullname => "userA", userid => "123" }
Some things I'm puzzled by and could use expertise with:
In order for the NFS home directories to work at all, I had to run the module on a machine to create the users locally, then mount the root directory of the NFS mount for home directories and create those user's folders owned by their uid/gid for the autofs to actually work when they log in.
When the module fails to "work" against the NFS-mounted home directories, the error is 'Permission denied' when it tries to create the home folder. I've tried no_root_squash to combat the error, but to no avail. I have tried running the agent as root, as not-root via sudo, as not-root at all, etc.
Error:
/Stage[main]/Ssh_keys/Local_user[userA]/File[/home/userA]/ensure:
change from absent to directory failed: Could not set 'directory' on ensure:
Permission denied - /home/userA at
80:/app/puppet/conf/environments/puppet_dev/modules/ssh_keys/manifests/init.pp
It's seemingly harmless to put ensure => present statements on these directories and file resources. They're technically already created on the NFS share, but the way autofs seems to work is that it won't actually "mount" that user's share until they login. It's not my expertise, but that's what I experience. When this module does run successfully, every user's home directory it creates shows as a mount in the df output.
I suspect that there's something on the machine itself that's preventing this module from working the way it should. Knowing that there are probably 500 things that I could diff between a machine where this module runs clean and one where it doesn't, what are some places I should investigate?
Any assistance would be greatly appreciated.
The way auto.home works is to mount the directory when the user logs in. If the user hasn't logged in, no mount exists -- and thus your directory/file resources fail.
Personally I wouldn't try creating home directories over an nfs mount. Plus you don't want multiple servers trying to manage the same physical resources. Split this out to run only on the NFS server if possible and run all your file resources related to the home directories there. Have the nfs clients just ensure nfs is configured and the local user accounts exist.
If you can't run puppet on the NFS server, pick 1 server to mount it as a regular mount -- i.e. mount the root of the home dirs section so they are all visible. Have no_root_squash set also. Then you should be able to have puppet create the directories.
Also the ssh_authorized_key resource is handy. I use it often.
It sounds to me like selinux is being enforced, which would cause a permission denied as described even if you have the right user/uid owning the directories. If you have selinux enforced, then you'll want to check to see if using nfs_home_dirs is allowed. First, check by running:
getsebool use_nfs_home_dirs
If it comes back as use_nfs_home_dirs --> off, then you can either manually correct this using setsebool -P use_nfs_home_dirs 1, or you can use puppet to manage this as well:
include selinux
selinux::boolean {'use_nfs_home_dirs':
ensure => 'on',
}
i am using the example of iptraf on github
I do a git clone, and then sudo puppet apply init.pp
but i dont see iptraf installed on the ubuntu 11.04 host
now this puppet is a client ONLY instance, and NO Master.
from another example i see i can install apache2 as:
class basic_services {
##Get Apache
package { 'apache2':
ensure => 'installed',
}
##Edit the Apache Conf
file { "/etc/apache2/sites-available/default":
require => Package["apache2"],
owner => "root",
group => "root",
content => "$some_variables::apache_config",
}
##Make sure Apache is running, and restarts on changes to conf
service {'apache2':
require => Package["apache2"],
ensure => running,
subscribe => File["/etc/apache2/sites-available/default"],
}
}
so for iptraf:
init.pp
class iptraf {
include iptraf::base
}
base.pp
class iptraf::base {
package{'iptraf': ensure => installed }
}
I will use this example as a base to develop a manifest for Testing Tools
So what am i missing here , as after i run :
sudo puppet apply init.pp , and try to access iptraf, i get the message:
iptraf
The program 'iptraf' is currently not installed. You can install it by typing:
sudo apt-get install iptraf
in the directory:
/etc/puppet/modules/iptraf
- create a file:
iptraf.pp
- with contents:
package { "iptraf":
ensure => "installed"
}
- issue the command:
puppet apply iptraf.pp
/Stage[main]//Package[iptraf]/ensure: ensure changed 'purged' to 'present'
Finished catalog run in 2.71 seconds
run iptraf on command line , the UI POPS UP.
Done!
move the iptraf directory to the modules. Your directory structure should be this :
/etc/puppet/modules/iptraf/manifests/{init.pp,base.pp}
then do,
sudo puppet apply -e 'include iptraf'
that should install iptraf.
sudo iptraf should open a nice screen in your terminal :)
I am trying to develop a CakePHP application, and I am using Vagrant to run a testing environment. However, I was getting this error in the browser
Warning (2):
session_start() [http://php.net/function.session-start]:
open(/var/lib/php/session/sess_speva7ghaftl8n98r9id5a7434, O_RDWR) failed:
Permission denied (13) [CORE/Cake/Model/Datasource/CakeSession.php, line 614]
I can get rid of the error by SSHing to the vm and doing
[vagrant#myserver ~]$ sudo su -
[root#myserver ~]# chown -R vagrant. /var/lib/php/session/
I don't want to have to do this every time I restart the vm, so I tried adding this to myserver.pp
exec { 'chown':
command => 'chown -R vagrant. /var/lib/php/session/',
path => '/bin',
user => 'root'
}
but it gets an error while starting up the vm...
err:
/Stage[main]/Myserver/Exec[chown]/returns: change from notrun to 0 failed:
chown -R vagrant. /var/lib/php/session/
returned 1 instead of one of [0] at /tmp/vagrant-puppet/manifests/myserver.pp:35
I was unable to find any useful examples of how to use exec on the internet, and I have never used Vagrant or Puppet before, so the above code is just the best guess I could come up with, and I apologize if it is a simple fix to get this working.
I have verified using which chown within the vm that the path is /bin, and the command is exactly the same as when I run it in the vm myself. I'm thinking it is the user that is causing problem. Do I have that line right? Is it even possible to exec commands as root from a .pp file?
When using exec, you normally have to enter the full path to the command you execute. So if you change your command into
exec { 'chown':
command => '/bin/chown -R vagrant:vagrant /var/lib/php/session/',
path => '/bin',
user => 'root'
}
it should work imo.
However, it depends a lot how you install your application. If the setup/start of the application is also managed with Puppet, you can also manage the directory you're interested in with Puppet, like this
file { "/var/lib/php/session" :
ensure => directory,
group => "vagrant",
owner => "vagrant",
recurse => true,
}
before you start your app. This would be much more the Puppet way, as you manage a reource then instead of executing commands. However, normally /var/lib/... should not be owned by someone other than root.
So you should maybe look into how your app is started and make it start with another user or as root. If it is started with an exec, you can add an additional property
user => root
to it and that should also do the trick.
I am trying to do the following using Puppet on an Ubuntu 10.04:
Copy a file that I have to a specific directory which will be owned by a specific user / group that does not exists yet since the package has not been installed
Install the package where it will not remove the directory and file that I created
To accomplish item #1, I basically tell Puppet to create a user and group first before copying the file. But the problem is that if I do not give a specific uid for Puppet, it will randomly pick a number like a number for user and not a number for system package.
So, how do I tell Puppet to choose a uid anything more than 1000?
If this is not possible, how do I tell Puppet not to start the package when it installs it. So I would just let Puppet install the package, but do not start the service, then copy my file, then I will start the service.
The user type has a parameter of system => which defaults to false, but can be set to true. This will generate the user with a UID below 500. Which seems to be what you want.
Ultimately what you'll want to do in my opinion is manage the config directory and the config via puppet as well.
This gives you the ability to do things like such:
package { foo: ensure => present }
file {
fooconfdir:
path => '/path/to/fooconfdir',
ensure => directory,
user => whatev,
group => alsowhatev,
require => Package[foo],
mode => morewhatev;
fooconf:
path => '/path/to/fooconfdir/fooconf',
ensure => present,
user => whatev,
content => template('whatev');
}
service { foo: ensure => running, enable => true, subscribe => File[fooconf] }
What that will do , is install your package then manage the config, then restart the service which will use your new config obviously on restart.