├── site ├── profile │ └── manifests │ │ ├── grafana.pp │ │ ├── lamp.pp │ │ ├── postfix.pp │ │ ├── splunk.pp │ │ ├── wordpress.pp │ │ ├── elasticsearch.pp │ │ ├── base.pp │ │ └── example.pp ├── role │ └── manifests │ │ ├── bloghost.pp │ │ ├── mailserver.pp │ │ ├── metrics.pp │ │ ├── example.pp │ │ └── classroom.pp ├── kerberos │ ├── examples │ │ └── init.pp │ ├── lib │ │ └── facter │ │ │ └── default_realm.rb │ └── manifests │ │ └── init.pp ├── review │ ├── examples │ │ └── init.pp │ ├── templates │ │ └── motd.epp │ ├── files │ │ ├── bashrc │ │ └── shells │ └── manifests │ │ └── init.pp ├── files │ ├── examples │ │ └── init.pp │ ├── manifests │ │ ├── motd.pp │ │ └── init.pp │ └── templates │ │ └── motd_header.epp ├── ordering │ ├── examples │ │ └── init.pp │ └── manifests │ │ ├── init.pp │ │ └── mysql.pp ├── system │ ├── examples │ │ ├── admins.pp │ │ ├── hosts.pp │ │ ├── aliases.pp │ │ └── managed_user.pp │ ├── manifests │ │ ├── hosts.pp │ │ ├── classroom.pp │ │ ├── aliases.pp │ │ ├── managed_user.pp │ │ └── admins.pp │ ├── lib │ │ └── puppet │ │ │ └── parser │ │ │ └── functions │ │ │ └── homedir.rb │ ├── files │ │ └── bashrc │ └── templates │ │ └── aliases.epp ├── webapp │ ├── examples │ │ └── wordpress.pp │ └── manifests │ │ ├── wordpress.pp │ │ ├── params.pp │ │ └── init.pp └── examples │ ├── manifests │ ├── managed_users.pp │ └── practitioner.pp │ └── files │ └── practitioner │ └── example.pp ├── environment.conf ├── hieradata └── common.yaml ├── Gemfile ├── .travis.yml ├── Puppetfile ├── README.md └── manifests └── site.pp /site/profile/manifests/grafana.pp: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /site/profile/manifests/lamp.pp: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /site/profile/manifests/postfix.pp: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /site/profile/manifests/splunk.pp: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /site/role/manifests/bloghost.pp: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /site/role/manifests/mailserver.pp: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /site/role/manifests/metrics.pp: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /site/profile/manifests/wordpress.pp: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /site/profile/manifests/elasticsearch.pp: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /site/kerberos/examples/init.pp: -------------------------------------------------------------------------------- 1 | include kerberos -------------------------------------------------------------------------------- /site/review/examples/init.pp: -------------------------------------------------------------------------------- 1 | include review 2 | -------------------------------------------------------------------------------- /site/files/examples/init.pp: -------------------------------------------------------------------------------- 1 | include files 2 | 3 | -------------------------------------------------------------------------------- /site/ordering/examples/init.pp: -------------------------------------------------------------------------------- 1 | include ordering 2 | 3 | -------------------------------------------------------------------------------- /site/system/examples/admins.pp: -------------------------------------------------------------------------------- 1 | include system::admins 2 | -------------------------------------------------------------------------------- /environment.conf: -------------------------------------------------------------------------------- 1 | modulepath = site:modules:$basemodulepath 2 | -------------------------------------------------------------------------------- /site/system/examples/hosts.pp: -------------------------------------------------------------------------------- 1 | include system::hosts 2 | 3 | -------------------------------------------------------------------------------- /site/webapp/examples/wordpress.pp: -------------------------------------------------------------------------------- 1 | include webapp::wordpress 2 | 3 | -------------------------------------------------------------------------------- /site/review/templates/motd.epp: -------------------------------------------------------------------------------- 1 | This machine is managed with Puppet. 2 | -------------------------------------------------------------------------------- /site/role/manifests/example.pp: -------------------------------------------------------------------------------- 1 | class role::example { 2 | include profile::example 3 | } 4 | -------------------------------------------------------------------------------- /site/role/manifests/classroom.pp: -------------------------------------------------------------------------------- 1 | class role::classroom { 2 | include profile::base 3 | } 4 | -------------------------------------------------------------------------------- /hieradata/common.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | message: This message came from the common hiera datasource. 3 | 4 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | gem "puppet", ENV['PUPPET_GEM_VERSION'] || '~> 3.8.0' 4 | -------------------------------------------------------------------------------- /site/profile/manifests/base.pp: -------------------------------------------------------------------------------- 1 | class profile::base { 2 | notify { "Hello, my name is ${::hostname}": } 3 | } 4 | -------------------------------------------------------------------------------- /site/profile/manifests/example.pp: -------------------------------------------------------------------------------- 1 | class profile::example { 2 | notify { 'This is the example profile!': } 3 | } 4 | 5 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | --- 2 | language: ruby 3 | sudo: false 4 | env: 5 | - PUPPET_GEM_VERSION="~> 4.2.0" 6 | rvm: 7 | - 2.0 8 | script: puppet parser validate . 9 | -------------------------------------------------------------------------------- /site/kerberos/lib/facter/default_realm.rb: -------------------------------------------------------------------------------- 1 | # Write a fact that returns the value of running the command 2 | # "/bin/awk '/default_realm/{print $NF}' /etc/krb5.conf" 3 | -------------------------------------------------------------------------------- /site/system/manifests/hosts.pp: -------------------------------------------------------------------------------- 1 | class system::hosts { 2 | # paste the output of `puppet resource host` in this class 3 | # and then purge unmanaged resources 4 | } 5 | -------------------------------------------------------------------------------- /site/kerberos/manifests/init.pp: -------------------------------------------------------------------------------- 1 | class kerberos { 2 | # use an augeas resource to manage the default_realm 3 | # determine the proper context with the augtool shell 4 | 5 | } 6 | -------------------------------------------------------------------------------- /site/system/examples/aliases.pp: -------------------------------------------------------------------------------- 1 | user { 'admin': 2 | ensure => present, 3 | } 4 | 5 | class { 'system::aliases': 6 | admin => 'admin', 7 | require => User['admin'], 8 | } 9 | 10 | -------------------------------------------------------------------------------- /site/files/manifests/motd.pp: -------------------------------------------------------------------------------- 1 | define files::motd ( 2 | $message = $name, 3 | $order = 10, 4 | ) { 5 | # what resource declaration do we need to add to the `motd` concat resource? 6 | 7 | } 8 | -------------------------------------------------------------------------------- /site/review/files/bashrc: -------------------------------------------------------------------------------- 1 | # User specific aliases and functions 2 | alias rm='rm -i' 3 | alias cp='cp -i' 4 | alias mv='mv -i' 5 | 6 | # Source global definitions 7 | [[ -f /etc/bashrc ]] && source /etc/bashrc 8 | -------------------------------------------------------------------------------- /site/system/lib/puppet/parser/functions/homedir.rb: -------------------------------------------------------------------------------- 1 | # Write a simple function called homedir that accepts a single string argument. 2 | # It should return the conventional Linux home directory based on a username 3 | -------------------------------------------------------------------------------- /site/files/templates/motd_header.epp: -------------------------------------------------------------------------------- 1 | Welcome to <%= $fqdn %> 2 | 3 | This system is managed by Puppet. Any manual modifications will likely be 4 | overwritten. Make configuration changes in the upstream repository. 5 | 6 | -------------------------------------------------------------------------------- /site/examples/manifests/managed_users.pp: -------------------------------------------------------------------------------- 1 | # example declarations for the defined type exercise 2 | class examples::managed_users($password) { 3 | system::managed_user { ['aaron', 'kaitlin', 'jose']: 4 | password => $password, 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /site/system/files/bashrc: -------------------------------------------------------------------------------- 1 | # User specific aliases and functions 2 | alias rm='rm -i' 3 | alias cp='cp -i' 4 | alias mv='mv -i' 5 | 6 | # Source global definitions 7 | [[ -f /etc/bashrc ]] && source /etc/bashrc 8 | 9 | cowsay "Hello there!" 10 | -------------------------------------------------------------------------------- /Puppetfile: -------------------------------------------------------------------------------- 1 | # Installs the puppetlabs/mysql module from the Puppet Forge 2 | mod 'puppetlabs/mysql', '3.10.0' 3 | 4 | # Installs the puppetlabs/vcsrepo module from its GitHub repository 5 | mod 'vcsrepo', 6 | :git => 'https://github.com/puppetlabs/puppetlabs-vcsrepo' 7 | -------------------------------------------------------------------------------- /site/ordering/manifests/init.pp: -------------------------------------------------------------------------------- 1 | class ordering { 2 | # include the ordering::mysql class 3 | # Does it need to be contained? 4 | 5 | notify { 'This should come after the entire MySQL class is enforced': 6 | require => Class['ordering::mysql'], 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /site/system/manifests/classroom.pp: -------------------------------------------------------------------------------- 1 | class system::classroom { 2 | # export a virtual host resource for yourself 3 | 4 | 5 | # collect all resources from the database (including your own) 6 | # enforce only those tagged with `classroom`. 7 | 8 | 9 | } 10 | -------------------------------------------------------------------------------- /site/webapp/manifests/wordpress.pp: -------------------------------------------------------------------------------- 1 | class webapp::wordpress inherits webapp { 2 | include ::wordpress 3 | 4 | # override load balancer to 'wordpress' listening service 5 | Haproxy::Balancermember[$facts['fqdn']] { 6 | listening_service => 'wordpress', 7 | } 8 | 9 | } 10 | -------------------------------------------------------------------------------- /site/examples/files/practitioner/example.pp: -------------------------------------------------------------------------------- 1 | file { '/etc/motd': 2 | ensure => file, 3 | owner => 'root', 4 | group => 'root', 5 | mode => '0644', 6 | content => "Hey, Puppet is fun!\n", 7 | } 8 | 9 | package { 'cowsay': 10 | ensure => present, 11 | provider => gem, 12 | } 13 | -------------------------------------------------------------------------------- /site/review/files/shells: -------------------------------------------------------------------------------- 1 | ################################################ 2 | ## This file is managed by Puppet. ## 3 | ## Any changes will be gleefully overwritten. ## 4 | ################################################ 5 | 6 | /bin/sh 7 | /bin/bash 8 | /sbin/nologin 9 | /bin/tcsh 10 | /bin/csh 11 | -------------------------------------------------------------------------------- /site/system/examples/managed_user.pp: -------------------------------------------------------------------------------- 1 | # Linux requires a hash for the password. This one is 'Puppet8Labs!' 2 | # Generate your own with the command `openssl passwd -1` if you'd like. 3 | $password = '$1$HdDw//gC$2VBiQ1x5blLPwNS.G.Iw21' 4 | 5 | system::managed_user { ['aaron', 'kaitlin', 'alison']: 6 | password => $password, 7 | } 8 | -------------------------------------------------------------------------------- /site/ordering/manifests/mysql.pp: -------------------------------------------------------------------------------- 1 | class ordering::mysql { 2 | # How do we make sure these classes don't float off the relationship graph? 3 | class { '::mysql::server': 4 | root_password => 'strongpassword', 5 | } 6 | 7 | class { '::mysql::bindings': 8 | php_enable => true, 9 | perl_enable => true, 10 | } 11 | 12 | 13 | } 14 | -------------------------------------------------------------------------------- /site/webapp/manifests/params.pp: -------------------------------------------------------------------------------- 1 | class webapp::params { 2 | case $facts['os']['family'] { 3 | 'RedHat': { 4 | $docroot = '/var/www/html' 5 | } 6 | 'Debian': { 7 | $docroot = '/var/www' 8 | } 9 | default: { 10 | fail("Module ${module_name} is not supported on ${facts['os']['family']}") 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /site/examples/manifests/practitioner.pp: -------------------------------------------------------------------------------- 1 | class examples::practitioner { 2 | File { 3 | owner => 'root', 4 | group => 'root', 5 | mode => '0644', 6 | } 7 | 8 | file { '/root/example.pp': 9 | ensure => file, 10 | source => 'puppet:///modules/examples/practitioner/example.pp', 11 | } 12 | 13 | package { 'cowsay': 14 | ensure => present, 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /site/system/manifests/aliases.pp: -------------------------------------------------------------------------------- 1 | class system::aliases ( 2 | $admin = 'root', 3 | ) { 4 | # uses $admin to build the aliases file 5 | file { '/etc/aliases': 6 | ensure => file, 7 | owner => 'root', 8 | group => 'root', 9 | mode => '0644', 10 | content => epp('system/aliases.epp', { admin => $admin }), 11 | } 12 | exec { '/usr/bin/newaliases': 13 | refreshonly => true, 14 | subscribe => File['/etc/aliases'], 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /site/webapp/manifests/init.pp: -------------------------------------------------------------------------------- 1 | class webapp { 2 | include mysql::server 3 | class { 'mysql::bindings': 4 | php_enable => true, 5 | } 6 | 7 | include apache 8 | include apache::mod::php 9 | apache::vhost { $facts['fqdn']: 10 | priority => '10', 11 | vhost_name => $facts['fqdn'], 12 | port => '80', 13 | docroot => '/var/www/html', 14 | } 15 | 16 | @@haproxy::balancermember { $facts['fqdn']: 17 | listening_service => 'webapp', 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /site/system/manifests/managed_user.pp: -------------------------------------------------------------------------------- 1 | define system::managed_user ( 2 | $home = undef, 3 | ) { 4 | if $home { 5 | $homedir = $home 6 | } 7 | else { 8 | $homedir = "/home/${name}" 9 | } 10 | 11 | File { 12 | owner => $name, 13 | group => 'wheel', 14 | mode => '0644', 15 | } 16 | 17 | # manage a user called $name and that user's `.bashrc` if they're on Linux 18 | # This can likely reuse some of the code you wrote for the `review` class. 19 | # Make sure you update variables or paths as required. 20 | } 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # `classroom-control-vp` 2 | 3 | This is the classroom control repository for the Virtual Practitioner class. 4 | 5 | ## Usage 6 | 7 | Small site modules should be developed in the `site` directory. This is appended 8 | to the `$modulepath` by the `environment.conf` file so that Puppet can use modules 9 | from this directory. 10 | 11 | Adding modules to the `Puppetfile` will manage them in the standard `modules` 12 | directory using r10k or PE Code Manager. 13 | 14 | ## Starter code 15 | 16 | Note that this repository includes some incomplete starter code. 17 | -------------------------------------------------------------------------------- /site/system/manifests/admins.pp: -------------------------------------------------------------------------------- 1 | class system::admins { 2 | require mysql::server 3 | mysql_user { 'zack@localhost': 4 | ensure => present, 5 | max_queries_per_hour => 1200, 6 | } 7 | mysql_user { 'monica@localhost': 8 | ensure => present, 9 | max_queries_per_hour => 600, 10 | } 11 | mysql_user { 'ralph@localhost': 12 | ensure => absent, 13 | } 14 | mysql_user { 'brad@localhost': 15 | ensure => present, 16 | max_queries_per_hour => 600, 17 | } 18 | mysql_user { 'luke@localhost': 19 | ensure => present, 20 | max_queries_per_hour => 600, 21 | } 22 | 23 | user { ['zack', 'monica', 'ralph', 'brad', 'luke']: 24 | ensure => present, 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /site/files/manifests/init.pp: -------------------------------------------------------------------------------- 1 | class files { 2 | File { 3 | owner => 'root', 4 | group => 'root', 5 | mode => '0644', 6 | } 7 | file { '/etc/cron.allow': 8 | ensure => file, 9 | } 10 | file_line { 'allow root cron jobs': 11 | ensure => present, 12 | path => '/etc/cron.allow', 13 | line => 'root', 14 | } 15 | # Add a rule to cron.deny to deny jobs by default 16 | 17 | 18 | # What concat resource is needed for this fragment to work? 19 | concat::fragment { 'motd header': 20 | target => '/etc/motd', 21 | order => '01', 22 | content => epp('files/motd_header.epp'), 23 | } 24 | 25 | # Add a few fragments to be appended to /etc/motd 26 | 27 | 28 | } 29 | -------------------------------------------------------------------------------- /site/review/manifests/init.pp: -------------------------------------------------------------------------------- 1 | class review { 2 | # this class should accept a parameter rather than having 3 | # the username hardcoded. 4 | 5 | # Uncomment and use this variable where appropriate 6 | # $homedir = $user ? { 7 | # 'root' => '/root', 8 | # default => "/home/$user", 9 | # } 10 | 11 | user { 'bob': 12 | ensure => present, 13 | shell => '/bin/bash', 14 | managehome => true, 15 | } 16 | 17 | file { '/home/bob/.bashrc': 18 | ensure => file, 19 | owner => 'bob', 20 | group => 'bob', 21 | mode => '0644', 22 | source => 'puppet:///modules/review/bashrc' 23 | } 24 | 25 | # add the proper resource to ensure that the Puppet agent is not running 26 | # in the background. How would you discover the service name? 27 | 28 | } 29 | -------------------------------------------------------------------------------- /manifests/site.pp: -------------------------------------------------------------------------------- 1 | ## site.pp ## 2 | 3 | # This file (/etc/puppetlabs/puppet/manifests/site.pp) is the main entry point 4 | # used when an agent connects to a master and asks for an updated configuration. 5 | # 6 | # Global objects like filebuckets and resource defaults should go in this file, 7 | # as should the default node definition. (The default node can be omitted 8 | # if you use the console and don't define any other nodes in site.pp. See 9 | # http://docs.puppetlabs.com/guides/language_guide.html#nodes for more on 10 | # node definitions.) 11 | 12 | ## Active Configurations ## 13 | 14 | # PRIMARY FILEBUCKET 15 | # This configures puppet agent and puppet inspect to back up file contents when 16 | # they run. The Puppet Enterprise console needs this to display file contents 17 | # and differences. 18 | 19 | # Disable filebucket by default for all File resources: 20 | File { backup => false } 21 | 22 | # Randomize enforcement order to help understand relationships 23 | ini_setting { 'random ordering': 24 | ensure => present, 25 | path => "${settings::confdir}/puppet.conf", 26 | section => 'agent', 27 | setting => 'ordering', 28 | value => 'title-hash', 29 | } 30 | 31 | # DEFAULT NODE 32 | # Node definitions in this file are merged with node data from the console. See 33 | # http://docs.puppetlabs.com/guides/language_guide.html#nodes for more on 34 | # node definitions. 35 | 36 | # The default node definition matches any node lacking a more specific node 37 | # definition. If there are no other nodes in this file, classes declared here 38 | # will be included in every node's catalog, *in addition* to any classes 39 | # specified in the console for that node. 40 | 41 | node default { 42 | # This is where you can declare classes for all nodes. 43 | # Example: 44 | # class { 'my_class': } 45 | include role::classroom 46 | } 47 | -------------------------------------------------------------------------------- /site/system/templates/aliases.epp: -------------------------------------------------------------------------------- 1 | # 2 | # Aliases in this file will NOT be expanded in the header from 3 | # Mail, but WILL be visible over networks or from /bin/mail. 4 | # 5 | # >>>>>>>>>> The program "newaliases" must be run after 6 | # >> NOTE >> this file is updated for any changes to 7 | # >>>>>>>>>> show through to sendmail. 8 | # 9 | 10 | # Basic system aliases -- these MUST be present. 11 | mailer-daemon: postmaster 12 | postmaster: root 13 | 14 | # General redirections for pseudo accounts. 15 | bin: root 16 | daemon: root 17 | adm: root 18 | lp: root 19 | sync: root 20 | shutdown: root 21 | halt: root 22 | mail: root 23 | news: root 24 | uucp: root 25 | operator: root 26 | games: root 27 | gopher: root 28 | ftp: root 29 | nobody: root 30 | radiusd: root 31 | nut: root 32 | dbus: root 33 | vcsa: root 34 | canna: root 35 | wnn: root 36 | rpm: root 37 | nscd: root 38 | pcap: root 39 | apache: root 40 | webalizer: root 41 | dovecot: root 42 | fax: root 43 | quagga: root 44 | radvd: root 45 | pvm: root 46 | amanda: root 47 | privoxy: root 48 | ident: root 49 | named: root 50 | xfs: root 51 | gdm: root 52 | mailnull: root 53 | postgres: root 54 | sshd: root 55 | smmsp: root 56 | postfix: root 57 | netdump: root 58 | ldap: root 59 | squid: root 60 | ntp: root 61 | mysql: root 62 | desktop: root 63 | rpcuser: root 64 | rpc: root 65 | nfsnobody: root 66 | 67 | ingres: root 68 | system: root 69 | toor: root 70 | manager: root 71 | dumper: root 72 | abuse: root 73 | 74 | newsadm: news 75 | newsadmin: news 76 | usenet: news 77 | ftpadm: ftp 78 | ftpadmin: ftp 79 | ftp-adm: ftp 80 | ftp-admin: ftp 81 | www: webmaster 82 | webmaster: root 83 | noc: root 84 | security: root 85 | hostmaster: root 86 | info: postmaster 87 | marketing: postmaster 88 | sales: postmaster 89 | support: postmaster 90 | 91 | 92 | # trap decode to catch security attacks 93 | decode: root 94 | 95 | # Person who should get root's mail 96 | #root: marc 97 | --------------------------------------------------------------------------------