Skip to content

Commit

Permalink
Merge pull request #1115 from lsst-it/IT-5219/puppetdb-auth
Browse files Browse the repository at this point in the history
(role/puppetdb) enable ldap auth
  • Loading branch information
jhoblitt authored Apr 4, 2024
2 parents 3ad8ee3 + 66829a8 commit 9be7308
Show file tree
Hide file tree
Showing 7 changed files with 257 additions and 11 deletions.
35 changes: 33 additions & 2 deletions hieradata/role/puppetdb.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,46 @@ classes:
- "profile::core::common"
- "profile::core::docker"
- "profile::core::docker::prune"
- "profile::core::firewall"
- "profile::core::puppetboard"
- "puppetdb"
- "profile::core::puppetdb"

apache::default_vhost: false
# apache::log_level: "debug" # for debugging ldap binding
firewall::ensure: "running"
postgresql::globals::manage_dnf_module: true # use appstream packages
profile::core::puppetdb::ldap_servers:
- "ipa1.ls.lsst.org"
- "ipa2.ls.lsst.org"
- "ipa3.ls.lsst.org"
puppetdb::database_listen_address: "localhost"
puppetdb::globals::version: "7.14.0"
puppetdb::listen_address: "localhost" # http only
puppetdb::manage_package_repo: false
puppetdb::postgres_version: "15"
puppetdb::ssl_listen_address: "0.0.0.0"
puppetdb::java_args:
"-Xmx": "1g"
"-Xms": "512m"
puppetdb::listen_address: "0.0.0.0"

profile::core::firewall::firewall:
"250 accept http - redirect to 443":
proto: "tcp"
state: "NEW"
dport: "80"
action: "accept"
"251 accept https - puppetboard ldap":
proto: "tcp"
state: "NEW"
dport: "443"
action: "accept"
"252 accept https - puppetdb x509":
proto: "tcp"
state: "NEW"
dport: "8081"
action: "accept"
"253 accept https - puppetdb ldap":
proto: "tcp"
state: "NEW"
dport: "8443"
action: "accept"
5 changes: 5 additions & 0 deletions hieradata/site/cp/role/puppetdb.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
profile::core::puppetdb::ldap_servers:
- "ipa1.cp.lsst.org"
- "ipa2.cp.lsst.org"
- "ipa3.cp.lsst.org"
5 changes: 5 additions & 0 deletions hieradata/site/tu/role/puppetdb.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
profile::core::puppetdb::ldap_servers:
- "ipa1.tu.lsst.org"
- "ipa2.tu.lsst.org"
- "ipa3.tu.lsst.org"
14 changes: 10 additions & 4 deletions site/profile/manifests/core/puppetboard.pp
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,19 @@
docker::image { 'ghcr.io/voxpupuli/puppetboard': }

docker::run { 'puppetboard':
image => 'ghcr.io/voxpupuli/puppetboard',
env => [
image => 'ghcr.io/voxpupuli/puppetboard',
volumes => ['/etc/puppetlabs/puppet/ssl:/etc/puppetlabs/puppet/ssl:ro'],
net => 'host',
env => [
'PUPPETDB_HOST=127.0.0.1',
'PUPPETDB_PORT=8080',
'PUPPETDB_PORT=8081',
'PUPPETBOARD_PORT=8088',
'ENABLE_CATALOG=true',
'PUPPETDB_SSL_VERIFY=false',
"PUPPETDB_KEY=/etc/puppetlabs/puppet/ssl/private_keys/${fact('networking.fqdn')}.pem",
"PUPPETDB_CERT=/etc/puppetlabs/puppet/ssl/certs/${fact('networking.fqdn')}.pem",
"SECRET_KEY=${secret_key.unwrap}",
'DEFAULT_ENVIRONMENT=*',
],
net => 'host',
}
}
105 changes: 105 additions & 0 deletions site/profile/manifests/core/puppetdb.pp
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
# @summary
# Install puppetdb
#
# @param ldap_servers
# An array of LDAP servers to use for authentication
#
# @param ldap_bind_user
# The user to use for binding to the LDAP server(s)
#
# @param ldap_bind_pass
# The password to use for binding to the LDAP server(s)
#
class profile::core::puppetdb (
Array[String[1]] $ldap_servers,
Sensitive[String[1]] $ldap_bind_user,
Sensitive[String[1]] $ldap_bind_pass,
) {
include apache
include apache::mod::authnz_ldap
include apache::mod::ldap
include profile::core::letsencrypt
include puppetdb

$fqdn = fact('networking.fqdn')
$le_root = "/etc/letsencrypt/live/${fqdn}"
# apache wants a space separated list of ldap servers as part of the ldap
# url...
$try_ldap_servers = join($ldap_servers, ' ')

letsencrypt::certonly { $fqdn:
plugin => 'dns-route53',
manage_cron => true,
}

# A cron job is needed to restart apache if the letsencrypt cert is renewed.
# We are being lazy and just restart apache every day at noon.
cron::job { 'restart-apache-on-letsencrypt-renewal':
minute => '0',
hour => '15',
date => '*',
month => '*',
weekday => '*',
command => '/bin/systemctl restart httpd',
description => 'Restart apache incase the letsencrypt cert is renewed',
}

apache::vhost { 'redirect-https':
servername => $fqdn,
port => 80,
docroot => '/var/www/html',
redirect_dest => "https://${fqdn}",
}

apache::vhost {
default:
servername => $fqdn,
docroot => '/var/www/html',
ssl => true,
ssl_cert => "${le_root}/fullchain.pem",
ssl_key => "${le_root}/privkey.pem",
rewrites => [
{
comment => 'Eliminate Trace and Track',
rewrite_cond => ['%{REQUEST_METHOD} ^(TRACE|TRACK)'],
rewrite_rule => [' .* - [F]'],
},
],
proxy_preserve_host => true,
# XXX show_diff isn't part of a forge release yet
# https://github.com/puppetlabs/puppetlabs-apache/pull/2536
# show_diff => false, # don't show ldap bind pass in diff
directories => [
{
path => '/',
provider => 'location',
auth_name => 'IPA Authentication',
auth_type => 'Basic',
auth_basic_provider => 'ldap',
# quotes are required around the ldap url because it contains a space
auth_ldap_url => "\"ldaps://${try_ldap_servers}/cn=users,cn=accounts,dc=lsst,dc=cloud?uid?sub?(objectClass=posixAccount)\"",
auth_ldap_bind_dn => "uid=${ldap_bind_user.unwrap},cn=users,cn=accounts,dc=lsst,dc=cloud",
auth_ldap_bind_password => $ldap_bind_pass.unwrap,
require => [
'ldap-group cn=admins,cn=groups,cn=accounts,dc=lsst,dc=cloud',
'ldap-group cn=puppetdb,cn=groups,cn=accounts,dc=lsst,dc=cloud',
],
},
],
;
'puppetboard-proxy':
port => 443,
proxy_pass => {
path => '/',
url => 'http://127.0.0.1:8088/',
},
;
'puppetdb-proxy':
port => 8443,
proxy_pass => {
path => '/',
url => 'http://127.0.0.1:8080/',
},
;
}
}
4 changes: 4 additions & 0 deletions spec/fixtures/hieradata/common.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ lookup_options:
convert_to: "Sensitive"
'^profile::ccs::postfix::auth$':
convert_to: "Sensitive"
'^profile::core::puppetdb::ldap_bind_(user|pass)$':
convert_to: "Sensitive"
ccs_database::database: "comcamdbprod"
ccs_database::password: "foo"
foreman_proxy::plugin::dns::route53::aws_access_key: "foo"
Expand All @@ -43,6 +45,8 @@ profile::core::monitoring::password: "foo"
profile::core::monitoring::url: "foo"
profile::core::monitoring::username: "foo"
profile::core::puppetboard::secret_key: "foo"
profile::core::puppetdb::ldap_bind_pass: "foo"
profile::core::puppetdb::ldap_bind_user: "foo"
restic::id: "foo"
restic::key: "foo"
restic::password: "foo"
Expand Down
100 changes: 95 additions & 5 deletions spec/hosts/roles/puppetdb_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,33 @@
PUPPETDB_VERSION = '7.14.0'

shared_examples 'puppetdb' do
%w[
apache
apache::mod::authnz_ldap
apache::mod::ldap
puppetdb
].each do |c|
it { is_expected.to contain_class(c) }
end

it do
is_expected.to contain_letsencrypt__certonly(facts[:networking]['fqdn']).with(
plugin: 'dns-route53',
manage_cron: true,
)
end

it { is_expected.to contain_cron__job('restart-apache-on-letsencrypt-renewal') }
it { is_expected.to contain_apache__vhost('redirect-https').with_port(80) }
it { is_expected.to contain_apache__vhost('puppetboard-proxy').with_port(443) }
it { is_expected.to contain_apache__vhost('puppetdb-proxy').with_port(8443) }

it { is_expected.to contain_class('puppetdb::globals').with_version(PUPPETDB_VERSION) }
it { is_expected.to contain_yum__versionlock('puppetdb').with_version(PUPPETDB_VERSION) }

it do
is_expected.to contain_class('puppetdb').with(
listen_address: '0.0.0.0',
listen_address: 'localhost',
java_args: {
'-Xmx' => '1g',
'-Xms' => '512m',
Expand All @@ -25,23 +46,65 @@
version: '15',
)
end

it do
is_expected.to contain_firewall('250 accept http - redirect to 443').with(
proto: 'tcp',
state: 'NEW',
dport: '80',
action: 'accept',
)
end

it do
is_expected.to contain_firewall('251 accept https - puppetboard ldap').with(
proto: 'tcp',
state: 'NEW',
dport: '443',
action: 'accept',
)
end

it do
is_expected.to contain_firewall('252 accept https - puppetdb x509').with(
proto: 'tcp',
state: 'NEW',
dport: '8081',
action: 'accept',
)
end

it do
is_expected.to contain_firewall('253 accept https - puppetdb ldap').with(
proto: 'tcp',
state: 'NEW',
dport: '8443',
action: 'accept',
)
end
end

shared_examples 'puppetboard' do
it { is_expected.to contain_class('docker') }
it { is_expected.to contain_cron__job('docker_prune') }
it { is_expected.to contain_docker__image('ghcr.io/voxpupuli/puppetboard') }

it do
is_expected.to contain_docker__run('puppetboard').with(
image: 'ghcr.io/voxpupuli/puppetboard',
volumes: [
'/etc/puppetlabs/puppet/ssl:/etc/puppetlabs/puppet/ssl:ro',
],
net: 'host',
env: [
'PUPPETDB_HOST=127.0.0.1',
'PUPPETDB_PORT=8080',
'PUPPETDB_PORT=8081',
'PUPPETBOARD_PORT=8088',
'ENABLE_CATALOG=true',
'PUPPETDB_SSL_VERIFY=false',
"PUPPETDB_KEY=/etc/puppetlabs/puppet/ssl/private_keys/#{facts[:networking]['fqdn']}.pem",
"PUPPETDB_CERT=/etc/puppetlabs/puppet/ssl/certs/#{facts[:networking]['fqdn']}.pem",
'SECRET_KEY=foo',
'DEFAULT_ENVIRONMENT=*',
],
net: 'host',
)
end
end
Expand Down Expand Up @@ -71,8 +134,35 @@
it { is_expected.to compile.with_all_deps }

include_examples 'common', os_facts: os_facts, site: site
include_examples 'docker'
it { is_expected.to contain_cron__job('docker_prune') }

include_examples 'ipset'
include_examples 'firewall default', os_facts: os_facts
include_examples 'firewall node_exporter scraping', site: site
include_examples 'puppetdb'
include_examples 'puppetboard'

case site
when 'dev', 'ls'
it do
expect(catalogue.resource('apache::vhost', 'puppetboard-proxy')[:directories].first).to include(
'auth_ldap_url' => '"ldaps://ipa1.ls.lsst.org ipa2.ls.lsst.org ipa3.ls.lsst.org/cn=users,cn=accounts,dc=lsst,dc=cloud?uid?sub?(objectClass=posixAccount)"',
)
end
when 'tu'
it do
expect(catalogue.resource('apache::vhost', 'puppetboard-proxy')[:directories].first).to include(
'auth_ldap_url' => '"ldaps://ipa1.tu.lsst.org ipa2.tu.lsst.org ipa3.tu.lsst.org/cn=users,cn=accounts,dc=lsst,dc=cloud?uid?sub?(objectClass=posixAccount)"',
)
end
when 'cp'
it do
expect(catalogue.resource('apache::vhost', 'puppetboard-proxy')[:directories].first).to include(
'auth_ldap_url' => '"ldaps://ipa1.cp.lsst.org ipa2.cp.lsst.org ipa3.cp.lsst.org/cn=users,cn=accounts,dc=lsst,dc=cloud?uid?sub?(objectClass=posixAccount)"',
)
end
end
end # host
end # lsst_sites
end
Expand Down

0 comments on commit 9be7308

Please sign in to comment.