a system for automating system administration tasks
|
|
Download from
http://reductivelabs.com/trac/puppet/wiki/DownloadingPuppet
or
http://reductivelabs.com/downloads/puppet/
Or use RPMS
[root@server ~] chkconfig puppetmaster on [root@server ~] service puppetmaster start Starting puppetmaster: [ OK ]puppetmasterd will start and listen on port 8140, you'll need to allow clients to connect to that port.
[root@server sysconfig]# iptables -I RH-Firewall-1-INPUT \ -p tcp -m tcp -m state --state NEW,ESTABLISHED,RELATED \ --destination-port 8140 -j ACCEPT [root@server sysconfig]# iptables-save >iptables
[facts] path /var/lib/puppet/facts allow *.example.com [files] path /var/lib/puppet/files allow *.example.com [web] path /var/lib/puppet/web allow www*.example.comfacts is a container for facter facts. files and web are file locations.
Manifests are puppet configuration files. they are used to describe functions, nodes, and installation classes.
It is good practice to separate out different functions, putting nodes in nodes.pp and functions in functions.pp or a similar naming convention. We default to making a new manifest for each class we define.
The first manifest is the master manifest (site.pp), it lists the other manifests that puppetmaster will load. puppetmaster only knows to load site.pp
import "functions.pp" import "nodes.pp" import "auth.pp" import "base.pp"
define remotefile($owner = root, $group= root, $mode, \
$server = "server.example.com", $cls="base", \
$backup = false, $recurse = false) {
file {
$name:
mode => $mode,
owner => $owner,
group => $group,
backup => $backup,
source => "puppet://$server/$cls/$name"
}
}
puppet already has file defined, we have simply wrapped file in a function that sets some defaults for us.
define append_if_no_such_line($file, $line, $refreshonly = 'false') {
exec { "/bin/echo '$line' >> '$file'":
unless => "/bin/grep -Fxqe '$line' '$file'",
path => "/bin",
refreshonly => $refreshonly
}
}
This is a generic function which looks for the argument $line using grep on $file. The appending is done with >> in the cmd argument for exec
node client0 {
include auth
}
node default {
include base
}
class base {
remotefile { "/etc/syslog.conf": mode => 644 }
remotefile { "/etc/logwatch/conf/logwatch.conf": mode => 644 }
# time
file { "/etc/ntp.conf": mode=> 644 }
service { ntpd: ensure => true, enable => true }
}
See http://reductivelabs.com/trac/puppet/wiki/FunctionReference for details on the different functions available
class auth {
# ldap
remotefile { "/etc/ldap.conf": mode => 644, cls => "auth" }
remotefile { "/etc/openldap/ldap.conf": mode => 644, cls => "auth" }
# ns
remotefile { "/etc/nsswitch.conf": mode => 644, cls => "auth" }
# pam
remotefile { "/etc/pam.d/system-auth": mode => 644, cls => "auth" }
}
http://reductivelabs.com/trac/puppet/wiki/TypeReference
file { "/etc/nsswitch.conf":
mode => 644,
source => "puppet://server.example.com/etc/nsswitch.conf" }
service { nscd:
ensure => true,
enable => true,
hasrestart => true,
subscribe => File['/etc/nsswitch.conf'] }
service { messagebus:
ensure => true,
enable => true,
hasrestart => true,
subscribe => File['/etc/nsswitch.conf'] }
exec { "restart auth dependencies":
command => "/sbin/service nscd stop; \
/sbin/service nscd restart; \
/sbin/service messagebus restart; \
/usr/sbin/gdm-restart",
logoutput => true,
refreshonly => true,
subscribe => File['/etc/nsswitch.conf'] }
selboolean { httpd_can_network_connect:
persistent => true,
value => on }
PUPPET_SERVER=puppet.example.com PUPPET_EXTRA_OPTS=--factsync
signing policy
autosign.conf
*example.com 10.0.0.0/8
[root@server ~]# puppetca --list
host.example.com
server.example.com
[root@server ~]# puppetca --clean host.example.com
Removing /var/lib/puppet/ssl/ca/requests/host.example.com.pem
[root@server ~]# puppetca --sign server.example.com
Signed server.example.com
[root@server ~]# puppetca --list
No cerificates to sign
[root@server ~]# puppetca --list -a
+ server.example.com
Configure ssh to not allow PasswordAuthentication
[root@server ~] export AUGEAS_ROOT=/root/augeas-sandbox
[root@server ~] mkdir $AUGEAS_ROOT
[root@server ~] cp -pr /etc $AUGEAS_ROOT
[root@server ~] grep PasswordAuthentication augeas-sandbox/etc/ssh/sshd_config
#PasswordAuthentication yes
# PasswordAuthentication, PermitEmptyPasswords, and
[root@server ~] augtool -b
augtool> set /files/etc/ssh/sshd_config/PasswordAuthentication no
augtool> save
Saved 1 file(s)
[root@server ~]# grep PasswordAuthentication augeas-sandbox/etc/ssh/sshd_config
#PasswordAuthentication yes
# PasswordAuthentication, PermitEmptyPasswords, and
PasswordAuthentication no
Same configuration change we did with augtool
class ssh {
augeas{ "ssh":
context => "/files/etc/ssh/sshd_config",
changes => [
"set PasswordAuthentication no"
],
notify => Service["sshd"]
}
service{ sshd: ensure => true, enable => true, hasrestart => true }
...
}
configuration change triggers sshd restart
advanced puppet
[puppetmasterd]
storeconfigs = true
dbadapter = mysql
dbuser = puppet
dbpassword = "reductiveLabs"
dbserver = localhost
dbsocket = /var/lib/mysql/mysql.sock
class ssh {
case $sshrsakey {
"": { # ignore empty keys
}
default: {
@@sshkey {"$hostname":
type => rsa,
key => $sshrsakey,
alias => $fqdn }
@@sshkey {"$ipaddress_eth0":
type => rsa,
key => $sshrsakey }
}
}
Sshkey <<| |>>
}
greatly simplified example, proper class file here. This example uses mysql to store ssh keys that are exported using the @@ operator. http://reductivelabs.com/trac/puppet/wiki/ExportedResourcesstore puppet class information for hosts in ldap*
[puppetmasterd]
node_terminus = ldap
ldapserver = ldap.example.com
ldapbase = ou=hosts,dc=example,dc=com
*requires ruby-ldap