diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..8100246 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,29 @@ +repos: + - repo: 'https://github.com/chriskuehl/puppet-pre-commit-hooks.git' + rev: v2.2.0 + hooks: + - id: bolt-validate + - id: epp-validate + - id: erb-validate + - id: puppet-lint + args: + - --no-80chars-check + - --no-documentation-check + - --no-puppet_url_without_modules-check + - --fail-on-warnings + - id: puppet-validate + - id: ruby-validate + - repo: 'https://github.com/jumanjihouse/pre-commit-hooks' + rev: 3.0.0 + hooks: + - id: reek + - id: rubocop + - repo: 'https://github.com/adrienverge/yamllint' + rev: v1.32.0 + hooks: + - id: 'yamllint' + args: + [ + "-d {extends: relaxed, rules: {line-length: disable}, ignore: chart}", + "-s", + ] diff --git a/Puppetfile b/Puppetfile index 8ea25d1..3c81565 100644 --- a/Puppetfile +++ b/Puppetfile @@ -2,5 +2,12 @@ forge 'forge.puppetlabs.com' moduledir 'external_modules' # Forge Modules -mod 'puppetlabs/ntp', '4.1.0' -mod 'puppetlabs/stdlib' +mod 'puppetlabs-stdlib', '9.1.0' +mod 'puppetlabs-inifile', '6.0.0' +mod 'puppetlabs-concat', '9.0.0' +mod 'eyp-eyplib', '0.1.24' +mod 'eyp-systemd', '3.1.0' +mod 'ghoneycutt-puppet', '3.3.0' +mod 'puppet-archive', '7.0.0' +mod 'puppet-chrony', '2.6.0' +mod 'puppetlabs-vcsrepo', '6.1.0' diff --git a/environment.conf b/environment.conf index 27d3019..4569646 100644 --- a/environment.conf +++ b/environment.conf @@ -1,2 +1,2 @@ -manifest = site.pp -modulepath = modules:site +manifest = manifests/site.pp +modulepath = external_modules:site diff --git a/hiera.yaml b/hiera.yaml new file mode 100644 index 0000000..600c7fd --- /dev/null +++ b/hiera.yaml @@ -0,0 +1,10 @@ +--- +version: 5 +defaults: + datadir: "hieradata" + data_hash: "yaml_data" +hierarchy: + - name: Node-specific data + path: "nodes/%{trusted.certname}.yaml" + - name: Common data shared across nodes + path: "common.yaml" diff --git a/hieradata/common.yaml b/hieradata/common.yaml index 569696d..0553b6c 100644 --- a/hieradata/common.yaml +++ b/hieradata/common.yaml @@ -1,7 +1,9 @@ --- -classes: - - 'profile::base' - -ntp::servers: +profile::base::ntp_servers: - 0.au.pool.ntp.org - 1.au.pool.ntp.org + +profile::puppet::autosign::subnet_ranges: + - '198.18.17.0/24' + +profile::puppet::enc::enc_repo: https://git.unkin.net/unkinben/puppet-enc.git diff --git a/manifests/site.pp b/manifests/site.pp new file mode 100644 index 0000000..f2695d5 --- /dev/null +++ b/manifests/site.pp @@ -0,0 +1 @@ +#hiera_include('classes') diff --git a/site.pp b/site.pp deleted file mode 100644 index 7959e7b..0000000 --- a/site.pp +++ /dev/null @@ -1 +0,0 @@ -hiera_include('classes') diff --git a/site/profile/manifests/base.pp b/site/profile/manifests/base.pp index cc96345..1e9744e 100644 --- a/site/profile/manifests/base.pp +++ b/site/profile/manifests/base.pp @@ -1,3 +1,8 @@ -class profile::base { - class { '::ntp': } +# this is the base class, which will be used by all servers +class profile::base ( + Array $ntp_servers, +) { + class { 'chrony': + servers => $ntp_servers, + } } diff --git a/site/profile/manifests/puppet/autosign.pp b/site/profile/manifests/puppet/autosign.pp new file mode 100644 index 0000000..56c072a --- /dev/null +++ b/site/profile/manifests/puppet/autosign.pp @@ -0,0 +1,54 @@ +# Class: profile::puppet::autosign +# +# This class manages an autosign script for the Puppet master. +# It sets up a Ruby script that automatically signs Puppet node requests +# originating from certain IP subnet ranges. +# +# Parameters: +# - `subnet_ranges`: An array of IP subnet ranges for which to automatically +# sign certificate requests. +# +# Actions: +# - Ensures the autosign script file is present and has the correct content and permissions. +# +# Usage: +# The class can be declared in a node definition or classified using an ENC or Hiera. +# Example: +# node 'puppet.example.com' { +# class { 'profile::puppet::autosign': +# subnet_ranges => ['198.18.17.0/24', '10.0.0.0/8'], +# } +# } +# +# Requirements: +# - Puppet master must have access to the /opt/puppetlabs/bin directory. +# - The gem 'ipaddr' module must be installed on the Puppet master. +# - The puppet 'puppetlabs/stdlib' module must be installed on the Puppet master. +# +# Limitations: +# This is designed to work on Unix-like systems. +class profile::puppet::autosign ( + Array[Stdlib::IP::Address::V4::CIDR] $subnet_ranges, +) { + + $script_content = @(END) + #!/usr/bin/env ruby + + require 'yaml' + require 'ipaddr' + + csr = YAML.load(STDIN.read) + networks = #{subnet_ranges} + + ip = IPAddr.new(csr['facts']['networking']['ip']) + + exit 1 unless networks.any? { |network| IPAddr.new(network).include?(ip) } + exit 0 + END + + file { '/opt/puppetlabs/bin/autosign.rb': + ensure => file, + content => $script_content, + mode => '0755', + } +} diff --git a/site/profile/manifests/puppet/enc.pp b/site/profile/manifests/puppet/enc.pp new file mode 100644 index 0000000..62db939 --- /dev/null +++ b/site/profile/manifests/puppet/enc.pp @@ -0,0 +1,83 @@ +# Class: profile::puppet::enc +# +# This class manages a Git repository at /opt/puppetlabs/enc. It includes a +# systemd service and timer to keep the repository updated every minute. +# The Git package is installed if not present, and the repository at the given +# location will always reflect the state of the remote Git repository. +# +# Parameters: +# - enc_repo: The URL of the Git repository to clone. +# +# Actions: +# - Ensures the Git package is installed. +# - Ensures the /opt/puppetlabs/enc directory is a clone of the given Git repository. +# - Creates a helper script '/opt/puppetlabs/bin/git_update' for updating the Git repository. +# - Creates a systemd service and timer that runs the git update script every minute. +# +# Usage: +# Directly include the class in your node definitions or classify your nodes +# using an ENC or Hiera. +# Example: +# node 'puppet.example.com' { +# class { 'profile::puppet::enc': +# enc_repo => 'https://github.com/user/repo.git', +# } +# } +# +# Requirements: +# - The 'puppet-vcsrepo' module should be installed on your puppetmaster. +# - The 'puppet-systemd' module should be installed on your puppetmaster. +# - '/opt/puppetlabs/bin/' directory must exist and be writable. +# - Puppet master must have access to the specified Git URL. +# +# Limitations: +# This is designed to work on Unix-like systems only. +# +class profile::puppet::enc ( + String $enc_repo, +) { + + package { 'git': + ensure => installed, + } + + vcsrepo { '/opt/puppetlabs/enc': + ensure => latest, + provider => git, + source => $enc_repo, + require => Package['git'], + } + + file { '/opt/puppetlabs/bin/enc': + ensure => link, + target => '/opt/puppetlabs/enc/enc.py', + require => Vcsrepo['/opt/puppetlabs/enc'], + } + + file { '/opt/puppetlabs/bin/puppet-enc': + ensure => file, + owner => 'root', + group => 'root', + mode => '0755', + content => "#!/bin/bash\n( + cd /opt/puppetlabs/enc/ + git reset --hard master + git clean -fd + git pull\n)", + require => Package['git'], + } + + systemd::service { 'puppet-enc': + description => 'puppet-enc update service', + execstart => '/opt/puppetlabs/bin/puppet-enc', + user => 'root', + require => File['/opt/puppetlabs/bin/puppet-enc'], + } + + systemd::timer { 'puppet-enc': + description => 'Run puppet-enc every minute', + unit => 'puppet-enc.service', + on_calendar => '*:0/1', + require => Systemd::Service['puppet-enc'], + } +} diff --git a/site/profile/manifests/puppet/g10k.pp b/site/profile/manifests/puppet/g10k.pp new file mode 100644 index 0000000..cc420c2 --- /dev/null +++ b/site/profile/manifests/puppet/g10k.pp @@ -0,0 +1,70 @@ +# Class: profile::puppet::g10k +# +# This class handles downloading and installation of the g10k tool, a fast +# Git and Forge based Puppet environment and module deployment tool. +# The latest release of g10k is downloaded from GitHub and placed into '/opt/puppetlabs/bin'. +# Additionally, it creates a helper script to easily run g10k with the appropriate configuration. +# It also creates a systemd service and timer that runs the g10k script every minute. +# +# Parameters: None +# +# Actions: +# - Downloads the latest g10k release from GitHub. +# - Extracts the download and places the executable in '/opt/puppetlabs/bin'. +# - Creates a helper script '/opt/puppetlabs/bin/puppet-g10k' for easy usage of g10k. +# - Creates a systemd service and timer that runs the g10k script every minute. +# +# Usage: +# Directly including the class in your node definitions or classify your nodes +# using an ENC or Hiera. +# Example: +# node 'puppet.example.com' { +# include profile::puppet::g10k +# } +# +# Requirements: +# - The 'puppet-archive' module should be installed in your puppetmaster. +# - The 'puppet-systemd' module should be installed on your puppetmaster. +# - '/opt/puppetlabs/bin/' directory must exist and be writable. +# - Puppet master must have access to the GitHub URL. +# +# Limitations: +# This is designed to work on Unix-like systems only. +class profile::puppet::g10k { + + package { 'unzip': + ensure => installed, + } + + archive { '/tmp/g10k.zip': + ensure => present, + source => 'https://github.com/xorpaul/g10k/releases/latest/download/g10k-linux-amd64.zip', + extract => true, + extract_path => '/opt/puppetlabs/bin', + creates => '/opt/puppetlabs/bin/g10k', + cleanup => true, + } + + file { '/opt/puppetlabs/bin/puppet-g10k': + ensure => file, + owner => 'root', + group => 'root', + mode => '0755', + content => "#!/usr/bin/bash\n/opt/puppetlabs/bin/g10k -config /etc/puppetlabs/r10k/r10k.yaml\n", + require => Archive['/tmp/g10k.zip'], + } + + systemd::service { 'puppet-g10k': + description => 'puppet-g10k update service', + execstart => '/opt/puppetlabs/bin/puppet-g10k', + user => 'root', + require => File['/opt/puppetlabs/bin/puppet-g10k'], + } + + systemd::timer { 'puppet-g10k': + description => 'Run puppet-g10k every minute', + unit => 'puppet-g10k.service', + on_calendar => '*:0/1', + require => Systemd::Service['puppet-g10k'], + } +} diff --git a/site/profile/manifests/puppet/puppetmaster.pp b/site/profile/manifests/puppet/puppetmaster.pp new file mode 100644 index 0000000..4424712 --- /dev/null +++ b/site/profile/manifests/puppet/puppetmaster.pp @@ -0,0 +1,42 @@ +# Class: profile::puppet::puppetmaster +# +# This class manages the puppetmaster using the ghoneycutt-puppet module. +# It manages the server settings in the puppet.conf file. +# +# Parameters: None +# +# Actions: +# - Sets up the server, main, agent, and master sections in the puppet.conf file +# +# Usage: +# Directly include the class in your node definitions or classify your nodes +# using an ENC or Hiera. +# Example: +# node 'puppet.example.com' { +# include profile::puppet::puppetmaster +# } +# +# Requirements: +# - The 'ghoneycutt/puppet' module should be installed in your Puppet master. +# - Puppet master must have access to the necessary directories. +# +# Limitations: +# This is designed to work on Unix-like systems. +class profile::puppet::puppetmaster { + include profile::puppet::g10k + include profile::puppet::enc + include profile::puppet::autosign + + class { 'profile::puppet::server': + vardir => '/opt/puppetlabs/server/data/puppetserver', + logdir => '/var/log/puppetlabs/puppetserver', + rundir => '/var/run/puppetlabs/puppetserver', + pidfile => '/var/run/puppetlabs/puppetserver/puppetserver.pid', + codedir => '/etc/puppetlabs/code', + dns_alt_names => ['prodinf01n01.main.unkin.net'], + server => 'prodinf01n01.main.unkin.net', + node_terminus => 'exec', + external_nodes => '/opt/puppetlabs/bin/enc', + autosign => '/etc/puppetlabs/puppet/autosign.rb', + } +} diff --git a/site/profile/manifests/puppet/server.pp b/site/profile/manifests/puppet/server.pp new file mode 100644 index 0000000..235bf88 --- /dev/null +++ b/site/profile/manifests/puppet/server.pp @@ -0,0 +1,57 @@ +# Class: profile::puppet::server +# +# This class manages Puppet server's configuration and service. +# +# Parameters: +# vardir - Directory path for variable data. +# logdir - Directory path for logs. +# rundir - Directory path for run-time data. +# pidfile - File path for the PID file. +# codedir - Directory path for code data. +# dns_alt_names - Array of alternate DNS names for the server. +# server - Server's name. +# node_terminus - Node terminus. +# external_nodes - Path to the external node classifier script. +# autosign - Path to the autosign script. +# +class profile::puppet::server ( + String $vardir, + String $logdir, + String $rundir, + String $pidfile, + String $codedir, + Array[String[1]] $dns_alt_names, + String $server, + String $node_terminus, + String $external_nodes, + String $autosign, +) { + + file { '/etc/puppetlabs/puppet/puppet.conf': + ensure => file, + owner => 'root', + group => 'root', + mode => '0644', + content => epp('profile/puppet/server/puppet.conf.epp', { + 'vardir' => $vardir, + 'logdir' => $logdir, + 'rundir' => $rundir, + 'pidfile' => $pidfile, + 'codedir' => $codedir, + 'dns_alt_names' => join($dns_alt_names, ','), + 'server' => $server, + 'node_terminus' => $node_terminus, + 'external_nodes' => $external_nodes, + 'autosign' => $autosign, + }), + notify => Service['puppetserver'], + } + + service { 'puppetserver': + ensure => running, + enable => true, + hasstatus => true, + hasrestart => true, + } +} + diff --git a/site/profile/templates/puppet/server/puppet.conf.epp b/site/profile/templates/puppet/server/puppet.conf.epp new file mode 100644 index 0000000..37f3a5e --- /dev/null +++ b/site/profile/templates/puppet/server/puppet.conf.epp @@ -0,0 +1,17 @@ +[server] +vardir = <%= $vardir %> +logdir = <%= $logdir %> +rundir = <%= $rundir %> +pidfile = <%= $pidfile %> +codedir = <%= $codedir %> + +[main] +dns_alt_names = <%= $dns_alt_names %> + +[agent] +server = <%= $server %> + +[master] +node_terminus = exec +external_nodes = <%= $external_nodes %> +autosign = <%= $autosign %> diff --git a/site/role/manifests/puppet/puppetmaster.pp b/site/role/manifests/puppet/puppetmaster.pp index 1d24efe..f04f3fe 100644 --- a/site/role/manifests/puppet/puppetmaster.pp +++ b/site/role/manifests/puppet/puppetmaster.pp @@ -1,3 +1,6 @@ +# a role to deploy the puppetmaster +# work in progress class role::puppet::puppetmaster { include profile::base + include profile::puppet::puppetmaster }