├── .fixtures.yml ├── .github └── workflows │ └── ci.yml ├── .gitignore ├── .pmtignore ├── .puppet-lint.rc ├── .rspec ├── .sync.yml ├── CHANGELOG.md ├── CONTRIBUTING.md ├── Gemfile ├── HISTORY.md ├── LICENSE ├── README.md ├── Rakefile ├── manifests ├── agent.pp ├── agent │ ├── config.pp │ ├── install.pp │ ├── service.pp │ └── service │ │ ├── cron.pp │ │ ├── daemon.pp │ │ └── systemd.pp ├── config.pp ├── config │ ├── agent.pp │ ├── entry.pp │ ├── main.pp │ └── server.pp ├── init.pp ├── params.pp ├── server.pp └── server │ ├── config.pp │ ├── enc.pp │ ├── foreman.pp │ ├── install.pp │ ├── puppetdb.pp │ ├── puppetserver.pp │ └── service.pp ├── metadata.json ├── spec ├── acceptance │ ├── hieradata │ │ └── common.yaml │ ├── puppet_spec.rb │ ├── puppetserver_latest_spec.rb │ └── puppetserver_upgrade_spec.rb ├── classes │ ├── puppet_agent_spec.rb │ ├── puppet_config_spec.rb │ ├── puppet_init_spec.rb │ ├── puppet_server_puppetdb_spec.rb │ ├── puppet_server_puppetserver_spec.rb │ ├── puppet_server_service_spec.rb │ └── puppet_server_spec.rb ├── defines │ └── puppet_config_entry_spec.rb ├── setup_acceptance_node.pp ├── spec.opts ├── spec_helper.rb ├── spec_helper_acceptance.rb └── support │ ├── acceptance │ └── puppetserver.rb │ └── aio.rb ├── templates ├── agent │ ├── systemd.puppet-run.service.erb │ └── systemd.puppet-run.timer.erb └── server │ ├── autosign.conf.erb │ ├── post-receive.erb │ └── puppetserver │ ├── conf.d │ ├── auth.conf.erb │ ├── ca.conf.erb │ ├── metrics.conf.erb │ ├── product.conf.erb │ ├── puppetserver.conf.erb │ └── webserver.conf.erb │ └── services.d │ └── ca.cfg.erb └── types └── custom_trusted_oid_mapping.pp /.fixtures.yml: -------------------------------------------------------------------------------- 1 | fixtures: 2 | repositories: 3 | augeas_core: 'https://github.com/puppetlabs/puppetlabs-augeas_core' 4 | concat: 'https://github.com/puppetlabs/puppetlabs-concat.git' 5 | cron_core: 'https://github.com/puppetlabs/puppetlabs-cron_core' 6 | extlib: 'https://github.com/voxpupuli/puppet-extlib.git' 7 | git: 'https://github.com/theforeman/puppet-git.git' 8 | inifile: 'https://github.com/puppetlabs/puppetlabs-inifile.git' 9 | puppetdb: 'https://github.com/puppetlabs/puppetlabs-puppetdb.git' 10 | puppetserver_foreman: 'https://github.com/theforeman/puppet-puppetserver_foreman.git' 11 | stdlib: 'https://github.com/puppetlabs/puppetlabs-stdlib.git' 12 | systemd: 'https://github.com/voxpupuli/puppet-systemd.git' 13 | vcsrepo: 'https://github.com/puppetlabs/puppetlabs-vcsrepo.git' 14 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: CI 3 | 4 | on: 5 | pull_request: 6 | push: 7 | branches: 8 | - 'develop' 9 | - 'master' 10 | - '*-stable' 11 | 12 | 13 | concurrency: 14 | group: ${{ github.ref_name }} 15 | cancel-in-progress: true 16 | 17 | jobs: 18 | puppet: 19 | name: Puppet 20 | uses: voxpupuli/gha-puppet/.github/workflows/beaker.yml@v3 21 | with: 22 | pidfile_workaround: 'true' 23 | rubocop: false 24 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # This file is managed centrally by modulesync 2 | # https://github.com/theforeman/foreman-installer-modulesync 3 | 4 | ## MAC OS 5 | .DS_Store 6 | 7 | ## TEXTMATE 8 | *.tmproj 9 | tmtags 10 | 11 | ## EMACS 12 | *~ 13 | \#* 14 | .\#* 15 | 16 | ## VIM 17 | *.swp 18 | *.swo 19 | tags 20 | 21 | ## Bundler 22 | Gemfile.lock 23 | .bundle 24 | vendor/ 25 | 26 | ## rbenv / rvm 27 | .rbenv* 28 | .rvmrc* 29 | .ruby-* 30 | 31 | ## rspec 32 | spec/fixtures/manifests 33 | spec/fixtures/modules 34 | junit/ 35 | 36 | ## Puppet module 37 | pkg/ 38 | coverage/ 39 | .yardoc/ 40 | REFERENCE.md 41 | 42 | ## InteliJ / RubyMine 43 | .idea 44 | 45 | ## Beaker 46 | .vagrant/ 47 | log/ 48 | -------------------------------------------------------------------------------- /.pmtignore: -------------------------------------------------------------------------------- 1 | # This file is managed centrally by modulesync 2 | # https://github.com/theforeman/foreman-installer-modulesync 3 | 4 | ## MAC OS 5 | .DS_Store 6 | 7 | ## TEXTMATE 8 | *.tmproj 9 | tmtags 10 | 11 | ## EMACS 12 | *~ 13 | \#* 14 | .\#* 15 | 16 | ## VIM 17 | *.swp 18 | *.swo 19 | tags 20 | 21 | ## Bundler 22 | Gemfile.lock 23 | .bundle 24 | vendor/ 25 | 26 | ## rbenv / rvm 27 | .rbenv* 28 | .rvmrc* 29 | .ruby-* 30 | 31 | ## rspec 32 | spec/fixtures/ 33 | junit/ 34 | 35 | ## Puppet module 36 | pkg/ 37 | coverage/ 38 | .yardoc/ 39 | 40 | ## InteliJ / RubyMine 41 | .idea 42 | 43 | ## Beaker 44 | .vagrant/ 45 | log/ 46 | 47 | # Files we don't want to ship in a release 48 | CONTRIBUTING.md 49 | Gemfile 50 | Rakefile 51 | spec/ 52 | -------------------------------------------------------------------------------- /.puppet-lint.rc: -------------------------------------------------------------------------------- 1 | --fail-on-warnings 2 | --no-140chars-check 3 | --no-class_inherits_from_params_class-check 4 | -------------------------------------------------------------------------------- /.rspec: -------------------------------------------------------------------------------- 1 | --format documentation 2 | --color 3 | --tty 4 | --backtrace 5 | -------------------------------------------------------------------------------- /.sync.yml: -------------------------------------------------------------------------------- 1 | --- 2 | .github/workflows/ci.yml: 3 | pidfile_workaround: true 4 | Gemfile: 5 | extra: 6 | - gem: hocon 7 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | Checklist (and a short version for the impatient) 2 | ================================================= 3 | 4 | * Commits: 5 | 6 | - Make commits of logical units. 7 | 8 | - Check for unnecessary whitespace with "git diff --check" before 9 | committing. 10 | 11 | - Commit using Unix line endings (check the settings around "crlf" in 12 | git-config(1)). 13 | 14 | - Do not check in commented out code or unneeded files. 15 | 16 | - The first line of the commit message should be a short 17 | description (50 characters is the soft limit, excluding ticket 18 | number(s)), and should skip the full stop. 19 | 20 | - If you have a [https://projects.theforeman.org/projects/puppet-foreman/issues](Redmine issue) 21 | number, associate the issue in the message. The first line should start 22 | with the issue number in the form "fixes #XXXX - rest of message". 23 | [More information on the Redmine style](https://projects.theforeman.org/projects/foreman/wiki/Reviewing_patches-commit_message_format). 24 | Tickets are not required for our installer Puppet modules. 25 | 26 | - If you have a GitHub issue number, associate the issue in the message. 27 | End the commit message with "Fixes GH-1234" on a new line. 28 | 29 | - The body should provide a meaningful commit message, which: 30 | 31 | - uses the imperative, present tense: "change", not "changed" or 32 | "changes". 33 | 34 | - includes motivation for the change, and contrasts its 35 | implementation with the previous behavior. 36 | 37 | - Make sure that you have tests for the bug you are fixing, or 38 | feature you are adding. 39 | 40 | - Make sure the test suites passes after your commit: 41 | `bundle exec rake spec` More information on [testing](#Testing) below 42 | 43 | - When introducing a large change, make sure it is properly 44 | documented in the README.md 45 | 46 | * Submission: 47 | 48 | * Pre-requisites: 49 | 50 | - Make sure you have a [GitHub account](https://github.com/join) 51 | 52 | * Preferred method: 53 | 54 | - Fork the repository on GitHub. 55 | 56 | - Push your changes to a topic branch in your fork of the 57 | repository, in a new branch. 58 | 59 | - Submit a pull request to the repository in the 'theforeman' 60 | organization. 61 | 62 | The long version 63 | ================ 64 | 65 | 1. Make separate commits for logically separate changes. 66 | 67 | Please break your commits down into logically consistent units 68 | which include new or changed tests relevant to the rest of the 69 | change. The goal of doing this is to make the diff easier to 70 | read for whoever is reviewing your code. In general, the easier 71 | your diff is to read, the more likely someone will be happy to 72 | review it and get it into the code base. 73 | 74 | If you are going to refactor a piece of code, please do so as a 75 | separate commit from your feature or bug fix changes. 76 | 77 | If you have many commits to fix one issue, use `git rebase` or 78 | `git commit --amend` to combine them into a single commit. 79 | 80 | We also really appreciate changes that include tests to make 81 | sure the bug is not re-introduced, and that the feature is not 82 | accidentally broken. 83 | 84 | Describe the technical detail of the change(s). If your 85 | description starts to get too long, that is a good sign that you 86 | probably need to split up your commit into more finely grained 87 | pieces. 88 | 89 | Commits which plainly describe the things which help 90 | reviewers check the patch and future developers understand the 91 | code are much more likely to be merged in with a minimum of 92 | bike-shedding or requested changes. Ideally, the commit message 93 | would include information, and be in a form suitable for 94 | inclusion in the release notes for the version of Puppet that 95 | includes them. 96 | 97 | Please also check that you are not introducing any trailing 98 | whitespace or other "whitespace errors". You can do this by 99 | running "git diff --check" on your changes before you commit. 100 | 101 | 2. Sending your patches 102 | 103 | To submit your changes via a GitHub pull request, we _highly_ 104 | recommend that you have them on a topic branch, instead of 105 | directly on "master". 106 | It makes things much easier to keep track of, especially if 107 | you decide to work on another thing before your first change 108 | is merged in. 109 | 110 | GitHub has some pretty good 111 | [general documentation](https://help.github.com/) on using 112 | their site. They also have documentation on 113 | [creating pull requests](https://help.github.com/send-pull-requests/). 114 | 115 | In general, after pushing your topic branch up to your 116 | repository on GitHub, you can switch to the branch in the 117 | GitHub UI and click "Pull Request" towards the top of the page 118 | in order to open a pull request. 119 | 120 | 121 | 3. Update the related GitHub issue. 122 | 123 | If there is a GitHub issue associated with the change you 124 | submitted, then you should update the ticket to include the 125 | location of your branch, along with any other commentary you 126 | may wish to make. 127 | 128 | Testing 129 | ======= 130 | 131 | Getting Started 132 | --------------- 133 | 134 | Our puppet modules provide [`Gemfile`](./Gemfile)s which can tell a ruby 135 | package manager such as [bundler](https://bundler.io/) what Ruby packages, 136 | or Gems, are required to build, develop, and test this software. 137 | 138 | **Prerequisites** 139 | 1. Make sure you have [bundler installed](https://bundler.io/#getting-started) 140 | on your system. If you are using Fedora, you can get `bundler` using 141 | ```shell 142 | sudo dnf install rubygem-bundler 143 | ``` 144 | 2. If you are using Fedora, you may need these additional packages 145 | ```shell 146 | sudo dnf install -y ruby-devel redhat-rpm-config 147 | ``` 148 | 149 | Now, go to the root directory of this project and use `bundler` to install all 150 | dependencies needed for this project by running 151 | 152 | ```console 153 | $ bundle install 154 | Fetching gem metadata from https://rubygems.org/........ 155 | Fetching gem metadata from https://rubygems.org/.. 156 | Using rake (10.1.0) 157 | Using builder (3.2.2) 158 | -- 8><-- many more --><8 -- 159 | Using rspec-system-puppet (2.2.0) 160 | Using serverspec (0.6.3) 161 | Using rspec-system-serverspec (1.0.0) 162 | Using bundler (1.3.5) 163 | Your bundle is complete! 164 | Use `bundle show [gemname]` to see where a bundled gem is installed. 165 | ``` 166 | 167 | NOTE some systems may require you to run this command with sudo. 168 | 169 | If you already have those gems installed, make sure they are up-to-date: 170 | 171 | ```shell 172 | bundle update 173 | ``` 174 | 175 | With all dependencies in place and up-to-date we can now run the tests: 176 | 177 | ```shell 178 | rake spec 179 | ``` 180 | 181 | This will execute all the [rspec tests](http://rspec-puppet.com/) tests under 182 | [spec/defines](./spec/defines), [spec/classes](./spec/classes), and so on. 183 | rspec tests may have the same kind of dependencies as the module they are 184 | testing. While the module defines in its [metadata.json](./metadata.json), 185 | rspec tests define them in [.fixtures.yml](./fixtures.yml). 186 | 187 | To run specific tests, use the spec test file name and a filter like: 188 | 189 | ```shell 190 | bundle exec rspec spec/classes/foreman_spec.rb -e 'should restart passenger' 191 | ``` 192 | More filter info available [here](https://relishapp.com/rspec/rspec-core/v/3-9/docs/command-line/example-option) 193 | 194 | To run OS specific tests: 195 | 196 | ```shell 197 | SPEC_FACTS_OS=redhat-8-x86_64 bundle exec rspec spec/classes/foreman_spec.rb 198 | ``` 199 | 200 | If you have more than one version of `redhat` OS specified in metadata.json, 201 | you can run them all like: 202 | 203 | ```shell 204 | SPEC_FACTS_OS=redhat bundle exec rspec spec/classes/foreman_spec.rb 205 | ``` 206 | For more information on running the tests, see [rspec-puppet-facts](https://github.com/mcanevet/rspec-puppet-facts) 207 | and specifically the [section for running tests](https://github.com/mcanevet/rspec-puppet-facts#running-your-tests). 208 | 209 | Writing Tests 210 | ------------- 211 | 212 | Our tests use [rspec-puppet](http://rspec-puppet.com/) to check that classes 213 | and defined types work when compiled with Puppet itself. Ideally, we want to 214 | test the smallest logical units possible (i.e. a single class, not the whole 215 | module), which helps with speed and reduces work when changing other parts of 216 | the module. 217 | 218 | By writing tests we ensure that future versions of the module don't introduce 219 | regressions, and that we find issues sooner (in this project) rather than later 220 | (when used in a Foreman installation). 221 | 222 | Each class has its own file within spec/classes/, ending with "_spec.rb" and 223 | inside each test file is a section for each test scenario ("describe"). 224 | 225 | A typical rspec-puppet test for a new class parameter would perhaps start with 226 | defining a set of parameters to pass into the class: 227 | 228 | describe 'with colour parameter' do 229 | let :params do 230 | {:colour => 'red'} 231 | end 232 | end 233 | 234 | The test then has to check for the presence or absence of certain Puppet 235 | resources with or without certain properties and relationships. e.g. a test 236 | for a service class would ensure the service resource is present, with the 237 | right name and the right ensure/enable properties. 238 | 239 | describe 'with colour parameter' do 240 | let :params do 241 | {:colour => 'red'} 242 | end 243 | 244 | it 'should configure colour' do 245 | should contain_file('/etc/service.conf').with_content('colour: red') 246 | end 247 | end 248 | 249 | More advanced topics: 250 | 251 | * Use rspec-puppet-facts loops: some tests use a loop with "on_supported_os" 252 | to test the class under every OS supported in metadata.json. 253 | * Test presence of inter-resource require/notify relationships. 254 | 255 | 256 | If you have commit access to the repository 257 | =========================================== 258 | 259 | Even if you have commit access to the repository, you will still need to 260 | go through the process above, and have someone else review and merge 261 | in your changes. The rule is that all changes must be reviewed by a 262 | developer on the project (that did not write the code) to ensure that 263 | all changes go through a code review process. 264 | 265 | Having someone other than the author of the topic branch recorded as 266 | performing the merge is the record that they performed the code 267 | review. 268 | 269 | 270 | Additional Resources 271 | ==================== 272 | 273 | * [Support and contact details](https://theforeman.org/support.html) 274 | 275 | * [General Foreman contribution details](https://theforeman.org/contribute.html) 276 | 277 | * [General GitHub documentation](https://help.github.com/) 278 | 279 | * [GitHub pull request documentation](https://help.github.com/send-pull-requests/) 280 | 281 | 282 | Modulesync 283 | ========== 284 | 285 | Various files, including this one, are 286 | [modulesynced](https://github.com/voxpupuli/modulesync) using 287 | [foreman-installer-modulesync](https://github.com/theforeman/foreman-installer-modulesync) 288 | configuration. Changes should be made over there and then synced to 289 | all [managed 290 | modules](https://github.com/theforeman/foreman-installer-modulesync/blob/master/managed_modules.yml). 291 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | # This file is managed centrally by modulesync 2 | # https://github.com/theforeman/foreman-installer-modulesync 3 | 4 | source 'https://rubygems.org' 5 | 6 | gem 'puppet', ENV.fetch('PUPPET_GEM_VERSION', '>= 7'), groups: ['development', 'test'] 7 | gem 'rake' 8 | 9 | gem 'kafo_module_lint', {"groups"=>["test"]} 10 | gem 'puppet-lint-spaceship_operator_without_tag-check', '~> 1.0', {"groups"=>["test"]} 11 | gem 'voxpupuli-test', '~> 9.0', {"groups"=>["test"]} 12 | gem 'github_changelog_generator', '>= 1.15.0', {"groups"=>["development"]} 13 | gem 'puppet_metadata', '~> 4.0' 14 | gem 'puppet-blacksmith', '>= 6.0.0', {"groups"=>["development"]} 15 | gem 'voxpupuli-acceptance', '~> 3.4', {"groups"=>["system_tests"]} 16 | gem 'puppetlabs_spec_helper', {"groups"=>["system_tests"]} 17 | gem 'hocon' 18 | 19 | # vim:ft=ruby 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Puppet Forge](https://img.shields.io/puppetforge/v/theforeman/puppet.svg)](https://forge.puppetlabs.com/theforeman/puppet) 2 | [![CI](https://github.com/theforeman/puppet-puppet/actions/workflows/ci.yml/badge.svg?event=schedule)](https://github.com/theforeman/puppet-puppet/actions/workflows/ci.yml) 3 | 4 | # Puppet module for installing the Puppet agent and server 5 | 6 | Installs and configures the Puppet agent and optionally a Puppet server (when 7 | `server` is true). Part of the [Foreman installer](https://github.com/theforeman/foreman-installer) 8 | or to be used as a Puppet module. 9 | 10 | Many puppet.conf options for agents, servers and other are parameterized, with 11 | class documentation provided at the top of the manifests. In addition, there 12 | are hash parameters for each configuration section that can be used to supply 13 | any options that are not explicitly supported. 14 | 15 | ## Compatibility 16 | 17 | See the module metadata for supported operating systems and compatible Puppet 18 | versions. The Puppetserver version should also match this. 19 | 20 | ## Environments support 21 | 22 | The module helps configure Puppet environments using directory environments. 23 | These are set up under /etc/puppetlabs/code/environments. 24 | 25 | ## Git repo support 26 | 27 | Environments can be backed by git by setting `server_git_repo` to true, which 28 | sets up `/var/lib/puppet/puppet.git` where each branch maps to one environment. 29 | Avoid using 'server' as this name isn't permitted. On each push to the repo, a 30 | hook updates `/etc/puppet/environments` with the contents of the branch. 31 | 32 | Permissions can be controlled via the `git_repo_{user,group,hook_mode,umask}` 33 | parameters. 34 | 35 | Requires [puppetlabs/vcsrepo](https://forge.puppetlabs.com/puppetlabs/vcsrepo) >= 5.2.0. 36 | 37 | ## Foreman integration 38 | 39 | The Foreman integration is optional, but on by default when `server` is true. 40 | It can be disabled by setting `server_foreman` to false. 41 | 42 | Requires [theforeman/puppetserver_foreman](https://forge.puppetlabs.com/theforeman/puppetserver_foreman). 43 | 44 | Since version 15.0.0 the integration bits depend on the standalone module where 45 | previously it depended on 46 | [theforeman/foreman](https://forge.puppetlabs.com/theforeman/foreman) 47 | 48 | There is also optional integration for [katello/certs](https://forge.puppetlabs.com/katello/certs). 49 | This can be enabled via Hiera: 50 | 51 | ```yaml 52 | puppet::server::foreman::katello: true 53 | ``` 54 | 55 | Then the `foreman_ssl_{ca,cert,key}` parameters are ignored and `certs::puppet` is used as a source. 56 | 57 | ## PuppetDB integration 58 | 59 | The Puppet server can be configured to export catalogs and reports to a 60 | PuppetDB instance, using the puppetlabs/puppetdb module. Use its 61 | `puppetdb::server` class to install the PuppetDB server and this module to 62 | configure the Puppet server to connect to PuppetDB. 63 | 64 | Requires [puppetlabs/puppetdb](https://forge.puppetlabs.com/puppetlabs/puppetdb) 65 | 66 | ```puppet 67 | class { 'puppet': 68 | server => true, 69 | server_reports => 'puppetdb,foreman', 70 | server_storeconfigs => true, 71 | } 72 | class { 'puppet::server::puppetdb': 73 | server => 'mypuppetdb.example.com', 74 | } 75 | ``` 76 | 77 | Above example manages Puppetserver + PuppetDB integration. It won't install the 78 | PuppetDB. To do so, you also need the `puppetdb` class 79 | 80 | ```puppet 81 | class { 'puppet': 82 | server => true, 83 | server_reports => 'puppetdb,foreman', 84 | server_storeconfigs => true, 85 | } 86 | include puppetdb 87 | class { 'puppet::server::puppetdb': 88 | server => 'mypuppetdb.example.com', 89 | } 90 | ``` 91 | 92 | Then the PuppetDB module will also configure postgresql and setup the database. 93 | If you want to manage postgresql installation on your own: 94 | 95 | ```puppet 96 | class { 'postgresql::globals': 97 | encoding => 'UTF-8', 98 | locale => 'en_US.UTF-8', 99 | version => '15', 100 | manage_package_repo => true, 101 | } 102 | class { 'postgresql::server': 103 | listen_addresses => '127.0.0.1', 104 | } 105 | postgresql::server::extension { 'pg_trgm': 106 | database => 'puppetdb', 107 | require => Postgresql::Server::Db['puppetdb'], 108 | before => Service['puppetdb'], 109 | } 110 | class { 'puppetdb': 111 | manage_dbserver => false, 112 | } 113 | class { 'puppet::server::puppetdb': 114 | server => 'mypuppetdb.example.com', 115 | } 116 | ``` 117 | 118 | Above code will install Puppetserver/PuppetDB/PostgreSQL on a single server. It 119 | will use the upstream postgresql repositories. It was tested on Ubuntu. 120 | 121 | Please also make sure your puppetdb ciphers are compatible with your puppet server ciphers, ie that the two following parameters match: 122 | ``` 123 | puppet::server::cipher_suites 124 | puppetdb::server::cipher_suites 125 | ``` 126 | 127 | # Installation 128 | 129 | Available from GitHub (via cloning or tarball), [Puppet Forge](https://forge.puppetlabs.com/theforeman/puppet) 130 | or as part of the Foreman installer. 131 | 132 | # Usage 133 | 134 | As a parameterized class, all the configurable options can be overridden from your 135 | wrapper classes or even your ENC (if it supports param classes). For example: 136 | 137 | ```puppet 138 | # Agent and cron (or daemon): 139 | class { 'puppet': runmode => 'cron', agent_server_hostname => 'hostname' } 140 | 141 | # Agent and puppetserver: 142 | class { 'puppet': server => true } 143 | 144 | # You want to use git? 145 | class { 'puppet': 146 | server => true 147 | server_git_repo => true 148 | } 149 | 150 | # Maybe you're using gitolite, new hooks, and a different port? 151 | class { 'puppet': 152 | server => true 153 | server_port => 8141, 154 | server_git_repo => true, 155 | server_git_repo_path => '/var/lib/gitolite/repositories/puppet.git', 156 | server_post_hook_name => 'post-receive.puppet', 157 | server_post_hook_content => 'puppetserver/post-hook.puppet', 158 | } 159 | 160 | # Configure server without Foreman integration 161 | class { 'puppet': 162 | server => true, 163 | server_foreman => false, 164 | server_reports => 'store', 165 | server_external_nodes => '', 166 | } 167 | 168 | # Want to integrate with an existing PuppetDB? 169 | class { 'puppet': 170 | server => true, 171 | server_reports => 'puppetdb,foreman', 172 | server_storeconfigs => true, 173 | } 174 | class { 'puppet::server::puppetdb': 175 | server => 'mypuppetdb.example.com', 176 | } 177 | ``` 178 | 179 | Look in _init.pp_ for what can be configured this way, see Contributing if anything 180 | doesn't work. 181 | 182 | To use this in standalone mode, edit a file (e.g. install.pp), put in a class resource, 183 | as per the examples above, and the execute _puppet apply_ e.g: 184 | 185 | ```sh 186 | puppet apply --modulepath /path_to/extracted_tarball < true } 188 | EOF 189 | ``` 190 | 191 | # Advanced scenarios 192 | 193 | An HTTP (non-SSL) puppetserver instance can be set up (standalone or in addition to 194 | the SSL instance) by setting the `server_http` parameter to `true`. This is useful for 195 | reverse proxy or load balancer scenarios where the proxy/load balancer takes care of SSL 196 | termination. The HTTP puppetserver instance expects the `X-Client-Verify`, `X-SSL-Client-DN` 197 | and `X-SSL-Subject` HTTP headers to have been set on the front end server. 198 | 199 | The listening port can be configured by setting `server_http_port` (which defaults to 8139). 200 | 201 | For puppetserver, this HTTP instance accepts **ALL** connections and no further restrictions can be configured. 202 | 203 | **Note that running an HTTP puppetserver is a huge security risk when improperly 204 | configured. Allowed hosts should be tightly controlled; anyone with access to an allowed 205 | host can access all client catalogues and client certificates.** 206 | 207 | ```puppet 208 | # Configure an HTTP puppetserver vhost in addition to the standard SSL vhost 209 | class { '::puppet': 210 | server => true, 211 | server_http => true, 212 | server_http_port => 8130, # default: 8139 213 | } 214 | ``` 215 | 216 | # Contributing 217 | 218 | * Fork the project 219 | * Commit and push until you are happy with your contribution 220 | 221 | # More info 222 | 223 | See https://theforeman.org or at #theforeman irc channel on freenode 224 | 225 | Copyright (c) 2010-2012 Ohad Levy 226 | 227 | This program and entire repository is free software: you can redistribute it and/or modify 228 | it under the terms of the GNU General Public License as published by 229 | the Free Software Foundation, either version 3 of the License, or 230 | any later version. 231 | 232 | This program is distributed in the hope that it will be useful, 233 | but WITHOUT ANY WARRANTY; without even the implied warranty of 234 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 235 | GNU General Public License for more details. 236 | You should have received a copy of the GNU General Public License 237 | along with this program. If not, see . 238 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | # This file is managed centrally by modulesync 2 | # https://github.com/theforeman/foreman-installer-modulesync 3 | 4 | # Attempt to load voxupuli-test (which pulls in puppetlabs_spec_helper), 5 | # otherwise attempt to load it directly. 6 | begin 7 | require 'voxpupuli/test/rake' 8 | rescue LoadError 9 | begin 10 | require 'puppetlabs_spec_helper/rake_tasks' 11 | rescue LoadError 12 | end 13 | end 14 | 15 | # load optional tasks for acceptance 16 | # only available if gem group releases is installed 17 | begin 18 | require 'voxpupuli/acceptance/rake' 19 | rescue LoadError 20 | else 21 | # We use fixtures in our modules, which is not the default 22 | task :beaker => 'spec_prep' 23 | end 24 | 25 | # blacksmith isn't always present, e.g. on Travis with --without development 26 | begin 27 | require 'puppet_blacksmith/rake_tasks' 28 | Blacksmith::RakeTask.new do |t| 29 | t.tag_pattern = "%s" 30 | t.tag_message_pattern = "Version %s" 31 | t.tag_sign = true 32 | end 33 | rescue LoadError 34 | end 35 | 36 | begin 37 | require 'github_changelog_generator/task' 38 | 39 | # https://github.com/github-changelog-generator/github-changelog-generator/issues/313 40 | module GitHubChangelogGeneratorExtensions 41 | def compound_changelog 42 | super.gsub(/(fixes|fixing|refs) \\#(\d+)/i, '\1 [\\#\2](https://projects.theforeman.org/issues/\2)') 43 | end 44 | end 45 | 46 | class GitHubChangelogGenerator::Generator 47 | prepend GitHubChangelogGeneratorExtensions 48 | end 49 | 50 | GitHubChangelogGenerator::RakeTask.new :changelog do |config| 51 | raise "Set CHANGELOG_GITHUB_TOKEN environment variable eg 'export CHANGELOG_GITHUB_TOKEN=valid_token_here'" if Rake.application.top_level_tasks.include? "changelog" and ENV['CHANGELOG_GITHUB_TOKEN'].nil? 52 | metadata = JSON.load(File.read('metadata.json')) 53 | config.user = 'theforeman' 54 | config.project = "puppet-#{metadata['name'].split('-').last}" 55 | config.future_release = metadata['version'] 56 | config.exclude_labels = ['duplicate', 'question', 'invalid', 'wontfix', 'Modulesync', 'skip-changelog'] 57 | end 58 | rescue LoadError 59 | end 60 | -------------------------------------------------------------------------------- /manifests/agent.pp: -------------------------------------------------------------------------------- 1 | # Puppet agent 2 | # @api private 3 | class puppet::agent { 4 | contain puppet::agent::install 5 | contain puppet::agent::config 6 | contain puppet::agent::service 7 | 8 | Class['puppet::agent::install'] ~> Class['puppet::agent::config', 'puppet::agent::service'] 9 | Class['puppet::config', 'puppet::agent::config'] ~> Class['puppet::agent::service'] 10 | } 11 | -------------------------------------------------------------------------------- /manifests/agent/config.pp: -------------------------------------------------------------------------------- 1 | # Puppet agent configuration 2 | # @api private 3 | class puppet::agent::config inherits puppet::config { 4 | puppet::config::agent { 5 | 'classfile': value => $puppet::classfile; 6 | 'default_schedules': value => $puppet::agent_default_schedules; 7 | 'report': value => $puppet::report; 8 | 'masterport': value => $puppet::agent_server_port; 9 | 'environment': value => $puppet::environment; 10 | 'splay': value => $puppet::splay; 11 | 'splaylimit': value => $puppet::splaylimit; 12 | 'runinterval': value => $puppet::runinterval; 13 | 'noop': value => $puppet::agent_noop; 14 | 'usecacheonfailure': value => $puppet::usecacheonfailure; 15 | } 16 | if $puppet::http_connect_timeout != undef { 17 | puppet::config::agent { 18 | 'http_connect_timeout': value => $puppet::http_connect_timeout; 19 | } 20 | } 21 | if $puppet::http_read_timeout != undef { 22 | puppet::config::agent { 23 | 'http_read_timeout': value => $puppet::http_read_timeout; 24 | } 25 | } 26 | if $puppet::prerun_command { 27 | puppet::config::agent { 28 | 'prerun_command': value => $puppet::prerun_command; 29 | } 30 | } 31 | if $puppet::postrun_command { 32 | puppet::config::agent { 33 | 'postrun_command': value => $puppet::postrun_command; 34 | } 35 | } 36 | 37 | $puppet::agent_additional_settings.each |$key,$value| { 38 | puppet::config::agent { $key: value => $value } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /manifests/agent/install.pp: -------------------------------------------------------------------------------- 1 | # Install the puppet agent package 2 | # @api private 3 | class puppet::agent::install ( 4 | Variant[Boolean, Enum['server', 'agent']] $manage_packages = $puppet::manage_packages, 5 | Variant[String, Array[String]] $package_name = $puppet::client_package, 6 | String[1] $package_version = $puppet::version, 7 | Optional[String[1]] $package_provider = $puppet::package_provider, 8 | Variant[Undef, String, Hash, Array] $package_install_options = $puppet::package_install_options, 9 | Variant[Undef, Stdlib::Absolutepath, Stdlib::HTTPUrl] $package_source = $puppet::package_source, 10 | ) { 11 | if $manage_packages == true or $manage_packages == 'agent' { 12 | package { $package_name: 13 | ensure => $package_version, 14 | provider => $package_provider, 15 | install_options => $package_install_options, 16 | source => $package_source, 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /manifests/agent/service.pp: -------------------------------------------------------------------------------- 1 | # Set up the puppet agent as a service 2 | # @api private 3 | class puppet::agent::service { 4 | case $puppet::runmode { 5 | 'service': { 6 | $service_enabled = true 7 | $cron_enabled = false 8 | $systemd_enabled = false 9 | } 10 | 'cron': { 11 | $service_enabled = false 12 | $cron_enabled = true 13 | $systemd_enabled = false 14 | } 15 | 'systemd.timer': { 16 | $service_enabled = false 17 | $cron_enabled = false 18 | $systemd_enabled = true 19 | } 20 | 'none', 'unmanaged': { 21 | $service_enabled = false 22 | $cron_enabled = false 23 | $systemd_enabled = false 24 | } 25 | default: { 26 | fail("Runmode of ${puppet::runmode} not supported by puppet::agent::config!") 27 | } 28 | } 29 | 30 | if $puppet::runmode in $puppet::unavailable_runmodes { 31 | fail("Runmode of ${puppet::runmode} not supported on ${facts['kernel']} operating systems!") 32 | } 33 | 34 | class { 'puppet::agent::service::daemon': 35 | enabled => $service_enabled, 36 | } 37 | contain puppet::agent::service::daemon 38 | 39 | class { 'puppet::agent::service::systemd': 40 | enabled => $systemd_enabled, 41 | hour => $puppet::run_hour, 42 | minute => $puppet::run_minute, 43 | timezone => $puppet::run_timezone, 44 | } 45 | contain puppet::agent::service::systemd 46 | 47 | class { 'puppet::agent::service::cron': 48 | enabled => $cron_enabled, 49 | hour => $puppet::run_hour, 50 | minute => $puppet::run_minute, 51 | } 52 | contain puppet::agent::service::cron 53 | } 54 | -------------------------------------------------------------------------------- /manifests/agent/service/cron.pp: -------------------------------------------------------------------------------- 1 | # Set up running the agent via cron 2 | # @api private 3 | class puppet::agent::service::cron ( 4 | Boolean $enabled = false, 5 | Optional[Integer[0,23]] $hour = undef, 6 | Variant[Integer[0,59], Array[Integer[0,59]], Undef] $minute = undef, 7 | ) { 8 | unless $puppet::runmode == 'unmanaged' or 'cron' in $puppet::unavailable_runmodes { 9 | if $enabled { 10 | $command = pick($puppet::cron_cmd, "${puppet::puppet_cmd} agent --config ${puppet::dir}/puppet.conf --onetime --no-daemonize") 11 | $times = extlib::ip_to_cron($puppet::runinterval) 12 | 13 | $_hour = pick($hour, $times[0]) 14 | $_minute = pick($minute, $times[1]) 15 | 16 | cron { 'puppet': 17 | command => $command, 18 | user => root, 19 | hour => $_hour, 20 | minute => $_minute, 21 | } 22 | } else { 23 | cron { 'puppet': 24 | ensure => absent, 25 | } 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /manifests/agent/service/daemon.pp: -------------------------------------------------------------------------------- 1 | # Set up running the agent as a daemon 2 | # @api private 3 | class puppet::agent::service::daemon ( 4 | Boolean $enabled = false, 5 | ) { 6 | unless $puppet::runmode == 'unmanaged' or 'service' in $puppet::unavailable_runmodes { 7 | if $enabled { 8 | service { 'puppet': 9 | ensure => running, 10 | name => $puppet::service_name, 11 | hasstatus => true, 12 | hasrestart => $puppet::agent_restart_command != undef, 13 | enable => true, 14 | restart => $puppet::agent_restart_command, 15 | } 16 | } else { 17 | service { 'puppet': 18 | ensure => stopped, 19 | name => $puppet::service_name, 20 | hasstatus => true, 21 | enable => false, 22 | } 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /manifests/agent/service/systemd.pp: -------------------------------------------------------------------------------- 1 | # Set up running the agent via a systemd timer 2 | # @api private 3 | class puppet::agent::service::systemd ( 4 | Boolean $enabled = false, 5 | Optional[Integer[0,23]] $hour = undef, 6 | Variant[Integer[0,59], Array[Integer[0,59]], Undef] $minute = undef, 7 | Optional[String[1]] $timezone = undef, 8 | ) { 9 | unless $puppet::runmode == 'unmanaged' or 'systemd.timer' in $puppet::unavailable_runmodes { 10 | # Use the same times as for cron 11 | $times = extlib::ip_to_cron($puppet::runinterval) 12 | 13 | # But only if they are not explicitly specified 14 | $_hour = pick($hour, $times[0]) 15 | $_minute = pick($minute, $times[1]) 16 | 17 | $command = pick($puppet::systemd_cmd, "${puppet::puppet_cmd} agent --config ${puppet::dir}/puppet.conf --onetime --no-daemonize --detailed-exitcode --no-usecacheonfailure") 18 | $randomizeddelaysec = $puppet::systemd_randomizeddelaysec 19 | 20 | systemd::timer { "${puppet::systemd_unit_name}.timer": 21 | ensure => bool2str($enabled, 'present', 'absent'), 22 | active => $enabled, 23 | enable => $enabled, 24 | timer_content => template('puppet/agent/systemd.puppet-run.timer.erb'), 25 | service_content => template('puppet/agent/systemd.puppet-run.service.erb'), 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /manifests/config.pp: -------------------------------------------------------------------------------- 1 | # Set up the puppet config 2 | # @api private 3 | class puppet::config ( 4 | # lint:ignore:parameter_types 5 | $allow_any_crl_auth = $puppet::allow_any_crl_auth, 6 | $auth_allowed = $puppet::auth_allowed, 7 | $ca_server = $puppet::ca_server, 8 | $ca_port = $puppet::ca_port, 9 | $certificate_revocation = $puppet::certificate_revocation, 10 | $dns_alt_names = $puppet::dns_alt_names, 11 | $module_repository = $puppet::module_repository, 12 | $pluginsource = $puppet::pluginsource, 13 | $pluginfactsource = $puppet::pluginfactsource, 14 | $puppet_dir = $puppet::dir, 15 | $agent_server_hostname = $puppet::agent_server_hostname, 16 | $syslogfacility = $puppet::syslogfacility, 17 | $srv_domain = $puppet::srv_domain, 18 | $use_srv_records = $puppet::use_srv_records, 19 | $additional_settings = $puppet::additional_settings, 20 | $client_certname = $puppet::client_certname, 21 | # lint:endignore 22 | ) { 23 | puppet::config::main { 24 | 'vardir': value => $puppet::vardir; 25 | 'logdir': value => $puppet::logdir; 26 | 'rundir': value => $puppet::rundir; 27 | 'ssldir': value => $puppet::ssldir; 28 | 'privatekeydir': value => '$ssldir/private_keys { group = service }'; 29 | 'hostprivkey': value => '$privatekeydir/$certname.pem { mode = 640 }'; 30 | 'show_diff': value => $puppet::show_diff; 31 | 'codedir': value => $puppet::codedir; 32 | } 33 | 34 | if $module_repository and !empty($module_repository) { 35 | puppet::config::main { 'module_repository': value => $module_repository; } 36 | } 37 | if $ca_server and !empty($ca_server) { 38 | puppet::config::main { 'ca_server': value => $ca_server; } 39 | } 40 | if $ca_port { 41 | puppet::config::main { 'ca_port': value => $ca_port; } 42 | } 43 | if $certificate_revocation != undef { 44 | puppet::config::main { 'certificate_revocation': value => $certificate_revocation; } 45 | } 46 | if $dns_alt_names and !empty($dns_alt_names) { 47 | puppet::config::main { 'dns_alt_names': value => $dns_alt_names; } 48 | } 49 | if $use_srv_records { 50 | unless $srv_domain { 51 | fail('domain fact found to be undefined and $srv_domain is undefined') 52 | } 53 | puppet::config::main { 54 | 'use_srv_records': value => true; 55 | 'srv_domain': value => $srv_domain; 56 | } 57 | } else { 58 | puppet::config::main { 59 | 'server': value => pick($agent_server_hostname, $facts['networking']['fqdn']); 60 | } 61 | } 62 | if $pluginsource { 63 | puppet::config::main { 'pluginsource': value => $pluginsource; } 64 | } 65 | if $pluginfactsource { 66 | puppet::config::main { 'pluginfactsource': value => $pluginfactsource; } 67 | } 68 | if $syslogfacility and !empty($syslogfacility) { 69 | puppet::config::main { 'syslogfacility': value => $syslogfacility; } 70 | } 71 | if $client_certname { 72 | puppet::config::main { 73 | 'certname': value => $client_certname; 74 | } 75 | } 76 | 77 | $additional_settings.each |$key,$value| { 78 | puppet::config::main { $key: value => $value } 79 | } 80 | 81 | concat::fragment { 'puppet.conf_comment': 82 | target => "${puppet_dir}/puppet.conf", 83 | content => '# file managed by puppet', 84 | order => '0_comment', 85 | } 86 | 87 | file { $puppet_dir: 88 | ensure => directory, 89 | owner => $puppet::dir_owner, 90 | group => $puppet::dir_group, 91 | } 92 | -> case $facts['os']['family'] { 93 | 'Windows': { 94 | concat { "${puppet_dir}/puppet.conf": 95 | mode => $puppet::puppetconf_mode, 96 | } 97 | } 98 | 99 | default: { 100 | concat { "${puppet_dir}/puppet.conf": 101 | owner => 'root', 102 | group => $puppet::params::root_group, 103 | mode => $puppet::puppetconf_mode, 104 | } 105 | } 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /manifests/config/agent.pp: -------------------------------------------------------------------------------- 1 | # Set a config entry in the [agent] section 2 | # 3 | # @param value 4 | # The value for the config entry 5 | # @param key 6 | # The key of the config entry 7 | # @param joiner 8 | # How to join an array value into a string 9 | define puppet::config::agent ( 10 | Variant[Array[String], Boolean, String, Integer] $value, 11 | String $key = $name, 12 | String $joiner = ',' 13 | ) { 14 | puppet::config::entry { "agent_${name}": 15 | key => $key, 16 | value => $value, 17 | joiner => $joiner, 18 | section => 'agent', 19 | sectionorder => 2, 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /manifests/config/entry.pp: -------------------------------------------------------------------------------- 1 | # Set a config entry 2 | # 3 | # @param key 4 | # The key of the config entry 5 | # @param value 6 | # The value for the config entry 7 | # @param section 8 | # The section for the config entry 9 | # @param sectionorder 10 | # How to order the section. This is only used on the first definition of the 11 | # section via ensure_resource. 12 | # @param joiner 13 | # How to join an array value into a string 14 | define puppet::config::entry ( 15 | String $key, 16 | Variant[Array[String], Boolean, String, Integer] $value, 17 | String $section, 18 | Variant[Integer[0], String] $sectionorder = 5, 19 | String $joiner = ',', 20 | ) { 21 | if ($value =~ Array) { 22 | $_value = join(flatten($value), $joiner) 23 | } elsif ($value =~ Boolean) { 24 | $_value = bool2str($value) 25 | } else { 26 | $_value = $value 27 | } 28 | 29 | # note the spaces at he end of the 'order' parameters, 30 | # they make sure that '1_main ' is ordered before '1_main_*' 31 | ensure_resource('concat::fragment', "puppet.conf_${section}", { 32 | target => "${puppet::dir}/puppet.conf", 33 | content => "\n[${section}]", 34 | order => "${sectionorder}_${section} ", 35 | }) 36 | ensure_resource('concat::fragment', "puppet.conf_${section}_end", { 37 | target => "${puppet::dir}/puppet.conf", 38 | content => "\n", 39 | order => "${sectionorder}_${section}~end", 40 | }) 41 | 42 | # this adds the '$key =' for the first value, 43 | # otherwise it just appends it with the joiner to separate it from the previous value. 44 | if (!defined(Concat::Fragment["puppet.conf_${section}_${key}"])) { 45 | concat::fragment { "puppet.conf_${section}_${key}": 46 | target => "${puppet::dir}/puppet.conf", 47 | content => "\n ${key} = ${_value}", 48 | order => "${sectionorder}_${section}_${key} ", 49 | } 50 | } else { 51 | concat::fragment { "puppet.conf_${section}_${key}_${name}": 52 | target => "${puppet::dir}/puppet.conf", 53 | content => "${joiner}${_value}", 54 | order => "${sectionorder}_${section}_${key}_${name} ", 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /manifests/config/main.pp: -------------------------------------------------------------------------------- 1 | # Set a config entry in the [main] section 2 | # 3 | # @param value 4 | # The value for the config entry 5 | # @param key 6 | # The key of the config entry 7 | # @param joiner 8 | # How to join an array value into a string 9 | define puppet::config::main ( 10 | Variant[Array[String], Boolean, String, Integer] $value, 11 | String $key = $name, 12 | String $joiner = ',' 13 | ) { 14 | puppet::config::entry { "main${name}": 15 | key => $key, 16 | value => $value, 17 | joiner => $joiner, 18 | section => 'main', 19 | sectionorder => 1, 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /manifests/config/server.pp: -------------------------------------------------------------------------------- 1 | # Set a config entry in the [server] section 2 | # 3 | # @param value 4 | # The value for the config entry 5 | # @param key 6 | # The key of the config entry 7 | # @param joiner 8 | # How to join an array value into a string 9 | define puppet::config::server ( 10 | Variant[Array[String], Boolean, String, Integer] $value, 11 | String $key = $name, 12 | String $joiner = ',' 13 | ) { 14 | puppet::config::entry { "server_${name}": 15 | key => $key, 16 | value => $value, 17 | joiner => $joiner, 18 | section => 'server', 19 | sectionorder => 3, 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /manifests/params.pp: -------------------------------------------------------------------------------- 1 | # Default parameters 2 | # @api private 3 | class puppet::params { 4 | # Basic config 5 | $version = 'present' 6 | $manage_user = true 7 | $user = 'puppet' 8 | $group = 'puppet' 9 | $ip = '0.0.0.0' 10 | $agent_server_port = 8140 11 | $splay = false 12 | $splaylimit = 1800 13 | $runinterval = 1800 14 | $runmode = 'service' 15 | $report = true 16 | 17 | # Not defined here as the commands depend on module parameter "dir" 18 | $cron_cmd = undef 19 | $systemd_cmd = undef 20 | 21 | $agent_noop = false 22 | $show_diff = false 23 | $module_repository = undef 24 | $hiera_config = '$confdir/hiera.yaml' 25 | $usecacheonfailure = true 26 | $ca_server = undef 27 | $ca_port = undef 28 | $ca_crl_filepath = undef 29 | $certificate_revocation = undef 30 | $server_crl_enable = undef 31 | $prerun_command = undef 32 | $postrun_command = undef 33 | $server_compile_mode = undef 34 | $dns_alt_names = [] 35 | $use_srv_records = false 36 | $agent_default_schedules = false 37 | 38 | $srv_domain = fact('networking.domain') 39 | 40 | # lint:ignore:puppet_url_without_modules 41 | $pluginsource = 'puppet:///plugins' 42 | $pluginfactsource = 'puppet:///pluginfacts' 43 | # lint:endignore 44 | $classfile = '$statedir/classes.txt' 45 | $syslogfacility = undef 46 | $environment = $server_facts['environment'] 47 | 48 | # aio_agent_version is a core fact that's empty on non-AIO 49 | $aio_package = fact('aio_agent_version') =~ String[1] 50 | 51 | $systemd_randomizeddelaysec = 0 52 | 53 | case $facts['os']['family'] { 54 | 'Windows' : { 55 | # Windows prefixes normal paths with the Data Directory's path and leaves 'puppet' off the end 56 | $dir_prefix = 'C:/ProgramData/PuppetLabs/puppet' 57 | $dir = "${dir_prefix}/etc" 58 | $codedir = "${dir_prefix}/etc" 59 | $logdir = "${dir_prefix}/var/log" 60 | $rundir = "${dir_prefix}/var/run" 61 | $ssldir = "${dir_prefix}/etc/ssl" 62 | $vardir = "${dir_prefix}/var" 63 | $sharedir = "${dir_prefix}/share" 64 | $bindir = "${dir_prefix}/bin" 65 | $root_group = undef 66 | $server_puppetserver_dir = undef 67 | $server_puppetserver_vardir = undef 68 | $server_puppetserver_rundir = undef 69 | $server_puppetserver_logdir = undef 70 | $server_ruby_load_paths = [] 71 | $server_jruby_gem_home = undef 72 | $puppetconf_mode = '0674' 73 | } 74 | 75 | /^(FreeBSD|DragonFly)$/ : { 76 | $dir = '/usr/local/etc/puppet' 77 | $codedir = '/usr/local/etc/puppet' 78 | $logdir = '/var/log/puppet' 79 | $rundir = '/var/run/puppet' 80 | $ssldir = '/var/puppet/ssl' 81 | $vardir = '/var/puppet' 82 | $sharedir = '/usr/local/share/puppet' 83 | $bindir = '/usr/local/bin' 84 | $root_group = undef 85 | $server_puppetserver_dir = '/usr/local/etc/puppetserver' 86 | $server_puppetserver_vardir = '/var/puppet/server/data/puppetserver' 87 | $server_puppetserver_rundir = '/var/run/puppetserver' 88 | $server_puppetserver_logdir = '/var/log/puppetserver' 89 | $ruby_gem_dir = regsubst($facts['ruby']['version'], '^(\d+\.\d+).*$', '/usr/local/lib/ruby/gems/\1/gems') 90 | $server_ruby_load_paths = [$facts['ruby']['sitedir'], "${ruby_gem_dir}/facter-${facts['facterversion']}/lib"] 91 | $server_jruby_gem_home = '/var/puppet/server/data/puppetserver/jruby-gems' 92 | $puppetconf_mode = '0644' 93 | } 94 | 95 | 'Archlinux' : { 96 | $dir = '/etc/puppetlabs/puppet' 97 | $codedir = '/etc/puppetlabs/code' 98 | $logdir = '/var/log/puppetlabs/puppet' 99 | $rundir = '/var/run/puppetlabs' 100 | $ssldir = '/etc/puppetlabs/puppet/ssl' 101 | $vardir = '/opt/puppetlabs/puppet/cache' 102 | $sharedir = '/opt/puppetlabs/puppet' 103 | $bindir = '/usr/bin' 104 | $root_group = undef 105 | $server_puppetserver_dir = undef 106 | $server_puppetserver_vardir = undef 107 | $server_puppetserver_rundir = undef 108 | $server_puppetserver_logdir = undef 109 | $server_ruby_load_paths = [] 110 | $server_jruby_gem_home = undef 111 | $puppetconf_mode = '0644' 112 | } 113 | 114 | default : { 115 | if $aio_package { 116 | $dir = '/etc/puppetlabs/puppet' 117 | $codedir = '/etc/puppetlabs/code' 118 | $logdir = '/var/log/puppetlabs/puppet' 119 | $rundir = '/var/run/puppetlabs' 120 | $ssldir = '/etc/puppetlabs/puppet/ssl' 121 | $vardir = '/opt/puppetlabs/puppet/cache' 122 | $sharedir = '/opt/puppetlabs/puppet' 123 | $bindir = '/opt/puppetlabs/bin' 124 | $server_puppetserver_dir = '/etc/puppetlabs/puppetserver' 125 | $server_puppetserver_vardir = '/opt/puppetlabs/server/data/puppetserver' 126 | $server_puppetserver_rundir = '/var/run/puppetlabs/puppetserver' 127 | $server_puppetserver_logdir = '/var/log/puppetlabs/puppetserver' 128 | $server_ruby_load_paths = ['/opt/puppetlabs/puppet/lib/ruby/vendor_ruby'] 129 | $server_jruby_gem_home = '/opt/puppetlabs/server/data/puppetserver/jruby-gems' 130 | } else { 131 | $dir = '/etc/puppet' 132 | $codedir = $facts['os']['family'] ? { 133 | 'Debian' => '/etc/puppet/code', 134 | default => '/etc/puppet', 135 | } 136 | $logdir = '/var/log/puppet' 137 | $rundir = '/var/run/puppet' 138 | $ssldir = '/var/lib/puppet/ssl' 139 | $vardir = '/var/lib/puppet' 140 | $sharedir = '/usr/share/puppet' 141 | $bindir = '/usr/bin' 142 | if $facts['os']['family'] == 'Debian' { 143 | $server_puppetserver_dir = '/etc/puppet/puppetserver' 144 | $server_puppetserver_vardir = '/var/lib/puppetserver' 145 | $server_puppetserver_rundir = '/run/puppetserver' 146 | $server_puppetserver_logdir = '/var/log/puppetserver' 147 | $server_ruby_load_paths = ['/usr/lib/puppetserver/ruby/vendor_ruby'] 148 | $server_jruby_gem_home = '/var/lib/puppetserver/jruby-gems' 149 | } else { 150 | $server_puppetserver_dir = '/etc/puppetserver' 151 | $server_puppetserver_vardir = $vardir 152 | $server_puppetserver_rundir = undef 153 | $server_puppetserver_logdir = undef 154 | $server_ruby_load_paths = [] 155 | $server_jruby_gem_home = '/var/lib/puppet/jruby-gems' 156 | } 157 | } 158 | $root_group = undef 159 | $puppetconf_mode = '0644' 160 | } 161 | } 162 | 163 | $http_connect_timeout = undef 164 | $http_read_timeout = undef 165 | 166 | $autosign = "${dir}/autosign.conf" 167 | $autosign_entries = [] 168 | $autosign_mode = '0664' 169 | $autosign_content = undef 170 | $autosign_source = undef 171 | 172 | $puppet_cmd = "${bindir}/puppet" 173 | $puppetserver_cmd = "${bindir}/puppetserver" 174 | 175 | $manage_packages = true 176 | 177 | if $facts['os']['family'] == 'Windows' { 178 | $dir_owner = undef 179 | $dir_group = undef 180 | } else { 181 | $dir_owner = 'root' 182 | $dir_group = $root_group 183 | } 184 | 185 | $package_provider = $facts['os']['family'] ? { 186 | 'windows' => 'chocolatey', 187 | default => undef, 188 | } 189 | 190 | $package_source = undef 191 | $package_install_options = undef 192 | 193 | # Allow any to the CRL. Needed in case of puppet CA proxy 194 | $allow_any_crl_auth = false 195 | 196 | # Authenticated nodes to allow 197 | $auth_allowed = ['$1'] 198 | 199 | # Will this host be a puppet agent ? 200 | $agent = true 201 | $client_certname = $trusted['certname'] 202 | 203 | # Set by the Foreman ENC 204 | $agent_server_hostname = getvar('puppetmaster') 205 | 206 | # Hashes containing additional settings 207 | $additional_settings = {} 208 | $agent_additional_settings = {} 209 | $server_additional_settings = {} 210 | 211 | # Will this host be a puppetserver? 212 | $server = false 213 | $server_ca = true 214 | $server_ca_crl_sync = false 215 | $server_reports = 'foreman' 216 | $server_external_nodes = "${dir}/node.rb" 217 | $server_trusted_external_command = undef 218 | $server_request_timeout = 60 219 | $server_certname = $trusted['certname'] 220 | $server_strict_variables = false 221 | $server_http = false 222 | $server_http_port = 8139 223 | 224 | # Need a new server template for the server? 225 | $server_template = 'puppet/server/puppet.conf.erb' 226 | # Template for server settings in [main] 227 | $server_main_template = 'puppet/server/puppet.conf.main.erb' 228 | 229 | # Set 'false' for static environments, or 'true' for git-based workflow 230 | $server_git_repo = false 231 | # Git branch to puppet env mapping for the post receive hook 232 | $server_git_branch_map = {} 233 | 234 | # Owner of the environments dir: for cases external service needs write 235 | # access to manage it. 236 | $server_environments_owner = $user 237 | $server_environments_group = $root_group 238 | $server_environments_mode = '0755' 239 | $server_environments_recurse = false 240 | # Where we store our puppet environments 241 | $server_envs_dir = ["${codedir}/environments"] 242 | $server_envs_target = undef 243 | # Modules in this directory would be shared across all environments 244 | $server_common_modules_path = unique(["${server_envs_dir[0]}/common", "${codedir}/modules", "${sharedir}/modules", '/usr/share/puppet/modules']) 245 | 246 | # Dynamic environments config, ignore if the git_repo is 'false' 247 | # Path to the repository on disk 248 | $server_git_repo_path = "${vardir}/puppet.git" 249 | # Umask for vcsrepo operations 250 | $server_git_repo_umask = '0022' 251 | # mode of the repository hooks 252 | $server_git_repo_hook_mode = '0755' 253 | # user of the repository 254 | $server_git_repo_user = $user 255 | # group of the repository 256 | $server_git_repo_group = $user 257 | # Override these if you need your own hooks 258 | $server_post_hook_content = 'puppet/server/post-receive.erb' 259 | $server_post_hook_name = 'post-receive' 260 | $server_custom_trusted_oid_mapping = undef 261 | 262 | $server_storeconfigs = false 263 | 264 | $puppet_major = regsubst($facts['puppetversion'], '^(\d+)\..*$', '\1') 265 | 266 | if ($facts['os']['family'] =~ /(FreeBSD|DragonFly)/) { 267 | $server_package = "puppetserver${puppet_major}" 268 | } else { 269 | $server_package = undef 270 | } 271 | 272 | $server_ssl_dir = $ssldir 273 | $server_version = undef 274 | 275 | if $aio_package or 276 | ($facts['os']['name'] == 'Debian' and versioncmp($facts['os']['release']['major'], '12') >= 0) { 277 | $client_package = ['puppet-agent'] 278 | } elsif ($facts['os']['family'] =~ /(FreeBSD|DragonFly)/) { 279 | $client_package = ["puppet${puppet_major}"] 280 | } else { 281 | $client_package = ['puppet'] 282 | } 283 | 284 | # Puppet service name 285 | $service_name = 'puppet' 286 | 287 | # Puppet onedshot systemd service and timer name 288 | $systemd_unit_name = 'puppet-run' 289 | # Mechanisms to manage and reload/restart the agent 290 | # If supported on the OS, reloading is prefered since it does not kill a currently active puppet run 291 | if $facts['service_provider'] == 'systemd' { 292 | $agent_restart_command = "/bin/systemctl reload-or-restart ${service_name}" 293 | $unavailable_runmodes = $facts['os']['family'] ? { 294 | 'Archlinux' => ['cron'], 295 | default => [], 296 | } 297 | } else { 298 | case $facts['os']['family'] { 299 | 'Debian': { 300 | $agent_restart_command = "/usr/sbin/service ${service_name} reload" 301 | $unavailable_runmodes = ['systemd.timer'] 302 | } 303 | 'Windows': { 304 | $agent_restart_command = undef 305 | $unavailable_runmodes = ['cron', 'systemd.timer'] 306 | } 307 | default : { 308 | $agent_restart_command = undef 309 | $unavailable_runmodes = ['systemd.timer'] 310 | } 311 | } 312 | } 313 | 314 | # Foreman parameters 315 | $lower_fqdn = downcase($facts['networking']['fqdn']) 316 | $server_foreman = true 317 | $server_foreman_facts = true 318 | $server_puppet_basedir = $aio_package ? { 319 | true => '/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet', 320 | false => undef, 321 | } 322 | $server_foreman_url = undef 323 | $server_foreman_ssl_ca = undef 324 | $server_foreman_ssl_cert = undef 325 | $server_foreman_ssl_key = undef 326 | 327 | # Which Parser do we want to use? https://docs.puppetlabs.com/references/latest/configuration.html#parser 328 | $server_parser = 'current' 329 | 330 | # Timeout for cached environments, changed in puppet 3.7.x 331 | $server_environment_timeout = undef 332 | 333 | # puppet server configuration file 334 | $server_jvm_config = $facts['os']['family'] ? { 335 | 'RedHat' => '/etc/sysconfig/puppetserver', 336 | 'Debian' => '/etc/default/puppetserver', 337 | default => '/etc/default/puppetserver', 338 | } 339 | 340 | $server_jvm_extra_args = undef 341 | $server_jvm_cli_args = undef 342 | 343 | # This is some very trivial "tuning". See the puppet reference: 344 | # https://docs.puppet.com/puppetserver/latest/tuning_guide.html 345 | $mem_in_mb = $facts['memory']['system']['total_bytes'] / 1024 / 1024 346 | if $mem_in_mb >= 3072 { 347 | $server_jvm_min_heap_size = '2G' 348 | $server_jvm_max_heap_size = '2G' 349 | $server_max_active_instances = min(abs($facts['processors']['count']), 4) 350 | } elsif $mem_in_mb >= 1024 { 351 | $server_max_active_instances = 1 352 | $server_jvm_min_heap_size = '1G' 353 | $server_jvm_max_heap_size = '1G' 354 | } else { 355 | # VMs with 1GB RAM and a crash kernel enabled usually have an effective 992MB RAM 356 | $server_max_active_instances = 1 357 | $server_jvm_min_heap_size = '768m' 358 | $server_jvm_max_heap_size = '768m' 359 | } 360 | 361 | $server_ssl_dir_manage = true 362 | $server_ssl_key_manage = true 363 | $server_default_manifest = false 364 | $server_default_manifest_path = '/etc/puppet/manifests/default_manifest.pp' 365 | $server_default_manifest_content = '' # lint:ignore:empty_string_assignment 366 | $server_max_requests_per_instance = 0 367 | $server_max_queued_requests = 0 368 | $server_max_retry_delay = 1800 369 | $server_multithreaded = false 370 | $server_idle_timeout = 1200000 371 | $server_web_idle_timeout = 30000 372 | $server_connect_timeout = 120000 373 | $server_ca_auth_required = true 374 | $server_ca_client_self_delete = false 375 | $server_admin_api_allowlist = ['localhost', $lower_fqdn] 376 | $server_ca_client_allowlist = ['localhost', $lower_fqdn] 377 | $server_cipher_suites = [ 378 | 'TLS_AES_128_GCM_SHA256', 379 | 'TLS_AES_256_GCM_SHA384', 380 | 'TLS_DHE_RSA_WITH_AES_128_GCM_SHA256', 381 | 'TLS_DHE_RSA_WITH_AES_256_GCM_SHA384', 382 | 'TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256', 383 | 'TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384', 384 | 'TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256', 385 | 'TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384', 386 | ] 387 | $server_ssl_protocols = ['TLSv1.3', 'TLSv1.2'] 388 | $server_ssl_chain_filepath = undef 389 | $server_check_for_updates = true 390 | $server_environment_class_cache_enabled = false 391 | $server_allow_header_cert_info = false 392 | $server_ca_allow_sans = false 393 | $server_ca_allow_auth_extensions = false 394 | $server_ca_enable_infra_crl = false 395 | $server_ca_allow_auto_renewal = false 396 | $server_ca_allow_auto_renewal_cert_ttl = '60d' 397 | $server_max_open_files = undef 398 | $server_environment_vars = {} 399 | 400 | $server_puppetserver_version = undef 401 | 402 | # Puppetserver metrics shipping 403 | $server_metrics_jmx_enable = true 404 | $server_metrics_graphite_enable = false 405 | $server_metrics_graphite_host = '127.0.0.1' 406 | $server_metrics_graphite_port = 2003 407 | $server_metrics_server_id = $lower_fqdn 408 | $server_metrics_graphite_interval = 5 409 | $server_metrics_allowed = undef 410 | 411 | # Should the /puppet/experimental route be enabled? 412 | $server_puppetserver_experimental = true 413 | 414 | # For custom auth.conf settings allow passing in a template 415 | $server_puppetserver_auth_template = undef 416 | 417 | # Normally agents can only fetch their own catalogs. If you want some nodes to be able to fetch *any* catalog, add them here. 418 | $server_puppetserver_trusted_agents = [] 419 | $server_puppetserver_trusted_certificate_extensions = [] 420 | } 421 | -------------------------------------------------------------------------------- /manifests/server/config.pp: -------------------------------------------------------------------------------- 1 | # Set up the puppet server config 2 | # @api private 3 | class puppet::server::config inherits puppet::config { 4 | contain 'puppet::server::puppetserver' 5 | unless empty($puppet::server::puppetserver_vardir) { 6 | puppet::config::server { 7 | 'vardir': value => $puppet::server::puppetserver_vardir; 8 | } 9 | } 10 | unless empty($puppet::server::puppetserver_rundir) { 11 | puppet::config::server { 12 | 'rundir': value => $puppet::server::puppetserver_rundir; 13 | } 14 | } 15 | unless empty($puppet::server::puppetserver_logdir) { 16 | puppet::config::server { 17 | 'logdir': value => $puppet::server::puppetserver_logdir; 18 | } 19 | } 20 | 21 | # Mirror the relationship, as defined() is parse-order dependent 22 | # Ensures puppetservers certs are generated before the proxy is needed 23 | if defined(Class['foreman_proxy::config']) and $foreman_proxy::ssl { 24 | Class['puppet::server::config'] ~> Class['foreman_proxy::config'] 25 | Class['puppet::server::config'] ~> Class['foreman_proxy::service'] 26 | } 27 | 28 | # And before Foreman's cert-using service needs it 29 | if defined(Class['foreman::service']) and $foreman::ssl { 30 | Class['puppet::server::config'] -> Class['foreman::service'] 31 | } 32 | 33 | ## General configuration 34 | $ca_server = $puppet::ca_server 35 | $ca_port = $puppet::ca_port 36 | $server_external_nodes = $puppet::server::external_nodes 37 | $server_environment_timeout = $puppet::server::environment_timeout 38 | $trusted_external_command = $puppet::server::trusted_external_command 39 | $primary_envs_dir = $puppet::server::envs_dir[0] 40 | 41 | if $server_external_nodes and $server_external_nodes != '' { 42 | class { 'puppet::server::enc': 43 | enc_path => $server_external_nodes, 44 | } 45 | } 46 | 47 | if $trusted_external_command { 48 | puppet::config::server { 49 | 'trusted_external_command': value => $trusted_external_command, 50 | } 51 | } 52 | 53 | $autosign = ($puppet::server::autosign =~ Boolean)? { 54 | true => $puppet::server::autosign, 55 | false => "${puppet::server::autosign} { mode = ${puppet::server::autosign_mode} }" 56 | } 57 | 58 | puppet::config::main { 59 | 'reports': value => $puppet::server::reports; 60 | 'environmentpath': value => $puppet::server::envs_dir.join(':'); 61 | } 62 | if $puppet::server::hiera_config and !empty($puppet::server::hiera_config) { 63 | puppet::config::main { 64 | 'hiera_config': value => $puppet::server::hiera_config; 65 | } 66 | } 67 | if $puppet::server::common_modules_path and !empty($puppet::server::common_modules_path) { 68 | puppet::config::main { 69 | 'basemodulepath': value => $puppet::server::common_modules_path, joiner => ':'; 70 | } 71 | } 72 | if $puppet::server::default_manifest { 73 | puppet::config::main { 74 | 'default_manifest': value => $puppet::server::default_manifest_path; 75 | } 76 | } 77 | 78 | puppet::config::server { 79 | 'autosign': value => $autosign; 80 | 'ca': value => $puppet::server::ca; 81 | 'certname': value => $puppet::server::certname; 82 | 'parser': value => $puppet::server::parser; 83 | 'strict_variables': value => $puppet::server::strict_variables; 84 | 'storeconfigs': value => $puppet::server::storeconfigs; 85 | } 86 | 87 | if $puppet::server::ssl_dir_manage { 88 | puppet::config::server { 89 | 'ssldir': value => $puppet::server::ssl_dir; 90 | } 91 | } 92 | if $server_environment_timeout { 93 | puppet::config::server { 94 | 'environment_timeout': value => $server_environment_timeout; 95 | } 96 | } 97 | 98 | $puppet::server::additional_settings.each |$key,$value| { 99 | puppet::config::server { $key: value => $value } 100 | } 101 | 102 | file { "${puppet::vardir}/reports": 103 | ensure => directory, 104 | owner => $puppet::server::user, 105 | group => $puppet::server::group, 106 | mode => '0750', 107 | } 108 | 109 | if '/usr/share/puppet/modules' in $puppet::server::common_modules_path { 110 | # Create Foreman share dir which does not depend on Puppet version 111 | exec { 'mkdir -p /usr/share/puppet/modules': 112 | creates => '/usr/share/puppet/modules', 113 | path => ['/usr/bin', '/bin'], 114 | } 115 | } 116 | 117 | ## SSL and CA configuration 118 | # Open read permissions to private keys to puppet group for foreman, proxy etc. 119 | file { "${puppet::server::ssl_dir}/private_keys": 120 | ensure => directory, 121 | owner => $puppet::server::user, 122 | group => $puppet::server::group, 123 | mode => '0750', 124 | require => Exec['puppet_server_config-create_ssl_dir'], 125 | } 126 | 127 | if $puppet::server::ssl_key_manage { 128 | file { "${puppet::server::ssl_dir}/private_keys/${puppet::server::certname}.pem": 129 | owner => $puppet::server::user, 130 | group => $puppet::server::group, 131 | mode => '0640', 132 | } 133 | } 134 | 135 | if $puppet::server::custom_trusted_oid_mapping { 136 | $_custom_trusted_oid_mapping = { 137 | oid_mapping => $puppet::server::custom_trusted_oid_mapping, 138 | } 139 | file { "${puppet::dir}/custom_trusted_oid_mapping.yaml": 140 | ensure => file, 141 | owner => 'root', 142 | group => $puppet::params::root_group, 143 | mode => '0644', 144 | content => to_yaml($_custom_trusted_oid_mapping), 145 | } 146 | } 147 | 148 | # If the ssl dir is not the default dir, it needs to be created before running 149 | # the generate ca cert or it will fail. 150 | exec { 'puppet_server_config-create_ssl_dir': 151 | creates => $puppet::server::ssl_dir, 152 | command => "/bin/mkdir -p ${puppet::server::ssl_dir}", 153 | umask => '0022', 154 | } 155 | 156 | # Generate a new CA and host cert if our host cert doesn't exist 157 | if $puppet::server::ca { 158 | exec { 'puppet_server_config-generate_ca_cert': 159 | creates => $puppet::server::ssl_ca_cert, 160 | command => "${puppet::puppetserver_cmd} ca setup", 161 | umask => '0022', 162 | require => [ 163 | Concat["${puppet::server::dir}/puppet.conf"], 164 | Exec['puppet_server_config-create_ssl_dir'], 165 | ], 166 | } 167 | } elsif $puppet::server::ca_crl_sync { 168 | # If not a ca AND sync the crl from the ca server 169 | if $server_facts['servername'] { 170 | file { $puppet::server::ssl_ca_crl: 171 | ensure => file, 172 | owner => $puppet::server::user, 173 | group => $puppet::server::group, 174 | mode => '0644', 175 | content => file($settings::cacrl, $settings::hostcrl, '/dev/null'), 176 | } 177 | } 178 | } 179 | 180 | # autosign file 181 | if $puppet::server_ca and !($puppet::server::autosign =~ Boolean) { 182 | if $puppet::server::autosign_content or $puppet::server::autosign_source { 183 | if !empty($puppet::server::autosign_entries) { 184 | fail('Cannot set both autosign_content/autosign_source and autosign_entries') 185 | } 186 | $autosign_content = $puppet::server::autosign_content 187 | } elsif !empty($puppet::server::autosign_entries) { 188 | $autosign_content = template('puppet/server/autosign.conf.erb') 189 | } else { 190 | $autosign_content = undef 191 | } 192 | file { $puppet::server::autosign: 193 | ensure => file, 194 | owner => $puppet::server::user, 195 | group => $puppet::server::group, 196 | mode => $puppet::server::autosign_mode, 197 | content => $autosign_content, 198 | source => $puppet::server::autosign_source, 199 | } 200 | } 201 | 202 | # only manage this file if we provide content 203 | if $puppet::server::default_manifest and $puppet::server::default_manifest_content != '' { 204 | file { $puppet::server::default_manifest_path: 205 | ensure => file, 206 | owner => $puppet::user, 207 | group => $puppet::group, 208 | mode => '0644', 209 | content => $puppet::server::default_manifest_content, 210 | } 211 | } 212 | 213 | ## Environments 214 | # location where our puppet environments are located 215 | if $puppet::server::envs_target and $puppet::server::envs_target != '' { 216 | $ensure = 'link' 217 | } else { 218 | $ensure = 'directory' 219 | } 220 | 221 | file { $puppet::server::envs_dir: 222 | ensure => $ensure, 223 | owner => $puppet::server::environments_owner, 224 | group => $puppet::server::environments_group, 225 | mode => $puppet::server::environments_mode, 226 | target => $puppet::server::envs_target, 227 | recurse => $puppet::server::environments_recurse, 228 | force => true, 229 | } 230 | 231 | if $puppet::server::git_repo { 232 | file { $puppet::vardir: 233 | ensure => directory, 234 | owner => 'root', 235 | group => 'root', 236 | } 237 | 238 | vcsrepo { 'puppet_repo': 239 | ensure => 'bare', 240 | provider => 'git', 241 | path => $puppet::server::git_repo_path, 242 | user => $puppet::server::git_repo_user, 243 | group => $puppet::server::git_repo_group, 244 | umask => $puppet::server::git_repo_umask, 245 | require => File[$puppet::vardir, $primary_envs_dir], 246 | } 247 | 248 | $git_branch_map = $puppet::server::git_branch_map 249 | # git post hook to auto generate an environment per branch 250 | file { "${puppet::server::git_repo_path}/hooks/${puppet::server::post_hook_name}": 251 | content => template($puppet::server::post_hook_content), 252 | owner => $puppet::server::git_repo_user, 253 | group => $puppet::server::git_repo_group, 254 | mode => $puppet::server::git_repo_hook_mode, 255 | require => Vcsrepo['puppet_repo'], 256 | } 257 | } 258 | 259 | file { $puppet::sharedir: 260 | ensure => directory, 261 | } 262 | 263 | if $puppet::server::common_modules_path and !empty($puppet::server::common_modules_path) { 264 | file { $puppet::server::common_modules_path: 265 | ensure => directory, 266 | owner => $puppet::server_environments_owner, 267 | group => $puppet::server_environments_group, 268 | mode => $puppet::server_environments_mode, 269 | } 270 | } 271 | 272 | if $puppet::server::foreman { 273 | contain puppet::server::foreman 274 | } 275 | } 276 | -------------------------------------------------------------------------------- /manifests/server/enc.pp: -------------------------------------------------------------------------------- 1 | # Set up the ENC config 2 | # @api private 3 | class puppet::server::enc ( 4 | Variant[Undef, String[0], Stdlib::Absolutepath] $enc_path = $puppet::server::external_nodes 5 | ) { 6 | puppet::config::server { 7 | 'external_nodes': value => $enc_path; 8 | 'node_terminus': value => 'exec'; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /manifests/server/foreman.pp: -------------------------------------------------------------------------------- 1 | # @summary Set up Foreman integration 2 | # @api private 3 | class puppet::server::foreman ( 4 | Boolean $katello = false, 5 | ) { 6 | if $katello { 7 | include certs::puppet 8 | Class['certs::puppet'] -> Class['puppetserver_foreman'] 9 | 10 | $ssl_ca = $certs::puppet::ssl_ca_cert 11 | $ssl_cert = $certs::puppet::client_cert 12 | $ssl_key = $certs::puppet::client_key 13 | } else { 14 | $ssl_ca = pick($puppet::server::foreman_ssl_ca, $puppet::server::ssl_ca_cert) 15 | $ssl_cert = pick($puppet::server::foreman_ssl_cert, $puppet::server::ssl_cert) 16 | $ssl_key = pick($puppet::server::foreman_ssl_key, $puppet::server::ssl_cert_key) 17 | } 18 | 19 | # Include foreman components for the puppetserver 20 | # ENC script, reporting script etc. 21 | class { 'puppetserver_foreman': 22 | foreman_url => $puppet::server::foreman_url, 23 | enc_upload_facts => $puppet::server::server_foreman_facts, 24 | enc_timeout => $puppet::server::request_timeout, 25 | puppet_home => $puppet::server::puppetserver_vardir, 26 | puppet_basedir => $puppet::server::puppet_basedir, 27 | puppet_etcdir => $puppet::dir, 28 | ssl_ca => $ssl_ca, 29 | ssl_cert => $ssl_cert, 30 | ssl_key => $ssl_key, 31 | } 32 | contain puppetserver_foreman 33 | } 34 | -------------------------------------------------------------------------------- /manifests/server/install.pp: -------------------------------------------------------------------------------- 1 | # Install the puppet server 2 | # @api private 3 | class puppet::server::install { 4 | # Mirror the relationship, as defined() is parse-order dependent 5 | # Ensures 'puppet' user group is present before managing users 6 | if defined(Class['foreman_proxy::config']) { 7 | Class['puppet::server::install'] -> Class['foreman_proxy::config'] 8 | } 9 | if defined(Class['foreman::config']) { 10 | Class['puppet::server::install'] -> Class['foreman::config'] 11 | } 12 | 13 | if $puppet::server::git_repo { 14 | stdlib::ensure_packages(['git']) 15 | } 16 | 17 | if $puppet::server::manage_user { 18 | $shell = $puppet::server::git_repo ? { 19 | true => $facts['os']['family'] ? { 20 | /^(FreeBSD|DragonFly)$/ => '/usr/local/bin/git-shell', 21 | default => '/usr/bin/git-shell' 22 | }, 23 | default => undef, 24 | } 25 | 26 | user { $puppet::server::user: 27 | shell => $shell, 28 | } 29 | 30 | if $puppet::server::git_repo { 31 | Package['git'] -> User[$puppet::server::user] 32 | } 33 | } 34 | 35 | if $puppet::manage_packages == true or $puppet::manage_packages == 'server' { 36 | $server_package = pick($puppet::server::package, 'puppetserver') 37 | $server_version = pick($puppet::server::version, $puppet::version) 38 | 39 | package { $server_package: 40 | ensure => $server_version, 41 | install_options => $puppet::package_install_options, 42 | } 43 | 44 | # Puppetserver 8 on EL 8 relies on JRE 11 or 17. This prefers JRE 17 by installing it first 45 | if ( 46 | !$puppet::server::jvm_java_bin and 47 | $facts['os']['family'] == 'RedHat' and $facts['os']['release']['major'] == '8' and 48 | # This doesn't use server_version because we have 2 mechanisms to set the version 49 | versioncmp(pick($puppet::server::puppetserver_version, $facts['puppetversion']), '8.0.0') >= 0 50 | ) { 51 | # EL 8 packaging can install either Java 17 or Java 11, but we prefer Java 17 52 | stdlib::ensure_packages(['jre-17-headless']) 53 | 54 | Package['jre-17-headless'] -> Package[$server_package] 55 | } 56 | 57 | if $puppet::server::manage_user { 58 | Package[$server_package] -> User[$puppet::server::user] 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /manifests/server/puppetdb.pp: -------------------------------------------------------------------------------- 1 | # @summary PuppetDB integration 2 | # 3 | # This class relies on the puppetlabs/puppetdb and essentially wraps 4 | # puppetdb::master::config with the proper resource chaining. 5 | # 6 | # Note that this doesn't manage the server itself. 7 | # 8 | # @example 9 | # class { 'puppet': 10 | # server => true, 11 | # server_reports => 'puppetdb,foreman', 12 | # server_storeconfigs => true, 13 | # } 14 | # class { 'puppet::server::puppetdb': 15 | # server => 'mypuppetdb.example.com', 16 | # } 17 | # 18 | # @param server 19 | # The PuppetDB server 20 | # 21 | # @param port 22 | # The PuppetDB port 23 | # 24 | # @param soft_write_failure 25 | # Whether to enable soft write failure 26 | class puppet::server::puppetdb ( 27 | Stdlib::Host $server = undef, 28 | Stdlib::Port $port = 8081, 29 | Boolean $soft_write_failure = false, 30 | ) { 31 | class { 'puppetdb::master::config': 32 | puppetdb_server => $server, 33 | puppetdb_port => $port, 34 | puppetdb_soft_write_failure => $soft_write_failure, 35 | manage_storeconfigs => false, 36 | restart_puppet => false, 37 | } 38 | Class['puppetdb::master::puppetdb_conf'] ~> Class['puppet::server::service'] 39 | } 40 | -------------------------------------------------------------------------------- /manifests/server/puppetserver.pp: -------------------------------------------------------------------------------- 1 | # Configures the puppetserver jvm configuration file using augeas. 2 | # 3 | # @api private 4 | # 5 | # @param java_bin 6 | # Path to the java executable to use 7 | # 8 | # @param config 9 | # Path to the jvm configuration file. 10 | # This file is usually either /etc/default/puppetserver or 11 | # /etc/sysconfig/puppetserver depending on your *nix flavor. 12 | # 13 | # @param jvm_min_heap_size 14 | # Translates into the -Xms option and is added to the JAVA_ARGS 15 | # 16 | # @param jvm_max_heap_size 17 | # Translates into the -Xmx option and is added to the JAVA_ARGS 18 | # 19 | # @param jvm_extra_args 20 | # Custom options to pass through to the java binary. These get added to 21 | # the end of the JAVA_ARGS variable 22 | # 23 | # @param jvm_cli_args 24 | # Custom options to pass through to the java binary when using a 25 | # puppetserver subcommand, (eg puppetserver gem). These get used 26 | # in the JAVA_ARGS_CLI variable. 27 | # 28 | # @param server_puppetserver_dir 29 | # Puppetserver config directory 30 | # 31 | # @param server_puppetserver_vardir 32 | # Puppetserver var directory 33 | # 34 | # @param server_jruby_gem_home 35 | # Puppetserver jruby gemhome 36 | # 37 | # @param server_environment_vars 38 | # Puppetserver hash of environment vars 39 | # 40 | # @param server_cipher_suites 41 | # Puppetserver array of acceptable ciphers 42 | # 43 | # @param server_ssl_protocols 44 | # Puppetserver array of acceptable ssl protocols 45 | # 46 | # @param server_max_active_instances 47 | # Puppetserver number of max jruby instances 48 | # 49 | # @param server_max_requests_per_instance 50 | # Puppetserver number of max requests per jruby instance 51 | # 52 | # @param server_max_queued_requests 53 | # The maximum number of requests that may be queued waiting 54 | # to borrow a JRuby from the pool. 55 | # 56 | # @param server_max_retry_delay 57 | # Sets the upper limit for the random sleep set as a Retry-After 58 | # header on 503 responses returned when max-queued-requests is enabled. 59 | # 60 | # @param server_multithreaded 61 | # Configures the puppetserver to use multithreaded jruby. 62 | # 63 | # @param disable_fips 64 | # Disables FIPS support within the JVM 65 | # 66 | # @example 67 | # 68 | # # configure memory for java < 8 69 | # class {'::puppet::server::puppetserver': 70 | # jvm_min_heap_size => '1G', 71 | # jvm_max_heap_size => '3G', 72 | # jvm_extra_args => '-XX:MaxPermSize=256m', 73 | # } 74 | # 75 | class puppet::server::puppetserver ( 76 | Optional[Pattern[/^[\d]\.[\d]+\.[\d]+$/]] $puppetserver_version = $puppet::server::puppetserver_version, 77 | String $config = $puppet::server::jvm_config, 78 | Optional[Stdlib::Absolutepath] $java_bin = $puppet::server::jvm_java_bin, 79 | Variant[String, Array[String]] $jvm_extra_args = $puppet::server::real_jvm_extra_args, 80 | Optional[String] $jvm_cli_args = $puppet::server::jvm_cli_args, 81 | Pattern[/^[0-9]+[kKmMgG]$/] $jvm_min_heap_size = $puppet::server::jvm_min_heap_size, 82 | Pattern[/^[0-9]+[kKmMgG]$/] $jvm_max_heap_size = $puppet::server::jvm_max_heap_size, 83 | Stdlib::Absolutepath $server_puppetserver_dir = $puppet::server::puppetserver_dir, 84 | Stdlib::Absolutepath $server_puppetserver_vardir = $puppet::server::puppetserver_vardir, 85 | Optional[Stdlib::Absolutepath] $server_puppetserver_rundir = $puppet::server::puppetserver_rundir, 86 | Optional[Stdlib::Absolutepath] $server_puppetserver_logdir = $puppet::server::puppetserver_logdir, 87 | Optional[Stdlib::Absolutepath] $server_jruby_gem_home = $puppet::server::jruby_gem_home, 88 | Hash[String, String] $server_environment_vars = $puppet::server::server_environment_vars, 89 | Array[String] $server_ruby_load_paths = $puppet::server::ruby_load_paths, 90 | Array[String] $server_cipher_suites = $puppet::server::cipher_suites, 91 | Integer[1] $server_max_active_instances = $puppet::server::max_active_instances, 92 | Integer[0] $server_max_requests_per_instance = $puppet::server::max_requests_per_instance, 93 | Integer[0] $server_max_queued_requests = $puppet::server::max_queued_requests, 94 | Integer[0] $server_max_retry_delay = $puppet::server::max_retry_delay, 95 | Boolean $server_multithreaded = $puppet::server::multithreaded, 96 | Array[String] $server_ssl_protocols = $puppet::server::ssl_protocols, 97 | Stdlib::Absolutepath $server_ssl_ca_crl = $puppet::server::ssl_ca_crl, 98 | Stdlib::Absolutepath $server_ssl_ca_cert = $puppet::server::ssl_ca_cert, 99 | Stdlib::Absolutepath $server_ssl_cert = $puppet::server::ssl_cert, 100 | Stdlib::Absolutepath $server_ssl_cert_key = $puppet::server::ssl_cert_key, 101 | Variant[Boolean, Stdlib::Absolutepath] $server_ssl_chain = $puppet::server::ssl_chain, 102 | Boolean $server_crl_enable = $puppet::server::crl_enable_real, 103 | String $server_ip = $puppet::server::ip, 104 | Stdlib::Port $server_port = $puppet::server::port, 105 | Boolean $server_http = $puppet::server::http, 106 | Stdlib::Port $server_http_port = $puppet::server::http_port, 107 | Boolean $server_ca = $puppet::server::ca, 108 | String $server_dir = $puppet::server::dir, 109 | Stdlib::Absolutepath $codedir = $puppet::server::codedir, 110 | Integer[0] $server_idle_timeout = $puppet::server::idle_timeout, 111 | Integer[0] $server_web_idle_timeout = $puppet::server::web_idle_timeout, 112 | Integer[0] $server_connect_timeout = $puppet::server::connect_timeout, 113 | Boolean $server_ca_auth_required = $puppet::server::ca_auth_required, 114 | Boolean $server_ca_client_self_delete = $puppet::server::ca_client_self_delete, 115 | Array[String] $server_ca_client_allowlist = $puppet::server::ca_client_allowlist, 116 | Array[String] $server_admin_api_allowlist = $puppet::server::admin_api_allowlist, 117 | Boolean $server_check_for_updates = $puppet::server::check_for_updates, 118 | Boolean $server_environment_class_cache_enabled = $puppet::server::environment_class_cache_enabled, 119 | Optional[Boolean] $server_metrics = $puppet::server::puppetserver_metrics, 120 | Boolean $server_profiler = $puppet::server::puppetserver_profiler, 121 | Boolean $server_telemetry = pick($puppet::server::puppetserver_telemetry, false), 122 | Boolean $metrics_jmx_enable = $puppet::server::metrics_jmx_enable, 123 | Boolean $metrics_graphite_enable = $puppet::server::metrics_graphite_enable, 124 | String $metrics_graphite_host = $puppet::server::metrics_graphite_host, 125 | Stdlib::Port $metrics_graphite_port = $puppet::server::metrics_graphite_port, 126 | String $metrics_server_id = $puppet::server::metrics_server_id, 127 | Integer $metrics_graphite_interval = $puppet::server::metrics_graphite_interval, 128 | Optional[Array] $metrics_allowed = $puppet::server::metrics_allowed, 129 | Boolean $server_experimental = $puppet::server::puppetserver_experimental, 130 | Optional[String[1]] $server_auth_template = $puppet::server::puppetserver_auth_template, 131 | Array[String] $server_trusted_agents = $puppet::server::puppetserver_trusted_agents, 132 | Array[Hash] $server_trusted_certificate_extensions = $puppet::server::puppetserver_trusted_certificate_extensions, 133 | Boolean $allow_header_cert_info = $puppet::server::allow_header_cert_info, 134 | Optional[Enum['off', 'jit', 'force']] $compile_mode = $puppet::server::compile_mode, 135 | Optional[Integer[1]] $acceptor_threads = $puppet::server::acceptor_threads, 136 | Optional[Integer[1]] $selector_threads = $puppet::server::selector_threads, 137 | Optional[Integer[1]] $ssl_acceptor_threads = $puppet::server::ssl_acceptor_threads, 138 | Optional[Integer[1]] $ssl_selector_threads = $puppet::server::ssl_selector_threads, 139 | Optional[Integer[1]] $max_threads = $puppet::server::max_threads, 140 | Boolean $ca_allow_sans = $puppet::server::ca_allow_sans, 141 | Boolean $ca_allow_auth_extensions = $puppet::server::ca_allow_auth_extensions, 142 | Boolean $ca_enable_infra_crl = $puppet::server::ca_enable_infra_crl, 143 | Boolean $server_ca_allow_auto_renewal = $puppet::server::server_ca_allow_auto_renewal, 144 | String $server_ca_allow_auto_renewal_cert_ttl = $puppet::server::server_ca_allow_auto_renewal_cert_ttl, 145 | Optional[Integer[1]] $max_open_files = $puppet::server::max_open_files, 146 | Optional[Stdlib::Absolutepath] $versioned_code_id = $puppet::server::versioned_code_id, 147 | Optional[Stdlib::Absolutepath] $versioned_code_content = $puppet::server::versioned_code_content, 148 | Boolean $disable_fips = $facts['os']['family'] == 'RedHat', 149 | Array[String[1]] $jolokia_metrics_allowlist = $puppet::server::jolokia_metrics_allowlist, 150 | ) { 151 | include puppet::server 152 | 153 | # For Puppetserver, certain configuration parameters are version specific. 154 | # We need a method to determine what version is installed. 155 | if $puppetserver_version { 156 | $real_puppetserver_version = $puppetserver_version 157 | } elsif versioncmp($facts['puppetversion'], '8.0.0') >= 0 { 158 | $real_puppetserver_version = '8.0.0' 159 | } else { 160 | # our minimum supported version of puppet server 161 | $real_puppetserver_version = '7.0.0' 162 | } 163 | 164 | $puppetserver_package = pick($puppet::server::package, 'puppetserver') 165 | 166 | if $java_bin { 167 | $_java_bin = $java_bin 168 | } elsif versioncmp($real_puppetserver_version, '8.0.0') >= 0 { 169 | # Follows logic that https://github.com/puppetlabs/ezbake/pull/627 suggests, but takes it a 170 | # step further by also ensuring EL 8 has Java 17 171 | $_java_bin = case $facts['os']['family'] { 172 | 'RedHat': { 173 | $facts['os']['release']['major'] ? { 174 | /^([89])$/ => '/usr/lib/jvm/jre-17/bin/java', 175 | default => '/usr/bin/java' 176 | } 177 | } 178 | default: { 179 | '/usr/bin/java' 180 | } 181 | } 182 | } else { 183 | $_java_bin = '/usr/bin/java' 184 | } 185 | 186 | $jvm_heap_arr = ["-Xms${jvm_min_heap_size}", "-Xmx${jvm_max_heap_size}"] 187 | if $disable_fips { 188 | $jvm_cmd_arr = $jvm_heap_arr + ['-Dcom.redhat.fips=false', $jvm_extra_args] 189 | } else { 190 | $jvm_cmd_arr = $jvm_heap_arr + [$jvm_extra_args] 191 | } 192 | $jvm_cmd = strip(join(flatten($jvm_cmd_arr), ' ')) 193 | 194 | if $facts['os']['family'] == 'FreeBSD' { 195 | $server_gem_paths = ['${jruby-puppet.gem-home}', "\"${server_puppetserver_vardir}/vendored-jruby-gems\"", sprintf('"%s"', regsubst($facts['ruby']['sitedir'], 'site_ruby', 'gems'))] # lint:ignore:single_quote_string_with_variables 196 | augeas { 'puppet::server::puppetserver::jvm': 197 | context => '/files/etc/rc.conf', 198 | changes => ["set puppetserver_java_opts '\"${jvm_cmd}\"'"], 199 | } 200 | } elsif $facts['os']['family'] == 'Debian' and !$puppet::params::aio_package { 201 | $server_gem_paths = ['${jruby-puppet.gem-home}', '/usr/lib/puppetserver/vendored-jruby-gems'] # lint:ignore:single_quote_string_with_variables 202 | } else { 203 | if $jvm_cli_args { 204 | $changes = [ 205 | "set JAVA_ARGS '\"${jvm_cmd}\"'", 206 | "set JAVA_BIN ${_java_bin}", 207 | "set JAVA_ARGS_CLI '\"${jvm_cli_args}\"'", 208 | ] 209 | } else { 210 | $changes = [ 211 | "set JAVA_ARGS '\"${jvm_cmd}\"'", 212 | "set JAVA_BIN ${_java_bin}", 213 | ] 214 | } 215 | augeas { 'puppet::server::puppetserver::jvm': 216 | lens => 'Shellvars.lns', 217 | incl => $config, 218 | context => "/files${config}", 219 | changes => $changes, 220 | } 221 | 222 | $bootstrap_paths = "${server_puppetserver_dir}/services.d/,/opt/puppetlabs/server/apps/puppetserver/config/services.d/" 223 | 224 | $server_gem_paths = ['${jruby-puppet.gem-home}', "\"${server_puppetserver_vardir}/vendored-jruby-gems\"", "\"/opt/puppetlabs/puppet/lib/ruby/vendor_gems\""] # lint:ignore:single_quote_string_with_variables 225 | 226 | augeas { 'puppet::server::puppetserver::bootstrap': 227 | lens => 'Shellvars.lns', 228 | incl => $config, 229 | context => "/files${config}", 230 | changes => "set BOOTSTRAP_CONFIG '\"${bootstrap_paths}\"'", 231 | } 232 | 233 | augeas { 'puppet::server::puppetserver::jruby_jar': 234 | lens => 'Shellvars.lns', 235 | incl => $config, 236 | context => "/files${config}", 237 | changes => 'rm JRUBY_JAR', 238 | } 239 | 240 | $ensure_max_open_files = $max_open_files ? { 241 | undef => 'absent', 242 | default => 'present', 243 | } 244 | if $facts['service_provider'] == 'systemd' { 245 | systemd::dropin_file { 'puppetserver.service-limits.conf': 246 | ensure => $ensure_max_open_files, 247 | filename => 'limits.conf', 248 | unit => 'puppetserver.service', 249 | content => "[Service]\nLimitNOFILE=${max_open_files}\n", 250 | } 251 | 252 | # https://github.com/puppetlabs/ezbake/pull/623 253 | systemd::dropin_file { 'puppetserver.service-privatetmp.conf': 254 | ensure => present, 255 | filename => 'privatetmp.conf', 256 | unit => 'puppetserver.service', 257 | content => "[Service]\nPrivateTmp=true\n", 258 | } 259 | } else { 260 | file_line { 'puppet::server::puppetserver::max_open_files': 261 | ensure => $ensure_max_open_files, 262 | path => $config, 263 | line => "ulimit -n ${max_open_files}", 264 | match => '^ulimit\ -n', 265 | } 266 | } 267 | } 268 | 269 | $servicesd = "${server_puppetserver_dir}/services.d" 270 | file { $servicesd: 271 | ensure => directory, 272 | } 273 | file { "${servicesd}/ca.cfg": 274 | ensure => file, 275 | content => template('puppet/server/puppetserver/services.d/ca.cfg.erb'), 276 | } 277 | 278 | file { "${server_puppetserver_dir}/conf.d/ca.conf": 279 | ensure => file, 280 | content => template('puppet/server/puppetserver/conf.d/ca.conf.erb'), 281 | } 282 | 283 | file { "${server_puppetserver_dir}/conf.d/puppetserver.conf": 284 | ensure => file, 285 | content => template('puppet/server/puppetserver/conf.d/puppetserver.conf.erb'), 286 | } 287 | 288 | $auth_template = pick($server_auth_template, 'puppet/server/puppetserver/conf.d/auth.conf.erb') 289 | file { "${server_puppetserver_dir}/conf.d/auth.conf": 290 | ensure => file, 291 | content => template($auth_template), 292 | } 293 | 294 | file { "${server_puppetserver_dir}/conf.d/webserver.conf": 295 | ensure => file, 296 | content => template('puppet/server/puppetserver/conf.d/webserver.conf.erb'), 297 | } 298 | 299 | file { "${server_puppetserver_dir}/conf.d/product.conf": 300 | ensure => file, 301 | content => template('puppet/server/puppetserver/conf.d/product.conf.erb'), 302 | } 303 | 304 | file { "${server_puppetserver_dir}/conf.d/metrics.conf": 305 | ensure => 'file', 306 | content => template('puppet/server/puppetserver/conf.d/metrics.conf.erb'), 307 | } 308 | } 309 | -------------------------------------------------------------------------------- /manifests/server/service.pp: -------------------------------------------------------------------------------- 1 | # Set up the puppet server as a service 2 | # 3 | # @param $enable Whether to enable the service or not 4 | # @param $service_name The service name to manage 5 | # 6 | # @api private 7 | class puppet::server::service ( 8 | Boolean $enable = true, 9 | String $service_name = 'puppetserver', 10 | ) { 11 | service { $service_name: 12 | ensure => $enable, 13 | enable => $enable, 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /metadata.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "theforeman-puppet", 3 | "version": "21.0.0", 4 | "author": "theforeman", 5 | "summary": "Puppet agent and server configuration", 6 | "license": "GPL-3.0+", 7 | "source": "https://github.com/theforeman/puppet-puppet", 8 | "project_page": "https://github.com/theforeman/puppet-puppet", 9 | "issues_url": "https://github.com/theforeman/puppet-puppet/issues", 10 | "description": "Module for installing the Puppet agent and Puppet server", 11 | "tags": [ 12 | "foreman", 13 | "puppet", 14 | "puppetserver", 15 | "puppet-server" 16 | ], 17 | "dependencies": [ 18 | { 19 | "name": "puppetlabs/concat", 20 | "version_requirement": ">= 4.1.0 < 10.0.0" 21 | }, 22 | { 23 | "name": "puppetlabs/stdlib", 24 | "version_requirement": ">= 9.0.0 < 10.0.0" 25 | }, 26 | { 27 | "name": "puppet/extlib", 28 | "version_requirement": ">= 3.0.0 < 8.0.0" 29 | }, 30 | { 31 | "name": "puppet/systemd", 32 | "version_requirement": ">= 2.9.0 < 9.0.0" 33 | } 34 | ], 35 | "requirements": [ 36 | { 37 | "name": "puppet", 38 | "version_requirement": ">= 7.0.0 < 9.0.0" 39 | } 40 | ], 41 | "operatingsystem_support": [ 42 | { 43 | "operatingsystem": "RedHat", 44 | "operatingsystemrelease": [ 45 | "8", 46 | "9" 47 | ] 48 | }, 49 | { 50 | "operatingsystem": "CentOS", 51 | "operatingsystemrelease": [ 52 | "8", 53 | "9" 54 | ] 55 | }, 56 | { 57 | "operatingsystem": "OracleLinux", 58 | "operatingsystemrelease": [ 59 | "9" 60 | ] 61 | }, 62 | { 63 | "operatingsystem": "AlmaLinux", 64 | "operatingsystemrelease": [ 65 | "8", 66 | "9" 67 | ] 68 | }, 69 | { 70 | "operatingsystem": "Rocky", 71 | "operatingsystemrelease": [ 72 | "9" 73 | ] 74 | }, 75 | { 76 | "operatingsystem": "Fedora", 77 | "operatingsystemrelease": [ 78 | "36" 79 | ] 80 | }, 81 | { 82 | "operatingsystem": "Debian", 83 | "operatingsystemrelease": [ 84 | "11", 85 | "12" 86 | ] 87 | }, 88 | { 89 | "operatingsystem": "Ubuntu", 90 | "operatingsystemrelease": [ 91 | "20.04", 92 | "22.04" 93 | ] 94 | }, 95 | { 96 | "operatingsystem": "FreeBSD", 97 | "operatingsystemrelease": [ 98 | "11", 99 | "12" 100 | ] 101 | }, 102 | { 103 | "operatingsystem": "DragonFly", 104 | "operatingsystemrelease": [ 105 | "4" 106 | ] 107 | }, 108 | { 109 | "operatingsystem": "Archlinux" 110 | }, 111 | { 112 | "operatingsystem": "SLES", 113 | "operatingsystemrelease": [ 114 | "12" 115 | ] 116 | }, 117 | { 118 | "operatingsystem": "windows", 119 | "operatingsystemrelease": [ 120 | "2012", 121 | "2012 R2" 122 | ] 123 | } 124 | ] 125 | } 126 | -------------------------------------------------------------------------------- /spec/acceptance/hieradata/common.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | puppet::server_foreman: false 3 | puppet::server_reports: 'store' 4 | puppet::server_external_nodes: '' 5 | # only for install test - don't think to use this in production! 6 | # https://docs.puppet.com/puppetserver/latest/tuning_guide.html 7 | puppet::server_jvm_max_heap_size: '768m' 8 | puppet::server_jvm_min_heap_size: '256m' 9 | -------------------------------------------------------------------------------- /spec/acceptance/puppet_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper_acceptance' 2 | 3 | describe 'Scenario: install puppet' do 4 | before(:context) do 5 | on default, 'puppet resource service puppet ensure=stopped enable=false' 6 | end 7 | 8 | it_behaves_like 'an idempotent resource' do 9 | let(:manifest) { 'include puppet' } 10 | end 11 | 12 | describe service('puppet') do 13 | it { is_expected.to be_running } 14 | it { is_expected.to be_enabled } 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /spec/acceptance/puppetserver_latest_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper_acceptance' 2 | 3 | describe 'Scenario: install puppetserver (latest):', unless: unsupported_puppetserver do 4 | before(:all) do 5 | if check_for_package(default, 'puppetserver') 6 | on default, 'puppet resource package puppetserver ensure=purged' 7 | on default, 'rm -rf /etc/sysconfig/puppetserver /etc/puppetlabs/puppetserver' 8 | on default, 'find /etc/puppetlabs/puppet/ssl/ -type f -delete' 9 | end 10 | 11 | # puppetserver won't start with lower than 2GB memory 12 | memoryfree_mb = fact('memoryfree_mb').to_i 13 | raise 'At least 2048MB free memory required' if memoryfree_mb < 256 14 | end 15 | 16 | context 'default options' do 17 | it_behaves_like 'an idempotent resource' do 18 | let(:manifest) do 19 | <<-EOS 20 | class { 'puppet': 21 | server => true, 22 | } 23 | EOS 24 | end 25 | end 26 | end 27 | 28 | if ENV['BEAKER_PUPPET_COLLECTION'] != 'puppet7' && fact('os.family') == 'RedHat' 29 | describe 'JRE version' do 30 | it { expect(package('java-17-openjdk-headless')).to be_installed } 31 | it { expect(package('java-11-openjdk-headless')).not_to be_installed } 32 | it { expect(file('/etc/sysconfig/puppetserver')).to be_file.and(have_attributes(content: include('JAVA_BIN=/usr/lib/jvm/jre-17/bin/java'))) } 33 | end 34 | end 35 | 36 | # This is broken on Ubuntu Focal 37 | # https://github.com/theforeman/puppet-puppet/issues/832 38 | describe 'server_max_open_files', unless: unsupported_puppetserver || fact('os.release.major') == '20.04' do 39 | it_behaves_like 'an idempotent resource' do 40 | let(:manifest) do 41 | <<-MANIFEST 42 | class { 'puppet': 43 | server => true, 44 | server_max_open_files => 32143, 45 | } 46 | MANIFEST 47 | end 48 | end 49 | 50 | # pgrep -f java.*puppetserver would be better. But i cannot get it to work. Shellwords.escape() seems to break something 51 | describe command("grep '^Max open files' /proc/`cat /var/run/puppetlabs/puppetserver/puppetserver.pid`/limits"), :sudo => true do 52 | its(:exit_status) { is_expected.to eq 0 } 53 | its(:stdout) { is_expected.to match %r{^Max open files\s+32143\s+32143\s+files\s*$} } 54 | end 55 | end 56 | end 57 | -------------------------------------------------------------------------------- /spec/acceptance/puppetserver_upgrade_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper_acceptance' 2 | 3 | unless unsupported_puppetserver || unsupported_puppetserver_upgrade 4 | describe 'Scenario: minor version upgrade' do 5 | before(:all) do 6 | if check_for_package(default, 'puppetserver') 7 | on default, 'puppet resource package puppetserver ensure=purged' 8 | on default, 'rm -rf /etc/sysconfig/puppetserver /etc/puppetlabs/puppetserver' 9 | on default, 'rm -rf /etc/puppetlabs/puppet/ssl' 10 | end 11 | 12 | # puppetserver won't start with low memory 13 | memoryfree_mb = fact('memoryfree_mb').to_i 14 | raise 'At least 256MB free memory required' if memoryfree_mb < 256 15 | end 16 | 17 | case ENV['BEAKER_PUPPET_COLLECTION'] 18 | when 'puppet8' 19 | from_version = '8.2.0' 20 | to_version = '8.5.0' 21 | when 'puppet7' 22 | from_version = '7.13.0' 23 | to_version = '7.16.0' 24 | else 25 | raise 'Unsupported Puppet collection' 26 | end 27 | 28 | case fact('os.family') 29 | when 'Debian' 30 | from_version_exact = "#{from_version}-1#{fact('os.distro.codename')}" 31 | to_version_exact = "#{to_version}-1#{fact('os.distro.codename')}" 32 | else 33 | from_version_exact = from_version 34 | to_version_exact = to_version 35 | end 36 | 37 | context "install #{from_version}" do 38 | it_behaves_like 'an idempotent resource' do 39 | let(:manifest) do 40 | <<-EOS 41 | class { 'puppet': 42 | server => true, 43 | server_version => '#{from_version_exact}', 44 | } 45 | EOS 46 | end 47 | end 48 | 49 | describe command('puppetserver --version') do 50 | its(:stdout) { is_expected.to match("puppetserver version: #{from_version}\n") } 51 | end 52 | 53 | describe service('puppetserver') do 54 | it { is_expected.to be_enabled } 55 | it { is_expected.to be_running } 56 | end 57 | 58 | describe port('8140') do 59 | it { is_expected.to be_listening } 60 | end 61 | end 62 | 63 | context "upgrade to #{to_version}" do 64 | it_behaves_like 'an idempotent resource' do 65 | let(:manifest) do 66 | <<-EOS 67 | class { 'puppet': 68 | server => true, 69 | server_version => '#{to_version_exact}', 70 | } 71 | EOS 72 | end 73 | end 74 | 75 | describe command('puppetserver --version') do 76 | its(:stdout) { is_expected.to match("puppetserver version: #{to_version}\n") } 77 | end 78 | 79 | describe service('puppetserver') do 80 | it { is_expected.to be_enabled } 81 | it { is_expected.to be_running } 82 | end 83 | 84 | describe port('8140') do 85 | it { is_expected.to be_listening } 86 | end 87 | end 88 | end 89 | end 90 | -------------------------------------------------------------------------------- /spec/classes/puppet_agent_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe 'puppet' do 4 | on_supported_os.each do |os, facts| 5 | context "on #{os}" do 6 | case facts[:os]['family'] 7 | when 'FreeBSD' 8 | puppet_major = facts[:puppetversion].to_i 9 | 10 | bindir = '/usr/local/bin' 11 | client_package = "puppet#{puppet_major}" 12 | confdir = '/usr/local/etc/puppet' 13 | package_provider = nil 14 | when 'windows' 15 | bindir = 'C:/ProgramData/PuppetLabs/puppet/bin' 16 | client_package = 'puppet-agent' 17 | confdir = 'C:/ProgramData/PuppetLabs/puppet/etc' 18 | package_provider = 'chocolatey' 19 | when 'Archlinux' 20 | bindir = '/usr/bin' 21 | client_package = 'puppet' 22 | confdir = '/etc/puppetlabs/puppet' 23 | package_provider = nil 24 | else 25 | bindir = '/opt/puppetlabs/bin' 26 | client_package = 'puppet-agent' 27 | confdir = '/etc/puppetlabs/puppet' 28 | package_provider = nil 29 | end 30 | 31 | let(:facts) do 32 | # Cron/systemd timers are based on the IP - make it consistent 33 | override_facts(facts, networking: {ip: '192.0.2.100'}) 34 | end 35 | 36 | let :params do 37 | { 38 | agent: true 39 | } 40 | end 41 | 42 | describe 'with no custom parameters' do 43 | # For windows we specify a package provider which doesn't compile 44 | if facts[:os]['family'] != 'windows' 45 | it { is_expected.to compile.with_all_deps } 46 | end 47 | 48 | # install 49 | it do 50 | is_expected.to contain_class('puppet::agent::install') 51 | .with_manage_packages(true) 52 | .with_package_name([client_package]) 53 | .with_package_version('present') 54 | .with_package_provider(package_provider) 55 | .with_package_source(nil) 56 | .that_notifies(['Class[puppet::agent::config]', 'Class[puppet::agent::service]']) 57 | end 58 | 59 | it do 60 | is_expected.to contain_package(client_package) 61 | .with_ensure('present') 62 | .with_provider(package_provider) 63 | .with_source(nil) 64 | .with_install_options(nil) 65 | end 66 | 67 | # config 68 | it { is_expected.to contain_class('puppet::agent::config').that_notifies('Class[puppet::agent::service]') } 69 | it { is_expected.to contain_file(confdir).with_ensure('directory') } 70 | it { is_expected.to contain_concat("#{confdir}/puppet.conf") } 71 | it { is_expected.to contain_concat__fragment('puppet.conf_agent').with_content(/^\[agent\]/) } 72 | it { is_expected.to contain_puppet__config__agent('report').with_value('true') } 73 | it { is_expected.not_to contain_puppet__config__agent('prerun_command') } 74 | it { is_expected.not_to contain_puppet__config__agent('postrun_command') } 75 | 76 | # service 77 | it { is_expected.to contain_class('puppet::agent::service') } 78 | 79 | it { is_expected.to contain_class('puppet::agent::service::daemon').with_enabled(true) } 80 | it do 81 | is_expected.to contain_service('puppet') 82 | .with_ensure('running') 83 | .with_name('puppet') 84 | .with_hasstatus('true') 85 | .with_enable('true') 86 | end 87 | 88 | it { is_expected.to contain_class('puppet::agent::service::cron').with_enabled(false) } 89 | if os =~ /\A(windows|archlinux)/ 90 | it { is_expected.not_to contain_cron('puppet') } 91 | else 92 | it { is_expected.to contain_cron('puppet').with_ensure('absent') } 93 | end 94 | 95 | it { is_expected.to contain_class('puppet::agent::service::systemd').with_enabled(false) } 96 | case os 97 | when /\A(debian|redhat|centos|scientific|fedora|ubuntu|sles|archlinux|oraclelinux|almalinux|rocky)-/ 98 | it do 99 | is_expected.to contain_service('puppet-run.timer') 100 | .with_ensure(false) 101 | .with_provider('systemd') 102 | .with_name('puppet-run.timer') 103 | .with_enable(false) 104 | end 105 | 106 | it { is_expected.to contain_file('/etc/systemd/system/puppet-run.timer').with_ensure(:absent) } 107 | it { is_expected.to contain_file('/etc/systemd/system/puppet-run.service').with_ensure(:absent) } 108 | else 109 | it { is_expected.not_to contain_service('puppet-run.timer') } 110 | it { is_expected.not_to contain_file('/etc/systemd/system/puppet-run.timer') } 111 | it { is_expected.not_to contain_file('/etc/systemd/system/puppet-run.service') } 112 | end 113 | end 114 | 115 | describe 'set prerun_command will be included in config' do 116 | let :params do 117 | super().merge(prerun_command: '/my/prerun') 118 | end 119 | 120 | it { is_expected.to contain_puppet__config__agent('prerun_command').with_value('/my/prerun') } 121 | end 122 | 123 | describe 'set postrun_command will be included in config' do 124 | let :params do 125 | super().merge(postrun_command: '/my/postrun') 126 | end 127 | 128 | it { is_expected.to contain_puppet__config__agent('postrun_command').with_value('/my/postrun') } 129 | end 130 | 131 | describe 'with additional settings' do 132 | let :params do 133 | super().merge(agent_additional_settings: { 'ignoreschedules' => true }) 134 | end 135 | 136 | it { is_expected.to contain_puppet__config__agent('ignoreschedules').with_value('true') } 137 | end 138 | 139 | context 'manage_packages' do 140 | describe 'when manage_packages => false' do 141 | let :params do 142 | super().merge(manage_packages: false) 143 | end 144 | 145 | it { is_expected.not_to contain_package(client_package) } 146 | end 147 | 148 | describe "when manage_packages => 'agent'" do 149 | let :params do 150 | super().merge(manage_packages: 'agent') 151 | end 152 | 153 | it { is_expected.to contain_package(client_package) } 154 | end 155 | 156 | describe "when manage_packages => 'server'" do 157 | let :params do 158 | super().merge(manage_packages: 'server') 159 | end 160 | 161 | it { is_expected.not_to contain_package(client_package) } 162 | end 163 | end 164 | 165 | context 'runmode' do 166 | describe 'when runmode => cron' do 167 | let :params do 168 | super().merge(runmode: 'cron') 169 | end 170 | 171 | case os 172 | when /\A(windows|archlinux)/ 173 | it { is_expected.to raise_error(Puppet::Error, /Runmode of cron not supported on #{facts[:kernel]} operating systems!/) } 174 | when /\A(debian|redhat|centos|scientific|fedora|ubuntu|sles|oraclelinux|almalinux|rocky)-/ 175 | it { is_expected.to compile.with_all_deps } 176 | it { is_expected.to contain_concat__fragment('puppet.conf_agent') } 177 | it { is_expected.to contain_class('puppet::agent::service::cron').with_enabled(true) } 178 | it { is_expected.to contain_class('puppet::agent::service::daemon').with_enabled(false) } 179 | it do 180 | is_expected.to contain_service('puppet') 181 | .with_ensure('stopped') 182 | .with_name('puppet') 183 | .with_hasstatus('true') 184 | .with_enable('false') 185 | end 186 | it { is_expected.to contain_class('puppet::agent::service::systemd').with_enabled(false) } 187 | it { is_expected.to contain_service('puppet-run.timer').with_ensure(false) } 188 | it do 189 | is_expected.to contain_cron('puppet') 190 | .with_command("#{bindir}/puppet agent --config #{confdir}/puppet.conf --onetime --no-daemonize") 191 | .with_user('root') 192 | .with_minute(%w[10 40]) 193 | .with_hour('*') 194 | end 195 | else 196 | it { is_expected.to compile.with_all_deps } 197 | it { is_expected.to contain_class('puppet::agent::service::cron').with_enabled(true) } 198 | it { is_expected.to contain_class('puppet::agent::service::daemon').with_enabled(false) } 199 | it { is_expected.to contain_class('puppet::agent::service::systemd').with_enabled(false) } 200 | it { is_expected.not_to contain_service('puppet-run.timer') } 201 | it do 202 | is_expected.to contain_cron('puppet') 203 | .with_command("#{bindir}/puppet agent --config #{confdir}/puppet.conf --onetime --no-daemonize") 204 | .with_user('root') 205 | .with_minute(%w[10 40]) 206 | .with_hour('*') 207 | end 208 | end 209 | end 210 | 211 | describe 'when runmode => cron with specified time' do 212 | let :params do 213 | super().merge(runmode: 'cron', 214 | run_hour: 22, 215 | run_minute: 01 216 | ) 217 | end 218 | 219 | case os 220 | when /\A(windows|archlinux)/ 221 | it { is_expected.to raise_error(Puppet::Error, /Runmode of cron not supported on #{facts[:kernel]} operating systems!/) } 222 | when /\A(debian|redhat|centos|scientific|fedora|ubuntu|sles|oraclelinux|almalinux|rocky)-/ 223 | it { is_expected.to contain_class('puppet::agent::service::cron').with_enabled(true) } 224 | it { is_expected.to contain_class('puppet::agent::service::daemon').with_enabled(false) } 225 | it do 226 | is_expected.to contain_service('puppet') 227 | .with_ensure('stopped') 228 | .with_name('puppet') 229 | .with_hasstatus('true') 230 | .with_enable('false') 231 | end 232 | it { is_expected.to contain_class('puppet::agent::service::systemd').with_enabled(false) } 233 | it { is_expected.to contain_service('puppet-run.timer').with_ensure(false) } 234 | it do 235 | is_expected.to contain_cron('puppet') 236 | .with_command("#{bindir}/puppet agent --config #{confdir}/puppet.conf --onetime --no-daemonize") 237 | .with_user('root') 238 | .with_minute('1') 239 | .with_hour('22') 240 | end 241 | else 242 | it { is_expected.to compile.with_all_deps } 243 | it { is_expected.to contain_class('puppet::agent::service::cron').with_enabled(true) } 244 | it { is_expected.to contain_class('puppet::agent::service::daemon').with_enabled(false) } 245 | it { is_expected.to contain_class('puppet::agent::service::systemd').with_enabled(false) } 246 | it { is_expected.not_to contain_service('puppet-run.timer') } 247 | it do 248 | is_expected.to contain_cron('puppet') 249 | .with_command("#{bindir}/puppet agent --config #{confdir}/puppet.conf --onetime --no-daemonize") 250 | .with_user('root') 251 | .with_minute('1') 252 | .with_hour('22') 253 | end 254 | end 255 | end 256 | 257 | describe 'when runmode => systemd.timer' do 258 | let :params do 259 | super().merge(runmode: 'systemd.timer') 260 | end 261 | 262 | case os 263 | when /\A(debian|redhat|centos|scientific|fedora|ubuntu|sles|archlinux|oraclelinux|almalinux|rocky)-/ 264 | it { is_expected.to compile.with_all_deps } 265 | it { is_expected.to contain_class('puppet::agent::service::daemon').with_enabled(false) } 266 | it { is_expected.to contain_class('puppet::agent::service::cron').with_enabled(false) } 267 | it { is_expected.to contain_class('puppet::agent::service::systemd').with_enabled(true) } 268 | it { is_expected.to contain_service('puppet-run.timer').with_ensure(true) } 269 | 270 | it do 271 | is_expected.to contain_file('/etc/systemd/system/puppet-run.timer') 272 | .with_content(/.*OnCalendar\=\*-\*-\* \*\:10,40:00.*/) 273 | end 274 | 275 | it do 276 | is_expected.to contain_file('/etc/systemd/system/puppet-run.timer') 277 | .with_content(/^RandomizedDelaySec\=0$/) 278 | end 279 | 280 | it do 281 | is_expected.to contain_file('/etc/systemd/system/puppet-run.service') 282 | .with_content(%r{^ExecStart=#{bindir}/puppet agent --config #{confdir}/puppet.conf --onetime --no-daemonize --detailed-exitcode --no-usecacheonfailure$}) 283 | end 284 | 285 | it do 286 | is_expected.to contain_service('puppet-run.timer') 287 | .with_provider('systemd') 288 | .with_ensure(true) 289 | .with_name('puppet-run.timer') 290 | .with_enable(true) 291 | end 292 | else 293 | it { is_expected.to raise_error(Puppet::Error, /Runmode of systemd.timer not supported on #{facts[:kernel]} operating systems!/) } 294 | end 295 | end 296 | 297 | describe 'when runmode => systemd.timer with configured time' do 298 | let :params do 299 | super().merge(runmode: 'systemd.timer', 300 | run_hour: 22, 301 | run_minute: 01 302 | ) 303 | end 304 | 305 | case os 306 | when /\A(debian|redhat|centos|scientific|fedora|ubuntu|sles|archlinux|oraclelinux|almalinux|rocky)-/ 307 | it { is_expected.to compile.with_all_deps } 308 | it { is_expected.to contain_class('puppet::agent::service::daemon').with_enabled(false) } 309 | it { is_expected.to contain_class('puppet::agent::service::cron').with_enabled(false) } 310 | it { is_expected.to contain_class('puppet::agent::service::systemd').with_enabled(true) } 311 | it { is_expected.to contain_service('puppet-run.timer').with_ensure(true) } 312 | 313 | it do 314 | is_expected.to contain_file('/etc/systemd/system/puppet-run.timer') 315 | .with_content(/.*OnCalendar\=\*-\*-\* 22:1:00.*/) 316 | end 317 | 318 | it do 319 | is_expected.to contain_file('/etc/systemd/system/puppet-run.timer') 320 | .with_content(/^RandomizedDelaySec\=0$/) 321 | end 322 | 323 | it do 324 | is_expected.to contain_file('/etc/systemd/system/puppet-run.service') 325 | .with_content(%r{^ExecStart=#{bindir}/puppet agent --config #{confdir}/puppet.conf --onetime --no-daemonize --detailed-exitcode --no-usecacheonfailure$}) 326 | end 327 | 328 | it do 329 | is_expected.to contain_service('puppet-run.timer') 330 | .with_provider('systemd') 331 | .with_ensure(true) 332 | .with_name('puppet-run.timer') 333 | .with_enable(true) 334 | end 335 | else 336 | it { is_expected.to raise_error(Puppet::Error, /Runmode of systemd.timer not supported on #{facts[:kernel]} operating systems!/) } 337 | end 338 | end 339 | 340 | describe 'when runmode => none' do 341 | let :params do 342 | super().merge(runmode: 'none') 343 | end 344 | 345 | # For windows we specify a package provider which doesn't compile 346 | if facts[:os]['family'] != 'windows' 347 | it { is_expected.to compile.with_all_deps } 348 | end 349 | it { is_expected.to contain_class('puppet::agent::service::daemon').with_enabled(false) } 350 | it { is_expected.to contain_class('puppet::agent::service::cron').with_enabled(false) } 351 | it { is_expected.to contain_class('puppet::agent::service::systemd').with_enabled(false) } 352 | 353 | case os 354 | when /\A(debian|redhat|centos|scientific|fedora|ubuntu|sles|archlinux|oraclelinux|almalinux|rocky)-/ 355 | it { is_expected.to contain_service('puppet-run.timer').with_ensure(false) } 356 | else 357 | it { is_expected.not_to contain_service('puppet-run.timer') } 358 | end 359 | end 360 | 361 | describe 'when runmode => unmanaged' do 362 | let :params do 363 | super().merge(runmode: 'unmanaged') 364 | end 365 | 366 | # For windows we specify a package provider which doesn't compile 367 | if facts[:os]['family'] != 'windows' 368 | it { is_expected.to compile.with_all_deps } 369 | end 370 | it { is_expected.to contain_class('puppet::agent::service::daemon').with_enabled(false) } 371 | it { is_expected.to contain_class('puppet::agent::service::cron').with_enabled(false) } 372 | it { is_expected.to contain_class('puppet::agent::service::systemd').with_enabled(false) } 373 | it { is_expected.not_to contain_cron('puppet') } 374 | it { is_expected.not_to contain_service('puppet') } 375 | it { is_expected.not_to contain_service('puppet-run.timer') } 376 | end 377 | end 378 | 379 | describe 'when unavailable_runmodes => ["cron"]' do 380 | let :params do 381 | super().merge(unavailable_runmodes: ['cron']) 382 | end 383 | 384 | it { is_expected.not_to contain_cron('puppet') } 385 | end 386 | 387 | describe 'with custom service_name' do 388 | let :params do 389 | super().merge(service_name: 'pe-puppet') 390 | end 391 | 392 | it { is_expected.to contain_service('puppet').with_name('pe-puppet') } 393 | end 394 | 395 | context 'with report => false' do 396 | let :params do 397 | super().merge(report: false) 398 | end 399 | 400 | it { is_expected.to contain_puppet__config__agent('report').with_value('false') } 401 | end 402 | end 403 | end 404 | end 405 | -------------------------------------------------------------------------------- /spec/classes/puppet_config_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe 'puppet' do 4 | on_supported_os.each do |os, os_facts| 5 | context "on #{os}" do 6 | case os_facts[:os]['family'] 7 | when 'FreeBSD' 8 | dir_owner = 'root' 9 | dir_group = nil 10 | confdir = '/usr/local/etc/puppet' 11 | logdir = '/var/log/puppet' 12 | rundir = '/var/run/puppet' 13 | ssldir = '/var/puppet/ssl' 14 | vardir = '/var/puppet' 15 | when 'windows' 16 | dir_owner = nil 17 | dir_group = nil 18 | confdir = 'C:/ProgramData/PuppetLabs/puppet/etc' 19 | logdir = 'C:/ProgramData/PuppetLabs/puppet/var/log' 20 | rundir = 'C:/ProgramData/PuppetLabs/puppet/var/run' 21 | ssldir = 'C:/ProgramData/PuppetLabs/puppet/etc/ssl' 22 | vardir = 'C:/ProgramData/PuppetLabs/puppet/var' 23 | when 'Archlinux' 24 | dir_owner = 'root' 25 | dir_group = nil 26 | confdir = '/etc/puppetlabs/puppet' 27 | logdir = '/var/log/puppetlabs/puppet' 28 | rundir = '/var/run/puppetlabs' 29 | ssldir = '/etc/puppetlabs/puppet/ssl' 30 | vardir = '/opt/puppetlabs/puppet/cache' 31 | else 32 | dir_owner = 'root' 33 | dir_group = nil 34 | confdir = '/etc/puppetlabs/puppet' 35 | logdir = '/var/log/puppetlabs/puppet' 36 | rundir = '/var/run/puppetlabs' 37 | ssldir = '/etc/puppetlabs/puppet/ssl' 38 | vardir = '/opt/puppetlabs/puppet/cache' 39 | end 40 | 41 | let :facts do 42 | override_facts(os_facts, networking: {domain: 'example.org'}) 43 | end 44 | 45 | let :params do 46 | {} 47 | end 48 | 49 | describe 'with default parameters' do 50 | it { is_expected.to contain_file(confdir).with_owner(dir_owner).with_group(dir_group) } 51 | it { is_expected.not_to contain_puppet__config__main('default_manifest') } 52 | it { is_expected.not_to contain_file('/etc/puppet/manifests/default_manifest.pp') } 53 | it { is_expected.not_to contain_puppet__config__main('reports') } 54 | it { is_expected.to contain_puppet__config__main('vardir').with_value(vardir) } 55 | it { is_expected.to contain_puppet__config__main('logdir').with_value(logdir) } 56 | it { is_expected.to contain_puppet__config__main('rundir').with_value(rundir) } 57 | it { is_expected.to contain_puppet__config__main('ssldir').with_value(ssldir) } 58 | it { is_expected.to contain_puppet__config__main('privatekeydir').with_value('$ssldir/private_keys { group = service }') } 59 | it { is_expected.to contain_puppet__config__main('hostprivkey').with_value('$privatekeydir/$certname.pem { mode = 640 }') } 60 | it { is_expected.to contain_puppet__config__main('show_diff').with_value('false') } 61 | it { is_expected.to contain_puppet__config__main('server').with_value(facts[:networking]['fqdn']) } 62 | end 63 | 64 | describe "when dns_alt_names => ['foo','bar']" do 65 | let :params do 66 | super().merge(dns_alt_names: %w[foo bar]) 67 | end 68 | 69 | it { is_expected.to contain_puppet__config__main('dns_alt_names').with_value(%w[foo bar]) } 70 | end 71 | 72 | describe "when syslogfacility => 'local6'" do 73 | let :params do 74 | super().merge(syslogfacility: 'local6') 75 | end 76 | 77 | it { is_expected.to contain_puppet__config__main('syslogfacility').with_value('local6') } 78 | end 79 | 80 | describe "when module_repository => 'https://myforgeapi.example.com'" do 81 | let :params do 82 | super().merge(module_repository: 'https://myforgeapi.example.com') 83 | end 84 | 85 | it { is_expected.to contain_puppet__config__main('module_repository').with_value('https://myforgeapi.example.com') } 86 | end 87 | 88 | describe 'when use_srv_records => true' do 89 | let :params do 90 | super().merge(use_srv_records: true) 91 | end 92 | 93 | context 'domain fact is defined' do 94 | it { is_expected.to contain_puppet__config__main('use_srv_records').with_value('true') } 95 | it { is_expected.to contain_puppet__config__main('srv_domain').with_value('example.org') } 96 | it { is_expected.to contain_puppet__config__main('pluginsource').with_value('puppet:///plugins') } 97 | it { is_expected.to contain_puppet__config__main('pluginfactsource').with_value('puppet:///pluginfacts') } 98 | it { is_expected.not_to contain_puppet__config__main('server') } 99 | end 100 | 101 | context 'domain fact is unset' do 102 | let(:facts) { override_facts(super(), networking: {domain: nil}) } 103 | 104 | it { is_expected.to raise_error(Puppet::Error, /domain fact found to be undefined and \$srv_domain is undefined/) } 105 | end 106 | 107 | context 'is overriden via param' do 108 | let :params do 109 | super().merge(srv_domain: 'special.example.com') 110 | end 111 | 112 | it { is_expected.to contain_puppet__config__main('use_srv_records').with_value(true) } 113 | it { is_expected.to contain_puppet__config__main('srv_domain').with_value('special.example.com') } 114 | end 115 | end 116 | 117 | describe 'client_certname' do 118 | let(:node) { 'client.example.com' } 119 | 120 | context 'with client_certname => trusted certname' do 121 | it { is_expected.to contain_puppet__config__main('certname').with_value('client.example.com') } 122 | end 123 | 124 | context 'with client_certname => "foobar"' do 125 | let :params do 126 | super().merge(client_certname: 'foobar') 127 | end 128 | 129 | it { is_expected.to contain_puppet__config__main('certname').with_value('foobar') } 130 | end 131 | 132 | context 'with client_certname => false' do 133 | let :params do 134 | super().merge(client_certname: false) 135 | end 136 | 137 | it { is_expected.not_to contain_puppet__config__main('certname') } 138 | end 139 | end 140 | 141 | context 'agent_server_hostname' do 142 | describe "when agent_server_hostname => 'myserver.example.com'" do 143 | let :params do 144 | super().merge(agent_server_hostname: 'myserver.example.com') 145 | end 146 | 147 | it { is_expected.to contain_puppet__config__main('server').with_value('myserver.example.com') } 148 | end 149 | 150 | # puppetmaster is provided via the Foreman ENC as a global variable 151 | context 'with global puppetmaster' do 152 | let(:facts) { super().merge(puppetmaster: 'global.example.com') } 153 | 154 | describe 'it overrides fqdn' do 155 | it { is_expected.to contain_puppet__config__main('server').with_value('global.example.com') } 156 | end 157 | 158 | describe 'the agent_server_hostname parameter overrides global puppetmaster' do 159 | let(:params) { super().merge(agent_server_hostname: 'myserver.example.com') } 160 | 161 | it { is_expected.to contain_puppet__config__main('server').with_value('myserver.example.com') } 162 | end 163 | end 164 | end 165 | 166 | describe 'with additional settings' do 167 | let :params do 168 | super().merge(additional_settings: { disable_warnings: 'deprecations' }) 169 | end 170 | 171 | it { is_expected.to contain_puppet__config__main('disable_warnings').with_value('deprecations') } 172 | end 173 | end 174 | end 175 | end 176 | -------------------------------------------------------------------------------- /spec/classes/puppet_init_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe 'puppet' do 4 | on_supported_os.each do |os, facts| 5 | context "on #{os}" do 6 | case facts[:os]['family'] 7 | when 'FreeBSD' 8 | puppet_major = facts[:puppetversion].to_i 9 | 10 | puppet_concat = '/usr/local/etc/puppet/puppet.conf' 11 | puppet_directory = '/usr/local/etc/puppet' 12 | puppet_package = "puppet#{puppet_major}" 13 | puppetconf_mode = '0644' 14 | when 'windows' 15 | puppet_concat = 'C:/ProgramData/PuppetLabs/puppet/etc/puppet.conf' 16 | puppet_directory = 'C:/ProgramData/PuppetLabs/puppet/etc' 17 | puppet_package = 'puppet-agent' 18 | puppetconf_mode = '0674' 19 | when 'Archlinux' 20 | puppet_concat = '/etc/puppetlabs/puppet/puppet.conf' 21 | puppet_directory = '/etc/puppetlabs/puppet' 22 | puppet_package = 'puppet' 23 | puppetconf_mode = '0644' 24 | else 25 | puppet_concat = '/etc/puppetlabs/puppet/puppet.conf' 26 | puppet_directory = '/etc/puppetlabs/puppet' 27 | puppet_package = 'puppet-agent' 28 | puppetconf_mode = '0644' 29 | end 30 | 31 | let :facts do 32 | facts 33 | end 34 | 35 | describe 'with no custom parameters' do 36 | it { is_expected.to compile.with_all_deps unless facts[:os]['family'] == 'windows' } 37 | it { should contain_class('puppet::agent') } 38 | it { should contain_class('puppet::config') } 39 | it { should_not contain_class('puppet::server') } 40 | it { should contain_file(puppet_directory).with_ensure('directory') } 41 | it { should contain_concat(puppet_concat).with_mode(puppetconf_mode) } 42 | it { should contain_package(puppet_package) 43 | .with_ensure('present') 44 | .with_install_options(nil) 45 | } 46 | end 47 | 48 | describe 'with server => true', :unless => unsupported_puppetserver_osfamily(facts[:os]['family']) do 49 | let :params do { 50 | :server => true, 51 | } end 52 | 53 | it { is_expected.to compile.with_all_deps } 54 | it { should contain_class('puppet::server') } 55 | it { should contain_class('puppet::agent::service').that_requires('Class[puppet::server]') } 56 | end 57 | 58 | describe 'with empty ca_server' do 59 | let :params do { 60 | :ca_server => '', 61 | } end 62 | 63 | it { should_not contain_puppet__config__main('ca_server') } 64 | end 65 | 66 | describe 'with ca_server' do 67 | let :params do { 68 | :ca_server => 'ca.example.org', 69 | } end 70 | 71 | it { should contain_puppet__config__main('ca_server').with_value('ca.example.org') } 72 | end 73 | 74 | describe 'with undef ca_port' do 75 | let :params do { 76 | :ca_port => :undef, 77 | } end 78 | 79 | it { should_not contain_puppet__config__main('ca_port') } 80 | end 81 | 82 | describe 'with ca_port' do 83 | let :params do { 84 | :ca_port => 8140, 85 | } end 86 | 87 | it { should contain_puppet__config__main('ca_port').with_value(8140) } 88 | end 89 | 90 | describe 'with undef certificate_revocation' do 91 | let :params do { 92 | :certificate_revocation => :undef, 93 | } end 94 | 95 | it { should_not contain_puppet__config__main('certificate_revocation') } 96 | end 97 | 98 | describe 'with certificate_revocation' do 99 | let :params do { 100 | :certificate_revocation => 'leaf', 101 | } end 102 | 103 | it { should contain_puppet__config__main('certificate_revocation').with_value('leaf') } 104 | end 105 | 106 | describe 'with puppetconf_mode' do 107 | let :params do { 108 | :puppetconf_mode => '0640', 109 | } end 110 | 111 | it { should contain_concat(puppet_concat).with_mode('0640') } 112 | end 113 | 114 | # compilation is broken due to paths 115 | context 'on non-windows', unless: facts[:os]['family'] == 'windows' do 116 | describe 'with package_source => Httpurl' do 117 | let :params do { 118 | :package_source => 'https://example.com:123/test' 119 | } end 120 | 121 | it { is_expected.to compile } 122 | end 123 | 124 | describe 'with package_source => Unixpath' do 125 | let :params do { 126 | :package_source => '/test/folder/path/source.rpm' 127 | } end 128 | 129 | it { is_expected.to compile } 130 | end 131 | 132 | describe 'with package_source => Windowspath' do 133 | let :params do { 134 | :package_source => 'C:\test\folder\path\source.exe' 135 | } end 136 | 137 | it { is_expected.to compile } 138 | end 139 | 140 | describe 'with package_source => foo' do 141 | let :params do { 142 | :package_source => 'foo' 143 | } end 144 | 145 | it { is_expected.not_to compile } 146 | end 147 | end 148 | end 149 | end 150 | end 151 | -------------------------------------------------------------------------------- /spec/classes/puppet_server_puppetdb_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe 'puppet::server::puppetdb' do 4 | on_supported_os.each do |os, os_facts| 5 | context "on #{os}", unless: unsupported_puppetserver_osfamily(os_facts[:os]['family']) do 6 | let(:facts) { os_facts } 7 | let(:params) { {server: 'mypuppetdb.example.com'} } 8 | let(:pre_condition) do 9 | <<-PUPPET 10 | class { 'puppet': 11 | server => true, 12 | server_reports => 'puppetdb,foreman', 13 | server_storeconfigs => true, 14 | } 15 | PUPPET 16 | end 17 | 18 | it { is_expected.to compile.with_all_deps } 19 | it { is_expected.to contain_puppet__config__server('storeconfigs').with_value(true) } 20 | it 'configures PuppetDB' do 21 | is_expected.to contain_class('puppetdb::master::config') 22 | .with_puppetdb_server('mypuppetdb.example.com') 23 | .with_puppetdb_port(8081) 24 | .with_puppetdb_soft_write_failure(false) 25 | .with_manage_storeconfigs(false) 26 | .with_restart_puppet(false) 27 | end 28 | end 29 | end 30 | end 31 | -------------------------------------------------------------------------------- /spec/classes/puppet_server_puppetserver_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | require 'hocon' 3 | 4 | describe 'puppet' do 5 | on_supported_os.each do |os, facts| 6 | next if unsupported_puppetserver_osfamily(facts[:os]['family']) 7 | context "on #{os}" do 8 | let(:facts) do 9 | facts 10 | end 11 | let(:java_bin) { %r{^set JAVA_BIN /usr/(lib/jvm/jre-1[17]/)?bin/java$} } 12 | let(:auth_conf) { '/etc/custom/puppetserver/conf.d/auth.conf' } 13 | let(:puppetserver_conf) { '/etc/custom/puppetserver/conf.d/puppetserver.conf' } 14 | 15 | let(:params) do 16 | { 17 | server: true, 18 | # We set these values because they're calculated 19 | server_jvm_config: '/etc/default/puppetserver', 20 | server_jvm_min_heap_size: '2G', 21 | server_jvm_max_heap_size: '2G', 22 | server_jvm_extra_args: '', 23 | server_max_active_instances: 2, 24 | server_puppetserver_dir: '/etc/custom/puppetserver', 25 | } 26 | end 27 | 28 | let(:server_vardir) do 29 | if ['FreeBSD', 'DragonFly'].include?(facts[:os]['name']) 30 | '/var/puppet/server/data/puppetserver' 31 | else 32 | '/opt/puppetlabs/server/data/puppetserver' 33 | end 34 | end 35 | 36 | describe 'with default parameters' do 37 | it { should contain_file('/etc/custom/puppetserver/services.d').with_ensure('directory') } 38 | it { 39 | should contain_file('/etc/custom/puppetserver/services.d/ca.cfg') 40 | .with_content(%r{^puppetlabs.services.ca.certificate-authority-service/certificate-authority-service}) 41 | .with_content(%r{^#puppetlabs.services.ca.certificate-authority-disabled-service/certificate-authority-disabled-service}) 42 | .with_content(%r{^puppetlabs.trapperkeeper.services.watcher.filesystem-watch-service/filesystem-watch-service}) 43 | } 44 | if facts[:os]['family'] == 'FreeBSD' 45 | it { 46 | should contain_augeas('puppet::server::puppetserver::jvm') 47 | .with_changes(['set puppetserver_java_opts \'"-Xms2G -Xmx2G"\'']) 48 | .with_context('/files/etc/rc.conf') 49 | } 50 | else 51 | it { 52 | should contain_augeas('puppet::server::puppetserver::bootstrap') 53 | .with_changes('set BOOTSTRAP_CONFIG \'"/etc/custom/puppetserver/services.d/,/opt/puppetlabs/server/apps/puppetserver/config/services.d/"\'') 54 | .with_context('/files/etc/default/puppetserver') 55 | .with_incl('/etc/default/puppetserver') 56 | .with_lens('Shellvars.lns') 57 | } 58 | if facts[:os]['family'] == 'RedHat' 59 | it { 60 | should contain_augeas('puppet::server::puppetserver::jvm') 61 | .with_changes(['set JAVA_ARGS \'"-Xms2G -Xmx2G -Dcom.redhat.fips=false"\'', java_bin]) 62 | .with_context('/files/etc/default/puppetserver') 63 | .with_incl('/etc/default/puppetserver') 64 | .with_lens('Shellvars.lns') 65 | } 66 | else 67 | it { 68 | should contain_augeas('puppet::server::puppetserver::jvm') 69 | .with_changes(['set JAVA_ARGS \'"-Xms2G -Xmx2G"\'', java_bin]) 70 | .with_context('/files/etc/default/puppetserver') 71 | .with_incl('/etc/default/puppetserver') 72 | .with_lens('Shellvars.lns') 73 | } 74 | end 75 | it do 76 | should contain_augeas('puppet::server::puppetserver::jruby_jar') 77 | .with_changes(['rm JRUBY_JAR']) 78 | .with_context('/files/etc/default/puppetserver') 79 | .with_incl('/etc/default/puppetserver') 80 | .with_lens('Shellvars.lns') 81 | end 82 | end 83 | it { should contain_file('/etc/custom/puppetserver/conf.d/ca.conf') 84 | .with_ensure('file') 85 | .with_content(/^( *)allow-subject-alt-names: false$/) 86 | .with_content(/^( *)allow-authorization-extensions: false$/) 87 | .with_content(/^( *)enable-infra-crl: false$/) 88 | } 89 | it { 90 | should contain_file(puppetserver_conf) 91 | .without_content(/^# Settings related to the puppet-admin HTTP API$/) 92 | .without_content(/^puppet-admin: \{$/) 93 | .without_content(/^\s+client-whitelist: \[$/) 94 | .without_content(/^\s+"localhost"\,$/) 95 | .without_content(/^\s+"puppetserver123.example.com"\,$/) 96 | .without_content(/^\s+"code-id-command"\,$/) 97 | .without_content(/^\s+"code-content-command"\,$/) 98 | .with_content(/^ max-queued-requests: 0\n/) 99 | .with_content(/^ max-retry-delay: 1800\n/) 100 | } 101 | it { 102 | should contain_file('/etc/custom/puppetserver/conf.d/webserver.conf') 103 | .with_content(/ssl-host:\s0\.0\.0\.0/) 104 | .with_content(/ssl-port:\s8140/) 105 | .without_content(/ host:\s/) 106 | .without_content(/ port:\s8139/) 107 | .without_content(/selector-threads:/) 108 | .without_content(/acceptor-threads:/) 109 | .without_content(/ssl-selector-threads:/) 110 | .without_content(/ssl-acceptor-threads:/) 111 | .without_content(/max-threads:/) 112 | } 113 | it { 114 | should contain_file(auth_conf) 115 | .with_content(/allow-header-cert-info: false/) 116 | .with_content(%r{^\s+path: "/puppet-ca/v1/certificate_status"}) 117 | .with_content(/^\s+name: "puppetlabs cert status"/) 118 | .with_content(%r{^\s+path: "/puppet-ca/v1/certificate_statuses"}) 119 | .with_content(/^\s+name: "puppetlabs cert statuses"/) 120 | .with_content(%r{^\s+path: "/puppet-admin-api/v1/environment-cache"}) 121 | .with_content(/^\s+name: "environment-cache"/) 122 | .with_content(%r{^\s+path: "/puppet-admin-api/v1/jruby-pool"}) 123 | .with_content(/^\s+name: "jruby-pool"/) 124 | .with_content(%r{^(\ *)path: "/puppet/v3/tasks"$}) 125 | .with_content(%r{^(\ *)path: "\^/puppet/v3/facts/(.*)$}) 126 | .with_content(/^( *)pp_cli_auth: "true"$/) 127 | .without_content(%r{^(\ *)name: "Allow nodes to delete their own certificates",$}) 128 | } 129 | end 130 | 131 | describe 'server_puppetserver_vardir' do 132 | context 'with default parameters' do 133 | it { should contain_file(puppetserver_conf).with_content(%r{^ server-var-dir: #{server_vardir}$}) } 134 | end 135 | 136 | context 'with custom server_puppetserver_vardir' do 137 | let(:params) { super().merge(server_puppetserver_vardir: '/opt/custom/puppetserver') } 138 | it { should contain_file(puppetserver_conf).with_content(%r{^ server-var-dir: /opt/custom/puppetserver$}) } 139 | end 140 | end 141 | 142 | describe 'environment-class-cache-enabled' do 143 | context 'with default parameters' do 144 | it { should contain_file(puppetserver_conf).with_content(/^ environment-class-cache-enabled: false$/) } 145 | end 146 | 147 | context 'when environment-class-cache-enabled = true' do 148 | let(:params) { super().merge(server_environment_class_cache_enabled: true) } 149 | it { should contain_file(puppetserver_conf).with_content(/^ environment-class-cache-enabled: true$/) } 150 | end 151 | end 152 | 153 | describe 'environment-vars' do 154 | context 'with default parameters' do 155 | it { should contain_file(puppetserver_conf).with_content(/^ environment-vars: \{\s*\}$/) } 156 | end 157 | context 'with {"foo" => "bar"}' do 158 | let(:params) { super().merge(server_environment_vars: { 'foo' => 'bar' }) } 159 | it { should contain_file(puppetserver_conf).with_content(/^ environment-vars: \{\s*"foo" : bar\s*\}$/) } 160 | end 161 | end 162 | 163 | describe 'server_max_requests_per_instance' do 164 | context 'with default parameters' do 165 | it { should contain_file(puppetserver_conf).with_content(/^ max-requests-per-instance: 0$/) } 166 | end 167 | 168 | context 'custom server_max_requests_per_instance' do 169 | let(:params) { super().merge(server_max_requests_per_instance: 123_456) } 170 | it { should contain_file(puppetserver_conf).with_content(/^ max-requests-per-instance: 123456$/) } 171 | end 172 | end 173 | 174 | describe 'server_max_queued_requests' do 175 | context 'with custom server_max_queued_requests' do 176 | let(:params) { super().merge(server_max_queued_requests: 100) } 177 | it { should contain_file(puppetserver_conf).with_content(/^ max-queued-requests: 100\n/) } 178 | end 179 | end 180 | 181 | describe 'server_max_retry_delay' do 182 | context 'with custom server_max_retry_delay' do 183 | let(:params) { super().merge(server_max_retry_delay: 100) } 184 | it { should contain_file(puppetserver_conf).with_content(/^ max-retry-delay: 100\n/) } 185 | end 186 | end 187 | 188 | describe 'server_multithreaded' do 189 | context 'with default parameters' do 190 | it { should contain_file(puppetserver_conf).with_content(/^ multithreaded: false\n/) } 191 | end 192 | context 'with custom server_multithreaded' do 193 | let(:params) { super().merge(server_multithreaded: true) } 194 | it { should contain_file(puppetserver_conf).with_content(/^ multithreaded: true\n/) } 195 | end 196 | end 197 | 198 | describe 'ca.cfg' do 199 | context 'when server_ca => false' do 200 | let(:params) { super().merge(server_ca: false) } 201 | it { 202 | should contain_file('/etc/custom/puppetserver/services.d/ca.cfg') 203 | .with_content(%r{^#puppetlabs.services.ca.certificate-authority-service/certificate-authority-service}) 204 | .with_content(%r{^puppetlabs.services.ca.certificate-authority-disabled-service/certificate-authority-disabled-service}) 205 | .with_content(%r{^puppetlabs.trapperkeeper.services.watcher.filesystem-watch-service/filesystem-watch-service}) 206 | } 207 | end 208 | end 209 | 210 | describe 'product.conf' do 211 | context 'with default parameters' do 212 | it { 213 | should contain_file('/etc/custom/puppetserver/conf.d/product.conf') 214 | .with_content(/^\s+check-for-updates: true/) 215 | } 216 | end 217 | 218 | context 'with server_check_for_updates => false' do 219 | let(:params) { super().merge(server_check_for_updates: false) } 220 | it { 221 | should contain_file('/etc/custom/puppetserver/conf.d/product.conf') 222 | .with_content(/^\s+check-for-updates: false/) 223 | } 224 | end 225 | end 226 | 227 | describe 'server_metrics' do 228 | context 'when server_metrics => true' do 229 | let(:params) do 230 | super().merge( 231 | server_puppetserver_metrics: true, 232 | server_metrics_graphite_enable: true, 233 | server_metrics_graphite_host: 'graphitehost.example.com', 234 | server_metrics_graphite_port: 2003, 235 | server_metrics_server_id: 'puppetserver.example.com', 236 | server_metrics_graphite_interval: 5, 237 | server_metrics_allowed: ['single.element.array'], 238 | ) 239 | end 240 | 241 | it { 242 | should contain_file(puppetserver_conf) 243 | .with_content(/^ # Whether to enable http-client metrics; defaults to 'true'.\n metrics-enabled: true$(.*)/) 244 | .with_content(/^profiler: \{\n # enable or disable profiling for the Ruby code;\n enabled: true/) 245 | } 246 | it { 247 | should contain_file('/etc/custom/puppetserver/conf.d/metrics.conf') 248 | .with_content(/^( *)metrics-allowed: \[\n( *)"single.element.array",\n( *)\]/) 249 | .with_content(/^( *)server-id: "puppetserver.example.com"/) 250 | .with_content(/^( *)jmx: \{\n( *)enabled: true/) 251 | .with_content(/^( *)graphite: \{\n( *)enabled: true/) 252 | .with_content(/^( *)host: "graphitehost.example.com"/) 253 | .with_content(/^( *)port: 2003/) 254 | .with_content(/^( *)update-interval-seconds: 5/) 255 | } 256 | end 257 | 258 | context 'when server_metrics => false' do 259 | let(:params) { super().merge(server_puppetserver_metrics: false) } 260 | it { 261 | should contain_file(puppetserver_conf) 262 | .with_content(/^ # Whether to enable http-client metrics; defaults to 'true'.\n metrics-enabled: false$/) 263 | .with_content(/^profiler: \{\n # enable or disable profiling for the Ruby code;\n enabled: true/) 264 | } 265 | it { should contain_file('/etc/custom/puppetserver/conf.d/metrics.conf').with_ensure('file') } 266 | end 267 | 268 | context 'when server_profiler => false' do 269 | let(:params) { super().merge(server_puppetserver_profiler: false) } 270 | it { 271 | should contain_file(puppetserver_conf) 272 | .with_content(/^profiler: \{\n # enable or disable profiling for the Ruby code;\n enabled: false/) 273 | } 274 | end 275 | end 276 | 277 | describe 'server_telemetry' do 278 | context 'with default parameters' do 279 | it { 280 | should contain_file(puppetserver_conf) 281 | .with_content(/^dropsonde: \{\n # enable or disable telemetry\n enabled: false/) 282 | } 283 | end 284 | 285 | context 'when server_telemetry => true' do 286 | let(:params) { super().merge(server_puppetserver_telemetry: true) } 287 | it { 288 | should contain_file(puppetserver_conf) 289 | .with_content(/^dropsonde: \{\n # enable or disable telemetry\n enabled: true/) 290 | } 291 | end 292 | 293 | context 'when server_telemetry => false' do 294 | let(:params) { super().merge(server_puppetserver_telemetry: false) } 295 | it { 296 | should contain_file(puppetserver_conf) 297 | .with_content(/^dropsonde: \{\n # enable or disable telemetry\n enabled: false/) 298 | } 299 | end 300 | end 301 | 302 | describe 'server_experimental' do 303 | context 'when server_experimental => true' do 304 | let(:params) { super().merge(server_puppetserver_experimental: true) } 305 | it { should contain_file(auth_conf).with_content(%r{^(\ *)path: "/puppet/experimental"$}) } 306 | end 307 | 308 | context 'when server_experimental => false' do 309 | let(:params) { super().merge(server_puppetserver_experimental: false) } 310 | it { should contain_file(auth_conf).without_content(%r{^(\ *)path: "/puppet/experimental"$}) } 311 | end 312 | end 313 | 314 | describe 'puppetlabs v3 catalog from agents rule' do 315 | let(:content) { catalogue.resource('file', auth_conf).send(:parameters)[:content] } 316 | let(:rules) { Hocon.parse(content)['authorization']['rules'] } 317 | let(:rule) { rules.find {|rule| rule['name'] == 'puppetlabs v3 catalog from agents' } } 318 | 319 | context 'when server_trusted_agents set' do 320 | let(:params) { super().merge(server_puppetserver_trusted_agents: ['jenkins', 'octocatalog-diff']) } 321 | 322 | it { expect(rule['allow']).to eq(['jenkins', 'octocatalog-diff', '$1']) } 323 | end 324 | 325 | context 'with server_trusted_certificate_extensions' do 326 | let(:params) { super().merge(server_puppetserver_trusted_certificate_extensions: [{'pp_authorization' => 'catalog'}]) } 327 | 328 | it { expect(rule['allow']).to eq(['$1',{'extensions'=>{'pp_authorization'=>'catalog'}}]) } 329 | end 330 | 331 | context 'with server_trusted_agents and server_trusted_certificate_extensions' do 332 | let(:params) { super().merge(server_puppetserver_trusted_agents: ['catalog-diff'], server_puppetserver_trusted_certificate_extensions: [{'pp_authorization' => 'catalog'}]) } 333 | 334 | it { expect(rule['allow']).to eq(['catalog-diff','$1',{'extensions'=>{'pp_authorization'=>'catalog'}}]) } 335 | end 336 | end 337 | 338 | describe 'ca_client_self_delete' do 339 | context 'when set' do 340 | let(:params) { super().merge(server_ca_client_self_delete: true)} 341 | it { should contain_file(auth_conf) 342 | .with_content(%r{^(\ *)name: "Allow nodes to delete their own certificates",$}) } 343 | end 344 | end 345 | 346 | describe 'server_max_open_files', unless: facts[:os]['family'] == 'FreeBSD' do 347 | context 'when server_max_open_files => undef' do 348 | it do 349 | if facts[:service_provider] == 'systemd' 350 | should contain_systemd__dropin_file('puppetserver.service-limits.conf') 351 | .with_ensure('absent') 352 | else 353 | should contain_file_line('puppet::server::puppetserver::max_open_files') 354 | .with_ensure('absent') 355 | end 356 | end 357 | end 358 | 359 | context 'when server_max_open_files => 32143' do 360 | let(:params) { super().merge(server_max_open_files: 32143) } 361 | 362 | it do 363 | if facts[:service_provider] == 'systemd' 364 | should contain_systemd__dropin_file('puppetserver.service-limits.conf') 365 | .with_ensure('present') 366 | .with_filename('limits.conf') 367 | .with_unit('puppetserver.service') 368 | .with_content("[Service]\nLimitNOFILE=32143\n") 369 | else 370 | should contain_file_line('puppet::server::puppetserver::max_open_files') 371 | .with_ensure('present') 372 | .with_path('/etc/default/puppetserver') 373 | .with_line('ulimit -n 32143') 374 | .with_match('^ulimit\ -n') 375 | end 376 | end 377 | end 378 | end 379 | 380 | describe 'with extra_args parameter' do 381 | let(:params) { super().merge(server_jvm_extra_args: ['-XX:foo=bar', '-XX:bar=foo']) } 382 | if facts[:os]['family'] == 'FreeBSD' 383 | it { 384 | should contain_augeas('puppet::server::puppetserver::jvm') 385 | .with_changes(['set puppetserver_java_opts \'"-Xms2G -Xmx2G -XX:foo=bar -XX:bar=foo"\'']) 386 | .with_context('/files/etc/rc.conf') 387 | } 388 | elsif facts[:os]['family'] == 'RedHat' 389 | it { 390 | should contain_augeas('puppet::server::puppetserver::jvm') 391 | .with_changes([ 392 | 'set JAVA_ARGS \'"-Xms2G -Xmx2G -Dcom.redhat.fips=false -XX:foo=bar -XX:bar=foo"\'', 393 | java_bin 394 | ]) 395 | .with_context('/files/etc/default/puppetserver') 396 | .with_incl('/etc/default/puppetserver') 397 | .with_lens('Shellvars.lns') 398 | } 399 | else 400 | it { 401 | should contain_augeas('puppet::server::puppetserver::jvm') 402 | .with_changes([ 403 | 'set JAVA_ARGS \'"-Xms2G -Xmx2G -XX:foo=bar -XX:bar=foo"\'', 404 | java_bin 405 | ]) 406 | .with_context('/files/etc/default/puppetserver') 407 | .with_incl('/etc/default/puppetserver') 408 | .with_lens('Shellvars.lns') 409 | } 410 | end 411 | end 412 | 413 | describe 'with cli_args parameter', unless: facts[:os]['family'] == 'FreeBSD' do 414 | let(:params) { super().merge(server_jvm_cli_args: '-Djava.io.tmpdir=/var/puppettmp') } 415 | if facts[:os]['family'] == 'RedHat' 416 | it { 417 | should contain_augeas('puppet::server::puppetserver::jvm') 418 | .with_changes([ 419 | 'set JAVA_ARGS \'"-Xms2G -Xmx2G -Dcom.redhat.fips=false"\'', 420 | java_bin, 421 | 'set JAVA_ARGS_CLI \'"-Djava.io.tmpdir=/var/puppettmp"\'' 422 | ]) 423 | .with_context('/files/etc/default/puppetserver') 424 | .with_incl('/etc/default/puppetserver') 425 | .with_lens('Shellvars.lns') 426 | } 427 | else 428 | it { 429 | should contain_augeas('puppet::server::puppetserver::jvm') 430 | .with_changes([ 431 | 'set JAVA_ARGS \'"-Xms2G -Xmx2G"\'', 432 | java_bin, 433 | 'set JAVA_ARGS_CLI \'"-Djava.io.tmpdir=/var/puppettmp"\'' 434 | ]) 435 | .with_context('/files/etc/default/puppetserver') 436 | .with_incl('/etc/default/puppetserver') 437 | .with_lens('Shellvars.lns') 438 | } 439 | end 440 | end 441 | 442 | describe 'with jvm_config file parameter' do 443 | let(:params) { super().merge(server_jvm_config: '/etc/custom/puppetserver') } 444 | if facts[:os]['family'] == 'FreeBSD' 445 | it { should contain_augeas('puppet::server::puppetserver::jvm').with_context('/files/etc/rc.conf') } 446 | else 447 | it do 448 | should contain_augeas('puppet::server::puppetserver::jvm') 449 | .with_context('/files/etc/custom/puppetserver') 450 | .with_incl('/etc/custom/puppetserver') 451 | .with_lens('Shellvars.lns') 452 | end 453 | end 454 | end 455 | 456 | describe 'gem-path' do 457 | if ['FreeBSD', 'DragonFly'].include?(facts[:os]['family']) 458 | it do 459 | should contain_file(puppetserver_conf) 460 | .with_content(%r{^ gem-path: \[\$\{jruby-puppet.gem-home\}, "#{server_vardir}/vendored-jruby-gems", "#{facts[:ruby]['sitedir'].sub(/site_ruby/,'gems')}"\]$}) 461 | end 462 | else 463 | it do 464 | should contain_file(puppetserver_conf) 465 | .with_content(%r{^ gem-path: \[\$\{jruby-puppet.gem-home\}, "#{server_vardir}/vendored-jruby-gems", "/opt/puppetlabs/puppet/lib/ruby/vendor_gems"\]$}) 466 | end 467 | end 468 | end 469 | 470 | describe 'Puppet Server CA related settings' do 471 | context 'with default parameters' do 472 | it { should contain_file('/etc/custom/puppetserver/conf.d/ca.conf') 473 | .with_ensure('file') 474 | .with_content(/^( *)allow-subject-alt-names: false$/) 475 | .with_content(/^( *)allow-authorization-extensions: false$/) 476 | .with_content(/^( *)enable-infra-crl: false$/) 477 | } 478 | it { should contain_file(auth_conf).with_content(/^( *)pp_cli_auth: "true"$/) } 479 | end 480 | 481 | context 'with ca parameters set' do 482 | let(:params) { super().merge( 483 | server_ca_allow_sans: true, 484 | server_ca_allow_auth_extensions: true, 485 | server_ca_enable_infra_crl: true, 486 | ) 487 | } 488 | it { should contain_file('/etc/custom/puppetserver/conf.d/ca.conf') 489 | .with_ensure('file') 490 | .with_content(/^( *)allow-subject-alt-names: true$/) 491 | .with_content(/^( *)allow-authorization-extensions: true$/) 492 | .with_content(/^( *)enable-infra-crl: true$/) 493 | } 494 | end 495 | end 496 | 497 | describe 'puppetlabs v4 catalog for services' do 498 | let(:content) { catalogue.resource('file', auth_conf).send(:parameters)[:content] } 499 | let(:rules) { Hocon.parse(content)['authorization']['rules'] } 500 | let(:rule) { rules.find {|rule| rule['name'] == 'puppetlabs v4 catalog for services' } } 501 | 502 | context 'by default' do 503 | it { should contain_file(auth_conf).with_content(%r{^(\ *)deny: "\*"\n(\ *)sort-order: 500\n(\ *)name: "puppetlabs v4 catalog for services"}) } 504 | end 505 | 506 | context 'with server_trusted_agents' do 507 | let(:params) { super().merge(server_puppetserver_trusted_agents: ['jenkins', 'octocatalog-diff']) } 508 | 509 | it { expect(rule['allow']).to eq(['jenkins', 'octocatalog-diff']) } 510 | end 511 | 512 | context 'with server_trusted_certificate_extensions' do 513 | let(:params) { super().merge(server_puppetserver_trusted_certificate_extensions: [{'pp_authorization' => 'catalog'}]) } 514 | 515 | it { expect(rule['allow']).to eq([{'extensions'=>{'pp_authorization'=>'catalog'}}]) } 516 | end 517 | 518 | context 'with server_trusted_agents and server_trusted_certificate_extensions' do 519 | let(:params) { super().merge(server_puppetserver_trusted_agents: ['catalog-diff'], server_puppetserver_trusted_certificate_extensions: [{'pp_authorization' => 'catalog'}]) } 520 | 521 | it { expect(rule['allow']).to eq(['catalog-diff',{'extensions'=>{'pp_authorization'=>'catalog'}}]) } 522 | end 523 | end 524 | 525 | describe 'allow jetty specific server threads' do 526 | context 'with thread config' do 527 | let(:params) do 528 | super().merge( 529 | server_selector_threads: 1, 530 | server_acceptor_threads: 2, 531 | server_ssl_selector_threads: 3, 532 | server_ssl_acceptor_threads: 4, 533 | server_max_threads: 5 534 | ) 535 | end 536 | 537 | it { is_expected.to compile.with_all_deps } 538 | it { is_expected.to contain_file('/etc/custom/puppetserver/conf.d/webserver.conf'). 539 | with_content(/selector-threads: 1/). 540 | with_content(/acceptor-threads: 2/). 541 | with_content(/ssl-selector-threads: 3/). 542 | with_content(/ssl-acceptor-threads: 4/). 543 | with_content(/max-threads: 5/) 544 | } 545 | end 546 | end 547 | 548 | describe 'versioned code' do 549 | context 'when versioned code parameters are set' do 550 | let(:params) do 551 | super().merge( 552 | server_versioned_code_id: '/some/code/id/bin', 553 | server_versioned_code_content: '/some/code/content/bin', 554 | ) 555 | end 556 | 557 | it { 558 | should contain_file(puppetserver_conf) 559 | .with_content(%r{^ code-id-command: /some/code/id/bin\n code-content-command: /some/code/content/bin$}) 560 | } 561 | end 562 | end 563 | 564 | describe 'jolokia_metrics_allowlist' do 565 | let(:content) { catalogue.resource('file', auth_conf).send(:parameters)[:content] } 566 | let(:rules) { Hocon.parse(content)['authorization']['rules'] } 567 | let(:rule) { rules.find {|rule| rule['name'] == 'jolokia metrics' } } 568 | 569 | context 'by default' do 570 | it { expect(rule).to be_nil } 571 | end 572 | 573 | context 'when set' do 574 | let(:params) { super().merge(server_jolokia_metrics_allowlist: ['localhost', 'host.example.com']) } 575 | 576 | it { expect(rule['match-request']['path']).to eq('/metrics/v2') } 577 | it { expect(rule['allow']).to eq(['localhost', 'host.example.com']) } 578 | end 579 | end 580 | end 581 | end 582 | end 583 | -------------------------------------------------------------------------------- /spec/classes/puppet_server_service_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe 'puppet::server::service' do 4 | context 'default parameters' do 5 | it { is_expected.to contain_service('puppetserver').with_ensure(true).with_enable(true) } 6 | end 7 | 8 | context 'enable => false' do 9 | let(:params) do 10 | { enable: false } 11 | end 12 | 13 | it { is_expected.to contain_service('puppetserver').with_ensure(false).with_enable(false) } 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /spec/defines/puppet_config_entry_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe 'puppet::config::entry' do 4 | on_supported_os.each do |os, facts| 5 | context "on #{os}" do 6 | let(:facts) { facts } 7 | 8 | let(:title) { 'foo' } 9 | 10 | context 'with a plain value' do 11 | let :pre_condition do 12 | "class {'puppet': }" 13 | end 14 | let :params do 15 | { 16 | :key => 'foo', 17 | :value => 'bar', 18 | :section => 'main', 19 | :sectionorder => 1, 20 | } 21 | end 22 | it 'should contain the section header' do 23 | should contain_concat__fragment('puppet.conf_main').with_content("\n[main]") 24 | should contain_concat__fragment('puppet.conf_main').with_order("1_main ") 25 | end 26 | it 'should contain the section end' do 27 | should contain_concat__fragment('puppet.conf_main_end').with_content("\n") 28 | should contain_concat__fragment('puppet.conf_main_end').with_order("1_main~end") 29 | end 30 | it 'should contain the keyvalue pair' do 31 | should contain_concat__fragment('puppet.conf_main_foo').with_content(/^\s+foo = bar$/) 32 | should contain_concat__fragment('puppet.conf_main_foo').with_order("1_main_foo ") 33 | end 34 | end 35 | context 'with an array value' do 36 | let :pre_condition do 37 | "class {'puppet': }" 38 | end 39 | let :params do 40 | { 41 | :key => 'foo', 42 | :value => ['bar','baz'], 43 | :section => 'main', 44 | :sectionorder => 1, 45 | } 46 | end 47 | it 'should contain the section header' do 48 | should contain_concat__fragment('puppet.conf_main').with_content("\n[main]") 49 | should contain_concat__fragment('puppet.conf_main').with_order("1_main ") 50 | end 51 | it 'should contain the section end' do 52 | should contain_concat__fragment('puppet.conf_main_end').with_content("\n") 53 | should contain_concat__fragment('puppet.conf_main_end').with_order("1_main~end") 54 | end 55 | it 'should contain the keyvalue pair' do 56 | should contain_concat__fragment('puppet.conf_main_foo').with_content(/^\s+foo = bar,baz$/) 57 | should contain_concat__fragment('puppet.conf_main_foo').with_order("1_main_foo ") 58 | end 59 | end 60 | context 'with a custom joiner' do 61 | let :pre_condition do 62 | "class {'puppet': }" 63 | end 64 | let :params do 65 | { 66 | :key => 'foo', 67 | :value => ['bar','baz'], 68 | :joiner => ':', 69 | :section => 'main', 70 | :sectionorder => 1, 71 | } 72 | end 73 | it 'should contain the section header' do 74 | should contain_concat__fragment('puppet.conf_main').with_content("\n[main]") 75 | should contain_concat__fragment('puppet.conf_main').with_order("1_main ") 76 | end 77 | it 'should contain the section end' do 78 | should contain_concat__fragment('puppet.conf_main_end').with_content("\n") 79 | should contain_concat__fragment('puppet.conf_main_end').with_order("1_main~end") 80 | end 81 | it 'should contain the keyvalue pair' do 82 | should contain_concat__fragment('puppet.conf_main_foo').with_content(/^\s+foo = bar:baz$/) 83 | should contain_concat__fragment('puppet.conf_main_foo').with_order("1_main_foo ") 84 | end 85 | end 86 | 87 | end 88 | end 89 | end 90 | -------------------------------------------------------------------------------- /spec/setup_acceptance_node.pp: -------------------------------------------------------------------------------- 1 | $packages = $facts['os']['name'] ? { 2 | # iproute is needed for the ss command in testing and not included in the base container 3 | 'Fedora' => ['cronie', 'iproute'], 4 | 'Ubuntu' => ['cron'], 5 | default => [], 6 | } 7 | 8 | package { $packages: 9 | ensure => installed, 10 | } 11 | -------------------------------------------------------------------------------- /spec/spec.opts: -------------------------------------------------------------------------------- 1 | --format 2 | documentation 3 | --colour 4 | mtime 5 | --backtrace 6 | -------------------------------------------------------------------------------- /spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | # This file is managed centrally by modulesync 2 | # https://github.com/theforeman/foreman-installer-modulesync 3 | 4 | require 'voxpupuli/test/spec_helper' 5 | 6 | add_mocked_facts! 7 | 8 | def get_content(subject, title) 9 | is_expected.to contain_file(title) 10 | content = subject.resource('file', title).send(:parameters)[:content] 11 | content.split(/\n/).reject { |line| line =~ /(^#|^$|^\s+#)/ } 12 | end 13 | 14 | def verify_exact_contents(subject, title, expected_lines) 15 | expect(get_content(subject, title)).to match_array(expected_lines) 16 | end 17 | 18 | def verify_concat_fragment_contents(subject, title, expected_lines) 19 | is_expected.to contain_concat__fragment(title) 20 | content = subject.resource('concat::fragment', title).send(:parameters)[:content] 21 | expect(content.split("\n") & expected_lines).to match_array(expected_lines) 22 | end 23 | 24 | def verify_concat_fragment_exact_contents(subject, title, expected_lines) 25 | is_expected.to contain_concat__fragment(title) 26 | content = subject.resource('concat::fragment', title).send(:parameters)[:content] 27 | expect(content.split(/\n/).reject { |line| line =~ /(^#|^$|^\s+#)/ }).to match_array(expected_lines) 28 | end 29 | 30 | Dir["./spec/support/**/*.rb"].sort.each { |f| require f } 31 | -------------------------------------------------------------------------------- /spec/spec_helper_acceptance.rb: -------------------------------------------------------------------------------- 1 | require 'voxpupuli/acceptance/spec_helper_acceptance' 2 | 3 | ENV['BEAKER_setfile'] ||= 'centos8-64{hostname=centos8-64.example.com}' 4 | 5 | configure_beaker(modules: :fixtures) do |host| 6 | if fact_on(host, 'os.family') == 'RedHat' 7 | unless fact_on(host, 'os.name') == 'Fedora' 8 | # don't delete downloaded rpm for use with BEAKER_provision=no + 9 | # BEAKER_destroy=no 10 | on host, 'sed -i "s/keepcache=.*/keepcache=1/" /etc/yum.conf' 11 | end 12 | # refresh check if cache needs refresh on next yum command 13 | on host, 'yum clean expire-cache' 14 | end 15 | end 16 | 17 | Dir["./spec/support/acceptance/**/*.rb"].sort.each { |f| require f } 18 | -------------------------------------------------------------------------------- /spec/support/acceptance/puppetserver.rb: -------------------------------------------------------------------------------- 1 | def unsupported_puppetserver 2 | case host_inventory['facter']['os']['name'] 3 | when 'Archlinux' 4 | true 5 | when 'Fedora' 6 | true 7 | when 'Debian' 8 | host_inventory['facter']['os']['release']['major'] == '12' 9 | end 10 | end 11 | 12 | def unsupported_puppetserver_upgrade 13 | # currently none 14 | false 15 | end 16 | -------------------------------------------------------------------------------- /spec/support/aio.rb: -------------------------------------------------------------------------------- 1 | add_custom_fact :aio_agent_version, ->(os, facts) do 2 | return facts[:puppetversion] unless ['Archlinux', 'FreeBSD', 'DragonFly', 'Windows'].include?(facts[:os]['family']) 3 | end 4 | 5 | def unsupported_puppetserver_osfamily(osfamily) 6 | ['Archlinux', 'windows', 'Suse'].include?(osfamily) 7 | end 8 | -------------------------------------------------------------------------------- /templates/agent/systemd.puppet-run.service.erb: -------------------------------------------------------------------------------- 1 | # 2 | # Managed by Puppet 3 | # 4 | [Unit] 5 | Description=Systemd Timer Service for Puppet Agent 6 | After=network.target 7 | 8 | [Service] 9 | Type=oneshot 10 | ExecStart=<%= @command %> 11 | SuccessExitStatus=2 12 | User=root 13 | Group=root 14 | -------------------------------------------------------------------------------- /templates/agent/systemd.puppet-run.timer.erb: -------------------------------------------------------------------------------- 1 | # 2 | # Managed by Puppet 3 | # 4 | [Unit] 5 | Description=Systemd Timer for Puppet Agent 6 | 7 | [Timer] 8 | OnCalendar=*-*-* <%= Array(@_hour).join(',') %>:<%= Array(@_minute).join(',') %>:00<% if @timezone -%> <%= @timezone %><% end %> 9 | Persistent=true 10 | RandomizedDelaySec=<%= @randomizeddelaysec %> 11 | 12 | [Install] 13 | WantedBy=timers.target 14 | -------------------------------------------------------------------------------- /templates/server/autosign.conf.erb: -------------------------------------------------------------------------------- 1 | # 2 | # Managed by Puppet 3 | # 4 | <% scope.lookupvar("puppet::server::autosign_entries").each do |entry| -%> 5 | <%= entry %> 6 | <% end -%> 7 | -------------------------------------------------------------------------------- /templates/server/post-receive.erb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # 3 | # Managed by Puppet 4 | # 5 | 6 | require 'fileutils' 7 | require 'etc' 8 | 9 | $stdout.sync = true 10 | $stderr.sync = true 11 | 12 | # Set this to where you want to keep your environments 13 | ENVIRONMENT_BASEDIR = "<%= scope.lookupvar("puppet::server::config::primary_envs_dir") %>" 14 | 15 | # post-receive hooks set GIT_DIR to the current repository. If you want to 16 | # clone from a non-local repository, set this to the URL of the repository, 17 | # such as git@git.host:puppet.git 18 | SOURCE_REPOSITORY = File.expand_path(ENV['GIT_DIR']) 19 | 20 | # Mapping of branches to directories. In many cases, the server branch is 21 | # checked out to the 'development' environment. 22 | BRANCH_MAP = { 23 | <% if @git_branch_map -%> 24 | <% @git_branch_map.sort.each do |g,p| -%> 25 | "<%= g %>" => "<%= p %>", 26 | <% end -%> 27 | <% end -%> 28 | } 29 | 30 | # The git_dir environment variable will override the --git-dir, so we remove it 31 | # to allow us to create new directories cleanly. 32 | ENV.delete('GIT_DIR') 33 | 34 | # Ensure that we have the underlying directories, otherwise the later commands 35 | # may fail in somewhat cryptic manners. 36 | unless File.directory? ENVIRONMENT_BASEDIR 37 | puts %Q{#{ENVIRONMENT_BASEDIR} does not exist, cannot create environment directories.} 38 | exit 1 39 | end 40 | 41 | # If we're running as root we change our UID to the owner of this file. 42 | file_uid = File.stat($0).uid 43 | if file_uid != Process.uid and Process.uid == 0 44 | Process::UID.change_privilege(file_uid) 45 | # Set LOGNAME and HOME directories to file-owning user's values 46 | # so git can read ~/.config/git/attributes (for example) without error 47 | file_pwuid = Etc::getpwuid(file_uid) 48 | ENV.store('LOGNAME',file_pwuid.name) 49 | ENV.store('HOME',file_pwuid.dir) 50 | end 51 | 52 | # Run a command, return its output and abort if it fails 53 | def do_cmd(cmd) 54 | ret = %x{#{cmd}} 55 | if $?.exitstatus != 0 56 | puts("'#{cmd}' failed. Giving up.") 57 | exit 1 58 | end 59 | ret 60 | end 61 | 62 | # You can push multiple refspecs at once, like 'git push origin branch1 branch2', 63 | # so we need to handle each one. 64 | $stdin.each_line do |line| 65 | oldrev, newrev, refname = line.split(" ") 66 | 67 | # Determine the branch name from the refspec we're received, which is in the 68 | # format refs/heads/, and make sure that it doesn't have any possibly 69 | # dangerous characters 70 | branchname = refname.sub(%r{^refs/heads/(.*$)}) { $1 } 71 | if branchname =~ /[\W]/ 72 | puts %Q{Branch "#{branchname}" contains non-word characters, ignoring it.} 73 | next 74 | end 75 | 76 | if BRANCH_MAP[branchname] != nil 77 | environment_name = BRANCH_MAP[branchname] 78 | environment_path = "#{ENVIRONMENT_BASEDIR}/#{BRANCH_MAP[branchname]}" 79 | else 80 | environment_name = branchname 81 | environment_path = "#{ENVIRONMENT_BASEDIR}/#{branchname}" 82 | end 83 | 84 | if newrev =~ /^0+$/ 85 | # We've received a push with a null revision, something like 000000000000, 86 | # which means that we should delete the given branch. 87 | puts "Deleting existing environment #{environment_name}" 88 | if File.directory? environment_path 89 | FileUtils.rm_rf environment_path, :secure => true 90 | end 91 | else 92 | # We have been given a branch that needs to be created or updated. If the 93 | # environment exists, update it. Else, create it. 94 | 95 | if File.directory? environment_path 96 | # Update an existing environment. We do a fetch and then reset in the 97 | # case that someone did a force push to a branch. 98 | 99 | puts "Updating existing environment #{environment_name}" 100 | Dir.chdir environment_path 101 | do_cmd("git fetch --all") 102 | do_cmd("git reset --hard 'origin/#{branchname}'") 103 | if File.exist? "#{environment_path}/.gitmodules" 104 | # ensure that we remove deleted sub modules too 105 | do_cmd("git status --short").split("\n").each do |file| 106 | # ?? old_submodule/ 107 | if file =~ /\s*\?{2}\s*(\S*)/ 108 | puts "Found a few unknown files.. deleting #{$1}" 109 | FileUtils.rm_rf $1, :secure => true 110 | end 111 | end 112 | do_cmd("git submodule sync") 113 | do_cmd("git submodule update --init --recursive") 114 | end 115 | else 116 | # Instantiate a new environment from the current repository. 117 | 118 | puts "Creating new environment #{environment_name}" 119 | do_cmd("git clone --recursive #{SOURCE_REPOSITORY} #{environment_path} --branch #{branchname}") 120 | end 121 | end 122 | end 123 | -------------------------------------------------------------------------------- /templates/server/puppetserver/conf.d/auth.conf.erb: -------------------------------------------------------------------------------- 1 | # 2 | # Managed by Puppet 3 | # 4 | authorization: { 5 | version: 1 6 | allow-header-cert-info: <%= @server_http || @allow_header_cert_info %> 7 | rules: [ 8 | { 9 | # Allow nodes to retrieve their own catalog 10 | match-request: { 11 | path: "^/puppet/v3/catalog/([^/]+)$" 12 | type: regex 13 | method: [get, post] 14 | } 15 | <%= scope.call_function( 16 | 'stdlib::to_json_pretty', 17 | [ 18 | {'allow' => @server_trusted_agents + ['$1'] + @server_trusted_certificate_extensions.map { |extension| { 'extensions' => extension } } } 19 | ] 20 | ).lines.to_a[1..-2].map{ |line| " #{line}"}.join 21 | -%> 22 | sort-order: 500 23 | name: "puppetlabs v3 catalog from agents" 24 | }, 25 | { 26 | # Allow services to retrieve catalogs on behalf of others 27 | match-request: { 28 | path: "^/puppet/v4/catalog/?$" 29 | type: regex 30 | method: post 31 | } 32 | <%- if @server_trusted_agents.empty? && @server_trusted_certificate_extensions.empty? -%> 33 | deny: "*" 34 | <%- else -%> 35 | <%= scope.call_function( 36 | 'stdlib::to_json_pretty', 37 | [ 38 | {'allow' => @server_trusted_agents + @server_trusted_certificate_extensions.map { |extension| { 'extensions' => extension } } } 39 | ] 40 | ).lines.to_a[1..-2].map{ |line| " #{line}"}.join 41 | -%> 42 | <%- end -%> 43 | sort-order: 500 44 | name: "puppetlabs v4 catalog for services" 45 | }, 46 | { 47 | # Allow nodes to retrieve the certificate they requested earlier 48 | match-request: { 49 | path: "/puppet-ca/v1/certificate/" 50 | type: path 51 | method: get 52 | } 53 | allow-unauthenticated: true 54 | sort-order: 500 55 | name: "puppetlabs certificate" 56 | }, 57 | { 58 | # Allow all nodes to access the certificate revocation list 59 | match-request: { 60 | path: "/puppet-ca/v1/certificate_revocation_list/ca" 61 | type: path 62 | method: get 63 | } 64 | allow-unauthenticated: true 65 | sort-order: 500 66 | name: "puppetlabs crl" 67 | }, 68 | { 69 | # Allow nodes to request a new certificate 70 | match-request: { 71 | path: "/puppet-ca/v1/certificate_request" 72 | type: path 73 | method: [get, put] 74 | } 75 | allow-unauthenticated: true 76 | sort-order: 500 77 | name: "puppetlabs csr" 78 | }, 79 | <%- if @server_ca -%> 80 | <%- if scope.function_versioncmp([@real_puppetserver_version, '8.0.0']) >= 0 -%> 81 | { 82 | # Allow nodes to renew their certificate 83 | match-request: { 84 | path: "/puppet-ca/v1/certificate_renewal" 85 | type: path 86 | method: post 87 | } 88 | # this endpoint should never be unauthenticated, as it requires the cert to be provided. 89 | allow: "*" 90 | sort-order: 500 91 | name: "puppetlabs certificate renewal" 92 | }, 93 | <%- end -%> 94 | { 95 | # Allow the CA CLI to access the certificate_status endpoint 96 | match-request: { 97 | path: "/puppet-ca/v1/certificate_status" 98 | type: path 99 | method: [get, put, delete] 100 | } 101 | <%- if @server_ca_auth_required == false -%> 102 | allow-unauthenticated: true 103 | <%- else -%> 104 | allow: [ 105 | <%- @server_ca_client_allowlist.each do |client| -%> 106 | "<%= client %>", 107 | <%- end -%> 108 | { 109 | extensions: { 110 | pp_cli_auth: "true" 111 | } 112 | } 113 | ] 114 | <%- end -%> 115 | sort-order: 500 116 | name: "puppetlabs cert status" 117 | }, 118 | { 119 | match-request: { 120 | path: "^/puppet-ca/v1/certificate_revocation_list$" 121 | type: regex 122 | method: put 123 | } 124 | allow: { 125 | extensions: { 126 | pp_cli_auth: "true" 127 | } 128 | } 129 | sort-order: 500 130 | name: "puppetlabs CRL update" 131 | }, 132 | { 133 | # Allow the CA CLI to access the certificate_statuses endpoint 134 | match-request: { 135 | path: "/puppet-ca/v1/certificate_statuses" 136 | type: path 137 | method: get 138 | } 139 | <%- if @server_ca_auth_required == false -%> 140 | allow-unauthenticated: true 141 | <%- else -%> 142 | allow: [ 143 | <%- @server_ca_client_allowlist.each do |client| -%> 144 | "<%= client %>", 145 | <%- end -%> 146 | { 147 | extensions: { 148 | pp_cli_auth: "true" 149 | } 150 | } 151 | ] 152 | <%- end -%> 153 | sort-order: 500 154 | name: "puppetlabs cert statuses" 155 | }, 156 | <%- if @server_ca_client_self_delete -%> 157 | { 158 | name: "Allow nodes to delete their own certificates", 159 | match-request: { 160 | path: "^/puppet-ca/v1/certificate(_status|_request)?/([^/]+)$" 161 | type: regex 162 | method: [delete] 163 | }, 164 | allow: [ 165 | "$2", 166 | <%- @server_admin_api_allowlist.each do |client| -%> 167 | "<%= client %>", 168 | <%- end -%> 169 | { 170 | extensions: { 171 | pp_cli_auth: "true" 172 | } 173 | } 174 | ] 175 | sort-order: 500 176 | }, 177 | <%- end -%> 178 | <%- end -%> 179 | { 180 | # Allow authenticated access to the CA expirations endpoint 181 | match-request: { 182 | path: "/puppet-ca/v1/expirations" 183 | type: path 184 | method: get 185 | } 186 | allow: "*" 187 | sort-order: 500 188 | name: "puppetlabs CA cert and CRL expirations" 189 | }, 190 | { 191 | # Allow the CA CLI to access the certificate clean endpoint 192 | match-request: { 193 | path: "/puppet-ca/v1/clean" 194 | type: path 195 | method: put 196 | } 197 | allow: { 198 | extensions: { 199 | pp_cli_auth: "true" 200 | } 201 | } 202 | sort-order: 500 203 | name: "puppetlabs cert clean" 204 | }, 205 | { 206 | # Allow unauthenticated access to the status service endpoint 207 | match-request: { 208 | path: "/status/v1/services" 209 | type: path 210 | method: get 211 | } 212 | allow-unauthenticated: true 213 | sort-order: 500 214 | name: "puppetlabs status service - full" 215 | }, 216 | { 217 | match-request: { 218 | path: "/status/v1/simple" 219 | type: path 220 | method: get 221 | } 222 | allow-unauthenticated: true 223 | sort-order: 500 224 | name: "puppetlabs status service - simple" 225 | }, 226 | { 227 | match-request: { 228 | path: "/puppet-admin-api/v1/environment-cache" 229 | type: path 230 | method: delete 231 | } 232 | allow: [ 233 | <%- @server_admin_api_allowlist.each do |client| -%> 234 | "<%= client %>", 235 | <%- end -%> 236 | ] 237 | sort-order: 200 238 | name: "environment-cache" 239 | }, 240 | { 241 | match-request: { 242 | path: "/puppet-admin-api/v1/jruby-pool" 243 | type: path 244 | method: delete 245 | } 246 | allow: [ 247 | <%- @server_admin_api_allowlist.each do |client| -%> 248 | "<%= client %>", 249 | <%- end -%> 250 | ] 251 | sort-order: 200 252 | name: "jruby-pool" 253 | }, 254 | { 255 | match-request: { 256 | path: "/puppet/v3/environments" 257 | type: path 258 | method: get 259 | } 260 | allow: "*" 261 | sort-order: 500 262 | name: "puppetlabs environments" 263 | }, 264 | { 265 | match-request: { 266 | path: "/puppet/v3/environment_classes" 267 | type: path 268 | method: get 269 | } 270 | allow: "*" 271 | sort-order: 500 272 | name: "puppetlabs environment classes" 273 | }, 274 | { 275 | # Allow nodes to access all file_bucket_files. Note that access for 276 | # the 'delete' method is forbidden by Puppet regardless of the 277 | # configuration of this rule. 278 | match-request: { 279 | path: "/puppet/v3/file_bucket_file" 280 | type: path 281 | method: [get, head, post, put] 282 | } 283 | allow: "*" 284 | sort-order: 500 285 | name: "puppetlabs file bucket file" 286 | }, 287 | { 288 | # Allow nodes to access all file_content. Note that access for the 289 | # 'delete' method is forbidden by Puppet regardless of the 290 | # configuration of this rule. 291 | match-request: { 292 | path: "/puppet/v3/file_content" 293 | type: path 294 | method: [get, post] 295 | } 296 | allow: "*" 297 | sort-order: 500 298 | name: "puppetlabs file content" 299 | }, 300 | { 301 | # Allow nodes to access all file_metadata. Note that access for the 302 | # 'delete' method is forbidden by Puppet regardless of the 303 | # configuration of this rule. 304 | match-request: { 305 | path: "/puppet/v3/file_metadata" 306 | type: path 307 | method: [get, post] 308 | } 309 | allow: "*" 310 | sort-order: 500 311 | name: "puppetlabs file metadata" 312 | }, 313 | { 314 | # Allow nodes to retrieve only their own node definition 315 | match-request: { 316 | path: "^/puppet/v3/node/([^/]+)$" 317 | type: regex 318 | method: get 319 | } 320 | allow: "$1" 321 | sort-order: 500 322 | name: "puppetlabs node" 323 | }, 324 | { 325 | # Allow nodes to store only their own reports 326 | match-request: { 327 | path: "^/puppet/v3/report/([^/]+)$" 328 | type: regex 329 | method: put 330 | } 331 | allow: "$1" 332 | sort-order: 500 333 | name: "puppetlabs report" 334 | }, 335 | { 336 | # Allow nodes to update their own facts 337 | match-request: { 338 | path: "^/puppet/v3/facts/([^/]+)$" 339 | type: regex 340 | method: put 341 | } 342 | allow: "$1" 343 | sort-order: 500 344 | name: "puppetlabs facts" 345 | }, 346 | { 347 | match-request: { 348 | path: "/puppet/v3/static_file_content" 349 | type: path 350 | method: get 351 | } 352 | allow: "*" 353 | sort-order: 500 354 | name: "puppetlabs static file content" 355 | }, 356 | { 357 | match-request: { 358 | path: "/puppet/v3/tasks" 359 | type: path 360 | } 361 | allow: "*" 362 | sort-order: 500 363 | name: "puppet tasks information" 364 | }, 365 | <%- if @server_experimental -%> 366 | { 367 | # Allow all users access to the experimental endpoint 368 | # which currently only provides a dashboard web ui. 369 | match-request: { 370 | path: "/puppet/experimental" 371 | type: path 372 | } 373 | allow-unauthenticated: true 374 | sort-order: 500 375 | name: "puppetlabs experimental" 376 | }, 377 | <%- end -%> 378 | <%- unless @jolokia_metrics_allowlist.empty? -%> 379 | { 380 | match-request: { 381 | path: "/metrics/v2" 382 | type: path 383 | } 384 | allow: [ 385 | <%- @jolokia_metrics_allowlist.each do |client| -%> 386 | "<%= client %>", 387 | <%- end -%> 388 | ] 389 | sort-order: 500 390 | name: "jolokia metrics" 391 | }, 392 | <%- end -%> 393 | { 394 | # Deny everything else. This ACL is not strictly 395 | # necessary, but illustrates the default policy 396 | match-request: { 397 | path: "/" 398 | type: path 399 | } 400 | deny: "*" 401 | sort-order: 999 402 | name: "puppetlabs deny all" 403 | } 404 | ] 405 | } 406 | -------------------------------------------------------------------------------- /templates/server/puppetserver/conf.d/ca.conf.erb: -------------------------------------------------------------------------------- 1 | certificate-authority: { 2 | # allow CA to sign certificate requests that have subject alternative names. 3 | allow-subject-alt-names: <%= @ca_allow_sans %> 4 | 5 | # allow CA to sign certificate requests that have authorization extensions. 6 | allow-authorization-extensions: <%= @ca_allow_auth_extensions %> 7 | 8 | # enable the separate CRL for Puppet infrastructure nodes 9 | enable-infra-crl: <%= @ca_enable_infra_crl %> 10 | 11 | # Setup auto renewal of certs 12 | allow-auto-renewal: <%= @server_ca_allow_auto_renewal %> 13 | # This value determines the lifetime of the cert if auto-renewal is enabled 14 | auto-renewal-cert-ttl: <%= @server_ca_allow_auto_renewal_cert_ttl %> 15 | # Default cert expiration time. If the value is set here, it will take precedence over ca-ttl setting in puppet.conf 16 | #ca-ttl: "60d" 17 | } 18 | -------------------------------------------------------------------------------- /templates/server/puppetserver/conf.d/metrics.conf.erb: -------------------------------------------------------------------------------- 1 | # 2 | # Managed by Puppet 3 | # 4 | # settings related to metrics 5 | metrics: { 6 | # a server id that will be used as part of the namespace for metrics produced 7 | # by this server 8 | server-id: "<%= @metrics_server_id %>" 9 | registries: { 10 | puppetserver: { 11 | # specify metrics to allow in addition to those in the default list 12 | <% if @metrics_allowed -%> 13 | metrics-allowed: [ 14 | <%- @metrics_allowed.each do |allowed_host| -%> 15 | "<%= allowed_host %>", 16 | <%- end -%> 17 | ] 18 | <%- else -%> 19 | #metrics-allowed: ["compiler.compile.production"] 20 | <% end -%> 21 | 22 | reporters: { 23 | # enable or disable JMX metrics reporter 24 | jmx: { 25 | enabled: <%= @metrics_jmx_enable %> 26 | } 27 | # enable or disable Graphite metrics reporter 28 | graphite: { 29 | enabled: <%= @metrics_graphite_enable %> 30 | } 31 | } 32 | 33 | } 34 | } 35 | 36 | # this section is used to configure settings for reporters that will send 37 | # the metrics to various destinations for external viewing 38 | reporters: { 39 | graphite: { 40 | # graphite host 41 | host: "<%= @metrics_graphite_host %>" 42 | # graphite metrics port 43 | port: <%= @metrics_graphite_port %> 44 | # how often to send metrics to graphite 45 | update-interval-seconds: <%= @metrics_graphite_interval %> 46 | } 47 | } 48 | metrics-webservice: { 49 | jolokia: { 50 | # Enable or disable the Jolokia-based metrics/v2 endpoint. 51 | # Default is true. 52 | # enabled: false 53 | 54 | # Configure any of the settings listed at: 55 | # https://jolokia.org/reference/html/agents.html#war-agent-installation 56 | servlet-init-params: { 57 | # Specify a custom security policy: 58 | # https://jolokia.org/reference/html/security.html 59 | # policyLocation: "file:///etc/puppetlabs/puppetserver/jolokia-access.xml" 60 | } 61 | } 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /templates/server/puppetserver/conf.d/product.conf.erb: -------------------------------------------------------------------------------- 1 | # 2 | # Managed by Puppet 3 | # 4 | product: { 5 | # automatic update checks and corresponding analytic data collection 6 | check-for-updates: <%= @server_check_for_updates %> 7 | } 8 | -------------------------------------------------------------------------------- /templates/server/puppetserver/conf.d/puppetserver.conf.erb: -------------------------------------------------------------------------------- 1 | # 2 | # Managed by Puppet 3 | # 4 | # configuration for the JRuby interpreters 5 | jruby-puppet: { 6 | # Where the puppet-agent dependency places puppet, facter, etc... 7 | # Puppet server expects to load Puppet from this location 8 | ruby-load-path: [ 9 | <%- @server_ruby_load_paths.each do |ruby_load_path| -%> 10 | <%= ruby_load_path %>, 11 | <%- end -%> 12 | ] 13 | 14 | # This setting determines where JRuby will install gems. It is used for loading gems, 15 | # and also by the `puppetserver gem` command line tool. 16 | gem-home: <%= @server_jruby_gem_home %> 17 | 18 | # This setting defines the complete "GEM_PATH" for jruby. If set, it should include 19 | # the gem-home directory as well as any other directories that gems can be loaded 20 | # from (including the vendored gems directory for gems that ship with puppetserver) 21 | gem-path: [<%= @server_gem_paths.join(', ') %>] 22 | 23 | # PLEASE NOTE: Use caution when modifying the below settings. Modifying 24 | # these settings will change the value of the corresponding Puppet settings 25 | # for Puppet Server, but not for the Puppet CLI tools. This likely will not 26 | # be a problem with server-var-dir, server-run-dir, or server-log-dir unless 27 | # some critical setting in puppet.conf is interpolating the value of one 28 | # of the corresponding settings, but it is important that any changes made to 29 | # server-conf-dir and server-code-dir are also made to the corresponding Puppet 30 | # settings when running the Puppet CLI tools. See 31 | # https://docs.puppetlabs.com/puppetserver/latest/puppet_conf_setting_diffs.html#overriding-puppet-settings-in-puppet-server 32 | # for more information. 33 | 34 | # (optional) path to puppet conf dir; if not specified, will use 35 | # the puppet default 36 | server-conf-dir: <%= @server_dir %> 37 | 38 | # (optional) path to puppet code dir; if not specified, will use 39 | # the puppet default 40 | server-code-dir: <%= @codedir %> 41 | 42 | # (optional) path to puppet var dir; if not specified, will use 43 | # the puppet default 44 | server-var-dir: <%= @server_puppetserver_vardir %> 45 | 46 | # (optional) path to puppet run dir; if not specified, will use 47 | # the puppet default 48 | server-run-dir: <%= @server_puppetserver_rundir %> 49 | 50 | # (optional) path to puppet log dir; if not specified, will use 51 | # the puppet default 52 | server-log-dir: <%= @server_puppetserver_logdir %> 53 | 54 | # (optional) maximum number of JRuby instances to allow 55 | max-active-instances: <%= @server_max_active_instances %> 56 | 57 | # (optional) the number of HTTP requests a given JRuby instance will handle in its lifetime. 58 | max-requests-per-instance: <%= @server_max_requests_per_instance %> 59 | 60 | # (optional) The maximum number of requests that may be queued waiting to borrow a JRuby from the pool. 61 | max-queued-requests: <%= @server_max_queued_requests %> 62 | 63 | # (optional) Sets the upper limit for the random sleep set as a Retry-After header on 503 responses returned when max-queued-requests is enabled. 64 | max-retry-delay: <%= @server_max_retry_delay %> 65 | 66 | # (optional) enable or disable environment class cache 67 | environment-class-cache-enabled: <%= @server_environment_class_cache_enabled %> 68 | 69 | # (optional) A map of environment variables which are made visible to 70 | # Ruby code running within JRuby, for example, via the Ruby ENV class. 71 | # By default, the only environment variables whose values are set into JRuby from the shell are HOME and PATH. 72 | # The default value for the GEM_HOME environment variable in JRuby is set from the value provided for the 73 | # jruby-puppet.gem-home key. 74 | # Any variable set from the map for the environment-vars key overrides these defaults. 75 | # Avoid overriding HOME, PATH, or GEM_HOME here because these values are already configurable via the shell 76 | # or jruby-puppet.gem-home. 77 | environment-vars: { 78 | <%- @server_environment_vars.each do |env_key, env_val| -%> 79 | "<%= env_key %>" : <%= env_val %> 80 | <%- end -%> 81 | } 82 | <%- if @compile_mode %> 83 | 84 | compile-mode: <%= @compile_mode %> 85 | <%- end -%> 86 | multithreaded: <%= @server_multithreaded %> 87 | } 88 | <%- if @versioned_code_id and @versioned_code_content -%> 89 | 90 | versioned-code: { 91 | code-id-command: <%= @versioned_code_id %> 92 | code-content-command: <%= @versioned_code_content %> 93 | } 94 | <%- end -%> 95 | 96 | # settings related to HTTPS client requests made by Puppet Server 97 | http-client: { 98 | # A list of acceptable protocols for making HTTPS requests 99 | ssl-protocols: [ 100 | <%- @server_ssl_protocols.each do |protocol| -%> 101 | <%= protocol %>, 102 | <%- end -%> 103 | ] 104 | 105 | # A list of acceptable cipher suites for making HTTPS requests 106 | cipher-suites: [ 107 | <%- @server_cipher_suites.each do |cipher| -%> 108 | <%= cipher %>, 109 | <%- end -%> 110 | ] 111 | 112 | # Whether to enable http-client metrics; defaults to 'true'. 113 | metrics-enabled: <%= @server_metrics %> 114 | 115 | # The amount of time, in milliseconds, that an outbound HTTP connection 116 | # will wait for data to be available before closing the socket. If not 117 | # defined, defaults to 20 minutes. If 0, the timeout is infinite and if 118 | # negative, the value is undefined by the application and governed by the 119 | # system default behavior. 120 | idle-timeout-milliseconds: <%= @server_idle_timeout %> 121 | 122 | # The amount of time, in milliseconds, that an outbound HTTP connection will 123 | # wait to connect before giving up. Defaults to 2 minutes if not set. If 0, 124 | # the timeout is infinite and if negative, the value is undefined in the 125 | # application and governed by the system default behavior. 126 | connect-timeout-milliseconds: <%= @server_connect_timeout %> 127 | } 128 | 129 | # settings related to profiling the puppet Ruby code 130 | profiler: { 131 | # enable or disable profiling for the Ruby code; 132 | enabled: <%= @server_profiler %> 133 | } 134 | 135 | # Settings related to telemetry 136 | dropsonde: { 137 | # enable or disable telemetry 138 | enabled: <%= @server_telemetry %> 139 | } 140 | -------------------------------------------------------------------------------- /templates/server/puppetserver/conf.d/webserver.conf.erb: -------------------------------------------------------------------------------- 1 | # 2 | # Managed by Puppet 3 | # 4 | webserver: { 5 | access-log-config: <%= @server_puppetserver_dir %>/request-logging.xml 6 | client-auth: want 7 | <%- if @server_http -%> 8 | host: <%= @server_ip %> 9 | port: <%= @server_http_port %> 10 | <%- end -%> 11 | ssl-host: <%= @server_ip %> 12 | ssl-port: <%= @server_port %> 13 | ssl-cert: <%= @server_ssl_cert %> 14 | ssl-key: <%= @server_ssl_cert_key %> 15 | ssl-ca-cert: <%= @server_ssl_ca_cert %> 16 | <%- if @server_crl_enable -%> 17 | ssl-crl-path: <%= @server_ssl_ca_crl %> 18 | <%- end -%> 19 | <%- if @server_ca -%> 20 | ssl-cert-chain: <%= @server_ssl_chain %> 21 | <%- end -%> 22 | idle-timeout-milliseconds: <%= @server_web_idle_timeout %> 23 | ssl-protocols: [ 24 | <%- @server_ssl_protocols.each do |ssl_protocol| -%> 25 | <%= ssl_protocol %>, 26 | <%- end -%> 27 | ] 28 | cipher-suites: [ 29 | <%- @server_cipher_suites.each do |cipher_suite| -%> 30 | <%= cipher_suite %>, 31 | <%- end -%> 32 | ] 33 | <%- if @acceptor_threads -%> 34 | acceptor-threads: <%= @acceptor_threads %> 35 | <%- end -%> 36 | <%- if @selector_threads -%> 37 | selector-threads: <%= @selector_threads %> 38 | <%- end -%> 39 | <%- if @ssl_acceptor_threads -%> 40 | ssl-acceptor-threads: <%= @ssl_acceptor_threads %> 41 | <%- end -%> 42 | <%- if @ssl_selector_threads -%> 43 | ssl-selector-threads: <%= @ssl_selector_threads %> 44 | <%- end -%> 45 | <%- if @max_threads -%> 46 | max-threads: <%= @max_threads %> 47 | <%- end -%> 48 | } 49 | -------------------------------------------------------------------------------- /templates/server/puppetserver/services.d/ca.cfg.erb: -------------------------------------------------------------------------------- 1 | # 2 | # Managed by Puppet 3 | # 4 | # To enable the CA service, leave the following line uncommented 5 | <%= '#' unless @server_ca -%>puppetlabs.services.ca.certificate-authority-service/certificate-authority-service 6 | # To disable the CA service, comment out the above line and uncomment the line below 7 | <%= '#' if @server_ca -%>puppetlabs.services.ca.certificate-authority-disabled-service/certificate-authority-disabled-service 8 | puppetlabs.trapperkeeper.services.watcher.filesystem-watch-service/filesystem-watch-service 9 | -------------------------------------------------------------------------------- /types/custom_trusted_oid_mapping.pp: -------------------------------------------------------------------------------- 1 | type Puppet::Custom_trusted_oid_mapping = Hash[String, Struct[{ shortname => String, longname => Optional[String], }]] 2 | --------------------------------------------------------------------------------