On Github karmab / puppetworkshop
By Karim Boumedhel
EMEA Senior Consultant, Red Hat / karim@redhat.comAll master-agent communication use SSL
$ puppet apply manifests.pp
class hardware {
case $manufacturer {
'VMware, Inc.': {include hardware::vmware}
'HP': {include hardware::hp}
'IBM': {include hardware::ibm}
}
}
$ yum install puppet-serverA Puppet Master service is created and available, so you can start it
$ service puppetmaster startBut don't do it yet! There is some stuff to configure first.
[main]
modulepath = /etc/puppet/modules
[master]
certname = puppetmaster.example.com
dns_alt_names = puppetmaster,puppetmaster.example.com
Now, we can start the Puppet master and have it create the CA Certificates
Modify additional parameters carefully, ensure DNS (FQDN) is configured accordingly !
[main]
logdir = /var/log/puppet
rundir = /var/run/puppet
ssldir = $vardir/ssl
modulepath = /etc/puppet/modules
report = true
[agent]
server = puppetmaster.example.com
report = true
classfile = $vardir/classes.txt
localconfig = $vardir/localconfig
[master]
certname = puppetmaster.example.com
$ puppet agent -t
On the Puppet master, check that the certificate is requested and sign it:
$ puppet cert list
$ puppet cert sign # On Client Validate it works!
$ puppet agent --test
Connection is established. Now, we can enable the puppet service, or run it anytime we want
cat /etc/puppet/autosign.conf
*.example.com
## site.pp ##
# Define filebucket 'main':
filebucket { 'main':
server => '.example.com',
path => false,
}
# Make filebucket 'main' the default backup location
# for all File resources:
File { backup => 'main' }
node default {
notify { 'example':
message => 'Hello World!'
}
}
node prod {
notify { 'prod':
message => 'This is a production machine'
}
}
node web inherits prod {
notify { 'web':
message => 'This is a production web server'
}
}
node 'webserver1.example.com' inherits web {}
[master]
node_terminus = exec
external_nodes = /usr/local/bin/puppet_node_classifier
user { 'karim':
ensure => present,
uid => '8000',
gid => 'admin',
shell => '/bin/bash',
home => '/rhome/karim',
managehome => true,
}
file package user group service augeas
notify host exec mount cron ssh_authorized_key
Plus some others. The full list will always be available at
augeas { "sshd_config":
require => File['/etc/ssh/sshd_config'],
context => "/files/etc/ssh/sshd_config",
changes => [
"set Port 22",
"set LogLevel VERBOSE",
"set PermitRootLogin yes",
"set PermitEmptyPasswords no"
]
}
# augtool
augtool> ls /files/etc/hosts/1
ipaddr = 127.0.0.1
canonical = localhost.localdomain
alias = localhost
augtool> set /files/etc/hosts/1/ipaddr 172.0.0.2
augtool> ls /files/etc/hosts/1
ipaddr = 172.0.0.2
canonical = localhost.localdomain
alias = localhost
package { 'httpd':
ensure => installed,
}
Execute interactively on the client, or place it on the puppet master
package { 'httpd':
ensure => installed,
}
service { 'httpd':
ensure => running,
enable => true,
require => Package ['httpd'],
}
The httpd service will only be started once the httpd package is installed
exec { '/bin/touch /tmp/test':
onlyif => '/usr/bin/test ! -f /tmp/test',
}
/tmp/test is only created if it does not exist as a file
exec { 'sysctl -p':
alias => 'sysctl',
path => '/sbin',
refreshonly => true,
subscribe => Augeas['sysctl'];
}
augeas { 'sysctl':
context => '/files/etc/sysctl.conf',
changes => [
# Enforcing ExecShield
"set kernel.exec-shield 1",
"set kernel.randomize_va_space 1"
]
}
exec { 'sysctl -p':
alias => 'sysctl',
path => '/sbin',
refreshonly => true,
}
augeas { 'sysctl':
context => '/files/etc/sysctl.conf',
changes => [
# Enforcing ExecShield
"set kernel.exec-shield 1",
"set kernel.randomize_va_space 1"
],
notify => Exec['sysctl -p']
}
$serverXaddr = '172.0.0.45'
augeas { 'test1':
context => '/files/etc/postfix/main.cf',
changes => [
"set relayhost ${serverXaddr}"
]
}
if $::is_virtual == 'true' {
$message = 'This is a virtual system'
} else {
$message = 'This is a physical system'
}
file { '/root/isvirt.txt':
content => “Hey man, ${message}”
}
case $::operatingsystem {
centos: { $apache = 'httpd'}
# Note that these matches are case-insensitive.
redhat: { $apache = 'httpd' }
debian: { $apache = 'apache2' }
ubuntu: { $apache = 'apache2' }
}
package { 'apache':
ensure => installed,
name => $apache,
}
node puppetossclient2.example.com
{
include production
include vsftpd
}
class { 'vsftpd':
package { 'vsftpd':
ensure => installed,
}
augeas {'vsftpd.conf':
require => Package ['vsftpd'],
context => '/files/etc/vsftpd/vsftpd.conf',
changes => [
"set anonymous_enable NO",
]
}
service { 'vsftpd':
ensure => running,
enable => true,
require => Augeas ['vsftpd.conf'];
}
}
-> {module}/
-> files/
-> lib/
-> manifests/
-> init.pp
-> {class}.pp
-> namespace/
-> {class}.pp
-> modules/
-> hardware/
-> manifests/
-> init.pp
-> vmware.pp
-> hp.pp
-> ibm.pp
class hardware {
case $manufacturer {
'VMware, Inc.': { include hardware::vmware }
'ibm': { include hardware::ibm }
'HP': { include hardware::hp }
}
}
file/filename.txtFrom within a module
module/files/filename.txt
file { '/etc/issue':
ensure => present,
source => 'puppet:///files/issue',
}
If the file is part of a module
file { '/etc/issue':
ensure => present,
source => 'puppet:///modules/testmodule/issue',
}
<%= fqdn %> is the name of this server.
Define file resource using template
file { '/root/testfile.txt':
ensure => present,
content => template('testmodule/testfile.txt.erb'),
}
<% Ruby code -- inline with output %>
<%= Ruby expression -- replace with result %>
<%# comment -- ignored -- useful in testing %>
% a line of Ruby code -- treated as <% line %> (optional)
%% replaced with % if first thing on a line and % processing is used
<%% or %%> -- replace with <% or %> respectively
<%- and -%> suppress leading and trailing whitespace,
including the trailing newline, and can be used interchangeably with <% and %>.
Facter.add(:iptables_version) do
confine :kernel => :linux
setcode do
version = Facter::Util::Resolution.exec('iptables --version')
if version
version.match(/\d+\.\d+\.\d+/).to_s
else
nil
end
end
end
archive_files = true
archive_file_server = puppetmaster.example.com
To ensure files are uploaded to the puppet master, add a cron job running puppet inspect every day
Files are archived under /var/lib/puppet/bucket in the puppet master
Before that, files also archived under /var/lib/puppet/clientbucket in the client
file { '/etc/hosts':
audit => content,
}
Can audit any resource parameter: