diff --git a/.fixtures.yml b/.fixtures.yml index 73040c53..62c8f39a 100644 --- a/.fixtures.yml +++ b/.fixtures.yml @@ -5,6 +5,5 @@ fixtures: concat: https://github.com/puppetlabs/puppetlabs-concat.git python: https://github.com/voxpupuli/puppet-python.git epel: https://github.com/voxpupuli/puppet-epel.git - apache: https://github.com/puppetlabs/puppetlabs-apache.git selinux_core: https://github.com/puppetlabs/puppetlabs-selinux_core.git yumrepo_core: https://github.com/puppetlabs/puppetlabs-yumrepo_core.git diff --git a/README.md b/README.md index b84c9b0d..1e56fb25 100644 --- a/README.md +++ b/README.md @@ -18,8 +18,7 @@ 1. [Offline Mode](#offline-mode) 1. [Set Default Environment](#set-default-environment) 1. [Disable SELinux Management](#disable-selinux-management) -1. [Apache](#apache) - - [Apache (with Reverse Proxy)](#apache-with-reverse-proxy) +1. [Web server integration](#web-server-integration) 1. [RedHat/CentOS 7 with Python 3](#redhatcentos-7-with-python-3) 1. [Using SSL to the PuppetDB host](#using-ssl-to-the-puppetdb-host) - [Using SSL to PuppetDB >= 6.9.1](#using-ssl-to-puppetdb--691) @@ -42,10 +41,6 @@ for the open source Puppet. ### Dependencies -Note that this module no longer explicitly requires the puppetlabs apache module. If you want to use the apache functionality of this module you will have to specify that the apache module is installed with: - - puppet module install puppetlabs-apache - In most cases the module requires the `virtualenv` package. This can be enabled in the module with the `manage_virtualenv` flag set to `true`: ```puppet @@ -138,92 +133,11 @@ class { 'puppetboard': If manage_selinux is true, manage policies related to SELinux. If false, do nothing. By default, this module will try to determine if SELinux is enabled, and manage the policies if it is. -## Apache - -If you want puppetboard accessible through Apache and you're able to use the -official `puppetlabs/apache` Puppet module, this module contains two classes -to help configuration. - -The first, `puppetboard::apache::vhost`, will use the `apache::vhost` -defined-type to create a full virtual host. This is useful if you want -puppetboard to be available under an address like http://pboard.example.com: - -(The following is generic code used in our tests, it works on Debian 9 and 10, also on Ubuntu 16.04 and 18.04. It will talk to PuppetDB on localhost via http) - -```puppet -# Configure Apache on this server -class { 'apache': - default_vhost => false, -} - -# Configure Puppetboard -class { 'puppetboard': - python_version => '3.8', - secret_key => fqdn_rand_string(32), - manage_virtualenv => true, -} - -# Access Puppetboard through pboard.example.com -class { 'puppetboard::apache::vhost': - vhost_name => 'pboard.example.com', - port => 80, -} -``` - -The second, `puppetboard::apache::conf`, will create an entry in -`/etc/apache2/conf.d` (or `/etc/httpd/conf.d`, depending on your distribution). -This is useful if you simply want puppetboard accessible from -http://example.com/puppetboard: - -```puppet -# Configure Puppetboard -class { 'puppetboard': - python_version => '3.8', - secret_key => fqdn_rand_string(32), -} - -# Access Puppetboard from example.com/puppetboard -class { 'puppetboard::apache::conf': } -``` - -### Apache (with Reverse Proxy) - -You can also relocate puppetboard to a sub-URI of a Virtual Host. This is -useful if you want to reverse-proxy puppetboard, but are not planning on -dedicating a domain just for puppetboard: +## Web server integration -```puppet -class { 'puppetboard::apache::vhost': - vhost_name => 'dashes.acme', - wsgi_alias => '/pboard', -} -``` - -In this case puppetboard will be available (on the default) on -http://dashes.acme:5000/pboard. You can then reverse-proxy to it like so: - -```apache -Redirect /pboard /pboard/ -ProxyPass /pboard/ http://dashes.acme:5000/pboard/ -ProxyPassReverse /pboard/ http://dashes.acme:5000/pboard/ -``` - -Using the puppetlabs/apache module: - -```puppet -apache::vhost { 'example.acme': - port => '80', - docroot => '/var/www/html', - redirect_source => [ '/pboard' ], - redirect_dest => [ '/pboard/' ], - proxy_pass => [ - { - 'path' => '/pboard/', - 'url' => 'http://dashes.acme:5000/pboard/', - }, - ], -} -``` +Integration PuppetBoard in your infrastructure is very site-specific, for this reason, the module does not manage web server configuration. +The `examples` directory contains example configurations sniptes for various web servers, using various systems to run the Python middleware and offering various authentication schemes. +Refer to them to implement a configuration that fits your needs. ## RedHat/CentOS 7 with Python 3 diff --git a/REFERENCE.md b/REFERENCE.md index f9ce918e..33673cf4 100644 --- a/REFERENCE.md +++ b/REFERENCE.md @@ -7,8 +7,6 @@ ### Classes * [`puppetboard`](#puppetboard): Base class for Puppetboard. Sets up the user and python environment. -* [`puppetboard::apache::conf`](#puppetboard--apache--conf): Creates an entry in your apache configuration directory to run PuppetBoard server-wide (i.e. not in a vhost). -* [`puppetboard::apache::vhost`](#puppetboard--apache--vhost): Sets up an apache::vhost to run PuppetBoard, and writes an appropriate wsgi.py from template ### Data types @@ -18,24 +16,7 @@ ### `puppetboard` -class { 'puppetboard': - user => 'pboard', - group => 'pboard', - basedir => '/www/puppetboard' - } -> - class { 'puppetboard::apache::conf': - user => 'pboard', - group => 'pboard', - basedir => '/www/puppetboard' - } - -#### Examples - -##### - -```puppet -configure puppetboard with an apache config for a subpath (http://$fqdn/puppetboard) -``` +Base class for Puppetboard. Sets up the user and python environment. #### Parameters @@ -79,10 +60,6 @@ The following parameters are available in the `puppetboard` class: * [`settings_file`](#-puppetboard--settings_file) * [`extra_settings`](#-puppetboard--extra_settings) * [`override`](#-puppetboard--override) -* [`enable_ldap_auth`](#-puppetboard--enable_ldap_auth) -* [`ldap_require_group`](#-puppetboard--ldap_require_group) -* [`apache_confd`](#-puppetboard--apache_confd) -* [`apache_service`](#-puppetboard--apache_service) * [`secret_key`](#-puppetboard--secret_key) ##### `install_from` @@ -387,34 +364,6 @@ Sets the Apache AllowOverride value Default value: `['None']` -##### `enable_ldap_auth` - -Data type: `Boolean` - -Whether to enable LDAP auth - -Default value: `false` - -##### `ldap_require_group` - -Data type: `Boolean` - -LDAP group to require on login - -Default value: `false` - -##### `apache_confd` - -Data type: `Stdlib::Absolutepath` - -path to the apache2 vhost directory - -##### `apache_service` - -Data type: `String[1]` - -name of the apache2 service - ##### `secret_key` Data type: `Optional[String[1]]` @@ -423,348 +372,6 @@ used for CSRF prevention and more. It should be a long, secret string, the same Default value: `undef` -### `puppetboard::apache::conf` - -Creates an entry in your apache configuration directory to run PuppetBoard server-wide (i.e. not in a vhost). - -* **Note** Make sure you have purge_configs set to false in your apache class! - -#### Parameters - -The following parameters are available in the `puppetboard::apache::conf` class: - -* [`wsgi_alias`](#-puppetboard--apache--conf--wsgi_alias) -* [`threads`](#-puppetboard--apache--conf--threads) -* [`max_reqs`](#-puppetboard--apache--conf--max_reqs) -* [`user`](#-puppetboard--apache--conf--user) -* [`group`](#-puppetboard--apache--conf--group) -* [`basedir`](#-puppetboard--apache--conf--basedir) -* [`enable_ldap_auth`](#-puppetboard--apache--conf--enable_ldap_auth) -* [`ldap_bind_dn`](#-puppetboard--apache--conf--ldap_bind_dn) -* [`ldap_bind_password`](#-puppetboard--apache--conf--ldap_bind_password) -* [`ldap_url`](#-puppetboard--apache--conf--ldap_url) -* [`ldap_bind_authoritative`](#-puppetboard--apache--conf--ldap_bind_authoritative) -* [`ldap_require_group`](#-puppetboard--apache--conf--ldap_require_group) -* [`ldap_require_group_dn`](#-puppetboard--apache--conf--ldap_require_group_dn) -* [`virtualenv_dir`](#-puppetboard--apache--conf--virtualenv_dir) - -##### `wsgi_alias` - -Data type: `Stdlib::Unixpath` - -WSGI script alias source - -Default value: `'/puppetboard'` - -##### `threads` - -Data type: `Integer[1]` - -Number of WSGI threads to use - -Default value: `5` - -##### `max_reqs` - -Data type: `Integer[0]` - -Limit on number of requests allowed to daemon process Defaults to 0 (no limit) - -Default value: `0` - -##### `user` - -Data type: `String[1]` - -WSGI daemon process user, and daemon process name - -Default value: `$puppetboard::user` - -##### `group` - -Data type: `String[1]` - -WSGI daemon process group owner, and daemon process group - -Default value: `$puppetboard::group` - -##### `basedir` - -Data type: `Stdlib::AbsolutePath` - -Base directory where to build puppetboard vcsrepo and python virtualenv. - -Default value: `$puppetboard::basedir` - -##### `enable_ldap_auth` - -Data type: `Boolean` - -Whether to enable LDAP auth - -Default value: `$puppetboard::enable_ldap_auth` - -##### `ldap_bind_dn` - -Data type: `Optional[String[1]]` - -LDAP Bind DN - -Default value: `undef` - -##### `ldap_bind_password` - -Data type: `Optional[String[1]]` - -LDAP password - -Default value: `undef` - -##### `ldap_url` - -Data type: `Optional[String[1]]` - -LDAP connection string - -Default value: `undef` - -##### `ldap_bind_authoritative` - -Data type: `Optional[String[1]]` - -Determines if other authentication providers are used when a user can be mapped to a DN but the server cannot bind with the credentials - -Default value: `undef` - -##### `ldap_require_group` - -Data type: `Boolean` - -LDAP group to require on login - -Default value: `$puppetboard::ldap_require_group` - -##### `ldap_require_group_dn` - -Data type: `Optional[String[1]]` - -LDAP group DN for LDAP group - -Default value: `undef` - -##### `virtualenv_dir` - -Data type: `Stdlib::Absolutepath` - -Set location where virtualenv will be installed - -Default value: `$puppetboard::virtualenv_dir` - -### `puppetboard::apache::vhost` - -Sets up an apache::vhost to run PuppetBoard, and writes an appropriate wsgi.py from template - -#### Parameters - -The following parameters are available in the `puppetboard::apache::vhost` class: - -* [`vhost_name`](#-puppetboard--apache--vhost--vhost_name) -* [`wsgi_alias`](#-puppetboard--apache--vhost--wsgi_alias) -* [`ip`](#-puppetboard--apache--vhost--ip) -* [`port`](#-puppetboard--apache--vhost--port) -* [`ssl`](#-puppetboard--apache--vhost--ssl) -* [`ssl_cert`](#-puppetboard--apache--vhost--ssl_cert) -* [`ssl_key`](#-puppetboard--apache--vhost--ssl_key) -* [`ssl_chain`](#-puppetboard--apache--vhost--ssl_chain) -* [`threads`](#-puppetboard--apache--vhost--threads) -* [`user`](#-puppetboard--apache--vhost--user) -* [`group`](#-puppetboard--apache--vhost--group) -* [`basedir`](#-puppetboard--apache--vhost--basedir) -* [`override`](#-puppetboard--apache--vhost--override) -* [`enable_ldap_auth`](#-puppetboard--apache--vhost--enable_ldap_auth) -* [`ldap_bind_dn`](#-puppetboard--apache--vhost--ldap_bind_dn) -* [`ldap_bind_password`](#-puppetboard--apache--vhost--ldap_bind_password) -* [`ldap_url`](#-puppetboard--apache--vhost--ldap_url) -* [`ldap_bind_authoritative`](#-puppetboard--apache--vhost--ldap_bind_authoritative) -* [`ldap_require_group`](#-puppetboard--apache--vhost--ldap_require_group) -* [`ldap_require_group_dn`](#-puppetboard--apache--vhost--ldap_require_group_dn) -* [`virtualenv_dir`](#-puppetboard--apache--vhost--virtualenv_dir) -* [`custom_apache_parameters`](#-puppetboard--apache--vhost--custom_apache_parameters) - -##### `vhost_name` - -Data type: `String[1]` - -The vhost ServerName. - -##### `wsgi_alias` - -Data type: `Stdlib::Unixpath` - -WSGI script alias source - -Default value: `'/'` - -##### `ip` - -Data type: `Optional[Stdlib::IP::Address]` - -IP for the vhost to bind to - -Default value: `undef` - -##### `port` - -Data type: `Stdlib::Port` - -Port for the vhost to listen on. - -Default value: `5000` - -##### `ssl` - -Data type: `Boolean` - -If vhost should be configured with ssl - -Default value: `false` - -##### `ssl_cert` - -Data type: `Optional[Stdlib::AbsolutePath]` - -Path to server SSL cert - -Default value: `undef` - -##### `ssl_key` - -Data type: `Optional[Stdlib::AbsolutePath]` - -Path to server SSL key - -Default value: `undef` - -##### `ssl_chain` - -Data type: `Optional[Stdlib::AbsolutePath]` - -Path to server CA Chain file - -Default value: `undef` - -##### `threads` - -Data type: `Integer[1]` - -Number of WSGI threads to use. - -Default value: `5` - -##### `user` - -Data type: `String[1]` - -WSGI daemon process user, and daemon process name - -Default value: `$puppetboard::user` - -##### `group` - -Data type: `String[1]` - -WSGI daemon process group owner, and daemon process group - -Default value: `$puppetboard::group` - -##### `basedir` - -Data type: `Stdlib::AbsolutePath` - -Base directory where to build puppetboard vcsrepo and python virtualenv. - -Default value: `$puppetboard::basedir` - -##### `override` - -Data type: `Variant[Array[String[1]], String[1]]` - -Sets the Apache AllowOverride value - -Default value: `$puppetboard::override` - -##### `enable_ldap_auth` - -Data type: `Boolean` - -Whether to enable LDAP auth - -Default value: `$puppetboard::enable_ldap_auth` - -##### `ldap_bind_dn` - -Data type: `Optional[String[1]]` - -LDAP Bind DN - -Default value: `undef` - -##### `ldap_bind_password` - -Data type: `Optional[String[1]]` - -LDAP password - -Default value: `undef` - -##### `ldap_url` - -Data type: `Optional[String[1]]` - -LDAP connection string - -Default value: `undef` - -##### `ldap_bind_authoritative` - -Data type: `Optional[String[1]]` - -Determines if other authentication providers are used when a user can be mapped to a DN but the server cannot bind with the credentials - -Default value: `undef` - -##### `ldap_require_group` - -Data type: `Boolean` - -LDAP group to require on login - -Default value: `$puppetboard::ldap_require_group` - -##### `ldap_require_group_dn` - -Data type: `Optional[String[1]]` - -LDAP group DN for LDAP group - -Default value: `undef` - -##### `virtualenv_dir` - -Data type: `Stdlib::Absolutepath` - -Set location where virtualenv will be installed - -Default value: `$puppetboard::virtualenv_dir` - -##### `custom_apache_parameters` - -Data type: `Hash` - -A hash passed to the `apache::vhost` for custom settings - -Default value: `{}` - ## Data types ### `Puppetboard::Syslogpriority` diff --git a/data/os/Debian.yaml b/data/os/Debian.yaml deleted file mode 100644 index 780605be..00000000 --- a/data/os/Debian.yaml +++ /dev/null @@ -1,2 +0,0 @@ -puppetboard::apache_confd: '/etc/apache2/conf-enabled' -puppetboard::apache_service: 'apache2' diff --git a/data/os/FreeBSD.yaml b/data/os/FreeBSD.yaml index c5fc7c17..ecc157ff 100644 --- a/data/os/FreeBSD.yaml +++ b/data/os/FreeBSD.yaml @@ -1,6 +1,4 @@ --- -puppetboard::apache_confd: "/usr/local/etc/apache24/conf.d" -puppetboard::apache_service: "apache24" puppetboard::install_from: "package" puppetboard::package_name: "py39-puppetboard" puppetboard::python_version: "3.9" diff --git a/data/os/RedHat.yaml b/data/os/RedHat.yaml deleted file mode 100644 index 7759fedc..00000000 --- a/data/os/RedHat.yaml +++ /dev/null @@ -1,2 +0,0 @@ -puppetboard::apache_confd: '/etc/httpd/conf.d' -puppetboard::apache_service: 'httpd' diff --git a/examples/apache_passenger_puppetca_integration.pp b/examples/apache_passenger_puppetca_integration.pp new file mode 100644 index 00000000..a87bd1b0 --- /dev/null +++ b/examples/apache_passenger_puppetca_integration.pp @@ -0,0 +1,51 @@ +# An example configuration that serve PuppetBeard with Apache and Passenger, +# using Puppet certificates for client authentication. + +$hostname = 'puppetboard.example.com' + +$puppetboard_path = "/srv/www/${hostname}" + +class { 'puppetboard': + version => '4.2.0', + basedir => $puppetboard_path, + secret_key => stdlib::fqdn_rand_string(64), +} + +$wsgi = @(WSGI) + from __future__ import absolute_import + import os + from puppetboard.app import app as application + | WSGI + +file { "${puppetboard_path}/wsgi.py": + ensure => file, + mode => '0755', + content => $wsgi, +} + +apache::vhost { $hostname: + port => 443, + docroot => "${puppetboard_path}/public", + aliases => [ + { + alias => '/static', + path => "${puppetboard_path}/puppetboard/static", + }, + ], + manage_docroot => false, + setenv => [ + "PUPPETBOARD_SETTINGS ${puppetboard_path}/settings.py", + ], + ssl => true, + ssl_ca => "${settings::ssldir}/certs/ca.pem", + ssl_crl => "${settings::ssldir}/crl.pem", + ssl_verify_client => 'require', + passenger_app_root => $puppetboard_path, + passenger_app_type => 'wsgi', + passenger_startup_file => 'wsgi.py', + passenger_python => "${puppetboard_path}/virtenv-puppetboard/bin/python3", + passenger_user => 'puppetboard', + passenger_group => 'puppetboard', +} + +Class['puppetboard'] ~> Class['apache::service'] diff --git a/examples/apache_wsgi_ldap_integration.pp b/examples/apache_wsgi_ldap_integration.pp new file mode 100644 index 00000000..12259f0c --- /dev/null +++ b/examples/apache_wsgi_ldap_integration.pp @@ -0,0 +1,79 @@ +# An example configuration that serve PuppetBoard with Apache and WSGI, using +# LDAP for authentication. + +$hostname = 'puppetboard.example.com' + +$puppetboard_path = "/srv/www/${hostname}" + +include apache::mod::wsgi + +class { 'puppetboard': + version => '4.2.0', + basedir => $puppetboard_path, + secret_key => stdlib::fqdn_rand_string(64), +} + +$wsgi = @(WSGI) + from __future__ import absolute_import + + import os + import sys + + me = os.path.dirname(os.path.abspath(__file__)) + os.environ['PUPPETBOARD_SETTINGS'] = os.path.join(me, 'settings.py') + + # Add us to the PYTHONPATH/sys.path if we're not on it + if not me in sys.path: + sys.path.insert(0, me) + + from puppetboard.app import app as application + | WSGI + +file { "${puppetboard_path}/wsgi.py": + ensure => file, + mode => '0755', + content => $wsgi, +} + +apache::vhost { $hostname: + port => 443, + docroot => "${puppetboard_path}/public", + aliases => [ + { + alias => '/static', + path => "${puppetboard_path}/puppetboard/static", + }, + ], + manage_docroot => false, + wsgi_daemon_process => { + puppetboard => { + 'python-home' => $virtualenv_dir, + user => $user, + group => $group, + threads => $threads, + 'maximum-requests' => $max_reqs, + }, + }, + wsgi_script_aliases => { + '/' => "${puppetboard_path}/wsgi.py", + }, + wsgi_process_group => 'puppetboard', + wsgi_application_group => '%{GLOBAL}', + directories => [ + { + path => '/', + provider => 'location', + auth_basic_provider => 'ldap', + auth_type => 'basic', + auth_name => 'Login to PuppetBoard', + auth_ldap_url => '"ldap://ldap.example.org/ou=people,dc=example,dc=org?uid" STARTTLS', + auth_ldap_bind_dn => $bind_dn, + auth_ldap_bind_pw => $bind_password.unwrap, + require => [ + 'ldap-group puppetboard', + ], + }, + ], +} + +Class['puppetboard'] ~> Class['apache::service'] diff --git a/examples/nginx_passenger_puppetca_integration.pp b/examples/nginx_passenger_puppetca_integration.pp new file mode 100644 index 00000000..7bce8a06 --- /dev/null +++ b/examples/nginx_passenger_puppetca_integration.pp @@ -0,0 +1,58 @@ +# An example configuration that serve PuppetBoard with Nginx and Passenger, +# using Puppet certificates for client authentication. + +$hostname = 'puppetboard.example.com' + +$puppetboard_path = "/srv/www/${hostname}" + +class { 'puppetboard': + version => '5.4.0', + basedir => $puppetboard_path, + secret_key => stdlib::fqdn_rand_string(64), + + # ... + + notify => Service['nginx'], +} + +$wsgi = @(WSGI) + from __future__ import absolute_import + import os + from puppetboard.app import app as application + | WSGI + +file { "/srv/www/${hostname}/puppetboard/wsgi.py": + ensure => file, + mode => '0755', + content => $wsgi, +} + +nginx::resource::server { $hostname: + ssl_verify_client => 'on', + ssl_client_cert => "${settings::ssldir}/certs/ca.pem", + ssl_crl => "${settings::ssldir}/crl.pem", + server_name => [ + $hostname, + ], + use_default_location => false, + server_cfg_prepend => { + passenger_app_root => "${puppetboard_path}/puppetboard", + passenger_app_type => 'wsgi', + passenger_startup_file => 'wsgi.py', + passenger_python => "${puppetboard_path}/virtenv-puppetboard/bin/python3", + passenger_user => 'puppetboard', + passenger_group => 'puppetboard', + passenger_enabled => 'on', + passenger_min_instances => 1, + passenger_env_var => { + 'PUPPETBOARD_SETTINGS' => "${puppetboard_path}/puppetboard/settings.py", + }, + }, + www_root => "${puppetboard_path}/puppetboard/public", +} + +nginx::resource::location { "${hostname} /static": + server => $hostname, + location => '/static', + www_root => "${puppetboard_path}/puppetboard/puppetboard", +} diff --git a/files/wsgi.py b/files/wsgi.py deleted file mode 100644 index c6b593c1..00000000 --- a/files/wsgi.py +++ /dev/null @@ -1,14 +0,0 @@ -# THIS FILE IS MANAGED BY PUPPET -from __future__ import absolute_import - -import os -import sys - -me = os.path.dirname(os.path.abspath(__file__)) -os.environ['PUPPETBOARD_SETTINGS'] = os.path.join(me, 'settings.py') - -# Add us to the PYTHONPATH/sys.path if we're not on it -if not me in sys.path: - sys.path.insert(0, me) - -from puppetboard.app import app as application diff --git a/manifests/apache/conf.pp b/manifests/apache/conf.pp deleted file mode 100644 index 81802f4e..00000000 --- a/manifests/apache/conf.pp +++ /dev/null @@ -1,82 +0,0 @@ -# @summary Creates an entry in your apache configuration directory to run PuppetBoard server-wide (i.e. not in a vhost). -# -# @param wsgi_alias WSGI script alias source -# @param threads Number of WSGI threads to use -# @param max_reqs Limit on number of requests allowed to daemon process Defaults to 0 (no limit) -# @param user WSGI daemon process user, and daemon process name -# @param group WSGI daemon process group owner, and daemon process group -# @param basedir Base directory where to build puppetboard vcsrepo and python virtualenv. -# @param enable_ldap_auth Whether to enable LDAP auth -# @param ldap_bind_dn LDAP Bind DN -# @param ldap_bind_password LDAP password -# @param ldap_url LDAP connection string -# @param ldap_bind_authoritative Determines if other authentication providers are used when a user can be mapped to a DN but the server cannot bind with the credentials -# @param ldap_require_group LDAP group to require on login -# @param ldap_require_group_dn LDAP group DN for LDAP group -# @param virtualenv_dir Set location where virtualenv will be installed -# -# @note Make sure you have purge_configs set to false in your apache class! -# @note This runs the WSGI application with a WSGIProcessGroup of $user and a WSGIApplicationGroup of %{GLOBAL}. -# -class puppetboard::apache::conf ( - Stdlib::Unixpath $wsgi_alias = '/puppetboard', - Integer[1] $threads = 5, - Integer[0] $max_reqs = 0, - String[1] $user = $puppetboard::user, - String[1] $group = $puppetboard::group, - Stdlib::AbsolutePath $basedir = $puppetboard::basedir, - Boolean $enable_ldap_auth = $puppetboard::enable_ldap_auth, - Optional[String[1]] $ldap_bind_dn = undef, - Optional[String[1]] $ldap_bind_password = undef, - Optional[String[1]] $ldap_url = undef, - Optional[String[1]] $ldap_bind_authoritative = undef, - Boolean $ldap_require_group = $puppetboard::ldap_require_group, - Optional[String[1]] $ldap_require_group_dn = undef, - Stdlib::Absolutepath $virtualenv_dir = $puppetboard::virtualenv_dir, -) { - $wsgi = $facts['os']['family'] ? { - 'Debian' => { - package_name => 'libapache2-mod-wsgi-py3', - mod_path => '/usr/lib/apache2/modules/mod_wsgi.so', - }, - default => {}, - } - class { 'apache::mod::wsgi': - * => $wsgi, - } - - $docroot = "${basedir}/puppetboard" - - file { "${puppetboard::apache_confd}/puppetboard.conf": - ensure => absent, - } - -> file { "${docroot}/wsgi.py": - ensure => file, - content => file("${module_name}/wsgi.py"), - owner => $user, - group => $group, - } - -> apache::custom_config { 'puppetboard': - ensure => present, - owner => 'root', - group => 'root', - content => epp("${module_name}/apache/conf.epp", - { - 'docroot' => $docroot, - 'enable_ldap_auth' => $enable_ldap_auth, - 'group' => $group, - 'ldap_bind_authoritative' => $ldap_bind_authoritative, - 'ldap_bind_dn' => $ldap_bind_dn, - 'ldap_bind_password' => $ldap_bind_password, - 'ldap_require_group_dn' => $ldap_require_group_dn, - 'ldap_require_group' => $ldap_require_group, - 'ldap_url' => $ldap_url, - 'max_reqs' => $max_reqs, - 'threads' => $threads, - 'user' => $user, - 'virtualenv_dir' => $virtualenv_dir, - 'wsgi_alias' => $wsgi_alias, - }, - ), - } -} diff --git a/manifests/apache/vhost.pp b/manifests/apache/vhost.pp deleted file mode 100644 index 30672b06..00000000 --- a/manifests/apache/vhost.pp +++ /dev/null @@ -1,128 +0,0 @@ -# @summary Sets up an apache::vhost to run PuppetBoard, and writes an appropriate wsgi.py from template -# -# @param vhost_name The vhost ServerName. -# @param wsgi_alias WSGI script alias source -# @param ip IP for the vhost to bind to -# @param port Port for the vhost to listen on. -# @param ssl If vhost should be configured with ssl -# @param ssl_cert Path to server SSL cert -# @param ssl_key Path to server SSL key -# @param ssl_chain Path to server CA Chain file -# @param threads Number of WSGI threads to use. -# @param user WSGI daemon process user, and daemon process name -# @param group WSGI daemon process group owner, and daemon process group -# @param basedir Base directory where to build puppetboard vcsrepo and python virtualenv. -# @param override Sets the Apache AllowOverride value -# @param enable_ldap_auth Whether to enable LDAP auth -# @param ldap_bind_dn LDAP Bind DN -# @param ldap_bind_password LDAP password -# @param ldap_url LDAP connection string -# @param ldap_bind_authoritative Determines if other authentication providers are used when a user can be mapped to a DN but the server cannot bind with the credentials -# @param ldap_require_group LDAP group to require on login -# @param ldap_require_group_dn LDAP group DN for LDAP group -# @param virtualenv_dir Set location where virtualenv will be installed -# @param custom_apache_parameters A hash passed to the `apache::vhost` for custom settings -class puppetboard::apache::vhost ( - String[1] $vhost_name, - Stdlib::Unixpath $wsgi_alias = '/', - Optional[Stdlib::IP::Address] $ip = undef, - Stdlib::Port $port = 5000, - Boolean $ssl = false, - Optional[Stdlib::AbsolutePath] $ssl_cert = undef, - Optional[Stdlib::AbsolutePath] $ssl_key = undef, - Optional[Stdlib::AbsolutePath] $ssl_chain = undef, - Integer[1] $threads = 5, - String[1] $user = $puppetboard::user, - String[1] $group = $puppetboard::group, - Stdlib::AbsolutePath $basedir = $puppetboard::basedir, - Variant[Array[String[1]], String[1]] $override = $puppetboard::override, - Boolean $enable_ldap_auth = $puppetboard::enable_ldap_auth, - Optional[String[1]] $ldap_bind_dn = undef, - Optional[String[1]] $ldap_bind_password = undef, - Optional[String[1]] $ldap_url = undef, - Optional[String[1]] $ldap_bind_authoritative = undef, - Boolean $ldap_require_group = $puppetboard::ldap_require_group, - Optional[String[1]] $ldap_require_group_dn = undef, - Stdlib::Absolutepath $virtualenv_dir = $puppetboard::virtualenv_dir, - Hash $custom_apache_parameters = {}, -) { - $wsgi = $facts['os']['family'] ? { - 'Debian' => { - package_name => 'libapache2-mod-wsgi-py3', - mod_path => '/usr/lib/apache2/modules/mod_wsgi.so', - }, - default => {}, - } - class { 'apache::mod::wsgi': - * => $wsgi, - } - - $docroot = "${basedir}/puppetboard" - - $wsgi_script_aliases = { - "${wsgi_alias}" => "${docroot}/wsgi.py", - } - - $wsgi_daemon_process = { - $user => { - threads => $threads, - group => $group, - user => $user, - python-home => $virtualenv_dir, - }, - } - - file { "${docroot}/wsgi.py": - ensure => file, - content => file("${module_name}/wsgi.py"), - owner => $user, - group => $group, - } - - if $enable_ldap_auth { - $ldap_additional_includes = ["${puppetboard::apache_confd}/puppetboard-ldap.part"] - $ldap_require = File["${puppetboard::apache_confd}/puppetboard-ldap.part"] - file { 'puppetboard-ldap.part': - ensure => file, - path => "${puppetboard::apache_confd}/puppetboard-ldap.part", - owner => 'root', - group => 'root', - content => epp("${module_name}/apache/ldap.epp", - { - 'ldap_bind_authoritative' => $ldap_bind_authoritative, - 'ldap_bind_dn' => $ldap_bind_dn, - 'ldap_bind_password' => $ldap_bind_password, - 'ldap_require_group_dn' => $ldap_require_group_dn, - 'ldap_require_group' => $ldap_require_group, - 'ldap_url' => $ldap_url, - }, - ), - require => File["${docroot}/wsgi.py"], - notify => Service[$puppetboard::apache_service], - } - } - else { - $ldap_additional_includes = undef - $ldap_require = undef - } - apache::vhost { $vhost_name: - port => $port, - ip => $ip, - docroot => $docroot, - manage_docroot => false, - ssl => $ssl, - ssl_cert => $ssl_cert, - ssl_key => $ssl_key, - ssl_chain => $ssl_chain, - additional_includes => $ldap_additional_includes, - wsgi_daemon_process => $wsgi_daemon_process, - wsgi_process_group => $group, - wsgi_script_aliases => $wsgi_script_aliases, - override => [$override].flatten, - require => [File["${docroot}/wsgi.py"], $ldap_require], - notify => Service[$puppetboard::apache_service], - * => $custom_apache_parameters, - } - - File[$puppetboard::settings_file] ~> Service[$puppetboard::apache_service] -} diff --git a/manifests/init.pp b/manifests/init.pp index 62f300d6..f6cf4aa5 100644 --- a/manifests/init.pp +++ b/manifests/init.pp @@ -38,29 +38,8 @@ # @param settings_file Path to puppetboard configuration file # @param extra_settings Defaults to an empty hash '{}'. Used to pass in arbitrary key/value # @param override Sets the Apache AllowOverride value -# @param enable_ldap_auth Whether to enable LDAP auth -# @param ldap_require_group LDAP group to require on login -# @param apache_confd path to the apache2 vhost directory -# @param apache_service name of the apache2 service # @param secret_key used for CSRF prevention and more. It should be a long, secret string, the same for all instances of the app. Required since Puppetboard 5.0.0. -# -# @example -# configure puppetboard with an apache config for a subpath (http://$fqdn/puppetboard) -# -# class { 'puppetboard': -# user => 'pboard', -# group => 'pboard', -# basedir => '/www/puppetboard' -# } -> -# class { 'puppetboard::apache::conf': -# user => 'pboard', -# group => 'pboard', -# basedir => '/www/puppetboard' -# } -# class puppetboard ( - Stdlib::Absolutepath $apache_confd, - String[1] $apache_service, Python::Version $python_version, Enum['package', 'pip', 'vcsrepo'] $install_from = 'pip', Boolean $manage_selinux = pick($facts['os.selinux.enabled'], false), @@ -97,8 +76,6 @@ Stdlib::Absolutepath $settings_file = "${basedir}/puppetboard/settings.py", Hash $extra_settings = {}, Variant[Array[String[1]], String[1]] $override = ['None'], - Boolean $enable_ldap_auth = false, - Boolean $ldap_require_group = false, Variant[Enum['latest'], String[1]] $version = 'latest', Boolean $use_pre_releases = false, Optional[String[1]] $secret_key = undef, diff --git a/spec/acceptance/class_spec.rb b/spec/acceptance/class_spec.rb index 458dc0d7..8d0327a9 100644 --- a/spec/acceptance/class_spec.rb +++ b/spec/acceptance/class_spec.rb @@ -5,199 +5,24 @@ require_relative 'support/puppetdb' describe 'puppetboard class', if: has_puppetdb do - case fact('os.family') - when 'RedHat' - apache_conf_file = '/etc/httpd/conf.d/25-puppetboard.conf' - when 'Debian' - apache_conf_file = '/etc/apache2/conf.d/25-puppetboard.conf' - end - - context 'configuring Apache without vhost / mod_wsgi' do - it 'works with no errors' do - pp = <<-EOS - # Configure PuppetDB - class { 'puppetdb': - disable_ssl => true, - manage_firewall => false, - } - - # Configure Puppetboard - class { 'puppetboard': - manage_virtualenv => true, - manage_git => true, - require => Class['puppetdb'], - secret_key => 'this_should_be_a_long_secret_string', - } - - # Configure Apache to allow access to localhost/puppetboard - class { 'puppetboard::apache::conf': } - EOS - - # Run it twice and test for idempotency - apply_manifest(pp, catch_failures: true) - apply_manifest(pp, catch_failures: true) - end - - it 'answers to localhost' do - shell('/usr/bin/curl localhost/puppetboard/') do |r| - expect(r.stdout).to match(%r{Puppetboard}) - expect(r.exit_code).to be_zero - end - end - end - - context 'configuring Apache with vhost / mod_wsgi' do - it 'works with no errors' do - pp = <<-EOS - # Configure Apache on this server - class { 'apache': - default_vhost => false, - } - - # Configure PuppetDB - class { 'puppetdb': - disable_ssl => true, - manage_firewall => false, - } - - # Configure Puppetboard - class { 'puppetboard': - manage_virtualenv => true, - manage_git => true, - require => Class['puppetdb'], - secret_key => 'this_should_be_a_long_secret_string', - } - - # Access Puppetboard through pboard.example.com - class { 'puppetboard::apache::vhost': - vhost_name => 'localhost', - port => 80, - } - EOS - - # Run it twice and test for idempotency - apply_manifest(pp, catch_failures: true) - apply_manifest(pp, catch_failures: true) - end - - it 'answers to localhost' do - shell('/usr/bin/curl localhost') do |r| - expect(r.stdout).to match(%r{Puppetboard}) - expect(r.exit_code).to be_zero - end - end - end - context 'with SSL' do it 'works with no errors' do pp = <<-EOS # Configure Apache on this server - class { 'apache': } - class { 'apache::mod::wsgi': } class { 'puppetboard': - manage_virtualenv => true, - manage_git => true, - puppetdb_host => 'puppet.example.com', - puppetdb_port => 8081, - puppetdb_key => '/var/lib/puppet/ssl/private_keys/test.networkninjas.net.pem', + manage_virtualenv => true, + manage_git => true, + puppetdb_host => 'puppet.example.com', + puppetdb_port => 8081, + puppetdb_key => '/var/lib/puppet/ssl/private_keys/test.networkninjas.net.pem', puppetdb_ssl_verify => true, - puppetdb_cert => '/var/lib/puppet/ssl/certs/test.networkninjas.net.pem', - require => Class['puppetdb'], - secret_key => 'this_should_be_a_long_secret_string', + puppetdb_cert => '/var/lib/puppet/ssl/certs/test.networkninjas.net.pem', + require => Class['puppetdb'], + secret_key => 'this_should_be_a_long_secret_string', } # Configure PuppetDB class { 'puppetdb': - disable_ssl => true, - manage_firewall => false, - } - EOS - - # Run it twice and test for idempotency - apply_manifest(pp, catch_failures: true) - apply_manifest(pp, catch_failures: true) - end - - describe file('/srv/puppetboard/puppetboard/settings.py') do - it { is_expected.to contain "PUPPETDB_KEY = '/var/lib/puppet/ssl/private_keys/test.networkninjas.net.pem'" } - it { is_expected.to contain "PUPPETDB_CERT = '/var/lib/puppet/ssl/certs/test.networkninjas.net.pem'" } - end - end - - context 'LDAP auth' do - it 'works with no errors' do - pp = <<-EOS - # Configure Apache on this server - class { 'apache': } - class { 'apache::mod::authnz_ldap': } - -> class { 'puppetboard': - manage_virtualenv => true, - manage_git => true, - puppetdb_host => 'puppet.example.com', - puppetdb_port => 8081, - puppetdb_key => "/var/lib/puppet/ssl/private_keys/test.networkninjas.net.pem", - puppetdb_ssl_verify => true, - puppetdb_cert => "/var/lib/puppet/ssl/certs/test.networkninjas.net.pem", - require => Class['puppetdb'], - secret_key => 'this_should_be_a_long_secret_string', - } - class { 'puppetboard::apache::conf': - enable_ldap_auth => true, - ldap_bind_dn => 'cn=user,dc=puppet,dc=example,dc=com', - ldap_bind_password => 'password', - ldap_url => 'ldap://puppet.example.com', - } - # Configure PuppetDB - class { 'puppetdb': - disable_ssl => true, - manage_firewall => false, - } - EOS - - # Run it twice and test for idempotency - apply_manifest(pp, catch_failures: true) - apply_manifest(pp, catch_failures: true) - end - - describe file(apache_conf_file) do - it { is_expected.to contain 'AuthBasicProvider ldap' } - it { is_expected.to contain 'AuthLDAPBindDN "cn=user,dc=puppet,dc=example,dc=com"' } - it { is_expected.to contain 'AuthLDAPURL "ldap://puppet.example.com"' } - end - - describe file('/srv/puppetboard/puppetboard/settings.py') do - it { is_expected.to contain "PUPPETDB_KEY = '/var/lib/puppet/ssl/private_keys/test.networkninjas.net.pem'" } - it { is_expected.to contain "PUPPETDB_CERT = '/var/lib/puppet/ssl/certs/test.networkninjas.net.pem'" } - end - end - - context 'AUTH ldap-group' do - it 'works with no errors' do - pp = <<-EOS - # Configure Apache on this server - class { 'apache': } - class { 'apache::mod::authnz_ldap': } - -> class { 'puppetboard': - manage_virtualenv => true, - manage_git => true, - puppetdb_host => 'puppet.example.com', - puppetdb_port => 8081, - puppetdb_key => "/var/lib/puppet/ssl/private_keys/test.networkninjas.net.pem", - puppetdb_ssl_verify => true, - puppetdb_cert => "/var/lib/puppet/ssl/certs/test.networkninjas.net.pem", - require => Class['puppetdb'], - secret_key => 'this_should_be_a_long_secret_string', - } - class { 'puppetboard::apache::conf': - enable_ldap_auth => true, - ldap_bind_dn => 'cn=user,dc=puppet,dc=example,dc=com', - ldap_bind_password => 'password', - ldap_url => 'ldap://puppet.example.com', - ldap_require_group => true, - ldap_require_group_dn => 'cn=admins,=cn=groups,dc=puppet,dc=example,dc=com', - } - # Configure PuppetDB - class { 'puppetdb': - disable_ssl => true, + disable_ssl => true, manage_firewall => false, } EOS @@ -207,13 +32,6 @@ class { 'puppetdb': apply_manifest(pp, catch_failures: true) end - describe file(apache_conf_file) do - it { is_expected.to contain 'AuthBasicProvider ldap' } - it { is_expected.to contain 'AuthLDAPBindDN "cn=user,dc=puppet,dc=example,dc=com"' } - it { is_expected.to contain 'AuthLDAPURL "ldap://puppet.example.com"' } - it { is_expected.to contain 'Require ldap-group cn=admins,=cn=groups,dc=puppet,dc=example,dc=com' } - end - describe file('/srv/puppetboard/puppetboard/settings.py') do it { is_expected.to contain "PUPPETDB_KEY = '/var/lib/puppet/ssl/private_keys/test.networkninjas.net.pem'" } it { is_expected.to contain "PUPPETDB_CERT = '/var/lib/puppet/ssl/certs/test.networkninjas.net.pem'" } diff --git a/spec/classes/apache/conf_spec.rb b/spec/classes/apache/conf_spec.rb deleted file mode 100644 index 4e5cac1d..00000000 --- a/spec/classes/apache/conf_spec.rb +++ /dev/null @@ -1,29 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -describe 'puppetboard::apache::conf' do - describe 'default params' do - let :params do - {} - end - let(:pre_condition) do - [ - 'class { "puppetboard": - secret_key => "this_should_be_a_long_secret_string", - }' - ] - end - - on_supported_os.each do |os, facts| - context "on #{os}" do - let :facts do - facts - end - - it { is_expected.to compile.with_all_deps } - it { is_expected.to contain_class('apache::mod::wsgi') } - end - end - end -end diff --git a/spec/classes/apache/vhost_spec.rb b/spec/classes/apache/vhost_spec.rb deleted file mode 100644 index f3d9f215..00000000 --- a/spec/classes/apache/vhost_spec.rb +++ /dev/null @@ -1,52 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -describe 'puppetboard::apache::vhost' do - describe 'default params' do - let :params do - { - 'vhost_name' => 'puppetboard.local', - 'port' => 80, - 'enable_ldap_auth' => true - } - end - let(:pre_condition) do - [ - 'class { "apache": - default_vhost => false, - default_mods => false, - }', - 'class { "puppetboard": - secret_key => "this_should_be_a_long_secret_string", - }' - ] - end - - on_supported_os.each do |os, facts| - context "on #{os}" do - let :facts do - facts - end - - it { is_expected.to compile.with_all_deps } - it { is_expected.to contain_class('puppetboard::apache::vhost') } - it { is_expected.to contain_class('apache::mod::wsgi') } - it { is_expected.to contain_file('/srv/puppetboard/puppetboard/wsgi.py') } - - it do - expect(subject).to contain_apache__vhost('puppetboard.local').with( - 'ensure' => 'present', - 'port' => 80 - ).that_requires('File[/srv/puppetboard/puppetboard/wsgi.py]') - end - - it do - expect(subject).to contain_file('puppetboard-ldap.part').with( - 'ensure' => 'file' - ) - end - end - end - end -end diff --git a/templates/apache/conf.epp b/templates/apache/conf.epp deleted file mode 100644 index 9fcb8a7a..00000000 --- a/templates/apache/conf.epp +++ /dev/null @@ -1,41 +0,0 @@ -WSGIDaemonProcess puppetboard python-home=<%= $virtualenv_dir %> user=<%= $user %> group=<%= $group %> threads=<%= $threads %> maximum-requests=<%= $max_reqs %> -WSGIScriptAlias <%= $wsgi_alias %> <%= $docroot %>/wsgi.py - -> - WSGIProcessGroup puppetboard - WSGIApplicationGroup %{GLOBAL} - - Order allow,deny - Allow from all - - = 2.4> - Require all granted - - -<% if $enable_ldap_auth { %> - - AuthType Basic - AuthName "Login to puppetboard" - Order Allow,Deny - Allow from All - - AuthBasicProvider ldap - <%- if $ldap_bind_dn { %> - AuthLDAPBindDN "<%= $ldap_bind_dn %>" - <%- } %> - <%- if $ldap_bind_password { %> - AuthLDAPBindPassword "<%= $ldap_bind_password %>" - <%- } %> - <%- if $ldap_url { %> - AuthLDAPURL "<%= $ldap_url %>" - <%- } %> - <%- if $ldap_bind_authoritative { %> - AuthLDAPBindAuthoritative <%= $ldap_bind_authoritative %> - <%- } %> - <%- if $ldap_require_group { %> - Require ldap-group <%= $ldap_require_group_dn %> - <% } else { %> - Require valid-user - <% } %> - -<% } %> diff --git a/templates/apache/ldap.epp b/templates/apache/ldap.epp deleted file mode 100644 index 31fad32a..00000000 --- a/templates/apache/ldap.epp +++ /dev/null @@ -1,25 +0,0 @@ - - AuthType Basic - AuthName "Login to puppetboard" - Order Allow,Deny - Allow from All - - AuthBasicProvider ldap - <%- if $ldap_bind_dn { %> - AuthLDAPBindDN "<%= $ldap_bind_dn %>" - <%- } %> - <%- if $ldap_bind_password { %> - AuthLDAPBindPassword "<%= $ldap_bind_password %>" - <%- } %> - <%- if $ldap_url { %> - AuthLDAPURL "<%= $ldap_url %>" - <%- } %> - <%- if $ldap_bind_authoritative { %> - AuthLDAPBindAuthoritative <%= $ldap_bind_authoritative %> - <%- } %> - <%- if $ldap_require_group { %> - Require ldap-group <%= $ldap_require_group_dn %> - <% } else { %> - Require valid-user - <% } %> -