diff --git a/Puppetfile b/Puppetfile index 5701a66..f29fb47 100644 --- a/Puppetfile +++ b/Puppetfile @@ -7,7 +7,7 @@ mod 'puppetlabs-inifile', '6.0.0' mod 'puppetlabs-concat', '9.0.0' mod 'puppetlabs-vcsrepo', '6.1.0' mod 'puppetlabs-yumrepo_core', '2.0.0' -mod 'puppetlabs-apt', '9.1.0' +mod 'puppetlabs-apt', '9.4.0' mod 'puppetlabs-lvm', '2.1.0' mod 'puppetlabs-puppetdb', '7.13.0' mod 'puppetlabs-postgresql', '9.1.0' @@ -15,6 +15,9 @@ mod 'puppetlabs-firewall', '6.0.0' mod 'puppetlabs-accounts', '8.1.0' mod 'puppetlabs-mysql', '15.0.0' mod 'puppetlabs-xinetd', '3.4.1' +mod 'puppetlabs-haproxy', '8.0.0' +mod 'puppetlabs-java', '10.1.2' +mod 'puppetlabs-reboot', '5.0.0' # puppet mod 'puppet-python', '7.0.0' @@ -29,16 +32,21 @@ mod 'puppet-prometheus', '13.4.0' mod 'puppet-grafana', '13.1.0' mod 'puppet-consul', '8.0.0' mod 'puppet-vault', '4.1.0' +mod 'puppet-dhcp', '6.1.0' +mod 'puppet-keepalived', '3.6.0' +mod 'puppet-extlib', '7.0.0' # other mod 'ghoneycutt-puppet', '3.3.0' mod 'saz-sudo', '8.0.0' +mod 'ghoneycutt-timezone', '4.0.0' mod 'dalen-puppetdbquery', '3.0.1' mod 'markt-galera', '3.1.0' mod 'kogitoapp-minio', '1.1.4' mod 'broadinstitute-certs', '3.0.1' mod 'stm-file_capability', '6.0.0' +mod 'h0tw1r3-gitea', '3.2.0' mod 'bind', - :git => 'https://git.unkin.net/unkinben/puppet-bind.git', + :git => 'https://git.service.au-syd1.consul/unkinben/puppet-bind.git', :tag => '1.0' diff --git a/hiera.yaml b/hiera.yaml index b763ee3..d46d2ee 100644 --- a/hiera.yaml +++ b/hiera.yaml @@ -29,6 +29,7 @@ hierarchy: - "roles/%{::enc_role_tier1}/%{::enc_role_tier2}.yaml" - "roles/%{::enc_role_tier1}.eyaml" - "roles/%{::enc_role_tier1}.yaml" + - "virtual/%{facts.virtual}.yaml" - "os/%{facts.os.name}/%{facts.os.name}%{facts.os.release.major}.yaml" - "os/%{facts.os.name}/all_releases.yaml" - "common.eyaml" diff --git a/hieradata/common.eyaml b/hieradata/common.eyaml new file mode 100644 index 0000000..a0d629d --- /dev/null +++ b/hieradata/common.eyaml @@ -0,0 +1,8 @@ +--- +profiles::accounts::sysadmin::password: ENC[PKCS7,MIIBqQYJKoZIhvcNAQcDoIIBmjCCAZYCAQAxggEhMIIBHQIBADAFMAACAQEwDQYJKoZIhvcNAQEBBQAEggEAoS7GyofFaXBNTWU+GtSiz4eCX/9j/sh3fDDRgOgNv1qpcQ87ZlTTenbHo9lxeURxKQ2HVVt7IsrBo/SC/WgipAKnliRkkIvo7nfAs+i+kEE8wakjAs0DcB4mhqtIZRuBkLG2Nay//DcG6cltVkbKEEKmKLMkDFZgTWreOZal8nDljpVe1S8QwtwP4/6hKTef5xsOnrisxuffWTXvwYJhj/VXrjdoH7EhtHGLybzEalglkVHEGft/WrrD/0bwJpmR0RegWI4HTsSvGiHgvf5DZJx8fXPZNPnicGtlfA9ccQPuVo17bY4Qf/WIc1A8Ssv4kHSbNIYJKRymI3UFb0Z4wzBsBgkqhkiG9w0BBwEwHQYJYIZIAWUDBAEqBBBBxDLb6pCGbittkcX6asd/gEBmMcUNupDjSECq5H09YA70eVwWWe0fBqxTxrr2cXCXtRKFvOk8SJmL0xHAWodaLN9+krTWHJcWbAK8JXEPC7rn] +profiles::accounts::root::password: ENC[PKCS7,MIIBeQYJKoZIhvcNAQcDoIIBajCCAWYCAQAxggEhMIIBHQIBADAFMAACAQEwDQYJKoZIhvcNAQEBBQAEggEAM79PRxeAZHrDcSm4eSFqU94/LjuSbdUmJWivX/Pa8GumoW2e/PT9nGHW3p98zHthMgCglk52PECQ+TBKjxr+9dTyNK5ePG6ZJEqSHNRqsPGm+kfQj/hlTmq8vOBaFM5GapD1iTHs5JFbGngI56swKBEVXW9+Z37BjQb2xJuyLsu5Bo/tA0BaOKuCtjq1a6E38bOX+nJ+YF1uZgV9ofAEh1YvkcTmnEWYXFRPWd7AaNcWn03V2pfhGqxc+xydak620I47P+FE+qIY72+aQ6tmLU3X9vyA1HLF2Tv572l4a2i+YIk6nAgQdi+hQKznqNL9M9YV+s1AcmcKLT7cfLrjsjA8BgkqhkiG9w0BBwEwHQYJYIZIAWUDBAEqBBCMWrdCWBQgtW3NOEpERwP+gBA3KDiqe4pQq6DwRfsEXQNZ] +profiles::consul::client::secret_id_salt: ENC[PKCS7,MIIBmQYJKoZIhvcNAQcDoIIBijCCAYYCAQAxggEhMIIBHQIBADAFMAACAQEwDQYJKoZIhvcNAQEBBQAEggEAS7pNFRX4onccFaR87zB/eFFORuF22j6xqjyeAqqjgEduYhkt6w5kkz+YfUoHUesU0Q6F2p6HrCSZ8yAsx5M25NCiud9P4hIpjKmOZ4zCNO7uhATh4AQDYw3BrdRwfO+c6jOl5wOiNLCfDBJ0sFT3akCvcuPS1xIoRJq4Gyn+uCbOsMbvSl25ld2xKt1/cqs8gc1d8mkpjwWto7t+qZSUFMCehTbehH3G4a3Q5rvfBoNwv42Wbs676BDcCurDaAzHNqE7pDbOWhGuVOBl+q+BU0Ri/CRkGcTViN9fr8Dc9SveVC6EPsMbw+05/8/NlfzQse3KAwQ34nR9tR2PQw5qEzBcBgkqhkiG9w0BBwEwHQYJYIZIAWUDBAEqBBB7LywscQtF7cG2nomfEsu9gDDVqJBFP1jAX2eGZ2crYS5gnBcsRwhc0HNo2/WWdhZprMW+vEJOOGXDelI53NxA3o0=] +profiles::consul::token::node_editor::secret_id: ENC[PKCS7,MIIBmQYJKoZIhvcNAQcDoIIBijCCAYYCAQAxggEhMIIBHQIBADAFMAACAQEwDQYJKoZIhvcNAQEBBQAEggEAO8IIF2r18dFf0bVKEwjJUe1TmXHH0AIzsQHxkHwV7d37kvH1cY9rYw0TtdHn7GTxvotJG7GZbWvbunpBs1g2p2RPADiM6TMhbO8mJ0tAWLnMk7bQ221xu8Pc7KceqWmU17dmgNhVCohyfwJNqbA756TlHVgxGA0LtNrKoLOmgKGXAL1VYZoKEQnWq7xOpO+z3e1UfjoO6CvX/Od2hGYfUkHdro8mwRw4GFKzU7XeKFdAMUGpn5rVmY3xe+1ARXwGFaSrTHzk2n85pvwhPRlQ+OwqzyT19Qo2FNeAO6RoCRIFTtqbsjTWPUlseHIhw4Q5bHO1I0Mrlm5IHDESw/22IzBcBgkqhkiG9w0BBwEwHQYJYIZIAWUDBAEqBBCEe9wD72qxnpeq5nCi/d7BgDCP29sDFObkFTabt2uZ/nF9MT1g+QOrrdFKgnG6ThnwH1hwpZPsSVgIs+yRQH8laB4=] +profiles::consul::server::acl_tokens_initial_management: ENC[PKCS7,MIIBmQYJKoZIhvcNAQcDoIIBijCCAYYCAQAxggEhMIIBHQIBADAFMAACAQEwDQYJKoZIhvcNAQEBBQAEggEAi1UH7AZirJ1PdxWy+KEgS5ufm0wbn2xy9rkg14hKYpcVjBa4pOZpSLMGMiiUpBIqBytDMZM4ezYa/luktpkBImJbM/TE16beGtsacQGA+9eZk2Tihs9GR2qbAQiu5lLITiDlwNnf0GeWdqHM8CTeD68DczQF320d9U14/k6pG/7z+w/MGLcjsQoSuOFTm42JVn1BI46t1CYSCHMXQc/9Tfs+FzI+vumohI8DxAYBIuyzU5HBX/MntAsvD/yixMJS1pZL9WwgqZJC/wK34rVRB39DpxWf/WROrI+WLuSJwr7WBjaeF9Ju+89WKCgsI53EWhFTj8GgDZm/jqPoE478NjBcBgkqhkiG9w0BBwEwHQYJYIZIAWUDBAEqBBAoACRzJdQKNYXZv6cghFIIgDAzB81DMcuY815nb8POtZpiA06jT/068AoZmSctHoFK/zW9tY229N5r1Tb+WHElqLk=] +profiles::consul::server::acl_tokens_default: ENC[PKCS7,MIIBmQYJKoZIhvcNAQcDoIIBijCCAYYCAQAxggEhMIIBHQIBADAFMAACAQEwDQYJKoZIhvcNAQEBBQAEggEAh4Ag95xgkIZHL0gP9OLnZauih0dB1/2l9Jzw8mP3OiIv7fw23otHYONlS3Emtj7oxW8MKcZGKDCzwCT6T2p+V5wx1n15wr2J+FmL24VbclJwrMPQ4AdgP359B9h21uoyo7Zdy7RuuvLfkU1fWXbs3SeWbi2HJs1Ed1/oI1jzr3OgwMbVtbyzd1VuAXeZ9bHQG3IA8z+w/k5m61th0HTyHjw7eldQulbohDuwv545z9axHEoHKCRT2a3ZwBufV2ST6Dm3g9GERzXE9Adp9DQC5adqM74wfsujOMLK2QFJSSIOj2uCs1CpEnrNrQ8zjP3fudM2z3l7KdSHZazEamCSxTBcBgkqhkiG9w0BBwEwHQYJYIZIAWUDBAEqBBBY/Tn9tzEKYc5dxnzP2rP7gDBWKgVP3lf2T4Q0WPQt3ns0E6RUSO6OtBegb/5qDyohY2nsDeJTnMKOYzYt/J1PhnY=] +profiles::consul::server::acl_tokens_replication: ENC[PKCS7,MIIBmQYJKoZIhvcNAQcDoIIBijCCAYYCAQAxggEhMIIBHQIBADAFMAACAQEwDQYJKoZIhvcNAQEBBQAEggEAEzTIxbaAR/TZYnC671aBhiahsfwf3ieyeSHpD5hQm40sMEF/fXlEDijq9i2ykPikm94074j1Uo4HNzv/V9GTf0NSC/64t61jJ/Ya3QKa5f/36+DcRj3lcETsSIyhWwmU+E+zkY8I2r68MtXAuvSoMSMZdpgWSkPx/3FFgZlrsg//bzDu69jS9cx4UK582N3A6QN4Uy/qwYtJcm+2iTQlqqgGRWGqnSgTirxhegxPbJGWTDoAEpAL4/DyF5/hqcUn6mgoSfAsHF3loPHOqN30lG+9o0THWJ9B8Gf4W/1X2UWA/avmUnqBnumGoz0p7AYdNgpW+qLl2rk4lyGYa4kvQjBcBgkqhkiG9w0BBwEwHQYJYIZIAWUDBAEqBBD9KSLH3Pn/1EIzgVJM+8VOgDDpKWzHfSVsfUMyTD0XIRPGclTdmxqCnsdhKNqmUfSjkYIf2nI9rQtSK6n42TYuO4k=] diff --git a/hieradata/common.yaml b/hieradata/common.yaml index aa7b70c..eda0ea1 100644 --- a/hieradata/common.yaml +++ b/hieradata/common.yaml @@ -1,5 +1,8 @@ --- lookup_options: + hiera_classes: + merge: + strategy: deep profiles::packages::install: merge: strategy: deep @@ -12,10 +15,107 @@ lookup_options: profiles::packages::remove_exclude: merge: strategy: deep + profiles::pki::vault::alt_names: + merge: + strategy: deep + profiles::pki::vault::ip_sans: + merge: + strategy: deep + profiles::yum::global::managed_repos: + merge: + strategy: deep + profiles::haproxy::server::defaults: + merge: + strategy: deep + profiles::haproxy::server::globals: + merge: + strategy: deep + profiles::haproxy::server::frontends: + merge: + strategy: deep + profiles::haproxy::server::backends: + merge: + strategy: deep + profiles::haproxy::server::mappings: + merge: + strategy: deep + profiles::haproxy::server::listeners: + merge: + strategy: deep + haproxy::backend: + merge: + strategy: deep + sudo::configs: + merge: + strategy: deep + profiles::base::groups::local: + merge: + strategy: deep + profiles::dns::resolver::zones: + merge: + strategy: deep + profiles::dns::resolver::acls: + merge: + strategy: deep + profiles::dns::resolver::views: + merge: + strategy: deep + profiles::dns::resolver::keys: + merge: + strategy: deep + profiles::dns::master::zones: + merge: + strategy: deep + profiles::dns::master::acls: + merge: + strategy: deep + profiles::dns::master::views: + merge: + strategy: deep + profiles::dns::master::keys: + merge: + strategy: deep + consul::services: + merge: + strategy: deep + consul::watch: + merge: + strategy: deep + consul::check: + merge: + strategy: deep + profiles::consul::client::node_rules: + merge: + strategy: deep + profiles::consul::prepared_query::rules: + merge: + strategy: deep + profiles::puppet::server::dns_alt_names: + merge: + strategy: deep + profiles::puppet::client::dns_alt_names: + merge: + strategy: deep + profiles::base::hosts::additional_hosts: + merge: + strategy: deep + postgresql_config_entries: + merge: + strategy: deep + profiles::yum::global::repos: + merge: + strategy: deep + profiles::nginx::simpleproxy::nginx_aliases: + merge: + strategy: deep facts_path: '/opt/puppetlabs/facter/facts.d' +hiera_classes: + - timezone + profiles::ntp::client::ntp_role: 'roles::infra::ntp::server' +profiles::ntp::client::use_ntp: 'region' profiles::ntp::client::peers: - 0.pool.ntp.org - 1.pool.ntp.org @@ -27,6 +127,21 @@ profiles::base::puppet_servers: profiles::dns::master::basedir: '/var/named/sources' profiles::dns::base::ns_role: 'roles::infra::dns::resolver' +profiles::dns::base::use_ns: 'region' +profiles::consul::server::members_role: roles::infra::storage::consul +profiles::consul::token::node_editor::accessor_id: '024e27bd-c5bb-41e7-a578-b766509e11bc' +profiles::consul::client::members_lookup: true +profiles::consul::client::members_role: roles::infra::storage::consul +profiles::consul::client::node_rules: + - resource: node + segment: "%{facts.networking.hostname}" + disposition: write + - resource: node + segment: "%{facts.networking.fqdn}" + disposition: write + - resource: node + segment: '' + disposition: read profiles::packages::install: - bash-completion @@ -34,6 +149,7 @@ profiles::packages::install: - ccze - curl - dstat + - expect - gzip - git - htop @@ -41,7 +157,6 @@ profiles::packages::install: - iotop - jq - lz4 - - lzo - mtr - ncdu - neovim @@ -49,6 +164,7 @@ profiles::packages::install: - pbzip2 - pigz - pv + - python3.11 - rsync - screen - socat @@ -60,7 +176,6 @@ profiles::packages::install: - vim - vnstat - wget - - xz - zsh - zstd @@ -83,15 +198,36 @@ profiles::packages::remove: profiles::base::scripts::scripts: puppet: puppetwrapper.py +profiles::puppet::client::server: 'puppet.query.consul' +profiles::puppet::client::ca_server: 'puppetca.query.consul' profiles::puppet::client::environment: 'develop' profiles::puppet::client::runinterval: 1800 profiles::puppet::client::runtimeout: 3600 profiles::puppet::client::show_diff: true profiles::puppet::client::usecacheonfailure: false +profiles::puppet::client::dns_alt_names: + - "%{trusted.certname}" + +# puppetdb +puppetdbapi: puppetdbapi.query.consul +puppetdbsql: puppetdbsql.service.au-syd1.consul prometheus::node_exporter::export_scrape_job: true prometheus::systemd_exporter::export_scrape_job: true +profiles::base::groups::local: + admins: + ensure: present + gid: 10000 + allowdupe: false + forcelocal: true + +sudo::configs: + admins: + priority: 10 + content: | + %admins ALL=(ALL) NOPASSWD: ALL + profiles::accounts::sysadmin::sshkeys: - ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDZ8SRLlPiDylBpdWR9LpvPg4fDVD+DZst4yRPFwMMhta4mnB1H9XuvZkptDhXywWQ7QIcqa2WbhCen0OQJCtwn3s7EYtacmF5MxmwBYocPoK2AArGuh6NA9rwTdLrPdzhZ+gwe88PAzRLNzjm0ZBR+mA9saMbPJdqpKp0AWeAM8QofRQAWuCzQg9i0Pn1KDMvVDRHCZof4pVlHSTyHNektq4ifovn0zhKC8jD/cYu95mc5ftBbORexpGiQWwQ3HZw1IBe0ZETB1qPIPwsoJpt3suvMrL6T2//fcIIUE3TcyJKb/yhztja4TZs5jT8370G/vhlT70He0YPxqHub8ZfBv0khlkY93VBWYpNGJwM1fVqlw7XbfBNdOuJivJac8eW317ZdiDnKkBTxapThpPG3et9ib1HoPGKRsd/fICzNz16h2R3tddSdihTFL+bmTCa6Lo+5t5uRuFjQvhSLSgO2/gRAprc3scYOB4pY/lxOFfq3pU2VvSJtRgLNEYMUYKk= ben@unkin.net @@ -107,7 +243,6 @@ profiles::base::hosts::additional_hosts: hostname: prodinf01n04.main.unkin.net aliases: - prodinf01n04 - - puppetdb - ip: 198.18.17.5 hostname: prodinf01n05.main.unkin.net aliases: diff --git a/hieradata/country/au/region/drw1.yaml b/hieradata/country/au/region/drw1.yaml new file mode 100644 index 0000000..703d863 --- /dev/null +++ b/hieradata/country/au/region/drw1.yaml @@ -0,0 +1,2 @@ +--- +timezone::timezone: 'Australia/Darwin' diff --git a/hieradata/country/au/region/drw1/infra/dns/resolver.yaml b/hieradata/country/au/region/drw1/infra/dns/resolver.yaml new file mode 100644 index 0000000..157667c --- /dev/null +++ b/hieradata/country/au/region/drw1/infra/dns/resolver.yaml @@ -0,0 +1,52 @@ +--- +profiles::dns::resolver::zones: + main.unkin.net-forward: + domain: 'main.unkin.net' + zone_type: 'forward' + forwarders: + - 198.18.17.23 + - 198.18.17.24 + forward: 'only' + 13.18.198.in-addr.arpa-forward: + domain: '13.18.198.in-addr.arpa' + zone_type: 'forward' + forwarders: + - 198.18.17.23 + - 198.18.17.24 + forward: 'only' + 14.18.198.in-addr.arpa-forward: + domain: '14.18.198.in-addr.arpa' + zone_type: 'forward' + forwarders: + - 198.18.17.23 + - 198.18.17.24 + forward: 'only' + 15.18.198.in-addr.arpa-forward: + domain: '15.18.198.in-addr.arpa' + zone_type: 'forward' + forwarders: + - 198.18.17.23 + - 198.18.17.24 + forward: 'only' + 16.18.198.in-addr.arpa-forward: + domain: '16.18.198.in-addr.arpa' + zone_type: 'forward' + forwarders: + - 198.18.17.23 + - 198.18.17.24 + forward: 'only' + 17.18.198.in-addr.arpa-forward: + domain: '17.18.198.in-addr.arpa' + zone_type: 'forward' + forwarders: + - 198.18.17.23 + - 198.18.17.24 + forward: 'only' + consul-forward: + domain: 'consul' + zone_type: 'forward' + forwarders: + - 198.18.17.34 + - 198.18.17.35 + - 198.18.17.36 + forward: 'only' diff --git a/hieradata/country/au/region/drw1/infra/halb/haproxy.yaml b/hieradata/country/au/region/drw1/infra/halb/haproxy.yaml new file mode 100644 index 0000000..2ac28f7 --- /dev/null +++ b/hieradata/country/au/region/drw1/infra/halb/haproxy.yaml @@ -0,0 +1,65 @@ +--- +# mappings +profiles::haproxy::mappings: + fe_http: + ensure: present + mappings: + - 'puppetboard.main.unkin.net be_puppetboard' + - 'puppetdbapi.main.unkin.net be_puppetdbapi' + fe_https: + ensure: present + mappings: + - 'puppetboard.main.unkin.net be_puppetboard' + - 'puppetdbapi.main.unkin.net be_puppetdbapi' + +profiles::haproxy::frontends: + fe_http: + options: + use_backend: + - "%[req.hdr(host),lower,map(/etc/haproxy/fe_http.map,be_default)]" + fe_https: + options: + use_backend: + - "%[req.hdr(host),lower,map(/etc/haproxy/fe_https.map,be_default)]" + +profiles::haproxy::backends: + be_puppetboard: + description: Backend for Puppetboard + collect_exported: false # handled in custom function + options: + balance: roundrobin + option: + - httpchk GET / + - forwardfor + cookie: SRVNAME insert + http-request: + - set-header X-Forwarded-Port %[dst_port] + - add-header X-Forwarded-Proto https if { dst_port 443 } + redirect: 'scheme https if !{ ssl_fc }' + be_puppetdbapi: + description: Backend for the PuppetDB API + collect_exported: false # handled in custom function + options: + balance: roundrobin + option: + - httpchk GET / + - forwardfor + cookie: SRVNAME insert + http-request: + - set-header X-Forwarded-Port %[dst_port] + - add-header X-Forwarded-Proto https if { dst_port 443 } + redirect: 'scheme https if !{ ssl_fc }' + +profiles::haproxy::certlist::enabled: true +profiles::haproxy::certlist::certificates: + - /etc/pki/tls/vault/certificate.pem + +# additional altnames +profiles::pki::vault::alt_names: + - puppetboard.main.unkin.net + - puppetdbapi.main.unkin.net + +# additional cnames +profiles::haproxy::dns::cnames: + - puppetboard.main.unkin.net + - puppetdbapi.main.unkin.net diff --git a/hieradata/country/au/region/drw1/infra/puppet/master.eyaml b/hieradata/country/au/region/drw1/infra/puppet/master.eyaml new file mode 100644 index 0000000..1dea3a5 --- /dev/null +++ b/hieradata/country/au/region/drw1/infra/puppet/master.eyaml @@ -0,0 +1,3 @@ +--- +certmanager::vault_token: ENC[PKCS7,MIIBygYJKoZIhvcNAQcDoIIBuzCCAbcCAQAxggEhMIIBHQIBADAFMAACAQEwDQYJKoZIhvcNAQEBBQAEggEAWh7bsttz/JCBo/CPoCgA2doo3jO6jT6NsOoE3/06W2IW+Ij6KHKYILMkG3tS4NAegMI48QR9n++4Xa7u+97w1HO4ENpfLrkuKUcWUFCxxb2OdWhxucIlt3Ay/2+tofOSvqiRKeEISBtOK//Q1a4Iu5GwEP+lvDQ5rcoS0dryNie/okXaLratWOsmctJ6LFuUw5siCcFyUzfvr2ROsB14YoF989np+X1dJqBWxcLmbVNKx766GrRhb1WGeF0qxounCmWEKGt0zY4Zk27KNFlFu7XByDWZoSCVCMvkQaRKhvdNA39Y9vscZJGPGFhz+qKPoeqwUidz0IY51CaFSXewmzCBjAYJKoZIhvcNAQcBMB0GCWCGSAFlAwQBKgQQC+e2iOlFLlr9inVU8nEVWIBgqb0u/ICsLtxZqOpN9OIFWl+4hVrvTo24JzTc1jMSCONeL4Ab7jtTMbsweE9zUf6XlwhHLXfxfg7FL3WBsOWCUBXIAh338cZCXUGX7m0Qvtgg3VTEbTNDJhZle8Sjo6Gl] +certmanager::role_id: ENC[PKCS7,MIIBmQYJKoZIhvcNAQcDoIIBijCCAYYCAQAxggEhMIIBHQIBADAFMAACAQEwDQYJKoZIhvcNAQEBBQAEggEAJuE+uzgQaBRUXBCigckEo1j+UxxbiUGrzdf/B9K7XPdVxZh6TzYLpBgNnyaT6vLo0boX4uRD/By0gT5R/2qcXD6d/j+fh517Ctk4d2uO64f0vH3PzyyOBalsNtcCdPiV3q/xGqzQSHhPiNkFEjDvMBz5p53UjfKA6gAiPrLklp4rN/NVyiLBw20NeIqbL25VdkQa13ViS0Gm/eUQu7a2xQ1dvQFWWfuLaQxO0dh8L0ynkfmWKIjaiD5412Z8hYURu0otxbqVDdIbEMx5xQsXnFKeN93yHmgs7a7M6fLdp9jh+G8B+IlK1W7/9v2+RT0/yI3ZgWHVTvDRhMHuPGBjfTBcBgkqhkiG9w0BBwEwHQYJYIZIAWUDBAEqBBC5avtOPp9N65U1ILQENnvAgDBqI8XAjqbWIvXHqOEiKYdu+co0EEtsHR1v5xAeCmj/ZA6MLeKFlAVJbvpyCpzjons=] diff --git a/hieradata/country/au/region/drw1/infra/puppet/master.yaml b/hieradata/country/au/region/drw1/infra/puppet/master.yaml new file mode 100644 index 0000000..1b3d42c --- /dev/null +++ b/hieradata/country/au/region/drw1/infra/puppet/master.yaml @@ -0,0 +1,4 @@ +--- +profiles::puppet::server::dns_alt_names: + - puppetca.main.unkin.net + - puppetca diff --git a/hieradata/country/au/region/drw1/infra/storage/consul.eyaml b/hieradata/country/au/region/drw1/infra/storage/consul.eyaml index 948b16f..33b5046 100644 --- a/hieradata/country/au/region/drw1/infra/storage/consul.eyaml +++ b/hieradata/country/au/region/drw1/infra/storage/consul.eyaml @@ -1,4 +1,4 @@ --- profiles::consul::server::gossip_key: ENC[PKCS7,MIIBmQYJKoZIhvcNAQcDoIIBijCCAYYCAQAxggEhMIIBHQIBADAFMAACAQEwDQYJKoZIhvcNAQEBBQAEggEADwwYLK+fU0M/uLqQpRjHnIAyrt6yPEZSXpUX2jvOGVOA63X8LOYpLVfEGWMmkZ7BHRO0fgr847UUI/xI8otIuiOpgtW2E7QLWs806KUNXz+L8c7kSnQ1XAD5R81/5joDHl4AIxl5fAGryTXH1gfnpTMWh2yjFzU/KYuk2GhrU0M9ewCGJErQG4pT4u3ymGmkLjx6AiZ8r9xb4Eos2bhCCpFWfyb0kKcJqdKU9mzy508byNCfp8lr1DoKxEQrdqSSAQdepn6wCgBZtlAK/k63tOqM9dxyDaCsK8vLG9LlvuEwi3OL2lzTtc1mAcdYxahDo3uBX0/VcCswaXq3nPnu3TBcBgkqhkiG9w0BBwEwHQYJYIZIAWUDBAEqBBCUwXPoMh/dylvFwyRzAsnRgDDvh5CHrzJYdUXWGsauYlifOOukYokkwG3yqqtCByveMqVWfWsQukiDTixdqpCgfzw=] -profiles::consul::server::acl_tokens_initial_management: ENC[PKCS7,MIIBmQYJKoZIhvcNAQcDoIIBijCCAYYCAQAxggEhMIIBHQIBADAFMAACAQEwDQYJKoZIhvcNAQEBBQAEggEAi1UH7AZirJ1PdxWy+KEgS5ufm0wbn2xy9rkg14hKYpcVjBa4pOZpSLMGMiiUpBIqBytDMZM4ezYa/luktpkBImJbM/TE16beGtsacQGA+9eZk2Tihs9GR2qbAQiu5lLITiDlwNnf0GeWdqHM8CTeD68DczQF320d9U14/k6pG/7z+w/MGLcjsQoSuOFTm42JVn1BI46t1CYSCHMXQc/9Tfs+FzI+vumohI8DxAYBIuyzU5HBX/MntAsvD/yixMJS1pZL9WwgqZJC/wK34rVRB39DpxWf/WROrI+WLuSJwr7WBjaeF9Ju+89WKCgsI53EWhFTj8GgDZm/jqPoE478NjBcBgkqhkiG9w0BBwEwHQYJYIZIAWUDBAEqBBAoACRzJdQKNYXZv6cghFIIgDAzB81DMcuY815nb8POtZpiA06jT/068AoZmSctHoFK/zW9tY229N5r1Tb+WHElqLk=] -profiles::consul::server::acl_tokens_default: ENC[PKCS7,MIIBmQYJKoZIhvcNAQcDoIIBijCCAYYCAQAxggEhMIIBHQIBADAFMAACAQEwDQYJKoZIhvcNAQEBBQAEggEAPRZN7DnYUhVL81p7xC9rUYPutoO3UrF2Sl8DlopfYoAG9omnXZlrut8wIffDZJSiU5XkOGv8x2QsXZc+bWqiplJ0VfzLClxEM2onWaT/GGGg7E+2YhrYuMG7mZYaqRYQ6/AgLDcIMBIdQBdL5mlpy+fVZn7Mu4cmsQYJTIe+yrNQtGMWMiNaHpwLGXvoXgwT6giX6L6VNiN51dAnHAdMYZ9Hf3G5CZEs6x8uOveqf6+qy+df24ItRUcsfQlSwsEaQRY+xjIVYIoiV8l8D8HiO+mVqbxtfQgyJIMv+0hl95zHGlc2W5lb6MvIFcJGu2xKIc00D7YOYgxLUx1aegixxzBcBgkqhkiG9w0BBwEwHQYJYIZIAWUDBAEqBBBnYSZmhDFSDoO1s329ktFegDC2Z7A+TGqTtZXKXaj2qQmowIvTZOVoUyF/5G0aED0wo/h+vfgosSS3Tx1dam0KUl0=] +#profiles::consul::server::acl_tokens_initial_management: ENC[PKCS7,MIIBmQYJKoZIhvcNAQcDoIIBijCCAYYCAQAxggEhMIIBHQIBADAFMAACAQEwDQYJKoZIhvcNAQEBBQAEggEAi1UH7AZirJ1PdxWy+KEgS5ufm0wbn2xy9rkg14hKYpcVjBa4pOZpSLMGMiiUpBIqBytDMZM4ezYa/luktpkBImJbM/TE16beGtsacQGA+9eZk2Tihs9GR2qbAQiu5lLITiDlwNnf0GeWdqHM8CTeD68DczQF320d9U14/k6pG/7z+w/MGLcjsQoSuOFTm42JVn1BI46t1CYSCHMXQc/9Tfs+FzI+vumohI8DxAYBIuyzU5HBX/MntAsvD/yixMJS1pZL9WwgqZJC/wK34rVRB39DpxWf/WROrI+WLuSJwr7WBjaeF9Ju+89WKCgsI53EWhFTj8GgDZm/jqPoE478NjBcBgkqhkiG9w0BBwEwHQYJYIZIAWUDBAEqBBAoACRzJdQKNYXZv6cghFIIgDAzB81DMcuY815nb8POtZpiA06jT/068AoZmSctHoFK/zW9tY229N5r1Tb+WHElqLk=] +#profiles::consul::server::acl_tokens_default: ENC[PKCS7,MIIBmQYJKoZIhvcNAQcDoIIBijCCAYYCAQAxggEhMIIBHQIBADAFMAACAQEwDQYJKoZIhvcNAQEBBQAEggEAPRZN7DnYUhVL81p7xC9rUYPutoO3UrF2Sl8DlopfYoAG9omnXZlrut8wIffDZJSiU5XkOGv8x2QsXZc+bWqiplJ0VfzLClxEM2onWaT/GGGg7E+2YhrYuMG7mZYaqRYQ6/AgLDcIMBIdQBdL5mlpy+fVZn7Mu4cmsQYJTIe+yrNQtGMWMiNaHpwLGXvoXgwT6giX6L6VNiN51dAnHAdMYZ9Hf3G5CZEs6x8uOveqf6+qy+df24ItRUcsfQlSwsEaQRY+xjIVYIoiV8l8D8HiO+mVqbxtfQgyJIMv+0hl95zHGlc2W5lb6MvIFcJGu2xKIc00D7YOYgxLUx1aegixxzBcBgkqhkiG9w0BBwEwHQYJYIZIAWUDBAEqBBBnYSZmhDFSDoO1s329ktFegDC2Z7A+TGqTtZXKXaj2qQmowIvTZOVoUyF/5G0aED0wo/h+vfgosSS3Tx1dam0KUl0=] diff --git a/hieradata/country/au/region/drw1/infra/storage/consul.yaml b/hieradata/country/au/region/drw1/infra/storage/consul.yaml index fef2905..b44e321 100644 --- a/hieradata/country/au/region/drw1/infra/storage/consul.yaml +++ b/hieradata/country/au/region/drw1/infra/storage/consul.yaml @@ -1,3 +1,7 @@ --- profiles::consul::server::bootstrap_count: 3 profiles::consul::server::raft_multiplier: 10 +profiles::consul::server::primary_datacenter: 'au-syd1' +profiles::consul::server::join_remote_regions: true +profiles::consul::server::remote_regions: + - syd1 diff --git a/hieradata/country/au/region/drw1/infra/storage/vault.eyaml b/hieradata/country/au/region/drw1/infra/storage/vault.eyaml new file mode 100644 index 0000000..11fff31 --- /dev/null +++ b/hieradata/country/au/region/drw1/infra/storage/vault.eyaml @@ -0,0 +1,7 @@ +--- +vault::unseal_keys: + - ENC[PKCS7,MIIBmQYJKoZIhvcNAQcDoIIBijCCAYYCAQAxggEhMIIBHQIBADAFMAACAQEwDQYJKoZIhvcNAQEBBQAEggEAHfDhuu2C5ZEALdJlmOqWukEiAQQiVJ7KjpSRuf9h7RYwR+u8UNdcJYK1xFvYwmUczw6hkST/Zr06T4JwavpAHHuaRbyl8N1qZjlwt4MO5CPUTBT8k+EOaocF2byUXpYBThETjLB+WNLJAU3Dq8JboekCJ2F1Zjd8Mmdtu1C3Ip5ii5iVGbQShxDSPsdjtk8Q49lUKj61tLyuvadcTcxllHyXs6siWl7atBfIS6OX5KgA66VJhxOeoyyBaiqSSu7OqqZa2siYGTvjJS3UFDf8J+itsJJ1+0KUtkl07PvItkIruSAlHZGagVPrizAyEx1j4hFvVTGHac86bcV/5M9z5DBcBgkqhkiG9w0BBwEwHQYJYIZIAWUDBAEqBBDCjxoJHSXr/4XvXaxVbUGOgDCQ4DL05Qnw3+3qHWZRKvNChHgrhRPi2HmkiGni+A4ZVF9LHs+mF8TQ/t3Q1DrSy3I=] + - ENC[PKCS7,MIIBmQYJKoZIhvcNAQcDoIIBijCCAYYCAQAxggEhMIIBHQIBADAFMAACAQEwDQYJKoZIhvcNAQEBBQAEggEAoapLUNj1f+7BEvjzR9CO0Qz3LhI5M326BVliikRY7hpL2+0CnTOlR9K3YapD83LtpuiNbXqbk1mhi44ak0CTet8yz0ZH/BPkVYgV2Ll9ISdN4Knnnlf2Ljt/gHGf03jiUKwfXxu87LfvCySAMgzYonQ90cfIDc+XH6CoQv27WM3U1q79RcWl/w9Z/XwJiKyANSCXfBT16+RawrzmVo+zWbteqx09MfOHr7Q36VwOqjJaO94A/Dj3m/YJIOhmYXd52h+am6Kc1Q9dnzycKZYoKYOv+qi+bY4frx9sRvBxoGDGMb1mXTDSPeIT6NXbMCIsTsmYxjxAvBET72oKWXJUcDBcBgkqhkiG9w0BBwEwHQYJYIZIAWUDBAEqBBDy/pkTHpz4F9l1J6cKW4A9gDD873VdHr3ArjpE1R82wS5brCbBe7ntEuNFQMbnFPvOXwI4EaYV3IMRNv6Lzk6BBSI=] + - ENC[PKCS7,MIIBmQYJKoZIhvcNAQcDoIIBijCCAYYCAQAxggEhMIIBHQIBADAFMAACAQEwDQYJKoZIhvcNAQEBBQAEggEAVKVb6/nhbgEx6b2b90gfuXbZglZpoJjQtyzDQtCZzcZxh/xVFjwUy1XX/3+dueazFd5Ge5NnqQdxs/h5MBSjexHJhEm3fmA+gnns8sdYX5SDJSnhYvS1cB/wmfHuvkj3ZhIFxg0jlPlKz24QST99ouxKI2c490ByIbcFCr+A5GWnO7D/kf1Y+M0Sg2YiPE4zqF2zx1sgOfaV2xvQbRqqSjDPim/mYff95AtWwN9KbcAvc/7vDi4PrHR8GY9RXhI8FBEvelAT0H0NmnaCw4TvWXF/YxztlG9E55G3MsFyVAQJT7Dl8w4w5nk4AJJBMaXlO2s4AWD4Y+MVQh62hjqgHjBcBgkqhkiG9w0BBwEwHQYJYIZIAWUDBAEqBBBptatyhSChU/V0R+IVd5hRgDCmA07/V4UBz1nVMc2vZm2KvnUOPofO74hwkkoxOnk6O2h6arbw8GNHj7WxeHXoXPk=] + - ENC[PKCS7,MIIBmQYJKoZIhvcNAQcDoIIBijCCAYYCAQAxggEhMIIBHQIBADAFMAACAQEwDQYJKoZIhvcNAQEBBQAEggEAOGvhPhbKt8hkYTif5C+IE7iqcoeXm68BeUzlzE9qAY7lzQoAENauDKoIgoQT0hA7zrKZXPTUDrcw8SdxNp7Zo/Dr44urdr4LiT+QZwYTE09Xn8yIA3ij1XnXQ5bYP70TycuOjpVT0BKK+qSkklfd7IAw76AnUWF1D6P9MjT+shOmVNHQQSRrL2JLNppetQRCyOEMzkeDI/58/ohexvyUcY8WT4YMNhl/IrNBdcJ3xOwnJqEAXSUTre15T2I+7f+prhj4cS2V9qd0ZwUXSueL38EIMKwmq1ugb+zm8UYzqfKpRk/1THqT8T/r8B4PR2QxtiwtzLk388ag1mqQ/jHL9zBcBgkqhkiG9w0BBwEwHQYJYIZIAWUDBAEqBBAlKLuJOARFD1vt/R9gfp4LgDA0irHwG41ByRyYcKT87ra9tsdhb+i9ugnNRbFQ1UPTk7bFwS3HUteEJwNzcNIwFXY=] + - ENC[PKCS7,MIIBmQYJKoZIhvcNAQcDoIIBijCCAYYCAQAxggEhMIIBHQIBADAFMAACAQEwDQYJKoZIhvcNAQEBBQAEggEAEQvjVATvI+UVWrowTWSxtluiPrfa8akOSgr+MdcAh5Mgypw6RUeVJ2Sh8jekePZOO7Y0IQSfyNWOFAsaxBgeG7aEu6loFwxcSzrilg9c/2bV7Ybxr5saDViTjHO+UOYPPVRsJKeYvWd+vTdM+J7Eg3LGwzdLqyYu824affGm41KsSJdtxbNC1EzR+AOEU7SO8FkDIUZl2ekwz+3FfBX5TyXywlZGrbS7DkABB1jrO/JJtgnRu4D1AgUWjSJINXKyi9Xf91ZUyYCbVJ1asmRhOcCDcRigs82CF6nWbsSad80Z/ZoGVGYSlCsSXd4t8iEujCzeTkfBRK6Azr71f0zbBjBcBgkqhkiG9w0BBwEwHQYJYIZIAWUDBAEqBBAeR7zOfSz3Sd19UkcmdMJLgDBiPUNdk6zh2inhCqms/qnt7BqDBAYEzHuzbsM3U3PO+UIeJdym51cu3YKw3MkVuyw=] diff --git a/hieradata/country/au/region/drw1/infra/storage/vault.yaml b/hieradata/country/au/region/drw1/infra/storage/vault.yaml new file mode 100644 index 0000000..3994ded --- /dev/null +++ b/hieradata/country/au/region/drw1/infra/storage/vault.yaml @@ -0,0 +1,9 @@ +--- +# additional altnames +profiles::pki::vault::alt_names: + - vault.service.au-drw1.consul + +profiles::nginx::simpleproxy::nginx_aliases: + - vault.service.au-drw1.consul + +profiles::vault::server::primary_datacenter: 'au-drw1' diff --git a/hieradata/country/au/region/syd1.yaml b/hieradata/country/au/region/syd1.yaml new file mode 100644 index 0000000..2a744b7 --- /dev/null +++ b/hieradata/country/au/region/syd1.yaml @@ -0,0 +1,2 @@ +--- +timezone::timezone: 'Australia/Sydney' diff --git a/hieradata/country/au/region/syd1/infra/dns/resolver.yaml b/hieradata/country/au/region/syd1/infra/dns/resolver.yaml new file mode 100644 index 0000000..088f065 --- /dev/null +++ b/hieradata/country/au/region/syd1/infra/dns/resolver.yaml @@ -0,0 +1,52 @@ +--- +profiles::dns::resolver::zones: + main.unkin.net-forward: + domain: 'main.unkin.net' + zone_type: 'forward' + forwarders: + - 198.18.13.14 + - 198.18.13.15 + forward: 'only' + 13.18.198.in-addr.arpa-forward: + domain: '13.18.198.in-addr.arpa' + zone_type: 'forward' + forwarders: + - 198.18.13.14 + - 198.18.13.15 + forward: 'only' + 14.18.198.in-addr.arpa-forward: + domain: '14.18.198.in-addr.arpa' + zone_type: 'forward' + forwarders: + - 198.18.13.14 + - 198.18.13.15 + forward: 'only' + 15.18.198.in-addr.arpa-forward: + domain: '15.18.198.in-addr.arpa' + zone_type: 'forward' + forwarders: + - 198.18.13.14 + - 198.18.13.15 + forward: 'only' + 16.18.198.in-addr.arpa-forward: + domain: '16.18.198.in-addr.arpa' + zone_type: 'forward' + forwarders: + - 198.18.13.14 + - 198.18.13.15 + forward: 'only' + 17.18.198.in-addr.arpa-forward: + domain: '17.18.198.in-addr.arpa' + zone_type: 'forward' + forwarders: + - 198.18.13.14 + - 198.18.13.15 + forward: 'only' + consul-forward: + domain: 'consul' + zone_type: 'forward' + forwarders: + - 198.18.13.19 + - 198.18.13.20 + - 198.18.13.21 + forward: 'only' diff --git a/hieradata/country/au/region/syd1/infra/halb/haproxy.yaml b/hieradata/country/au/region/syd1/infra/halb/haproxy.yaml new file mode 100644 index 0000000..c7877aa --- /dev/null +++ b/hieradata/country/au/region/syd1/infra/halb/haproxy.yaml @@ -0,0 +1,79 @@ +--- +# mappings +profiles::haproxy::mappings: + fe_http: + ensure: present + mappings: + - 'au-syd1-pve.main.unkin.net be_ausyd1pve_web' + - 'au-syd1-pve-api.main.unkin.net be_ausyd1pve_api' + fe_https: + ensure: present + mappings: + - 'au-syd1-pve.main.unkin.net be_ausyd1pve_web' + - 'au-syd1-pve-api.main.unkin.net be_ausyd1pve_api' + +profiles::haproxy::frontends: + fe_http: + options: + use_backend: + - "%[req.hdr(host),lower,map(/etc/haproxy/fe_http.map,be_default)]" + fe_https: + options: + acl: + - 'acl_ausyd1pve req.hdr(host) -i https://au-syd1-pve.main.unkin.net' + - 'acl_internalsubnets src 198.18.0.0/16 10.10.12.0/24' + use_backend: + - "%[req.hdr(host),lower,map(/etc/haproxy/fe_https.map,be_default)]" + http-request: + - 'deny if { hdr_dom(host) -i au-syd1-pve.main.unkin.net } !acl_internalsubnets' + http-response: + - 'set-header X-Frame-Options DENY if acl_ausyd1pve' + - 'set-header X-Content-Type-Options nosniff' + - 'set-header X-XSS-Protection 1;mode=block' + +profiles::haproxy::backends: + be_ausyd1pve_web: + description: Backend for au-syd1 pve cluster (Web) + collect_exported: false # handled in custom function + options: + balance: roundrobin + option: + - httpchk GET / + - forwardfor + - http-keep-alive + - prefer-last-server + cookie: SRVNAME insert indirect nocache + http-reuse: always + http-request: + - set-header X-Forwarded-Port %[dst_port] + - add-header X-Forwarded-Proto https if { dst_port 443 } + redirect: 'scheme https if !{ ssl_fc }' + be_ausyd1pve_api: + description: Backend for au-syd1 pve cluster (API only) + collect_exported: false # handled in custom function + options: + balance: roundrobin + option: + - httpchk GET / + - forwardfor + - http-keep-alive + - prefer-last-server + http-reuse: always + http-request: + - set-header X-Forwarded-Port %[dst_port] + - add-header X-Forwarded-Proto https if { dst_port 443 } + redirect: 'scheme https if !{ ssl_fc }' + +profiles::haproxy::certlist::enabled: true +profiles::haproxy::certlist::certificates: + - /etc/pki/tls/vault/certificate.pem + +# additional altnames +profiles::pki::vault::alt_names: + - au-syd1-pve.main.unkin.net + - au-syd1-pve-api.main.unkin.net + +# additional cnames +profiles::haproxy::dns::cnames: + - au-syd1-pve.main.unkin.net + - au-syd1-pve-api.main.unkin.net diff --git a/hieradata/country/au/region/syd1/infra/proxmox.yaml b/hieradata/country/au/region/syd1/infra/proxmox.yaml new file mode 100644 index 0000000..5e07a1c --- /dev/null +++ b/hieradata/country/au/region/syd1/infra/proxmox.yaml @@ -0,0 +1,8 @@ +--- +profiles::proxmox::params::pve_members_role: 'roles::infra::proxmox::node' +profiles::proxmox::params::pve_kernel_version: '1.0.1' +profiles::proxmox::params::pve_kernel_release: '6.5.13-5-pve' +profiles::proxmox::params::pve_ceph_repos: true +profiles::proxmox::params::pve_ceph_release: 'reef' +profiles::proxmox::params::pve_ceph_install: true +profiles::proxmox::params::pve_ceph_network: '10.18.15.1/24' diff --git a/hieradata/country/au/region/syd1/infra/puppet/master.eyaml b/hieradata/country/au/region/syd1/infra/puppet/master.eyaml new file mode 100644 index 0000000..a6c1883 --- /dev/null +++ b/hieradata/country/au/region/syd1/infra/puppet/master.eyaml @@ -0,0 +1,3 @@ +--- +certmanager::vault_token: ENC[PKCS7,MIIBmQYJKoZIhvcNAQcDoIIBijCCAYYCAQAxggEhMIIBHQIBADAFMAACAQEwDQYJKoZIhvcNAQEBBQAEggEAJuE+uzgQaBRUXBCigckEo1j+UxxbiUGrzdf/B9K7XPdVxZh6TzYLpBgNnyaT6vLo0boX4uRD/By0gT5R/2qcXD6d/j+fh517Ctk4d2uO64f0vH3PzyyOBalsNtcCdPiV3q/xGqzQSHhPiNkFEjDvMBz5p53UjfKA6gAiPrLklp4rN/NVyiLBw20NeIqbL25VdkQa13ViS0Gm/eUQu7a2xQ1dvQFWWfuLaQxO0dh8L0ynkfmWKIjaiD5412Z8hYURu0otxbqVDdIbEMx5xQsXnFKeN93yHmgs7a7M6fLdp9jh+G8B+IlK1W7/9v2+RT0/yI3ZgWHVTvDRhMHuPGBjfTBcBgkqhkiG9w0BBwEwHQYJYIZIAWUDBAEqBBC5avtOPp9N65U1ILQENnvAgDBqI8XAjqbWIvXHqOEiKYdu+co0EEtsHR1v5xAeCmj/ZA6MLeKFlAVJbvpyCpzjons=] +certmanager::role_id: ENC[PKCS7,MIIBmQYJKoZIhvcNAQcDoIIBijCCAYYCAQAxggEhMIIBHQIBADAFMAACAQEwDQYJKoZIhvcNAQEBBQAEggEAJuE+uzgQaBRUXBCigckEo1j+UxxbiUGrzdf/B9K7XPdVxZh6TzYLpBgNnyaT6vLo0boX4uRD/By0gT5R/2qcXD6d/j+fh517Ctk4d2uO64f0vH3PzyyOBalsNtcCdPiV3q/xGqzQSHhPiNkFEjDvMBz5p53UjfKA6gAiPrLklp4rN/NVyiLBw20NeIqbL25VdkQa13ViS0Gm/eUQu7a2xQ1dvQFWWfuLaQxO0dh8L0ynkfmWKIjaiD5412Z8hYURu0otxbqVDdIbEMx5xQsXnFKeN93yHmgs7a7M6fLdp9jh+G8B+IlK1W7/9v2+RT0/yI3ZgWHVTvDRhMHuPGBjfTBcBgkqhkiG9w0BBwEwHQYJYIZIAWUDBAEqBBC5avtOPp9N65U1ILQENnvAgDBqI8XAjqbWIvXHqOEiKYdu+co0EEtsHR1v5xAeCmj/ZA6MLeKFlAVJbvpyCpzjons=] diff --git a/hieradata/country/au/region/syd1/infra/puppet/master.yaml b/hieradata/country/au/region/syd1/infra/puppet/master.yaml new file mode 100644 index 0000000..1b3d42c --- /dev/null +++ b/hieradata/country/au/region/syd1/infra/puppet/master.yaml @@ -0,0 +1,4 @@ +--- +profiles::puppet::server::dns_alt_names: + - puppetca.main.unkin.net + - puppetca diff --git a/hieradata/country/au/region/syd1/infra/sql/galera.yaml b/hieradata/country/au/region/syd1/infra/sql/galera.yaml new file mode 100644 index 0000000..9c4119c --- /dev/null +++ b/hieradata/country/au/region/syd1/infra/sql/galera.yaml @@ -0,0 +1,4 @@ +--- +profiles::sql::galera_member::cluster_name: au-syd1 +profiles::sql::galera_member::galera_master: ausyd1nxvm1027.main.unkin.net +profiles::sql::galera_member::innodb_buffer_pool_size: 256M diff --git a/hieradata/country/au/region/syd1/infra/storage/consul.eyaml b/hieradata/country/au/region/syd1/infra/storage/consul.eyaml new file mode 100644 index 0000000..fd508a6 --- /dev/null +++ b/hieradata/country/au/region/syd1/infra/storage/consul.eyaml @@ -0,0 +1,2 @@ +--- +profiles::consul::server::gossip_key: ENC[PKCS7,MIIBmQYJKoZIhvcNAQcDoIIBijCCAYYCAQAxggEhMIIBHQIBADAFMAACAQEwDQYJKoZIhvcNAQEBBQAEggEADwwYLK+fU0M/uLqQpRjHnIAyrt6yPEZSXpUX2jvOGVOA63X8LOYpLVfEGWMmkZ7BHRO0fgr847UUI/xI8otIuiOpgtW2E7QLWs806KUNXz+L8c7kSnQ1XAD5R81/5joDHl4AIxl5fAGryTXH1gfnpTMWh2yjFzU/KYuk2GhrU0M9ewCGJErQG4pT4u3ymGmkLjx6AiZ8r9xb4Eos2bhCCpFWfyb0kKcJqdKU9mzy508byNCfp8lr1DoKxEQrdqSSAQdepn6wCgBZtlAK/k63tOqM9dxyDaCsK8vLG9LlvuEwi3OL2lzTtc1mAcdYxahDo3uBX0/VcCswaXq3nPnu3TBcBgkqhkiG9w0BBwEwHQYJYIZIAWUDBAEqBBCUwXPoMh/dylvFwyRzAsnRgDDvh5CHrzJYdUXWGsauYlifOOukYokkwG3yqqtCByveMqVWfWsQukiDTixdqpCgfzw=] diff --git a/hieradata/country/au/region/syd1/infra/storage/consul.yaml b/hieradata/country/au/region/syd1/infra/storage/consul.yaml new file mode 100644 index 0000000..52a084f --- /dev/null +++ b/hieradata/country/au/region/syd1/infra/storage/consul.yaml @@ -0,0 +1,7 @@ +--- +profiles::consul::server::bootstrap_count: 3 +profiles::consul::server::raft_multiplier: 10 +profiles::consul::server::primary_datacenter: 'au-syd1' +profiles::consul::server::join_remote_regions: true +profiles::consul::server::remote_regions: + - drw1 diff --git a/hieradata/country/au/region/syd1/infra/storage/vault.eyaml b/hieradata/country/au/region/syd1/infra/storage/vault.eyaml new file mode 100644 index 0000000..74c3111 --- /dev/null +++ b/hieradata/country/au/region/syd1/infra/storage/vault.eyaml @@ -0,0 +1,7 @@ +--- +vault::unseal_keys: + - ENC[PKCS7,MIIBmQYJKoZIhvcNAQcDoIIBijCCAYYCAQAxggEhMIIBHQIBADAFMAACAQEwDQYJKoZIhvcNAQEBBQAEggEABDaLiGSq+xu4DjB/MygqwyVX2cRBlypzRTdijD0Q/Pk/KF4X/6dP1jFVH1hQOI4/oxfsv13PaLFFh/mHgh/WGtwsDKoc20KgUR9N5wvA6p83OLBfuueFFiFM6myh1uzcwgCETGAyGbIy3+Zm2KECfQGJVvcVVEvlCTdqSq8VRMpaxlVrjFA/A/JVI8Gcscuv/44SVAeQi0xsCt0e+HwiaBYq7b+bUjDIR3cHJq1/WZx9mY1rVlOK2385AXhZbN0yi3J+18TYY1ngNq4ag+8T5oFUNfvd66rjFE7sXVKwUCZ64vEVOO08E06rQmv9LHT6DLwPucWIp5AZ8Dc59yWBGzBcBgkqhkiG9w0BBwEwHQYJYIZIAWUDBAEqBBBmNT7lhDBPD628O6AMkH15gDDuoa6S9NGknF8IOhFVUUSxODg/VCKI43Z9IXBgv3iboD1Q+Dhfje6Vmiyi1sukLRw=] + - ENC[PKCS7,MIIBmQYJKoZIhvcNAQcDoIIBijCCAYYCAQAxggEhMIIBHQIBADAFMAACAQEwDQYJKoZIhvcNAQEBBQAEggEAdpCkAgYhBO6psgTovA9cD0NEu3QxwT14KSzmxr37aHuhSBoh3tIX9asLvR3AduGbDRNI+eTGohSmQRMraTOFWHcTpVv1GShG/KD/wKwW9BGlNze/MwEuoV/OeFcrjfYbsSA338IMgWbG5+MfEduZGxWKIT5F5D14vx6pb9V7bYvbH9jKwSOwWry/RfWkEvMhMZSjFxtRrlMQqj7yqjs9RjauWXctYt4Rx9jK+I+ghWjjV26Q3Pust3OxYCJfCffZ0tpW6YikkGd1Qtq3kuPeh72YU1kYmuQIsDpcgwIuJIMJy2ekteQ/14JtIqN43OvXW5CVrmBemF0AK059LQ96WDBcBgkqhkiG9w0BBwEwHQYJYIZIAWUDBAEqBBCDOOqa8oCU1St/MStiB/dngDCUp3/Vs0caWnMBi6z0oQ8FhfQR7zPSH8666bXh1U1ETCVL+B1c0NKLiig/3I4ncaQ=] + - ENC[PKCS7,MIIBmQYJKoZIhvcNAQcDoIIBijCCAYYCAQAxggEhMIIBHQIBADAFMAACAQEwDQYJKoZIhvcNAQEBBQAEggEALAt+ASQS+MoaVoMTBGadYksrKq7REP3OchGXMZL97xdfRVtxaV75/HMES13q4B2dewJzBhpvgTBy9lqPCHXk7PXAkGv0YP2gbj3FXuzlXtZtXD0QHv1SY9assGABCQMdQY+DlZasGIRer/RzOLXpi3zSLlHVFu6dLndKhVs7B6RXgPMnf5Xo0yRijTKHRh8G2oizOxN7X0g5RNZAfAXN+gbDXF/KzpCM8Hox0+6UgJs9ghL7hH8c5Z8odJZcfNuqg87ELSp2XAvpC4jO4KC8VkcT0lIuDgYafyRZcWT4O8Zx6FNvSnDWEdtWHfOUYIg0RTXQ0OR0p28PzS8+0Fhh8TBcBgkqhkiG9w0BBwEwHQYJYIZIAWUDBAEqBBCXnDOd5VnrCXt3QIM9BCsIgDD3P5XS+w/EV85vkp9SciOtH95jZ1M0tt7uwA76Bsk69O5qxEbNlv40ZUOC1i02Z4w=] + - ENC[PKCS7,MIIBmQYJKoZIhvcNAQcDoIIBijCCAYYCAQAxggEhMIIBHQIBADAFMAACAQEwDQYJKoZIhvcNAQEBBQAEggEAlBQxsb/TK3gdOmohjoRs5ICN9PjQJvIxW5co7NDsynU6kT6jBinokhbfCRt2RpTUeZqRC2eodMxZSQrkqkMaAbkwSVnMLWzK5444VwT9OrSSwQ0NfT2CuGW9/Vb/XbGy4jwlwGlG23Zf6GptdwxKq1PaJb5FGgUcTXB1XUsDPwLRqpduH4JTdi7BIovOFzsz/hLkaAvrx3BD1ls+21oJpHiGGoomSoTki0tv9Yq2mgB3sn5/P4hIs2vA5gGKTE74nd71hGCg6LBQT9q29cuiM367qebKcSH+nzUlJXYvTxbJiMrs3k5K8IdPd7ocxn1iIuxprSVe6cxEPeoyUIm2dzBcBgkqhkiG9w0BBwEwHQYJYIZIAWUDBAEqBBCSHy2XB/CfyCxkgWoLNPWRgDB23dqS9tTUKvXffAAucl5pttdtg5PUknvs7uiOndQDY5J3R0b5hapS186njvlsrW0=] + - ENC[PKCS7,MIIBmQYJKoZIhvcNAQcDoIIBijCCAYYCAQAxggEhMIIBHQIBADAFMAACAQEwDQYJKoZIhvcNAQEBBQAEggEAY3xFtGYy4lQDhHa/t4qri4TJ2/nWAg+EP+tAP4P/9a1er2mR2WkSZD6zBpDMBwN73V0b7XNgAV1W3lPi3XsJlzjhE27a2qBGzoXXekkW5+C65hrVfcPrATos4vpY+ly7ldu6gsZgaE5TlRVt6BE/joi2U5+PfzICOG1Zwpb6/aPdW9UhNPLIRVmAVZBTdnh2qXbYhg/IpUeuX1CSK8F7ptryGXO/aiL4adSYluJkgDtjFplP0yy4IRe7PztnBb2w1XsgIL3SodyhT64OqvoIQd7g6lKwvPmpBJB/VqHwoQDw/GvZg8/BN9514hNpwYsZNIpvtJRE8HX7QJ28mv7TzjBcBgkqhkiG9w0BBwEwHQYJYIZIAWUDBAEqBBClVGY4pKZs+wNZ9dIPRSZVgDAW1mDpEnYXfciwNU/aUpZyo2GkTC2DUsNwFtKlgG1aICTfCjLOUhBzcON+Tfhq+7c=] diff --git a/hieradata/country/au/region/syd1/infra/storage/vault.yaml b/hieradata/country/au/region/syd1/infra/storage/vault.yaml new file mode 100644 index 0000000..47d6b32 --- /dev/null +++ b/hieradata/country/au/region/syd1/infra/storage/vault.yaml @@ -0,0 +1,31 @@ +--- +# additional altnames +profiles::pki::vault::alt_names: + - vault.service.au-syd1.consul + - vault.query.consul + +profiles::nginx::simpleproxy::nginx_aliases: + - vault.service.au-syd1.consul + - vault.query.consul + +profiles::vault::server::primary_datacenter: 'au-syd1' +consul::services: + vault: + service_name: 'vault' + tags: + - 'https' + - 'secure' + address: "%{facts.networking.ip}" + port: 8200 + checks: + - id: 'vault_https_check' + name: 'Vault HTTPS Check' + http: "https://%{facts.networking.fqdn}:8200/v1/sys/health" + method: 'GET' + tls_skip_verify: true + interval: '10s' + timeout: '1s' +profiles::consul::client::node_rules: + - resource: service + segment: vault + disposition: write diff --git a/hieradata/nodes/ausyd1nxvm1017.main.unkin.net.yaml b/hieradata/nodes/ausyd1nxvm1017.main.unkin.net.yaml new file mode 100644 index 0000000..f7ad64b --- /dev/null +++ b/hieradata/nodes/ausyd1nxvm1017.main.unkin.net.yaml @@ -0,0 +1,2 @@ +--- +profiles::cobbler::params::is_cobbler_master: true diff --git a/hieradata/nodes/ausyd1nxvm1036.main.unkin.net.yaml b/hieradata/nodes/ausyd1nxvm1036.main.unkin.net.yaml new file mode 100644 index 0000000..a909eb0 --- /dev/null +++ b/hieradata/nodes/ausyd1nxvm1036.main.unkin.net.yaml @@ -0,0 +1,9 @@ +--- +profiles::puppet::server::dns_alt_names: + - puppetca.main.unkin.net + - puppetca.service.consul + - puppetca.query.consul + - puppetca + +profiles::puppet::puppetca::is_puppetca: true +profiles::puppet::puppetca::allow_subject_alt_names: true diff --git a/hieradata/nodes/prodinf01n01.main.unkin.net.yaml b/hieradata/nodes/prodinf01n01.main.unkin.net.yaml new file mode 100644 index 0000000..e6e8fc8 --- /dev/null +++ b/hieradata/nodes/prodinf01n01.main.unkin.net.yaml @@ -0,0 +1,9 @@ +--- +profiles::puppet::server::dns_alt_names: + - puppetca.main.unkin.net + - puppetca.service.consul + - puppetca.query.consul + - puppetca + +profiles::puppet::puppetca::is_puppetca: false +profiles::puppet::puppetca::allow_subject_alt_names: true diff --git a/hieradata/nodes/prodnxsr0001.main.unkin.net.yaml b/hieradata/nodes/prodnxsr0001.main.unkin.net.yaml new file mode 100644 index 0000000..13bad49 --- /dev/null +++ b/hieradata/nodes/prodnxsr0001.main.unkin.net.yaml @@ -0,0 +1,5 @@ +--- +profiles::proxmox::params::pve_clusterinit_master: true +profiles::proxmox::params::pve_ceph_mon: true +profiles::proxmox::params::pve_ceph_mgr: true +profiles::proxmox::params::pve_ceph_osd: true diff --git a/hieradata/nodes/prodnxsr0002.main.unkin.net.yaml b/hieradata/nodes/prodnxsr0002.main.unkin.net.yaml new file mode 100644 index 0000000..5fb387e --- /dev/null +++ b/hieradata/nodes/prodnxsr0002.main.unkin.net.yaml @@ -0,0 +1,4 @@ +--- +profiles::proxmox::params::pve_ceph_mon: true +profiles::proxmox::params::pve_ceph_mgr: true +profiles::proxmox::params::pve_ceph_osd: true diff --git a/hieradata/nodes/prodnxsr0003.main.unkin.net.yaml b/hieradata/nodes/prodnxsr0003.main.unkin.net.yaml new file mode 100644 index 0000000..5fb387e --- /dev/null +++ b/hieradata/nodes/prodnxsr0003.main.unkin.net.yaml @@ -0,0 +1,4 @@ +--- +profiles::proxmox::params::pve_ceph_mon: true +profiles::proxmox::params::pve_ceph_mgr: true +profiles::proxmox::params::pve_ceph_osd: true diff --git a/hieradata/nodes/prodnxsr0004.main.unkin.net.yaml b/hieradata/nodes/prodnxsr0004.main.unkin.net.yaml new file mode 100644 index 0000000..342f672 --- /dev/null +++ b/hieradata/nodes/prodnxsr0004.main.unkin.net.yaml @@ -0,0 +1,2 @@ +--- +profiles::proxmox::params::pve_ceph_osd: true diff --git a/hieradata/nodes/prodnxsr0005.main.unkin.net.yaml b/hieradata/nodes/prodnxsr0005.main.unkin.net.yaml new file mode 100644 index 0000000..342f672 --- /dev/null +++ b/hieradata/nodes/prodnxsr0005.main.unkin.net.yaml @@ -0,0 +1,2 @@ +--- +profiles::proxmox::params::pve_ceph_osd: true diff --git a/hieradata/nodes/prodnxsr0006.main.unkin.net.yaml b/hieradata/nodes/prodnxsr0006.main.unkin.net.yaml new file mode 100644 index 0000000..342f672 --- /dev/null +++ b/hieradata/nodes/prodnxsr0006.main.unkin.net.yaml @@ -0,0 +1,2 @@ +--- +profiles::proxmox::params::pve_ceph_osd: true diff --git a/hieradata/nodes/prodnxsr0007.main.unkin.net.yaml b/hieradata/nodes/prodnxsr0007.main.unkin.net.yaml new file mode 100644 index 0000000..342f672 --- /dev/null +++ b/hieradata/nodes/prodnxsr0007.main.unkin.net.yaml @@ -0,0 +1,2 @@ +--- +profiles::proxmox::params::pve_ceph_osd: true diff --git a/hieradata/nodes/prodnxsr0008.main.unkin.net.yaml b/hieradata/nodes/prodnxsr0008.main.unkin.net.yaml new file mode 100644 index 0000000..342f672 --- /dev/null +++ b/hieradata/nodes/prodnxsr0008.main.unkin.net.yaml @@ -0,0 +1,2 @@ +--- +profiles::proxmox::params::pve_ceph_osd: true diff --git a/hieradata/os/AlmaLinux/AlmaLinux8.yaml b/hieradata/os/AlmaLinux/AlmaLinux8.yaml index 75984dc..7861fca 100644 --- a/hieradata/os/AlmaLinux/AlmaLinux8.yaml +++ b/hieradata/os/AlmaLinux/AlmaLinux8.yaml @@ -1,11 +1,2 @@ # hieradata/os/AlmaLinux/AlmaLinux8.yaml --- -profiles::yum::managed_repos: - - 'base' - - 'appstream' - - 'epel' - - 'powertools' - - 'highavailability' - - 'puppet7' - - 'yum.postgresql.org' - - 'unkin' diff --git a/hieradata/os/AlmaLinux/AlmaLinux9.yaml b/hieradata/os/AlmaLinux/AlmaLinux9.yaml index 40c32c1..03c8c55 100644 --- a/hieradata/os/AlmaLinux/AlmaLinux9.yaml +++ b/hieradata/os/AlmaLinux/AlmaLinux9.yaml @@ -1,8 +1,2 @@ # hieradata/os/AlmaLinux/AlmaLinux9.yaml --- -profiles::yum::managed_repos: - - 'base' - - 'appstream' - - 'epel' - - 'puppet7' - - 'yum.postgresql.org' diff --git a/hieradata/os/AlmaLinux/all_releases.yaml b/hieradata/os/AlmaLinux/all_releases.yaml index 9a85522..c383966 100644 --- a/hieradata/os/AlmaLinux/all_releases.yaml +++ b/hieradata/os/AlmaLinux/all_releases.yaml @@ -1,10 +1,62 @@ # hieradata/os/almalinux/all_releases.yaml --- -profiles::yum::base::baseurl: http://repos.main.unkin.net/almalinux -profiles::yum::epel::baseurl: http://repos.main.unkin.net/epel -profiles::yum::unkin::baseurl: http://repos.main.unkin.net/unkin profiles::firewall::firewalld::ensure_package: 'absent' profiles::firewall::firewalld::ensure_service: 'stopped' profiles::firewall::firewalld::enable_service: false - profiles::puppet::agent::puppet_version: '7.26.0' + +profiles::packages::install: + - lzo + - xz + - policycoreutils + +lm-sensors::package: lm_sensors + +profiles::yum::global::repos: + baseos: + name: baseos + descr: baseos repository + target: /etc/yum.repos.d/baseos.repo + baseurl: https://edgecache.query.consul/almalinux/%{facts.os.release.full}/BaseOS/%{facts.os.architecture}/os + gpgkey: http://edgecache.query.consul/almalinux/RPM-GPG-KEY-AlmaLinux-%{facts.os.release.major} + extras: + name: extras + descr: extras repository + target: /etc/yum.repos.d/extras.repo + baseurl: https://edgecache.query.consul/almalinux/%{facts.os.release.full}/extras/%{facts.os.architecture}/os + gpgkey: http://edgecache.query.consul/almalinux/RPM-GPG-KEY-AlmaLinux-%{facts.os.release.major} + appstream: + name: appstream + descr: appstream repository + target: /etc/yum.repos.d/appstream.repo + baseurl: https://edgecache.query.consul/almalinux/%{facts.os.release.full}/AppStream/%{facts.os.architecture}/os + gpgkey: http://edgecache.query.consul/almalinux/RPM-GPG-KEY-AlmaLinux-%{facts.os.release.major} + powertools: + name: powertools + descr: powertools repository + target: /etc/yum.repos.d/powertools.repo + baseurl: https://edgecache.query.consul/almalinux/%{facts.os.release.full}/PowerTools/%{facts.os.architecture}/os + gpgkey: http://edgecache.query.consul/almalinux/RPM-GPG-KEY-AlmaLinux-%{facts.os.release.major} + highavailability: + name: highavailability + descr: highavailability repository + target: /etc/yum.repos.d/highavailability.repo + baseurl: https://edgecache.query.consul/almalinux/%{facts.os.release.full}/HighAvailability/%{facts.os.architecture}/os + gpgkey: http://edgecache.query.consul/almalinux/RPM-GPG-KEY-AlmaLinux-%{facts.os.release.major} + epel: + name: epel + descr: epel repository + target: /etc/yum.repos.d/epel.repo + baseurl: https://edgecache.query.consul/epel/%{facts.os.release.major}/Everything/%{facts.os.architecture} + gpgkey: http://edgecache.query.consul/epel/RPM-GPG-KEY-EPEL-%{facts.os.release.major} + puppet: + name: puppet + descr: puppet repository + target: /etc/yum.repos.d/puppet.repo + baseurl: https://yum.puppet.com/puppet7/el/%{facts.os.release.major}/%{facts.os.architecture} + gpgkey: https://yum.puppet.com/RPM-GPG-KEY-puppet-20250406 + unkin: + name: unkin + descr: unkin repository + target: /etc/yum.repos.d/unkin.repo + baseurl: https://repos.main.unkin.net/unkin/%{facts.os.release.major}/%{facts.os.architecture}/os diff --git a/hieradata/os/Debian/all_releases.yaml b/hieradata/os/Debian/all_releases.yaml index aa8a5bf..221b479 100644 --- a/hieradata/os/Debian/all_releases.yaml +++ b/hieradata/os/Debian/all_releases.yaml @@ -1,7 +1,14 @@ # hieradata/os/debian/all_releases.yaml --- -profiles::apt::base::mirrorurl: http://debian.mirror.digitalpacific.com.au/debian +profiles::apt::base::mirrorurl: http://repos.main.unkin.net/debian profiles::apt::base::secureurl: http://security.debian.org/debian-security profiles::apt::puppet7::mirror: http://apt.puppetlabs.com profiles::apt::puppet7::repo: puppet7 -profiles::apt::puppet7::dist: bullseye +profiles::pki::vaultca::ca_cert-path: /usr/local/share/ca-certificates/ + +profiles::packages::install: + - lzop + - python3.11-venv + - xz-utils + +lm-sensors::package: lm-sensors diff --git a/hieradata/roles/infra.yaml b/hieradata/roles/infra.yaml index 3192355..8c2ae06 100644 --- a/hieradata/roles/infra.yaml +++ b/hieradata/roles/infra.yaml @@ -2,7 +2,5 @@ profiles::packages::install: - policycoreutils -profiles::puppet::puppetdb::puppetdb_host: prodinf01n04.main.unkin.net -profiles::puppet::puppetdb::postgres_host: prodinf01n05.main.unkin.net puppetdb::master::config::create_puppet_service_resource: false #puppetdb::master::config::puppetdb_host: "%{lookup('profiles::puppet::puppetdb::puppetdb_host')}" diff --git a/hieradata/roles/infra/cobbler/server.eyaml b/hieradata/roles/infra/cobbler/server.eyaml new file mode 100644 index 0000000..6ccffe3 --- /dev/null +++ b/hieradata/roles/infra/cobbler/server.eyaml @@ -0,0 +1,2 @@ +--- +profiles::cobbler::params::default_password_crypted: ENC[PKCS7,MIIBmQYJKoZIhvcNAQcDoIIBijCCAYYCAQAxggEhMIIBHQIBADAFMAACAQEwDQYJKoZIhvcNAQEBBQAEggEAJidO18dSzKXgDEvFhigrDmiMTW+D7obTCZVAvl0JzQ6nqRdnh6Xa+j+yc7YzYtCg9VH60vfcutHFGhJptlMbTQq3vSUoF9ylgTutaW/to4T8jb8gBqK1n7b+devEQh4soJtOdAPSidCX4aqsP9dK3I8IijNWMABz59usGbY6oWedmC4865PBcxyIu3phWynNULTXPBEAqdXAutkh4N3P1ydFk3eARCVS3uWo7zaXVsu4vIkjYRDCUyFXBWb12L/NmQ2EhGwckPwgX/rcKRL9r49GxQTLBHJ5MoHQanwoiRw+5Tz3qLW69z+hk91VpnpkZgANc081rmhdyp6qmuIAVDBcBgkqhkiG9w0BBwEwHQYJYIZIAWUDBAEqBBBiDUwXVJ6mmwzt4YAxg3+qgDDWm5mlWEgsZqCHwG0n94v7oqCBqY2WQdTJAM3TtKlX2nOPlLEmfLrwqtsS2r3QzLo=] diff --git a/hieradata/roles/infra/cobbler/server.yaml b/hieradata/roles/infra/cobbler/server.yaml new file mode 100644 index 0000000..6709152 --- /dev/null +++ b/hieradata/roles/infra/cobbler/server.yaml @@ -0,0 +1,21 @@ +--- +profiles::packages::install: + - cobbler + - cobbler3.2-web + - httpd + - syslinux + - dnf-plugins-core + - debmirror + - pykickstart + - fence-agents + - selinux-policy-devel + - ipxe-bootimgs + +profiles::pki::vault::alt_names: + - cobbler.main.unkin.net + +profiles::cobbler::params::service_cname: 'cobbler.main.unkin.net' +profiles::selinux::setenforce::mode: permissive + +hiera_classes: + - profiles::selinux::setenforce diff --git a/hieradata/roles/infra/dhcp/server.yaml b/hieradata/roles/infra/dhcp/server.yaml new file mode 100644 index 0000000..a186d6c --- /dev/null +++ b/hieradata/roles/infra/dhcp/server.yaml @@ -0,0 +1,77 @@ +--- +profiles::dhcp::server::ntpservers: + - ntp01.main.unkin.net + - ntp02.main.unkin.net +profiles::dhcp::server::interfaces: + - eth0 +profiles::dhcp::server::default_lease_time: 1200 +profiles::dhcp::server::globaloptions: + - 'arch code 93 = unsigned integer 16' + +profiles::dhcp::server::pools: + syd1-prod: + network: 198.18.15.0 + mask: 255.255.255.0 + range: + - '198.18.15.200 198.18.15.220' + gateway: 198.18.15.254 + nameservers: + - 198.18.13.12 + - 198.18.13.13 + domain_name: main.unkin.net + pxeserver: 198.18.13.27 + syd1-test: + network: 198.18.16.0 + mask: 255.255.255.0 + range: + - '198.18.16.200 198.18.16.220' + gateway: 198.18.16.254 + nameservers: + - 198.18.13.12 + - 198.18.13.13 + domain_name: main.unkin.net + pxeserver: 198.18.13.27 + syd1-prod1: + network: 198.18.13.0 + mask: 255.255.255.0 + range: + - '198.18.13.200 198.18.13.220' + gateway: 198.18.13.254 + nameservers: + - 198.18.13.12 + - 198.18.13.13 + domain_name: main.unkin.net + pxeserver: 198.18.13.27 + syd1-prod2: + network: 198.18.14.0 + mask: 255.255.255.0 + range: + - '198.18.14.200 198.18.14.220' + gateway: 198.18.14.254 + nameservers: + - 198.18.13.12 + - 198.18.13.13 + domain_name: main.unkin.net + pxeserver: 198.18.13.27 + drw1-prod: + network: 198.18.17.0 + mask: 255.255.255.0 + range: + - '198.18.17.200 198.18.17.220' + gateway: 198.18.17.1 + nameservers: + - 198.18.17.7 + - 198.18.17.8 + domain_name: main.unkin.net + pxeserver: 198.18.13.27 + + # UFI 64-bit +profiles::dhcp::server::classes: + UEFI-64: + parameters: + - 'match if option arch = 00:07 or option arch = 00:09' + - 'filename "/ipxe.efi"' + Legacy: + parameters: + - 'match if option arch = 00:00' + - 'filename "/undionly.kpxe"' diff --git a/hieradata/roles/infra/dns/master.yaml b/hieradata/roles/infra/dns/master.yaml index 4f0dcbc..e9b81b7 100644 --- a/hieradata/roles/infra/dns/master.yaml +++ b/hieradata/roles/infra/dns/master.yaml @@ -1,11 +1,13 @@ --- -profiles::dns::master::nameservers: - - prodinf01n23.main.unkin.net - - prodinf01n24.main.unkin.net - +profiles::dns::master::ns_role: roles::infra::dns::master +profiles::dns::master::use_ns: region profiles::dns::master::acls: acl-main.unkin.net: addresses: + - 198.18.13.0/24 + - 198.18.14.0/24 + - 198.18.15.0/24 + - 198.18.16.0/24 - 198.18.17.0/24 profiles::dns::master::zones: @@ -15,6 +17,30 @@ profiles::dns::master::zones: dynamic: false ns_notify: true source: '/var/named/sources/main.unkin.net.conf' + 13.18.198.in-addr.arpa: + domain: '13.18.198.in-addr.arpa' + zone_type: 'master' + dynamic: false + ns_notify: true + source: '/var/named/sources/13.18.198.in-addr.arpa.conf' + 14.18.198.in-addr.arpa: + domain: '14.18.198.in-addr.arpa' + zone_type: 'master' + dynamic: false + ns_notify: true + source: '/var/named/sources/14.18.198.in-addr.arpa.conf' + 15.18.198.in-addr.arpa: + domain: '15.18.198.in-addr.arpa' + zone_type: 'master' + dynamic: false + ns_notify: true + source: '/var/named/sources/15.18.198.in-addr.arpa.conf' + 16.18.198.in-addr.arpa: + domain: '16.18.198.in-addr.arpa' + zone_type: 'master' + dynamic: false + ns_notify: true + source: '/var/named/sources/16.18.198.in-addr.arpa.conf' 17.18.198.in-addr.arpa: domain: '17.18.198.in-addr.arpa' zone_type: 'master' @@ -27,6 +53,10 @@ profiles::dns::master::views: recursion: false zones: - main.unkin.net + - 13.18.198.in-addr.arpa + - 14.18.198.in-addr.arpa + - 15.18.198.in-addr.arpa + - 16.18.198.in-addr.arpa - 17.18.198.in-addr.arpa match_clients: - acl-main.unkin.net diff --git a/hieradata/roles/infra/dns/resolver.yaml b/hieradata/roles/infra/dns/resolver.yaml index 2e80a11..10751b9 100644 --- a/hieradata/roles/infra/dns/resolver.yaml +++ b/hieradata/roles/infra/dns/resolver.yaml @@ -2,28 +2,64 @@ profiles::dns::resolver::acls: acl-main.unkin.net: addresses: + - 10.10.8.1/32 + - 198.18.21.160/27 + - 198.18.21.192/27 + - 198.18.13.0/24 + - 198.18.14.0/24 + - 198.18.15.0/24 + - 198.18.16.0/24 - 198.18.17.0/24 profiles::dns::resolver::zones: - main.unkin.net-forward: - domain: 'main.unkin.net' + 8.10.10.in-addr.arpa-forward: + domain: '8.10.10.in-addr.arpa' zone_type: 'forward' forwarders: - - 198.18.17.23 - - 198.18.17.24 + - 10.10.16.32 + - 10.10.16.33 + forward: 'only' + 16.10.10.in-addr.arpa-forward: + domain: '16.10.10.in-addr.arpa' + zone_type: 'forward' + forwarders: + - 10.10.16.32 + - 10.10.16.33 + forward: 'only' + 20.10.10.in-addr.arpa-forward: + domain: '20.10.10.in-addr.arpa' + zone_type: 'forward' + forwarders: + - 10.10.16.32 + - 10.10.16.33 + forward: 'only' + unkin.net-forward: + domain: 'unkin.net' + zone_type: 'forward' + forwarders: + - 10.10.16.32 + - 10.10.16.33 + forward: 'only' + dmz.unkin.net-forward: + domain: 'dmz.unkin.net' + zone_type: 'forward' + forwarders: + - 10.10.16.32 + - 10.10.16.33 + forward: 'only' + network.unkin.net-forward: + domain: 'network.unkin.net' + zone_type: 'forward' + forwarders: + - 10.10.16.32 + - 10.10.16.33 forward: 'only' prod.unkin.net-forward: domain: 'prod.unkin.net' zone_type: 'forward' forwarders: - - 10.10.8.1 - forward: 'only' - 17.18.198.in-addr.arpa-forward: - domain: '17.18.198.in-addr.arpa' - zone_type: 'forward' - forwarders: - - 198.18.17.23 - - 198.18.17.24 + - 10.10.16.32 + - 10.10.16.33 forward: 'only' profiles::dns::resolver::views: @@ -31,7 +67,18 @@ profiles::dns::resolver::views: recursion: true zones: - main.unkin.net-forward + - unkin.net-forward + - dmz.unkin.net-forward + - network.unkin.net-forward - prod.unkin.net-forward + - consul-forward + - 13.18.198.in-addr.arpa-forward + - 14.18.198.in-addr.arpa-forward + - 15.18.198.in-addr.arpa-forward + - 16.18.198.in-addr.arpa-forward - 17.18.198.in-addr.arpa-forward + - 8.10.10.in-addr.arpa-forward + - 16.10.10.in-addr.arpa-forward + - 20.10.10.in-addr.arpa-forward match_clients: - acl-main.unkin.net diff --git a/hieradata/roles/infra/git/gitea.eyaml b/hieradata/roles/infra/git/gitea.eyaml new file mode 100644 index 0000000..fa29e19 --- /dev/null +++ b/hieradata/roles/infra/git/gitea.eyaml @@ -0,0 +1,3 @@ +--- +profiles::gitea::init::mysql_pass: ENC[PKCS7,MIIBiQYJKoZIhvcNAQcDoIIBejCCAXYCAQAxggEhMIIBHQIBADAFMAACAQEwDQYJKoZIhvcNAQEBBQAEggEAjmMVHQcvy0PLruFWI6UmYqM2uEqXntV8HdA54RCTm7GaneXsW+rom+ibFVd0i9L+spQPQzcidh7FlzBRYgny8yH8TqZlh7XMraXSYG2EvrjwzNvgnwhY5mGEQNQcQkqN9Orfsf6HjXmXg2CxajYibKu0/belJZFffzPzzrn15wy3Cj5lDjAziqYoD+8Ko1zkF9lWz4ewVjll82yo8iSpidN+PyvoeWsi/eJ9cW72TgFLt/rvGquLq3MuW54J716hrR1Z37Uf0OO18AiKCVjoCi5Cf/k0VKRsXM8Myu2KInqrGcUHAO+fsOXBXnmU0MOxW0OIOmwxfwY6LJfN23arlDBMBgkqhkiG9w0BBwEwHQYJYIZIAWUDBAEqBBB6GktEMe8gSTijJ/dIHC5/gCCblMojNKO1ig9fNsuT9I2u5Bt4iJrSMN+GBGnCzO1Bvw==] +profiles::gitea::init::lfs_jwt_secret: ENC[PKCS7,MIIBmQYJKoZIhvcNAQcDoIIBijCCAYYCAQAxggEhMIIBHQIBADAFMAACAQEwDQYJKoZIhvcNAQEBBQAEggEACd6q4E/4l1EYD3SFjc1okibyJ13kcGGWU+ShbCgwLgkW7INkyCxhbNm69yPA7WcyuRhH/Lfz/XjJKd3BSCyRQPr5IUOIRINspx82tLBcaMzY/99GFrfyDnf3+SV/AxrPJ/zD5TGkKQP7uX6WjC9DXpHE+pFJa9wBAipmV439y0JDVt2gXFmhqBWThSjBDBfJ5X4zO5wY8CfBX4APOcD5hIQP/T4n04dQLNpigEKKy6B+GFuooTbdmMmFj3ZpT+cUS8Aw9mFkBwyyN1o+50XU3vW4eieUz8cYkzDPu574XfTunqD2jcvPiFjCla8G1SpKfHkruKnZWwgO0Ntw9td5QDBcBgkqhkiG9w0BBwEwHQYJYIZIAWUDBAEqBBAIRVL5j4dzbYg6f2XjvkQ6gDAd2qUNzPn2flZgKwsjIZcYdmFMTn48hGPUFfVaMDeyzPoJi84CyRJl8cQvcAe52sw=] diff --git a/hieradata/roles/infra/git/gitea.yaml b/hieradata/roles/infra/git/gitea.yaml new file mode 100644 index 0000000..3199ed6 --- /dev/null +++ b/hieradata/roles/infra/git/gitea.yaml @@ -0,0 +1,39 @@ +--- +# additional altnames +profiles::pki::vault::alt_names: + - git.main.unkin.net + - git.service.consul + - git.query.consul + - "git.service.%{facts.country}-%{facts.region}.consul" + +consul::services: + git: + service_name: 'git' + tags: + - 'git' + - 'gitea' + address: "%{facts.networking.ip}" + port: 443 + checks: + - id: 'gitea_https_check' + name: 'Gitea HTTPS Check' + http: "https://%{facts.networking.fqdn}:443" + method: 'GET' + tls_skip_verify: true + interval: '10s' + timeout: '1s' +profiles::consul::client::node_rules: + - resource: service + segment: git + disposition: write + +# manage a simple nginx reverse proxy +profiles::nginx::simpleproxy::nginx_vhost: 'git.query.consul' +profiles::nginx::simpleproxy::nginx_aliases: + - git.main.unkin.net + - git.service.consul + - git.query.consul + - "git.service.%{facts.country}-%{facts.region}.consul" +profiles::nginx::simpleproxy::proxy_port: 3000 +profiles::nginx::simpleproxy::proxy_path: '/' +nginx::client_max_body_size: 250M diff --git a/hieradata/roles/infra/halb/haproxy.yaml b/hieradata/roles/infra/halb/haproxy.yaml new file mode 100644 index 0000000..cd212ad --- /dev/null +++ b/hieradata/roles/infra/halb/haproxy.yaml @@ -0,0 +1,91 @@ +--- +profiles::haproxy::ls_stats::port: 9090 +profiles::haproxy::ls_stats::user: 'admin' +profiles::selinux::setenforce::mode: permissive + +profiles::haproxy::selinux::ports: + - 9090 +profiles::haproxy::selinux::sebooleans: + - haproxy_connect_any + +profiles::haproxy::server::globals: + log: + - /dev/log local0 + - /dev/log local1 notice + stats: + - timeout 30s + - socket /var/lib/haproxy/stats + ca-base: /etc/ssl/certs + crt-base: /etc/ssl/private + ssl-default-bind-ciphers: EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH + ssl-default-bind-options: 'ssl-min-ver TLSv1.2 ssl-max-ver TLSv1.3' + ssl-default-server-ciphers: kEECDH+aRSA+AES:kRSA+AES:+AES256:RC4-SHA:!kEDH:!LOW:!EXP:!MD5:!aNULL:!eNULL + ssl-default-server-options: no-sslv3 + tune.ssl.default-dh-param: 2048 + +profiles::haproxy::server::defaults: + mode: http + option: + - httplog + - dontlognull + - http-server-close + - forwardfor except 127.0.0.0/8 + - redispatch + timeout: + - http-request 10s + - queue 1m + - connect 10s + - client 5m + - server 5m + - http-keep-alive 10s + - check 10s + retries: 3 + maxconn: 5000 + +profiles::haproxy::frontends: + fe_http: + description: 'Global HTTP Frontend' + bind: + 0.0.0.0:80: + - transparent + mode: 'http' + options: + acl: + - 'acl-letsencrypt path_beg /.well-known/acme-challenge/' + http-request: + - 'set-header X-Forwarded-Proto https' + - 'set-header X-Real-IP %[src]' + fe_https: + description: 'Global HTTPS Frontend' + bind: + 0.0.0.0:443: + - ssl + - crt-list /etc/haproxy/certificate.list + - ciphers EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH + - force-tlsv12 + mode: 'http' + options: + acl: + - 'acl-letsencrypt path_beg /.well-known/acme-challenge/' + http-request: + - 'set-header X-Forwarded-Proto https' + - 'set-header X-Real-IP %[src]' + +profiles::haproxy::backends: + be_letsencrypt: + description: Backend for LetsEncrypt Verifications + collect_exported: true + options: + balance: roundrobin + be_default: + description: Backend for unmatched HTTP traffic + collect_exported: true + options: + balance: roundrobin + option: + - httpchk GET / + - forwardfor + cookie: SRVNAME insert + http-request: + - set-header X-Forwarded-Port %[dst_port] + - add-header X-Forwarded-Proto https if { dst_port 443 } diff --git a/hieradata/roles/infra/ntp/server.yaml b/hieradata/roles/infra/ntp/server.yaml index e618573..839e32d 100644 --- a/hieradata/roles/infra/ntp/server.yaml +++ b/hieradata/roles/infra/ntp/server.yaml @@ -1,6 +1,10 @@ --- profiles::ntp::client::client_only: false profiles::ntp::server::allowquery: + - '198.18.13.0/24' + - '198.18.14.0/24' + - '198.18.15.0/24' + - '198.18.16.0/24' - '198.18.17.0/24' profiles::ntp::server::peers: diff --git a/hieradata/roles/infra/ovirt/engine.yaml b/hieradata/roles/infra/ovirt/engine.yaml new file mode 100644 index 0000000..b2a934d --- /dev/null +++ b/hieradata/roles/infra/ovirt/engine.yaml @@ -0,0 +1,50 @@ +--- +profiles::yum::global::repos: + centos_8_advanced_virtualization: + name: 'virt-advanced-virtualization' + descr: 'CentOS Advanced Virtualization' + target: /etc/yum.repos.d/ovirt.repo + baseurl: https://edgecache.query.consul/centos/8-stream/virt/x86_64/advancedvirt-common + gpgkey: 'https://www.centos.org/keys/RPM-GPG-KEY-CentOS-SIG-Virtualization' + centos_8_ceph_pacific: + name: 'storage-ceph-pacific' + descr: 'CentOS Ceph Pacific' + target: /etc/yum.repos.d/ovirt.repo + baseurl: https://edgecache.query.consul/centos/8-stream/storage/x86_64/ceph-pacific + gpgkey: 'https://www.centos.org/keys/RPM-GPG-KEY-CentOS-SIG-Storage' + centos_8_rabbitmq_38: + name: 'messaging-rabbitmq-38' + descr: 'CentOS RabbitMQ 38' + target: /etc/yum.repos.d/ovirt.repo + baseurl: https://edgecache.query.consul/centos/8-stream/messaging/x86_64/rabbitmq-38 + gpgkey: 'https://www.centos.org/keys/RPM-GPG-KEY-CentOS-SIG-Messaging' + centos_8_nfv_openvswitch: + name: 'nfv-openvswitch-2' + descr: 'CentOS NFV OpenvSwitch' + target: /etc/yum.repos.d/ovirt.repo + baseurl: https://edgecache.query.consul/centos/8-stream/nfv/x86_64/openvswitch-2 + gpgkey: 'https://www.centos.org/keys/RPM-GPG-KEY-CentOS-SIG-NFV' + centos_8_openstack_xena: + name: 'cloud-openstack-xena' + descr: 'CentOS OpenStack Xena' + target: /etc/yum.repos.d/ovirt.repo + baseurl: https://edgecache.query.consul/centos/8-stream/cloud/x86_64/openstack-xena + gpgkey: 'https://www.centos.org/keys/RPM-GPG-KEY-CentOS-SIG-Cloud' + centos_8_opstools: + name: 'opstools-collectd-5' + descr: 'CentOS OpsTools - collectd' + target: /etc/yum.repos.d/ovirt.repo + baseurl: https://edgecache.query.consul/centos/8-stream/opstools/x86_64/collectd-5 + gpgkey: 'https://www.centos.org/keys/RPM-GPG-KEY-CentOS-SIG-OpsTools' + centos_8_ovirt45: + name: 'virt-ovirt-45' + descr: 'CentOS oVirt 4.5' + target: /etc/yum.repos.d/ovirt.repo + baseurl: https://edgecache.query.consul/centos/8-stream/virt/x86_64/ovirt-45 + gpgkey: 'https://www.centos.org/keys/RPM-GPG-KEY-CentOS-SIG-Virtualization' + centos_8_stream_gluster10: + name: 'storage-gluster-10' + descr: 'CentOS oVirt 4.5 - Glusterfs 10' + target: /etc/yum.repos.d/ovirt.repo + baseurl: https://edgecache.query.consul/centos/8-stream/storage/x86_64/gluster-10 + gpgkey: 'https://www.centos.org/keys/RPM-GPG-KEY-CentOS-SIG-Storage' diff --git a/hieradata/roles/infra/ovirt/node.yaml b/hieradata/roles/infra/ovirt/node.yaml new file mode 100644 index 0000000..762c1aa --- /dev/null +++ b/hieradata/roles/infra/ovirt/node.yaml @@ -0,0 +1,58 @@ +--- +profiles::firewall::firewalld::ensure_package: 'installed' +profiles::firewall::firewalld::ensure_service: 'running' + +sudo::purge_ignore: + - '50_vdsm' + - '50_vdsm_hook_ovirt_provider_ovn_hook' + - '60_ovirt-ha' + +profiles::yum::global::repos: + centos_8_advanced_virtualization: + name: 'virt-advanced-virtualization' + descr: 'CentOS Advanced Virtualization' + target: /etc/yum.repos.d/ovirt.repo + baseurl: https://edgecache.query.consul/centos/8-stream/virt/x86_64/advancedvirt-common + gpgkey: 'https://www.centos.org/keys/RPM-GPG-KEY-CentOS-SIG-Virtualization' + centos_8_ceph_pacific: + name: 'storage-ceph-pacific' + descr: 'CentOS Ceph Pacific' + target: /etc/yum.repos.d/ovirt.repo + baseurl: https://edgecache.query.consul/centos/8-stream/storage/x86_64/ceph-pacific + gpgkey: 'https://www.centos.org/keys/RPM-GPG-KEY-CentOS-SIG-Storage' + centos_8_rabbitmq_38: + name: 'messaging-rabbitmq-38' + descr: 'CentOS RabbitMQ 38' + target: /etc/yum.repos.d/ovirt.repo + baseurl: https://edgecache.query.consul/centos/8-stream/messaging/x86_64/rabbitmq-38 + gpgkey: 'https://www.centos.org/keys/RPM-GPG-KEY-CentOS-SIG-Messaging' + centos_8_nfv_openvswitch: + name: 'nfv-openvswitch-2' + descr: 'CentOS NFV OpenvSwitch' + target: /etc/yum.repos.d/ovirt.repo + baseurl: https://edgecache.query.consul/centos/8-stream/nfv/x86_64/openvswitch-2 + gpgkey: 'https://www.centos.org/keys/RPM-GPG-KEY-CentOS-SIG-NFV' + centos_8_openstack_xena: + name: 'cloud-openstack-xena' + descr: 'CentOS OpenStack Xena' + target: /etc/yum.repos.d/ovirt.repo + baseurl: https://edgecache.query.consul/centos/8-stream/cloud/x86_64/openstack-xena + gpgkey: 'https://www.centos.org/keys/RPM-GPG-KEY-CentOS-SIG-Cloud' + centos_8_opstools: + name: 'opstools-collectd-5' + descr: 'CentOS OpsTools - collectd' + target: /etc/yum.repos.d/ovirt.repo + baseurl: https://edgecache.query.consul/centos/8-stream/opstools/x86_64/collectd-5 + gpgkey: 'https://www.centos.org/keys/RPM-GPG-KEY-CentOS-SIG-OpsTools' + centos_8_ovirt45: + name: 'virt-ovirt-45' + descr: 'CentOS oVirt 4.5' + target: /etc/yum.repos.d/ovirt.repo + baseurl: https://edgecache.query.consul/centos/8-stream/virt/x86_64/ovirt-45 + gpgkey: 'https://www.centos.org/keys/RPM-GPG-KEY-CentOS-SIG-Virtualization' + centos_8_stream_gluster10: + name: 'storage-gluster-10' + descr: 'CentOS oVirt 4.5 - Glusterfs 10' + target: /etc/yum.repos.d/ovirt.repo + baseurl: https://edgecache.query.consul/centos/8-stream/storage/x86_64/gluster-10 + gpgkey: 'https://www.centos.org/keys/RPM-GPG-KEY-CentOS-SIG-Storage' diff --git a/hieradata/roles/infra/proxmox.yaml b/hieradata/roles/infra/proxmox.yaml new file mode 100644 index 0000000..7a1b911 --- /dev/null +++ b/hieradata/roles/infra/proxmox.yaml @@ -0,0 +1,7 @@ +--- +sudo::configs: + ceph-smartctl: + priority: 20 + content: | + ceph ALL=NOPASSWD: /usr/sbin/smartctl -x --json=o /dev/* + ceph ALL=NOPASSWD: /usr/sbin/nvme * smart-log-add --json /dev/* diff --git a/hieradata/roles/infra/puppet.yaml b/hieradata/roles/infra/puppet.yaml new file mode 100644 index 0000000..6ae5977 --- /dev/null +++ b/hieradata/roles/infra/puppet.yaml @@ -0,0 +1,3 @@ +--- +profiles::packages::install: + - puppetserver diff --git a/hieradata/roles/infra/puppet/master.eyaml b/hieradata/roles/infra/puppet/master.eyaml new file mode 100644 index 0000000..07427fe --- /dev/null +++ b/hieradata/roles/infra/puppet/master.eyaml @@ -0,0 +1,3 @@ +--- +profiles::puppet::eyaml::publickey: ENC[PKCS7,MIIFjQYJKoZIhvcNAQcDoIIFfjCCBXoCAQAxggEhMIIBHQIBADAFMAACAQEwDQYJKoZIhvcNAQEBBQAEggEAizhVN1svMJqLlkDWcm/qhMNajKL9G7GvBxG04dOdYLUu99wgmIlD1vetNIoJrQ6defmVuMMzT3IxzIDrRf8QEVL7hstIFoGlhv0ObBewjLJY34v3B7Sxj0nv8XPTLd8Q6LZQb+KSo0SLQxbjEw60qAl5DbDqXUNOx2OIV3yP1IaCzzi6llb1ZOWPcBESt6HEnLzqkwzEK+2/QGBOMqChP1EP7JHFrWQw5YYCLUcYCLVts1K57Q7ThFwckUA0v8Vh9HdlZqA0XPxKyVK7nfw/Y1CpwRTwZ8GYnry1/iLNYjFGkDU0V5pf+ZhlZfIChVccma9NCSlQtA+7DikNcpLTfTCCBE4GCSqGSIb3DQEHATAdBglghkgBZQMEASoEEJQ4jJz/oSqW79tDOSv2pWCAggQgvi+p2P7tkIY4c0yNEIFjnXa3Imopg4bZ29TQJnPLAqVM7Bexh0XhxAjWk8YFvxQ0Yio+3JKlvqlsFVpecumV6NHwVPe521Hl7l88eRvgCHBC3tVm98+N2A0GdGbT+begqsj0nPTDScixJE79dGZK6/qgf3NuYPCj+drFwWrDuZXpIYMHJcOrVhqlg4RFW4ZYUxbsAC2eNFXUF0bYpKej3voCnlj/o6RxLEC/Gv2T66e9sFjeANo9W84uAfZ1t4cweVzYh1h6Yiw+0ewWA6ndg8thgr2Uk9JdpjXzS0QTtElGmNv+tZmCH45o0HUunPZs0gkn5unT0pzZosqgSeu0HdHcsImJpuJVRIVjAXypku7LtBKnP3VA5iXi2lld/suEOeeU18Aw3pxFQrKV3cexiWLa4mpKn8JR1HBxw4NcLj3/fes41fxW0zLyY8m4MksaIpc4BXz33uup5rHdVblbD1raZJPAg7k8KufStsRBmeokdysF+PJebrCfTH8goR3BWGfCVWQEoDjB2wAhVTQKuzAh3d51k+s4uvJchNBDgfGt/s9hdBFU/VQTZUyOoSEOwxB1857sOF3iPLM1233XEhZd2AOl4h5xy1z3+aSOG0jiihWt6QdosUig/IHxyO4gWaEO37iaLlF0ZVSJKjOV/IBCHJAaAG476uSNv+kTKgvu0PQtIfcKHpa1ppHi96fO8FKX76l26VoGKf/kMi6bWdTObYZnyiN7fz342ewMpwu70wQQWo33riK0hhF6bRu40J/KmgoUaUz3jSnErv+EeeREYww5SSNlMhpQNBNj+WfEDRC4Zx9VsF1cjtTY1um0kYdoyTHBLH6V1oAEiFIScHqkW1zKVAEiBh2v6C1U3fwAzOyAbnDlBrsuhnVxbJa8O1d5yw+U2py6xdC3Wq6FsAP9kdfDu+mjNDOwwJWZa8iTj3NHum1G6xklF2JHtmp2p1gY0e/JCETIk5Xh1okf404F9Xi+CWvlmlPXie9SdwgyJWpXOM60pJN2iMOFKPGn4chppMka38HakDKbdNNTELxNE+/yVECT0uQ8iBvETX1FU+y4LpGFghmwAIiKB1HZXx/0Gof0+txj/p9AgnpeVvDbq4iiZOulcu2BepsrFDg2zNLollfhAo+6QvElpk2MI1yHrg3OaTt7U8JV1dxHyIWjbtRvbiiS1E6mKGiOpkIQd/IHBjkujvEd7LVeE721HrLdGRaTR9QJfTR8jPZGHMlZa14a2pcxliyYd9RFSVOkVZH2LetuSWStQ1gPdBEeKDSWyFBA0Rxzlw2Sl25MJ4PAIpimyUYrnxTa2XgHyavMa0kjVAhX15+ywze2ypOVnB9/q3L3M5JCq+eaOBicJQiERX4h7Yj499S9Y/2nxk2DOUxi965BDIZGSG3/qOtl] +profiles::puppet::eyaml::privatekey: ENC[PKCS7,MIIH/QYJKoZIhvcNAQcDoIIH7jCCB+oCAQAxggEhMIIBHQIBADAFMAACAQEwDQYJKoZIhvcNAQEBBQAEggEAkH2q64bYf5Es/YNK6c6d5t9PYcbc9NGzC6F2AzjWeLV9rdT+DBNmhPeyHN4jR6edzLRaNL+u3cuur3mTxwSJcEXdyHQSbXJLlGpd9CPEjuerqdsXkFvamP//nHjwvSosBUo4PKtllphX0XHP6JS0Mm+nukv0YyDk+63+cETuyP5M1FVsLSK8ZWblOn1uBgNhhjGZF5nNeayjJKloWdVY8+pS8L6/y0QprF05oLDvI0JgK9wud8NID+LCNtb2Z5/mq2ScpMB/r/ji/oPHs40zhANqOiAuy/sUWwIivdB2iKKvcLfJ8tbtCanXuQxboqnulL1+C87Y4m1rmk4cNtKU3DCCBr4GCSqGSIb3DQEHATAdBglghkgBZQMEASoEELXUERpdYNf8m2IXbCw/MxiAggaQ187hqDCftN9RvnFRHnlHyPZijykRgs558tdh0yA8GscJ9vim8kxQXrxM6gqAGgmV7xYnpyK0pvEn0/6cEFkcBkpkQOtlyil+4WB9bcLJIF4LzPut0pz4Eq/6zMSM9PGWCRFe3ufkdoDq5M1SlHa/Aoi/LwNu5EFFlFZeeDiZyUMupLJUHbTQ+wt2JgQLfpBzeCGb5BRLvSPH0+Y7ShwHgp2ZCtxc/tT5cdQq5a3+tt9ZYSy5Hj+c8I2WBPm3wghA7QULCB1+42K4A8BJ7HQucaT1mRMc0QnCt68xQkhBulxGnADPaRAWICmuAF2KBv/eS74TdYj3z0OCSZW5k1wDBz8FCSIodn2a1LgBMrFRCAS2fwRn7Hc0yguCRl9ppERW+8K3pg7aAiBqJbeTwQN/VICNan92y+cbUndO9a/U16zKD4SxfW8PMwSu/qz6i45gUjQ83THjwNAE6el0lYFYivBsEEg66Sqo2cXtPQlAdB8lOsS34TQq21zipikgAAii0mGoH738t2CYL6tMUGthpcfXLioU0AhXjLVED1PIpmWxieFENWO8SUx3NjXyoefBVQrzc1PPAgeVGSaOBoJSN7xNx3/RQhWck0240DZmi+41z5CF1z91eZY+ZJYa/SaHVWWZ7GgQDEXGnWKQkMZce6RK0qw0/8B0x5O6aIlBrB7aSVQIkDLSUw8bq7N5dAeKXLu+2QHhG1yl+Bmn1xDMILFphJNT2ZNXkoSd0r1WUePWBEFCOBPsu3cHaK9DZiXSdfJ3dY+1NYuVZDQshQ1Fe4IKpHm/0mtz60DjrTTaJ3kAsPLCpeFGJ+1U/TdO+IgPAsiHUIaDRtv19ZeH7/Pa/kAceIe16F8CRNkzJ62D8CH4RYEXxTJ7oogYbhsw+5WQ3ZGzJHNvxcX4EVofjIsr2uIQEAVTu9VSDY2LyihJBEs0EBw25dai52u2g1Jjtteod9p6B+rwrcVGKAzdEo7nF9qK6+dS8VlfFbmbU1/ulIpM0hUr3ZFsUSv1qUGqUmYdgndvE0+gHop71fsnQRmT9wTdQlUs7RC0+BPWvf7eGljJT+omDwv+wSShikWku9ZSk58HqZ74f2RizxL7Ny8SWCkOf1u+Gi8kalMhr+1p8e39S6WTws8rJHxIQrzfY7aqZwYIZzLl4JMnqBvbkUlCEKNHmVAVt6AgPGfTmoEzSgulHEMCETuBQl4dS8mtFvWRKCy0jC2fAUfIAoihoh/2g3MTbKQCM3aSHrqyPTAduN2VkQwTM4JmgU6YYWy4kXjPWsgEm+FjqOKQqd5Q5bwIOoFLSVQgrTtoKVUXzK8VbTDNDhLj+LggB9MMncr5X44LkdtrktYWeQ1CbBGYUTNHyXxT2nbJm7DJos4zjSIqnkSiR2VyRAkxF9TSXjnZwtsziXC4gdonjA+ImV5aUvL5aTO2zbTYQOqgrauS/SWS4tXbZ4Thw86d2zbO32Kvuu4bfHVTN087eiRuiFmjtz43PwBRMxjABLDe/ZRUHLDomAVydTS98aIswUb33jHoPtEkz4bWEtZlhwrqguvPzLSJT1SNZnDhNsdzO96GDB2vtvXmIiQq+/8jh0LKIoOCFWKsFfB0GrkZZvLnF6oQQ/MiYNNY1TLnHMAg2uSF+ap/g8QRvfE5FX2UquYE1ATeD+8iRw0g2crNXGVRynBo6ESd5O+zwcMitO/Re9tQM4rfNj83VgWeSUNLxhOZmbYs0hDEbS0lXIWa1NbASuXWk/FBXzr8X/ZdlZPWAMWe3J9Bqh6e1FhgGD6ZZmSTYxHzlz5TNCf+aMqnJRb5eyN+UM5iWgW/VpAlKWMl98c1lsKwccAS/SH2zugKwBT8Bf/4wnbpHrZe817vVF7raVcaYvNnYTzdSQCcnvRK/D40sqleOhtfX/vdjOFWfoukbEJnXNytkTZeKrBm83z6tmYe4siQdfn4X9/lGNWEDyjYiJX8czH6yMlRW+FposOpE4Y9Dgs694iPHmYt1/1VbuW240uG6VT/d+OjSD5L6JfTT47pghoWTl0dQGbKd3kmoku7C7ll5etCdz5UIY2JOmS1gx6NgvsElJyflgQHgXLiSKpB0iSZ7zTRKlBmRG7uiU582nkbXHQ7BwZkP3nq95bgtCmk+0pvioYYg/jK8hvuiv+b8Ez2pHaTLabn/jYww8ewIZz0W5mWgcCDwdebtP2CCSnB2IPjyzAh2TW8JTljeoJAe9ai+iqiX4400R2hXZl6KMpC] diff --git a/hieradata/roles/infra/puppet/master.yaml b/hieradata/roles/infra/puppet/master.yaml index f47db83..4af2c1c 100644 --- a/hieradata/roles/infra/puppet/master.yaml +++ b/hieradata/roles/infra/puppet/master.yaml @@ -1,5 +1,9 @@ --- profiles::puppet::autosign::subnet_ranges: + - '198.18.13.0/24' + - '198.18.14.0/24' + - '198.18.15.0/24' + - '198.18.16.0/24' - '198.18.17.0/24' profiles::puppet::autosign::domains: @@ -8,8 +12,14 @@ profiles::puppet::autosign::domains: # profiles::puppet::autosign::nodes: # - 'somenode.main.unkin.net' -profiles::puppet::enc::repo: https://git.unkin.net/unkinben/puppet-enc.git -profiles::puppet::r10k::r10k_repo: https://git.unkin.net/unkinben/puppet-r10k.git +profiles::puppet::cobbler_enc::cobbler_scheme: https +profiles::puppet::cobbler_enc::cobbler_hostname: cobbler.main.unkin.net +profiles::puppet::cobbler_enc::version: 'system' +profiles::puppet::cobbler_enc::packages: + - 'requests' + - 'PyYAML' +profiles::puppet::enc::repo: https://git.service.au-syd1.consul/unkinben/puppet-enc.git +profiles::puppet::r10k::r10k_repo: https://git.service.au-syd1.consul/unkinben/puppet-r10k.git profiles::puppet::g10k::bin_path: '/opt/puppetlabs/bin/g10k' profiles::puppet::g10k::cfg_path: '/etc/puppetlabs/r10k/r10k.yaml' profiles::puppet::g10k::environments_path: '/etc/puppetlabs/code/environments' @@ -18,3 +28,48 @@ profiles::puppet::gems::puppet: - 'deep_merge' - 'ipaddr' - 'hiera-eyaml' + +profiles::helpers::certmanager::vault_config: + addr: 'https://vault.query.consul:8200' + mount_point: 'pki_int' + approle_path: 'approle' + role_name: 'servers_default' + output_path: '/tmp/certmanager' + role_id: "%{lookup('certmanager::role_id')}" + +profiles::puppet::server::agent_server: 'puppet.query.consul' +profiles::puppet::server::report_server: 'puppet.query.consul' +profiles::puppet::server::ca_server: 'puppetca.query.consul' +profiles::puppet::server::dns_alt_names: + - "%{facts.networking.fqdn}" + - "%{facts.networking.hostname}" + - puppetmaster.main.unkin.net + - puppet.main.unkin.net + - puppet.service.consul + - puppet.query.consul + - puppetmaster + - puppet + +consul::services: + puppet: + service_name: 'puppet' + tags: + - 'puppet' + - 'master' + address: "%{facts.networking.ip}" + port: 8140 + checks: + - id: 'puppet_https_check' + name: 'Puppet HTTPS Check' + http: "https://%{facts.networking.fqdn}:8140/status/v1/simple" + method: 'GET' + tls_skip_verify: true + interval: '10s' + timeout: '1s' +profiles::consul::client::node_rules: + - resource: service + segment: puppet + disposition: write + - resource: service + segment: puppetca + disposition: write diff --git a/hieradata/roles/infra/puppetboard/server.yaml b/hieradata/roles/infra/puppetboard/server.yaml new file mode 100644 index 0000000..d835603 --- /dev/null +++ b/hieradata/roles/infra/puppetboard/server.yaml @@ -0,0 +1,35 @@ +--- +# additional servername aliases +profiles::puppet::puppetboard::nginx_aliases: + - puppetboard.service.consul + - puppetboard.query.consul + - "puppetboard.service.%{facts.country}-%{facts.region}.consul" + - "%{facts.networking.fqdn}" + +# additional altnames +profiles::pki::vault::alt_names: + - puppetboard.main.unkin.net + - puppetboard.service.consul + - puppetboard.query.consul + - "puppetboard.service.%{facts.country}-%{facts.region}.consul" + +consul::services: + puppetboard: + service_name: 'puppetboard' + tags: + - 'puppet' + - 'puppetboard' + address: "%{facts.networking.ip}" + port: 80 + checks: + - id: 'puppetboard_http_check' + name: 'Puppetboard HTTP Check' + http: "http://%{facts.networking.fqdn}:80" + method: 'GET' + tls_skip_verify: true + interval: '10s' + timeout: '1s' +profiles::consul::client::node_rules: + - resource: service + segment: puppetboard + disposition: write diff --git a/hieradata/roles/infra/puppetdb/api.yaml b/hieradata/roles/infra/puppetdb/api.yaml new file mode 100644 index 0000000..784200a --- /dev/null +++ b/hieradata/roles/infra/puppetdb/api.yaml @@ -0,0 +1,39 @@ +--- +profiles::puppet::puppetdb_api::java_bin: /usr/lib/jvm/jre-11/bin/java +profiles::puppet::puppetdb_api::java_args: + '-Xmx': '2048m' + '-Xms': '256m' + +profiles::puppet::client::dns_alt_names: + - puppetdbapi.main.unkin.net + - puppetdbapi.service.consul + - puppetdbapi.query.consul + +# additional altnames +profiles::pki::vault::alt_names: + - puppetdbapi.main.unkin.net + - puppetdbapi.service.consul + - puppetdbapi.query.consul + - puppetdbapi + +consul::services: + puppetdbapi: + service_name: 'puppetdbapi' + tags: + - 'puppet' + - 'puppetdb' + - 'puppetdbapi' + address: "%{facts.networking.ip}" + port: 8080 + checks: + - id: 'puppetdbapi_http_check' + name: 'PuppetDB API HTTP Check' + http: "http://%{facts.networking.fqdn}:8080" + method: 'GET' + tls_skip_verify: true + interval: '10s' + timeout: '1s' +profiles::consul::client::node_rules: + - resource: service + segment: puppetdbapi + disposition: write diff --git a/hieradata/roles/infra/puppetdb/sql.yaml b/hieradata/roles/infra/puppetdb/sql.yaml new file mode 100644 index 0000000..0d6409a --- /dev/null +++ b/hieradata/roles/infra/puppetdb/sql.yaml @@ -0,0 +1,4 @@ +--- +postgresql_config_entries: + max_connections: 300 + shared_buffers: '256MB' diff --git a/hieradata/roles/infra/reposync/syncer.yaml b/hieradata/roles/infra/reposync/syncer.yaml index 762a9d4..f893a5b 100644 --- a/hieradata/roles/infra/reposync/syncer.yaml +++ b/hieradata/roles/infra/reposync/syncer.yaml @@ -2,6 +2,11 @@ profiles::packages::install: - createrepo +profiles::pki::vault::alt_names: + - repos.main.unkin.net + +profiles::reposync::webserver::nginx_listen_mode: both +profiles::reposync::webserver::nginx_cert_type: vault profiles::reposync::repos_list: almalinux_8_9_baseos: repository: 'BaseOS' @@ -38,6 +43,62 @@ profiles::reposync::repos_list: release: '8.9' mirrorlist: https://mirrors.almalinux.org/mirrorlist/8.9/extras gpgkey: 'http://mirror.aarnet.edu.au/pub/almalinux/RPM-GPG-KEY-AlmaLinux' + centos_8_advanced_virtualization: + repository: 'virt-advanced-virtualization' + description: 'CentOS Advanced Virtualization' + osname: 'centos' + release: '8' # Assumed static value for demonstration + mirrorlist: 'http://mirrorlist.centos.org/?release=8&arch=x86_64&repo=virt-advanced-virtualization' # Assuming 'stream' and 'x86_64' + gpgkey: 'https://www.centos.org/keys/RPM-GPG-KEY-CentOS-SIG-Virtualization' + centos_8_ceph_pacific: + repository: 'storage-ceph-pacific' + description: 'CentOS Ceph Pacific' + osname: 'centos' + release: '8' # Assumed static value for demonstration + mirrorlist: 'http://mirrorlist.centos.org/?release=8&arch=x86_64&repo=storage-ceph-pacific' # Assuming '8' and 'x86_64' + gpgkey: 'https://www.centos.org/keys/RPM-GPG-KEY-CentOS-SIG-Storage' + centos_8_rabbitmq_38: + repository: 'messaging-rabbitmq-38' + description: 'CentOS RabbitMQ 38' + osname: 'centos' + release: '8-stream' # Specified based on the repository name + mirrorlist: 'http://mirrorlist.centos.org/?release=8-stream&arch=x86_64&repo=messaging-rabbitmq-38' # Assuming '8' and 'x86_64' + gpgkey: 'https://www.centos.org/keys/RPM-GPG-KEY-CentOS-SIG-Messaging' + centos_8_nfv_openvswitch: + repository: 'nfv-openvswitch-2' + description: 'CentOS NFV OpenvSwitch' + osname: 'centos' + release: '8-stream' # Assumed static value for demonstration + mirrorlist: 'http://mirrorlist.centos.org/?release=8-stream&arch=x86_64&repo=nfv-openvswitch-2' # Assuming 'stream' and 'x86_64' + gpgkey: 'https://www.centos.org/keys/RPM-GPG-KEY-CentOS-SIG-NFV' + centos_8_openstack_xena: + repository: 'cloud-openstack-xena' + description: 'CentOS OpenStack Xena' + osname: 'centos' + release: '8-stream' # Directly taken from the provided mirrorlist + mirrorlist: 'http://mirrorlist.centos.org/?release=8-stream&arch=x86_64&repo=cloud-openstack-xena' # Assuming 'x86_64' + gpgkey: 'https://www.centos.org/keys/RPM-GPG-KEY-CentOS-SIG-Cloud' + centos_8_opstools: + repository: 'opstools-collectd-5' + description: 'CentOS OpsTools - collectd' + osname: 'centos' + release: '8-stream' # Assumed static value for demonstration + mirrorlist: 'http://mirrorlist.centos.org/?arch=x86_64&release=8-stream&repo=opstools-collectd-5' # Assuming 'stream' and 'x86_64' + gpgkey: 'https://www.centos.org/keys/RPM-GPG-KEY-CentOS-SIG-OpsTools' + centos_8_ovirt45: + repository: 'virt-ovirt-45' + description: 'CentOS oVirt 4.5' + osname: 'centos' + release: '8-stream' # Assumed static value for demonstration + mirrorlist: 'http://mirrorlist.centos.org/?release=8-stream&arch=x86_64&repo=virt-ovirt-45' # Assuming 'stream' and 'x86_64' + gpgkey: 'https://www.centos.org/keys/RPM-GPG-KEY-CentOS-SIG-Virtualization' + centos_8_stream_gluster10: + repository: 'storage-gluster-10' + description: 'CentOS oVirt 4.5 - Glusterfs 10' + osname: 'centos' + release: '8-stream' # Assumed static value for demonstration + mirrorlist: 'http://mirrorlist.centos.org/?release=8-stream&arch=x86_64&repo=storage-gluster-10' # Assuming 'stream' and 'x86_64' + gpgkey: 'https://www.centos.org/keys/RPM-GPG-KEY-CentOS-SIG-Storage' epel_8_everything: repository: 'Everything' description: 'EPEL 8 Everything' @@ -58,18 +119,18 @@ profiles::reposync::repos_list: osname: 'puppet7' release: 'el' baseurl: 'https://yum.puppet.com/puppet7/el/8/x86_64/' - gpgkey: 'https://yum.puppet.com/RPM-GPG-KEY-puppet' + gpgkey: 'https://yum.puppet.com/RPM-GPG-KEY-puppet-20250406' postgresql_rhel8_common: repository: 'common' description: 'PostgreSQL Common RHEL 8' osname: 'postgresql' release: 'rhel8' baseurl: 'https://download.postgresql.org/pub/repos/yum/common/redhat/rhel-8-x86_64/' - gpgkey: 'https://download.postgresql.org/pub/repos/yum/RPM-GPG-KEY-PGDG' + gpgkey: 'https://download.postgresql.org/pub/repos/yum/keys/PGDG-RPM-GPG-KEY-RHEL' postgresql_rhel8_16: repository: '16' description: 'PostgreSQL 16 RHEL 8' osname: 'postgresql' release: 'rhel8' baseurl: 'https://download.postgresql.org/pub/repos/yum/16/redhat/rhel-8-x86_64/' - gpgkey: 'https://download.postgresql.org/pub/repos/yum/RPM-GPG-KEY-PGDG' + gpgkey: 'https://download.postgresql.org/pub/repos/yum/keys/PGDG-RPM-GPG-KEY-RHEL' diff --git a/hieradata/roles/infra/sql/galera.yaml b/hieradata/roles/infra/sql/galera.yaml index f6965e6..084072a 100644 --- a/hieradata/roles/infra/sql/galera.yaml +++ b/hieradata/roles/infra/sql/galera.yaml @@ -1,11 +1,27 @@ --- -profiles::sql::galera_member::cluster_name: galera01 -profiles::sql::galera_member::galera_master: prodinf01n29.main.unkin.net profiles::sql::galera_member::configure_firewall: false profiles::sql::galera_member::wsrep_sst_method: rsync profiles::sql::galera_member::galera_members_lookup: true profiles::sql::galera_member::galera_members_role: roles::infra::sql::galera profiles::sql::galera_member::datadir: /data/mariadb -profiles::sql::galera_member::innodb_buffer_pool_size: 256M profiles::sql::galera_member::innodb_file_per_table: 1 profiles::sql::galera_member::package_name: mariadb-galera-server + +consul::services: + mariadb: + service_name: "mariadb-%{facts.environment}" + tags: + - 'database' + - 'mariadb' + address: "%{facts.networking.ip}" + port: 3306 + checks: + - id: 'mariadb_tcp_check' + name: 'MariaDB TCP Check' + tcp: "%{facts.networking.ip}:3306" + interval: '10s' + timeout: '1s' +profiles::consul::client::node_rules: + - resource: service + segment: "mariadb-%{facts.environment}" + disposition: write diff --git a/hieradata/roles/infra/storage/consul.yaml b/hieradata/roles/infra/storage/consul.yaml index e3eb0fd..a3ea581 100644 --- a/hieradata/roles/infra/storage/consul.yaml +++ b/hieradata/roles/infra/storage/consul.yaml @@ -1,8 +1,6 @@ --- -profiles::consul::server::members_role: roles::infra::storage::consul profiles::consul::server::members_lookup: true profiles::consul::server::data_dir: /data/consul -profiles::consul::server::primary_datacenter: 'au-drw1' profiles::consul::server::addresses: dns: "%{::networking.ip}" http: "%{::networking.ip}" @@ -20,3 +18,62 @@ profiles::consul::server::acl: tokens: initial_management: "%{alias('profiles::consul::server::acl_tokens_initial_management')}" default: "%{alias('profiles::consul::server::acl_tokens_default')}" + replication: "%{alias('profiles::consul::server::acl_tokens_replication')}" + +# additional altnames +profiles::pki::vault::alt_names: + - consul.main.unkin.net + - consul.service.consul + - consul + +# manage a simple nginx reverse proxy +profiles::nginx::simpleproxy::nginx_vhost: 'consul.service.consul' +profiles::nginx::simpleproxy::nginx_aliases: + - consul + - consul.main.unkin.net +profiles::nginx::simpleproxy::proxy_port: 8500 +profiles::nginx::simpleproxy::proxy_path: '/' + +profiles::consul::prepared_query::rules: + vault: + ensure: 'present' + service_name: 'vault' + service_failover_n: 3 + service_only_passing: true + ttl: 10 + puppet: + ensure: 'present' + service_name: 'puppet' + service_failover_n: 3 + service_only_passing: true + ttl: 10 + puppetca: + ensure: 'present' + service_name: 'puppetca' + service_failover_n: 3 + service_only_passing: true + ttl: 10 + edgecache: + ensure: 'present' + service_name: 'edgecache' + service_failover_n: 3 + service_only_passing: true + ttl: 10 + puppetdbapi: + ensure: 'present' + service_name: 'puppetdbapi' + service_failover_n: 3 + service_only_passing: true + ttl: 10 + puppetboard: + ensure: 'present' + service_name: 'puppetboard' + service_failover_n: 3 + service_only_passing: true + ttl: 10 + git: + ensure: 'present' + service_name: 'git' + service_failover_n: 3 + service_only_passing: true + ttl: 10 diff --git a/hieradata/roles/infra/storage/edgecache.yaml b/hieradata/roles/infra/storage/edgecache.yaml new file mode 100644 index 0000000..7fcd2f8 --- /dev/null +++ b/hieradata/roles/infra/storage/edgecache.yaml @@ -0,0 +1,120 @@ +--- +consul::services: + edgecache: + service_name: 'edgecache' + tags: + - 'cache' + - 'edge' + address: "%{facts.networking.ip}" + port: 443 + checks: + - id: 'edgecache_https_check' + name: 'EdgeCache HTTPS Check' + http: "https://%{facts.networking.fqdn}" + method: 'GET' + tls_skip_verify: true + interval: '10s' + timeout: '1s' +profiles::consul::client::node_rules: + - resource: service + segment: edgecache + disposition: write + +# additional altnames +profiles::pki::vault::alt_names: + - edgecache.service.consul + - edgecache.query.consul + +profiles::edgecache::params::nginx_resolvers_enable: true +profiles::edgecache::params::nginx_resolvers_ipv4only: true +profiles::edgecache::params::nginx_listen_mode: both +profiles::edgecache::params::nginx_cert_type: vault +profiles::edgecache::params::nginx_aliases: + - edgecache.service.consul + - edgecache.query.consul +profiles::edgecache::params::directories: + /data/edgecache: { owner: root, group: root } + /data/edgecache/pub: { owner: nginx, group: nginx } + /data/edgecache/pub/centos: { owner: nginx, group: nginx } + /data/edgecache/pub/almalinux: { owner: nginx, group: nginx } + /data/edgecache/pub/debian: { owner: nginx, group: nginx } + /data/edgecache/pub/epel: { owner: nginx, group: nginx } + /data/edgecache/pub/postgres: { owner: nginx, group: nginx } + /data/edgecache/pub/postgres/apt: { owner: nginx, group: nginx } + /data/edgecache/pub/postgres/yum: { owner: nginx, group: nginx } + +profiles::edgecache::params::mirrors: + debian: + ensure: present + location: /debian + proxy: http://mirror.gsl.icu + debian_pool: + ensure: present + location: /debian/pool + proxy: http://mirror.gsl.icu + proxy_cache: cache + proxy_cache_valid: + - '200 302 1440h' + - '404 1m' + centos_repodata: + ensure: present + location: '~* ^/centos/.*/repodata/' + proxy: http://gsl-syd.mm.fcix.net + centos_data: + ensure: present + location: /centos + proxy: http://gsl-syd.mm.fcix.net + proxy_cache: cache + proxy_cache_valid: + - '200 302 1440h' + - '404 1m' + almalinux_repodata: + ensure: present + location: '~* ^/almalinux/.*/repodata/' + proxy: http://gsl-syd.mm.fcix.net + almalinux_data: + ensure: present + location: /almalinux + proxy: http://gsl-syd.mm.fcix.net + proxy_cache: cache + proxy_cache_valid: + - '200 302 1440h' + - '404 1m' + epel_repodata: + ensure: present + location: '~* ^/epel/.*/repodata/' + proxy: http://gsl-syd.mm.fcix.net + epel_data: + ensure: present + location: /epel + proxy: http://gsl-syd.mm.fcix.net + proxy_cache: cache + proxy_cache_valid: + - '200 302 1440h' + - '404 1m' + postgres_yum_repodata: + ensure: present + location: '~* ^/postgres/yum/.*/repodata/' + rewrite_rules: + - '^/postgres/yum/(.*)$ /pub/repos/yum/$1 break' + proxy: https://download.postgresql.org + postgres_yum_data: + ensure: present + location: /postgres/yum + proxy: https://download.postgresql.org/pub/repos/yum + proxy_cache: cache + proxy_cache_valid: + - '200 302 1440h' + - '404 1m' + postgres_apt: + ensure: present + location: /postgres/apt + proxy: https://download.postgresql.org/pub/repos/apt + postgres_apt_pool: + ensure: present + location: /postgres/apt/pool + proxy: https://download.postgresql.org/pub/repos/apt/pool + proxy_cache: cache + proxy_cache_valid: + - '200 302 1440h' + - '404 1m' diff --git a/hieradata/roles/infra/storage/vault.eyaml b/hieradata/roles/infra/storage/vault.eyaml index 4e68db5..11fff31 100644 --- a/hieradata/roles/infra/storage/vault.eyaml +++ b/hieradata/roles/infra/storage/vault.eyaml @@ -1,7 +1,7 @@ --- vault::unseal_keys: - - ENC[PKCS7,MIIBmQYJKoZIhvcNAQcDoIIBijCCAYYCAQAxggEhMIIBHQIBADAFMAACAQEwDQYJKoZIhvcNAQEBBQAEggEAobuA26wCD25sP6t0w3VgcrjBdpwVsglUz119X/y9o5FHkUibXuHkesNktUKzSMWpVBV+EsoTQ9HFisUOX3ykSIyYOVntm4BTECYBZKAyVXzkolAqX32IWtYqV4H4eKb3/OXw8zayJn9cPWbQkVtNDq3mZUMzgGj46DPFpH8aNQOI/xpovldY+WK1wo6WY7MGSCKw/+0mXK1Qa6wjh2K1X8cCg344ODZQD/h2SCT25qYPFVSBEzFwzQyLWULFOozg5RdE4OXkviqtq2PFtWxCD4S87WiG4elpttJAH0bbKFJs4PMZFgi0HdHqnMHXWiQgB/A9lNRhSPaU16Y2OTJ2HzBcBgkqhkiG9w0BBwEwHQYJYIZIAWUDBAEqBBCw46SHa6ZZKMhxpG8VG7fJgDDj4cQ2/7//RszV99oDP3OyCHRPt6PylAyWVBCxj54faILV/2OaF3GwW05gWzlmwVI=] - - ENC[PKCS7,MIIBmQYJKoZIhvcNAQcDoIIBijCCAYYCAQAxggEhMIIBHQIBADAFMAACAQEwDQYJKoZIhvcNAQEBBQAEggEAKeXpQMz90SUeIojz659+AX9hdTn5EiPOprrdI4EjqPL5BItr2xkrk8XbDnhlgM6PWwbo5jzEKBYGFTRbnHHF6/xdQQoUALMyhD3SSwDZOv8B92zSWkRMUpXlrUFMJeHldDMXS9enpg4Y4jL7i7GWsf7PEuEOTidNid3ZViKT32miSoJvGRENZvGyYA8Rd1Vh+3lIxtJNWqEUiw6yDUUO6H8bRKQ0JVBxW4JQOkLeaKbz+M2WjvE+PDeYykCWaApzfcxE3XPxv7MhBLJskf/37h/pHFGLhAUEcATiXrdUHzDuGnCLHQohW4B6NnKH7GNTby7Nbxzuq5zA3g9yavKj1DBcBgkqhkiG9w0BBwEwHQYJYIZIAWUDBAEqBBCbXFapwcT7R268E9Zih4i2gDC4cSSmU+33i5j6uKbgydDGqeooT4j2GzWCr0Ya52aVZnoeqYEFdp+dBFcCnvwFTQU=] - - ENC[PKCS7,MIIBmQYJKoZIhvcNAQcDoIIBijCCAYYCAQAxggEhMIIBHQIBADAFMAACAQEwDQYJKoZIhvcNAQEBBQAEggEApI/exTnGbzLFuIYAVqLi27O8CxBXDOPDB5K9GVIDIL8pyXoqv8LDO1fkg0TZJREZIHUNBwx4DNg0ruveuEcHXTleLLKGk51Cn89YQB3bvUPJ7BfBq8GRV6TpNNj50jstjGqyesw+q4r9cx8F/l1qxlHBmJPT6h332GXO1Fzmh6wIF+poqD2KfsbppOtk/YGLtdTa87RuNS0eQ9LcayMIqWE2+vrkUlEtjNYgNWHnKFQhlB0kety4IKV6rdZd9thVIbyQctJmoNSf8mB2vLm+ufgQqQHc6RpwwZEkAaX+i6pACN44tgEnFuQ96KMW+GX5LCZ7cAUfrLXDNoGfbve2LDBcBgkqhkiG9w0BBwEwHQYJYIZIAWUDBAEqBBC/1fBbDfgMoKR98FOvafR2gDDhENLMdjZWJBNHmMYJj2xYOnfv9tAe7F/JCIPrs2yPMwriyzOsgoAHFGkznKWHyvw=] - - ENC[PKCS7,MIIBmQYJKoZIhvcNAQcDoIIBijCCAYYCAQAxggEhMIIBHQIBADAFMAACAQEwDQYJKoZIhvcNAQEBBQAEggEAbx8zkPuZRlyeA/27xJZqXyjNkEA4JjsJQPh7BwuiLAqXUDeLLcUWTPOZ/YcJUS2IxLcYXsyWC/WAuhvKrLPCObHDndyWOq32sjI2ywaehMJc2w2cG0Iq4wdHo9Plfmu8T2jA2Tbe/cSuV84bh+toBTIKgckqulcBcgCMKSb5NUbdb33pB/YGieUMdrMfVyLVQUT88lmIXpKkfPN4z49cGEHXxbI7mgi7iUM0JbDJDddkH3jD1v3AI8Cr+/3y68+KMMxPVn1kwzPmLAjxkIJ/WySf7uEBEPrbshvsqS0D+OLk4ujOoBb3dpk5o07O6Sv4UA3R3Qa3Co63l8hGykjNSzBcBgkqhkiG9w0BBwEwHQYJYIZIAWUDBAEqBBA70ywaIoOH465wLatsqHP3gDDB+GjjyySugoeismeS+5WMCuepilQ9mBned/nqw0i+8+WrNhsSTTP23hmpWeYAdug=] - - ENC[PKCS7,MIIBmQYJKoZIhvcNAQcDoIIBijCCAYYCAQAxggEhMIIBHQIBADAFMAACAQEwDQYJKoZIhvcNAQEBBQAEggEAoVY4a2yUJnvWJAC1gs0+ZgYcMMI1ZDGniNbIc4h6vb3ic7OPSa+QKZtEyboNSGWyLgLDhO6IPeeW+YgOhwo6tpgltBu34/1czwWiRSd9pZo7kq9J+UnnmvXxlfcD9S/hGAqzv+ouPQjWcpOm9rMYGrq78e3Z/VnscA3LtdtQVQtXLFERCIc3xCDNat47rQnWLvCGsDMSqCbUFOX/xnExmifLnHoRlOrg8K+Iw+oIIbI6LlOiE1lb5b8ml8RqckcKTx3ppRQiVNSCGIrjyVyWLtOU+zDmHFqsSf6JLZ0Twlfboafu2/Iz3NZiikSma564NcexTVkbk5bsZeMWB3+oWDBcBgkqhkiG9w0BBwEwHQYJYIZIAWUDBAEqBBDoWpCRs2064iTVyEvjpXg9gDB/Y/86kLRp6IqmPjFH71oslQ674PK3SfO1jpJJRyJ/61zrdoef+jaK0eEvvJIW70o=] + - ENC[PKCS7,MIIBmQYJKoZIhvcNAQcDoIIBijCCAYYCAQAxggEhMIIBHQIBADAFMAACAQEwDQYJKoZIhvcNAQEBBQAEggEAHfDhuu2C5ZEALdJlmOqWukEiAQQiVJ7KjpSRuf9h7RYwR+u8UNdcJYK1xFvYwmUczw6hkST/Zr06T4JwavpAHHuaRbyl8N1qZjlwt4MO5CPUTBT8k+EOaocF2byUXpYBThETjLB+WNLJAU3Dq8JboekCJ2F1Zjd8Mmdtu1C3Ip5ii5iVGbQShxDSPsdjtk8Q49lUKj61tLyuvadcTcxllHyXs6siWl7atBfIS6OX5KgA66VJhxOeoyyBaiqSSu7OqqZa2siYGTvjJS3UFDf8J+itsJJ1+0KUtkl07PvItkIruSAlHZGagVPrizAyEx1j4hFvVTGHac86bcV/5M9z5DBcBgkqhkiG9w0BBwEwHQYJYIZIAWUDBAEqBBDCjxoJHSXr/4XvXaxVbUGOgDCQ4DL05Qnw3+3qHWZRKvNChHgrhRPi2HmkiGni+A4ZVF9LHs+mF8TQ/t3Q1DrSy3I=] + - ENC[PKCS7,MIIBmQYJKoZIhvcNAQcDoIIBijCCAYYCAQAxggEhMIIBHQIBADAFMAACAQEwDQYJKoZIhvcNAQEBBQAEggEAoapLUNj1f+7BEvjzR9CO0Qz3LhI5M326BVliikRY7hpL2+0CnTOlR9K3YapD83LtpuiNbXqbk1mhi44ak0CTet8yz0ZH/BPkVYgV2Ll9ISdN4Knnnlf2Ljt/gHGf03jiUKwfXxu87LfvCySAMgzYonQ90cfIDc+XH6CoQv27WM3U1q79RcWl/w9Z/XwJiKyANSCXfBT16+RawrzmVo+zWbteqx09MfOHr7Q36VwOqjJaO94A/Dj3m/YJIOhmYXd52h+am6Kc1Q9dnzycKZYoKYOv+qi+bY4frx9sRvBxoGDGMb1mXTDSPeIT6NXbMCIsTsmYxjxAvBET72oKWXJUcDBcBgkqhkiG9w0BBwEwHQYJYIZIAWUDBAEqBBDy/pkTHpz4F9l1J6cKW4A9gDD873VdHr3ArjpE1R82wS5brCbBe7ntEuNFQMbnFPvOXwI4EaYV3IMRNv6Lzk6BBSI=] + - ENC[PKCS7,MIIBmQYJKoZIhvcNAQcDoIIBijCCAYYCAQAxggEhMIIBHQIBADAFMAACAQEwDQYJKoZIhvcNAQEBBQAEggEAVKVb6/nhbgEx6b2b90gfuXbZglZpoJjQtyzDQtCZzcZxh/xVFjwUy1XX/3+dueazFd5Ge5NnqQdxs/h5MBSjexHJhEm3fmA+gnns8sdYX5SDJSnhYvS1cB/wmfHuvkj3ZhIFxg0jlPlKz24QST99ouxKI2c490ByIbcFCr+A5GWnO7D/kf1Y+M0Sg2YiPE4zqF2zx1sgOfaV2xvQbRqqSjDPim/mYff95AtWwN9KbcAvc/7vDi4PrHR8GY9RXhI8FBEvelAT0H0NmnaCw4TvWXF/YxztlG9E55G3MsFyVAQJT7Dl8w4w5nk4AJJBMaXlO2s4AWD4Y+MVQh62hjqgHjBcBgkqhkiG9w0BBwEwHQYJYIZIAWUDBAEqBBBptatyhSChU/V0R+IVd5hRgDCmA07/V4UBz1nVMc2vZm2KvnUOPofO74hwkkoxOnk6O2h6arbw8GNHj7WxeHXoXPk=] + - ENC[PKCS7,MIIBmQYJKoZIhvcNAQcDoIIBijCCAYYCAQAxggEhMIIBHQIBADAFMAACAQEwDQYJKoZIhvcNAQEBBQAEggEAOGvhPhbKt8hkYTif5C+IE7iqcoeXm68BeUzlzE9qAY7lzQoAENauDKoIgoQT0hA7zrKZXPTUDrcw8SdxNp7Zo/Dr44urdr4LiT+QZwYTE09Xn8yIA3ij1XnXQ5bYP70TycuOjpVT0BKK+qSkklfd7IAw76AnUWF1D6P9MjT+shOmVNHQQSRrL2JLNppetQRCyOEMzkeDI/58/ohexvyUcY8WT4YMNhl/IrNBdcJ3xOwnJqEAXSUTre15T2I+7f+prhj4cS2V9qd0ZwUXSueL38EIMKwmq1ugb+zm8UYzqfKpRk/1THqT8T/r8B4PR2QxtiwtzLk388ag1mqQ/jHL9zBcBgkqhkiG9w0BBwEwHQYJYIZIAWUDBAEqBBAlKLuJOARFD1vt/R9gfp4LgDA0irHwG41ByRyYcKT87ra9tsdhb+i9ugnNRbFQ1UPTk7bFwS3HUteEJwNzcNIwFXY=] + - ENC[PKCS7,MIIBmQYJKoZIhvcNAQcDoIIBijCCAYYCAQAxggEhMIIBHQIBADAFMAACAQEwDQYJKoZIhvcNAQEBBQAEggEAEQvjVATvI+UVWrowTWSxtluiPrfa8akOSgr+MdcAh5Mgypw6RUeVJ2Sh8jekePZOO7Y0IQSfyNWOFAsaxBgeG7aEu6loFwxcSzrilg9c/2bV7Ybxr5saDViTjHO+UOYPPVRsJKeYvWd+vTdM+J7Eg3LGwzdLqyYu824affGm41KsSJdtxbNC1EzR+AOEU7SO8FkDIUZl2ekwz+3FfBX5TyXywlZGrbS7DkABB1jrO/JJtgnRu4D1AgUWjSJINXKyi9Xf91ZUyYCbVJ1asmRhOcCDcRigs82CF6nWbsSad80Z/ZoGVGYSlCsSXd4t8iEujCzeTkfBRK6Azr71f0zbBjBcBgkqhkiG9w0BBwEwHQYJYIZIAWUDBAEqBBAeR7zOfSz3Sd19UkcmdMJLgDBiPUNdk6zh2inhCqms/qnt7BqDBAYEzHuzbsM3U3PO+UIeJdym51cu3YKw3MkVuyw=] diff --git a/hieradata/roles/infra/storage/vault.yaml b/hieradata/roles/infra/storage/vault.yaml index df6387a..7d5cc42 100644 --- a/hieradata/roles/infra/storage/vault.yaml +++ b/hieradata/roles/infra/storage/vault.yaml @@ -2,7 +2,23 @@ profiles::vault::server::members_role: roles::infra::storage::vault profiles::vault::server::members_lookup: true profiles::vault::server::data_dir: /data/vault -profiles::vault::server::primary_datacenter: 'au-drw1' profiles::vault::server::manage_storage_dir: true profiles::vault::server::tls_disable: false vault::download_url: http://repos.main.unkin.net/unkin/8/x86_64/os/Archives/vault_1.15.5_linux_amd64.zip + +# additional altnames +profiles::pki::vault::alt_names: + - vault.main.unkin.net + - vault.service.consul + - vault.service.consul + - vault + +# manage a simple nginx reverse proxy +profiles::nginx::simpleproxy::nginx_vhost: 'vault.service.consul' +profiles::nginx::simpleproxy::nginx_aliases: + - vault.main.unkin.net + - vault +profiles::nginx::simpleproxy::proxy_scheme: 'http' +profiles::nginx::simpleproxy::proxy_host: '127.0.0.1' +profiles::nginx::simpleproxy::proxy_port: 8200 +profiles::nginx::simpleproxy::proxy_path: '/' diff --git a/hieradata/virtual/kvm.yaml b/hieradata/virtual/kvm.yaml new file mode 100644 index 0000000..e69de29 diff --git a/hieradata/virtual/physical.yaml b/hieradata/virtual/physical.yaml new file mode 100644 index 0000000..75630e7 --- /dev/null +++ b/hieradata/virtual/physical.yaml @@ -0,0 +1,3 @@ +--- +profiles::packages::install: + - "%{hiera('lm-sensors::package')}" diff --git a/modules/libs/lib/facter/cobbler_data_dir_exists.rb b/modules/libs/lib/facter/cobbler_data_dir_exists.rb new file mode 100644 index 0000000..d716b35 --- /dev/null +++ b/modules/libs/lib/facter/cobbler_data_dir_exists.rb @@ -0,0 +1,8 @@ +# frozen_string_literal: true + +Facter.add('cobbler_data_dir_exists') do + confine enc_role: 'roles::infra::cobbler::server' + setcode do + File.exist?('/data/cobbler') + end +end diff --git a/modules/libs/lib/facter/cobbler_var_www_exists.rb b/modules/libs/lib/facter/cobbler_var_www_exists.rb new file mode 100644 index 0000000..aa445b8 --- /dev/null +++ b/modules/libs/lib/facter/cobbler_var_www_exists.rb @@ -0,0 +1,8 @@ +# frozen_string_literal: true + +Facter.add('cobbler_var_www_exists') do + confine enc_role: 'roles::infra::cobbler::server' + setcode do + File.exist?('/var/www/cobbler') + end +end diff --git a/modules/libs/lib/facter/cobbler_var_www_islink.rb b/modules/libs/lib/facter/cobbler_var_www_islink.rb new file mode 100644 index 0000000..13d9c6e --- /dev/null +++ b/modules/libs/lib/facter/cobbler_var_www_islink.rb @@ -0,0 +1,8 @@ +# frozen_string_literal: true + +Facter.add('cobbler_var_www_islink') do + confine enc_role: 'roles::infra::cobbler::server' + setcode do + File.exist?('/var/www/cobbler') and File.symlink?('/var/www/cobbler') + end +end diff --git a/modules/libs/lib/facter/country.rb b/modules/libs/lib/facter/country.rb deleted file mode 100644 index 52977d6..0000000 --- a/modules/libs/lib/facter/country.rb +++ /dev/null @@ -1,28 +0,0 @@ -# frozen_string_literal: true - -# set country based on the subnet - -Facter.add('country') do - setcode do - # use facts['networking']['ip']to find the promary IP address - ip = Facter.value(:networking)['ip'] - - # subnet to region mapping - subnet_to_country = { - '198.18.17.0/24' => 'au' - } - - require 'ipaddr' - - # Find the region for the IP - country = 'stateless' # default to 'stateless' if no country matches - subnet_to_country.each do |subnet, country_initial| - if IPAddr.new(subnet).include?(IPAddr.new(ip)) - country = country_initial - break - end - end - - country - end -end diff --git a/modules/libs/lib/facter/enc_env.rb b/modules/libs/lib/facter/enc_env.rb new file mode 100644 index 0000000..2975c45 --- /dev/null +++ b/modules/libs/lib/facter/enc_env.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +Facter.add('enc_env') do + setcode do + require 'yaml' + # Check if the YAML file exists + if File.exist?('/root/.cache/custom_facts.yaml') + data = YAML.load_file('/root/.cache/custom_facts.yaml') + # Use safe navigation to return 'enc_env' or nil + data&.dig('enc_env') + end + end +end diff --git a/modules/libs/lib/facter/enc_role.rb b/modules/libs/lib/facter/enc_role.rb new file mode 100644 index 0000000..979b4bf --- /dev/null +++ b/modules/libs/lib/facter/enc_role.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +Facter.add('enc_role') do + setcode do + require 'yaml' + # Check if the YAML file exists + if File.exist?('/root/.cache/custom_facts.yaml') + data = YAML.load_file('/root/.cache/custom_facts.yaml') + # Use safe navigation to return 'enc_role' or nil + data&.dig('enc_role') + end + end +end diff --git a/modules/libs/lib/facter/firstrun.rb b/modules/libs/lib/facter/firstrun.rb new file mode 100644 index 0000000..012aafc --- /dev/null +++ b/modules/libs/lib/facter/firstrun.rb @@ -0,0 +1,8 @@ +# frozen_string_literal: true + +Facter.add(:firstrun) do + confine kernel: 'Linux' + setcode do + File.exist?('/root/.cache/puppet_firstrun_complete') ? false : true + end +end diff --git a/modules/libs/lib/facter/is_pveceph_mgr.rb b/modules/libs/lib/facter/is_pveceph_mgr.rb new file mode 100644 index 0000000..cb1a243 --- /dev/null +++ b/modules/libs/lib/facter/is_pveceph_mgr.rb @@ -0,0 +1,10 @@ +# frozen_string_literal: true + +require 'facter' + +Facter.add('is_pveceph_mgr') do + confine enc_role: 'roles::infra::proxmox::node' + setcode do + system('pgrep -x ceph-mgr > /dev/null 2>&1') + end +end diff --git a/modules/libs/lib/facter/is_pveceph_mon.rb b/modules/libs/lib/facter/is_pveceph_mon.rb new file mode 100644 index 0000000..e32a312 --- /dev/null +++ b/modules/libs/lib/facter/is_pveceph_mon.rb @@ -0,0 +1,10 @@ +# frozen_string_literal: true + +require 'facter' + +Facter.add('is_pveceph_mon') do + confine enc_role: 'roles::infra::proxmox::node' + setcode do + system('pgrep -x ceph-mon > /dev/null 2>&1') + end +end diff --git a/modules/libs/lib/facter/nameservers.rb b/modules/libs/lib/facter/nameservers.rb new file mode 100644 index 0000000..8ece095 --- /dev/null +++ b/modules/libs/lib/facter/nameservers.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +Facter.add(:nameservers) do + confine kernel: 'Linux' + setcode do + nameservers = File.readlines('/etc/resolv.conf').grep(/^nameserver\s+(\S+)/) { Regexp.last_match(1) } + nameservers + end +end diff --git a/modules/libs/lib/facter/pve_ceph_config.rb b/modules/libs/lib/facter/pve_ceph_config.rb new file mode 100644 index 0000000..e836a99 --- /dev/null +++ b/modules/libs/lib/facter/pve_ceph_config.rb @@ -0,0 +1,34 @@ +# frozen_string_literal: true + +require 'facter' + +Facter.add('ceph_global_config') do + confine enc_role: 'roles::infra::proxmox::node' + setcode do + config_file = '/etc/pve/ceph.conf' + config_hash = {} + in_global_section = false + + if File.exist?(config_file) + File.readlines(config_file).each do |line| + line.strip! + # Detect the [global] section and set flag + if line == '[global]' + in_global_section = true + next + end + + # Exit the loop once we're out of the global section + break if line.start_with?('[') && in_global_section + + # Parse key-value pairs if we are in the global section + if in_global_section && line.include?('=') + key, value = line.split('=', 2).map(&:strip) + config_hash[key] = value + end + end + end + + config_hash + end +end diff --git a/modules/libs/lib/facter/pve_ceph_initialised.rb b/modules/libs/lib/facter/pve_ceph_initialised.rb new file mode 100644 index 0000000..52c4c4e --- /dev/null +++ b/modules/libs/lib/facter/pve_ceph_initialised.rb @@ -0,0 +1,10 @@ +# frozen_string_literal: true + +require 'facter' + +Facter.add('pve_ceph_initialised') do + confine enc_role: 'roles::infra::proxmox::node' + setcode do + File.exist?('/etc/pve/ceph.conf') + end +end diff --git a/modules/libs/lib/facter/pve_cluster.rb b/modules/libs/lib/facter/pve_cluster.rb new file mode 100644 index 0000000..05efec1 --- /dev/null +++ b/modules/libs/lib/facter/pve_cluster.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +require 'facter' + +Facter.add('pve_cluster') do + confine enc_role: 'roles::infra::proxmox::node' + setcode do + conf_file = '/etc/pve/corosync.conf' + totem_details = {} + in_totem_section = false + + if File.exist?(conf_file) + File.foreach(conf_file) do |line| + if line =~ /^\s*totem\s*\{/ + in_totem_section = true + elsif line =~ /^\s*\}/ && in_totem_section + break + elsif in_totem_section && line =~ /^\s*(\w+):\s*(.+)$/ + key = Regexp.last_match(1).strip + value = Regexp.last_match(2).strip + totem_details[key] = value + end + end + end + + totem_details.empty? ? nil : totem_details + end +end diff --git a/modules/libs/lib/facter/pve_cluster_member.rb b/modules/libs/lib/facter/pve_cluster_member.rb new file mode 100644 index 0000000..602adf8 --- /dev/null +++ b/modules/libs/lib/facter/pve_cluster_member.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +require 'facter' + +Facter.add('pve_cluster_member') do + confine enc_role: 'roles::infra::proxmox::node' + setcode do + if Facter::Util::Resolution.which('pvesh') + cluster_status = `pvesh get /cluster/status --output-format json` + if cluster_status.empty? + false + else + require 'json' + status = JSON.parse(cluster_status) + !status.empty? + end + else + false + end + end +end diff --git a/modules/libs/lib/facter/pve_nodelist.rb b/modules/libs/lib/facter/pve_nodelist.rb new file mode 100644 index 0000000..4e16d81 --- /dev/null +++ b/modules/libs/lib/facter/pve_nodelist.rb @@ -0,0 +1,35 @@ +# frozen_string_literal: true + +require 'facter' + +Facter.add('pve_nodelist') do + confine enc_role: 'roles::infra::proxmox::node' + setcode do + conf_file = '/etc/pve/corosync.conf' + node_list = {} + current_node = nil + # rubocop:disable Metrics/BlockNesting + + if File.exist?(conf_file) + File.foreach(conf_file) do |line| + if line =~ /^\s*node\s*\{/ + current_node = {} + elsif line =~ /^\s*\}/ + if current_node + node_name = current_node['name'] + node_list[node_name] = current_node if node_name + current_node = nil + end + elsif current_node && line =~ /^\s*(\w+):\s*(.+)$/ + key = Regexp.last_match(1).strip + value = Regexp.last_match(2).strip + current_node[key] = value + end + end + end + + # rubocop:enable Metrics/BlockNesting + + node_list.empty? ? nil : node_list + end +end diff --git a/modules/libs/lib/facter/pve_nodes_active.rb b/modules/libs/lib/facter/pve_nodes_active.rb new file mode 100644 index 0000000..fade65d --- /dev/null +++ b/modules/libs/lib/facter/pve_nodes_active.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +require 'facter' + +Facter.add('pve_nodes_active') do + confine enc_role: 'roles::infra::proxmox::node' + setcode do + if Facter::Util::Resolution.which('pvesh') + proxmox_nodes = `pvesh get /nodes --output-format json` + unless proxmox_nodes.empty? + require 'json' + nodes = JSON.parse(proxmox_nodes) + nodes.count + end + end + end +end diff --git a/modules/libs/lib/facter/region.rb b/modules/libs/lib/facter/region.rb deleted file mode 100644 index 248fb12..0000000 --- a/modules/libs/lib/facter/region.rb +++ /dev/null @@ -1,28 +0,0 @@ -# frozen_string_literal: true - -# set region based on the subnet - -Facter.add('region') do - setcode do - # use facts['networking']['ip']to find the promary IP address - ip = Facter.value(:networking)['ip'] - - # subnet to region mapping - subnet_to_region = { - '198.18.17.0/24' => 'drw1' - } - - require 'ipaddr' - - # Find the region for the IP - region = 'lost' # default to 'lost' if no region matches - subnet_to_region.each do |subnet, region_name| - if IPAddr.new(subnet).include?(IPAddr.new(ip)) - region = region_name - break - end - end - - region - end -end diff --git a/modules/libs/lib/facter/subnet_facts.rb b/modules/libs/lib/facter/subnet_facts.rb new file mode 100644 index 0000000..458c8e0 --- /dev/null +++ b/modules/libs/lib/facter/subnet_facts.rb @@ -0,0 +1,38 @@ +# frozen_string_literal: true + +require 'ipaddr' + +# a class that creates facts based on the subnet +class SubnetAttributes + SUBNET_TO_ATTRIBUTES = { + '198.18.13.0/24' => { environment: 'prod', region: 'syd1', country: 'au' }, + '198.18.14.0/24' => { environment: 'prod', region: 'syd1', country: 'au' }, + '198.18.15.0/24' => { environment: 'prod', region: 'syd1', country: 'au' }, + '198.18.16.0/24' => { environment: 'test', region: 'syd1', country: 'au' }, + '198.18.17.0/24' => { environment: 'prod', region: 'drw1', country: 'au' }, + '198.18.18.0/24' => { environment: 'test', region: 'drw1', country: 'au' } + }.freeze + + # Default attributes if no subnet matches, also defined as a constant + DEFAULT_ATTRIBUTES = { environment: 'unknown', region: 'unknown', country: 'unknown' }.freeze + + # provide ip to return attributes + def self.attributes(ip) + SUBNET_TO_ATTRIBUTES.each do |subnet, attrs| + return attrs if IPAddr.new(subnet).include?(IPAddr.new(ip)) + end + + DEFAULT_ATTRIBUTES + end +end + +# Use the primary IP address from facts +ip = Facter.value(:networking)['ip'] + +# Call the class method directly without creating an instance +subnet_attributes = SubnetAttributes.attributes(ip) + +# Add separate facts for environment, region, and country +Facter.add('environment') { setcode { subnet_attributes[:environment] } } +Facter.add('region') { setcode { subnet_attributes[:region] } } +Facter.add('country') { setcode { subnet_attributes[:country] } } diff --git a/modules/libs/lib/facter/vault_cert_altnames.rb b/modules/libs/lib/facter/vault_cert_altnames.rb new file mode 100644 index 0000000..05194f0 --- /dev/null +++ b/modules/libs/lib/facter/vault_cert_altnames.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +# lib/facter/vault_cert_altnames.rb +require 'puppet' + +Facter.add('vault_cert_altnames') do + setcode do + alt_names_file = '/etc/pki/tls/vault/alt_names' + if File.exist?(alt_names_file) + File.read(alt_names_file).split("\n") + else + [] + end + end +end diff --git a/modules/libs/lib/facter/vault_cert_expiring.rb b/modules/libs/lib/facter/vault_cert_expiring.rb new file mode 100644 index 0000000..359609c --- /dev/null +++ b/modules/libs/lib/facter/vault_cert_expiring.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +# lib/facter/vault_cert_expiring.rb +require 'puppet' + +Facter.add(:vault_cert_expiring) do + setcode do + require 'openssl' + cert_path = '/etc/pki/tls/vault/certificate.crt' + if File.exist?(cert_path) + # If the certificate file exists, check its expiration + cert = OpenSSL::X509::Certificate.new(File.read(cert_path)) + cert_expiry = cert.not_after + days_remaining = (cert_expiry - Time.now).to_i / (24 * 60 * 60) + days_remaining < 30 + else + # Report true if the certificate file does not exist + true + end + end +end diff --git a/site/profiles/manifests/accounts/sysadmin.pp b/site/profiles/manifests/accounts/sysadmin.pp index 81bde92..f766f31 100644 --- a/site/profiles/manifests/accounts/sysadmin.pp +++ b/site/profiles/manifests/accounts/sysadmin.pp @@ -1,15 +1,16 @@ # create the sysadmin user class profiles::accounts::sysadmin( + String $password, Array[String] $sshkeys = [], ){ profiles::base::account {'sysadmin': - username => 'sysadmin', - uid => 1000, - gid => 1000, - groups => ['wheel'], - sshkeys => $sshkeys, - sudo_rules => ['sysadmin ALL=(ALL) NOPASSWD:ALL'], - password => '', - ignore_pass => true, + username => 'sysadmin', + uid => 1000, + gid => 1000, + groups => ['adm', 'admins', 'systemd-journal'], + sshkeys => $sshkeys, + sudo_rules => ['sysadmin ALL=(ALL) NOPASSWD:ALL'], + password => $password, + require => Group['admins'], } } diff --git a/site/profiles/manifests/apt/puppet7.pp b/site/profiles/manifests/apt/puppet7.pp index e9e336f..6424efe 100644 --- a/site/profiles/manifests/apt/puppet7.pp +++ b/site/profiles/manifests/apt/puppet7.pp @@ -30,27 +30,17 @@ class profiles::apt::puppet7 ( Array[String] $managed_repos, String $mirror, String $repo, - String $dist, ) { $codename = $facts['os']['distro']['codename'] if 'puppet7' in $managed_repos { - $puppet_source = "${mirror}/${repo}-release-${dist}.deb" - - # Install the puppet release using dpkg - package { "${repo}-${dist}": - ensure => installed, - name => "${repo}-release", - provider => dpkg, - source => $puppet_source, - } # deb http://apt.puppet.com bullseye puppet7 apt::source { 'puppet7': location => $mirror, repos => $repo, - release => $dist, + release => $codename, include => { 'src' => false, 'deb' => true, diff --git a/site/profiles/manifests/base.pp b/site/profiles/manifests/base.pp index 40eaa2b..13f6b10 100644 --- a/site/profiles/manifests/base.pp +++ b/site/profiles/manifests/base.pp @@ -3,55 +3,64 @@ class profiles::base ( Array $puppet_servers, ) { - case $facts['os']['family'] { - 'RedHat': { - include profiles::yum::global - include profiles::firewall::firewalld + # run a limited set of classes on the first run aimed at bootstrapping the new node + if $facts['firstrun'] { + include profiles::firstrun::init + }else{ + + # install the vault ca first + include profiles::pki::vaultca + + # manage the puppet agent + include profiles::puppet::agent + + # manage puppet clients + if ! member($puppet_servers, $trusted['certname']) { + include profiles::puppet::client } - 'Debian': { - include profiles::apt::global + + # include the base profiles + include profiles::base::repos + include profiles::packages + include profiles::base::facts + include profiles::base::motd + include profiles::base::scripts + include profiles::base::hosts + include profiles::base::groups + include profiles::base::root + include profiles::accounts::sysadmin + include profiles::ntp::client + include profiles::dns::base + include profiles::pki::vault + include profiles::cloudinit::init + include profiles::metrics::default + include profiles::helpers::node_lookup + include profiles::consul::client + + # include the python class + class { 'python': + manage_python_package => true, + manage_venv_package => true, + manage_pip_package => true, + use_epel => false, } - default: { - fail("Unsupported OS family ${facts['os']['family']}") + + # all hosts will have sudo applied + class { 'sudo': + secure_path => '/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin:/opt/puppetlabs/bin' } - } - # manage the puppet agent - include profiles::puppet::agent + # manage virtualised guest agents + if $::facts['is_virtual'] and $::facts['dmi']['manufacturer'] == 'QEMU' { + include profiles::qemu::agent + } - # manage puppet clients - if ! member($puppet_servers, $trusted['certname']) { - include profiles::puppet::client - } + # include classes from hiera + lookup('hiera_classes', Array[String], 'unique').include - # include the base profiles - include profiles::packages - include profiles::base::facts - include profiles::base::motd - include profiles::base::scripts - include profiles::base::hosts - include profiles::accounts::sysadmin - include profiles::ntp::client - include profiles::dns::base - include profiles::cloudinit::init - include profiles::metrics::default - include profiles::helpers::node_lookup - - # include the python class - class { 'python': - manage_python_package => true, - manage_venv_package => true, - manage_pip_package => true, - use_epel => false, - } - - # all hosts will have sudo applied - class { 'sudo': - secure_path => '/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin:/opt/puppetlabs/bin' - } - - # manage virtualised guest agents - if $::facts['is_virtual'] and $::facts['dmi']['manufacturer'] == 'QEMU' { - include profiles::qemu::agent + # specifc ordering constraints + Class['profiles::pki::vaultca'] + -> Class['profiles::base::repos'] + -> Class['profiles::packages'] } } diff --git a/site/profiles/manifests/base/facts.pp b/site/profiles/manifests/base/facts.pp index e234625..5344d19 100644 --- a/site/profiles/manifests/base/facts.pp +++ b/site/profiles/manifests/base/facts.pp @@ -12,18 +12,28 @@ class profiles::base::facts { mode => '0755', } - # facts to create + # cleanup old facts files $fact_list = [ 'enc_role', 'enc_env' ] - - # Manage the external fact file with content from the template $fact_list.each | String $item | { file { "${facts_d_path}/${item}.txt": - ensure => file, - owner => 'root', - group => 'root', - mode => '0644', - content => template("profiles/base/facts/${item}.erb"), - require => File[$facts_d_path], + ensure => absent, } } + + # ensure the path to the custom store exists + file { '/root/.cache': + ensure => directory, + owner => 'root', + group => 'root', + mode => '0750', + } + + # create the file that will be read + file { '/root/.cache/custom_facts.yaml': + ensure => file, + owner => 'root', + group => 'root', + mode => '0644', + content => template('profiles/base/facts/custom_facts.yaml.erb'), + } } diff --git a/site/profiles/manifests/base/groups.pp b/site/profiles/manifests/base/groups.pp new file mode 100644 index 0000000..56d9237 --- /dev/null +++ b/site/profiles/manifests/base/groups.pp @@ -0,0 +1,12 @@ +# profiles::base::groups +# simple group management +class profiles::base::groups ( + Hash $local = {}, +) { + $local.each |$group, $data| { + group { $group: + name => $group, + * => $data, + } + } +} diff --git a/site/profiles/manifests/base/motd.pp b/site/profiles/manifests/base/motd.pp index e1dd5ca..4799976 100644 --- a/site/profiles/manifests/base/motd.pp +++ b/site/profiles/manifests/base/motd.pp @@ -7,6 +7,8 @@ class profiles::base::motd ( String $nic = $facts['networking']['primary'], String $os_name = $facts['os']['name'], String $os_release = $facts['os']['release']['full'], + String $location = "${facts['country']}-${facts['region']}", + String $env = $facts['environment'], ) { # Use the regsubst function to remove the 'roles::' prefix from the role name diff --git a/site/profiles/manifests/base/repos.pp b/site/profiles/manifests/base/repos.pp new file mode 100644 index 0000000..8d3223f --- /dev/null +++ b/site/profiles/manifests/base/repos.pp @@ -0,0 +1,16 @@ +# profiles::base::repos +class profiles::base::repos { + # manage package repositories + case $facts['os']['family'] { + 'RedHat': { + include profiles::yum::global + include profiles::firewall::firewalld + } + 'Debian': { + include profiles::apt::global + } + default: { + fail("Unsupported OS family ${facts['os']['family']}") + } + } +} diff --git a/site/profiles/manifests/base/root.pp b/site/profiles/manifests/base/root.pp new file mode 100644 index 0000000..d53951e --- /dev/null +++ b/site/profiles/manifests/base/root.pp @@ -0,0 +1,13 @@ +# manage the root user +class profiles::base::root { + + # TODO + # for now, add some root directories + + file {'/root/.config': + ensure => directory, + owner => 'root', + group => 'root', + mode => '0600', + } +} diff --git a/site/profiles/manifests/cobbler/config.pp b/site/profiles/manifests/cobbler/config.pp new file mode 100644 index 0000000..90aee5d --- /dev/null +++ b/site/profiles/manifests/cobbler/config.pp @@ -0,0 +1,77 @@ +# profiles::cobbler::config +class profiles::cobbler::config { + + include profiles::cobbler::params + + $default_password_crypted = $profiles::cobbler::params::default_password_crypted + $httpd_ssl_certificate = $profiles::cobbler::params::httpd_ssl_certificate + $httpd_ssl_privatekey = $profiles::cobbler::params::httpd_ssl_privatekey + $pxe_just_once = $profiles::cobbler::params::pxe_just_once + $is_cobbler_master = $profiles::cobbler::params::is_cobbler_master + $service_cname = $profiles::cobbler::params::service_cname + $next_server = $profiles::cobbler::params::next_server + $server = $profiles::cobbler::params::server + + # manage the cobbler settings file + file { '/etc/cobbler/settings.yaml': + ensure => 'file', + content => template('profiles/cobbler/settings.yaml.erb'), + group => 'apache', + owner => 'root', + mode => '0640', + require => Package['cobbler'], + notify => Service['cobblerd'], + } + + # manage the debmirror config to meet cobbler requirements + file { '/etc/debmirror.conf': + ensure => 'file', + content => template('profiles/cobbler/debmirror.conf.erb'), + group => 'root', + owner => 'root', + mode => '0644', + require => Package['debmirror'], + } + + # manage the httpd ssl configuration + file { '/etc/httpd/conf.d/ssl.conf': + ensure => 'file', + content => template('profiles/cobbler/httpd_ssl.conf.erb'), + group => 'root', + owner => 'root', + mode => '0644', + require => Package['httpd'], + notify => Service['httpd'], + } + + # fix permissions in /var/lib/cobbler/web.ss + file {'/var/lib/cobbler/web.ss': + ensure => 'file', + group => 'root', + owner => 'apache', + mode => '0660', + require => Package['cobbler'], + notify => Service['cobblerd'], + } + + # manage the main ipxe menu script + file { '/var/lib/tftpboot/main.ipxe': + ensure => 'file', + content => template('profiles/cobbler/main.ipxe.erb'), + owner => 'root', + group => 'root', + mode => '0644', + require => Package['cobbler'], + } + + # export cnames for cobbler + if $is_cobbler_master { + profiles::dns::record { "${::facts['networking']['fqdn']}_${service_cname}_CNAME": + value => $::facts['networking']['hostname'], + type => 'CNAME', + record => "${service_cname}.", + zone => $::facts['networking']['domain'], + order => 10, + } + } +} diff --git a/site/profiles/manifests/cobbler/init.pp b/site/profiles/manifests/cobbler/init.pp new file mode 100644 index 0000000..24b1555 --- /dev/null +++ b/site/profiles/manifests/cobbler/init.pp @@ -0,0 +1,17 @@ +# profiles::cobbler::init +class profiles::cobbler::init ( +) { + # wait for enc_role to be populated, needed for hieradata to match + if $facts['enc_role'] == 'roles::infra::cobbler::server' { + include profiles::cobbler::config + include profiles::cobbler::install + include profiles::cobbler::ipxebins + include profiles::cobbler::selinux + include profiles::cobbler::service + + Class['profiles::cobbler::install'] + -> Class['profiles::cobbler::config'] + -> Class['profiles::cobbler::ipxebins'] + -> Class['profiles::cobbler::selinux'] + } +} diff --git a/site/profiles/manifests/cobbler/install.pp b/site/profiles/manifests/cobbler/install.pp new file mode 100644 index 0000000..f6bb8d6 --- /dev/null +++ b/site/profiles/manifests/cobbler/install.pp @@ -0,0 +1,34 @@ +# profiles::cobbler::install +class profiles::cobbler::install { + + include profiles::cobbler::params + + $packages = $profiles::cobbler::params::packages + + ensure_packages($packages, { ensure => 'present' }) + + # move the /var/www/cobbler directory to /data/cobbler + if ! $facts['cobbler_var_www_islink'] and ! $facts['cobbler_data_exists'] { + exec {'move_cobbler_data': + command => 'mv /var/www/cobbler /data/cobbler', + onlyif => 'test -d /var/www/cobbler', + path => ['/bin', '/usr/bin'], + before => Service['cobblerd'], + } + file { '/var/www/cobbler': + ensure => 'link', + target => '/data/cobbler', + require => Exec['move_cobbler_data'], + before => Service['httpd'], + notify => Service['httpd'], + } + } + if ! $facts['cobbler_var_www_exists'] and $facts['cobbler_data_exists'] { + file { '/var/www/cobbler': + ensure => 'link', + target => '/data/cobbler', + before => Service['httpd'], + notify => Service['httpd'], + } + } +} diff --git a/site/profiles/manifests/cobbler/ipxebins.pp b/site/profiles/manifests/cobbler/ipxebins.pp new file mode 100644 index 0000000..1fc0bf9 --- /dev/null +++ b/site/profiles/manifests/cobbler/ipxebins.pp @@ -0,0 +1,48 @@ +# profiles::cobbler::ipxebins +class profiles::cobbler::ipxebins { + + include profiles::cobbler::params + + # download the custom undionly.kpxe file + # https://gist.github.com/rikka0w0/50895b82cbec8a3a1e8c7707479824c1 + exec { 'download_undionly_kpxe': + command => 'wget -O /var/lib/tftpboot/undionly.kpxe http://repos.main.unkin.net/unkin/8/x86_64/os/Archives/undionly.kpxe', + path => ['/bin', '/usr/bin'], + creates => '/var/lib/tftpboot/undionly.kpxe', + } + + # set correct permissions ipxe boot image to tftpboot + file { '/var/lib/tftpboot/undionly.kpxe': + ensure => 'file', + owner => 'root', + group => 'root', + mode => '0644', + require => [ + Package['ipxe-bootimgs'], + Package['cobbler'], + Exec['download_undionly_kpxe'] + ], + } + + # download the custom ipxe.efi file + # https://gist.github.com/rikka0w0/50895b82cbec8a3a1e8c7707479824c1 + exec { 'download_ipxe_efi': + command => 'wget -O /var/lib/tftpboot/ipxe.efi http://repos.main.unkin.net/unkin/8/x86_64/os/Archives/ipxe.efi', + path => ['/bin', '/usr/bin'], + creates => '/var/lib/tftpboot/ipxe.efi', + } + + # set correct permissions ipxe boot image to tftpboot + file { '/var/lib/tftpboot/ipxe.efi': + ensure => 'file', + owner => 'root', + group => 'root', + mode => '0644', + require => [ + Package['ipxe-bootimgs'], + Package['cobbler'], + Exec['download_ipxe_efi'] + ], + } +} + diff --git a/site/profiles/manifests/cobbler/params.pp b/site/profiles/manifests/cobbler/params.pp new file mode 100644 index 0000000..877f986 --- /dev/null +++ b/site/profiles/manifests/cobbler/params.pp @@ -0,0 +1,25 @@ +# profiles::cobbler::params +class profiles::cobbler::params ( + Stdlib::Absolutepath $httpd_ssl_certificate = '/etc/pki/tls/vault/certificate.crt', + Stdlib::Absolutepath $httpd_ssl_privatekey = '/etc/pki/tls/vault/private.key', + Stdlib::Absolutepath $tftpboot_path = '/var/lib/tftpboot/boot', + Stdlib::Fqdn $service_cname = $facts['networking']['fqdn'], + String $default_password_crypted = 'changeme', + String $server = $::facts['networking']['ip'], + String $next_server = $::facts['networking']['ip'], + Boolean $pxe_just_once = true, + Boolean $is_cobbler_master = false, + Array $packages = [ + 'cobbler', + 'cobbler3.2-web', + 'httpd', + 'syslinux', + 'dnf-plugins-core', + 'debmirror', + 'pykickstart', + 'fence-agents', + 'selinux-policy-devel', + 'ipxe-bootimgs', + ] +){ +} diff --git a/site/profiles/manifests/cobbler/selinux.pp b/site/profiles/manifests/cobbler/selinux.pp new file mode 100644 index 0000000..df8dab5 --- /dev/null +++ b/site/profiles/manifests/cobbler/selinux.pp @@ -0,0 +1,48 @@ +# profiles::cobbler::selinux +class profiles::cobbler::selinux inherits profiles::cobbler::params { + + include profiles::cobbler::params + + $tftpboot_path = $profiles::cobbler::params::tftpboot_path + + # manage selinux requirements for cobbler + if $::facts['os']['selinux']['config_mode'] == 'enforcing' { + + $enable_sebooleans = [ + 'httpd_can_network_connect_cobbler', + 'httpd_serve_cobbler_files', + 'cobbler_can_network_connect' + ] + + $enable_sebooleans.each |$bool| { + selboolean { $bool: + value => on, + persistent => true, + } + } + + selinux::fcontext { $tftpboot_path: + ensure => 'present', + seltype => 'cobbler_var_lib_t', + pathspec => "${tftpboot_path}(/.*)?", + } + selinux::fcontext { '/data/cobbler': + ensure => 'present', + seltype => 'cobbler_var_lib_t', + pathspec => '/data/cobbler(/.*)?', + } + + exec { "restorecon_${tftpboot_path}": + path => ['/bin', '/usr/bin', '/sbin', '/usr/sbin'], + command => "restorecon -Rv ${tftpboot_path}", + refreshonly => true, + subscribe => Selinux::Fcontext[$tftpboot_path], + } + exec { 'restorecon_/data/cobbler': + path => ['/bin', '/usr/bin', '/sbin', '/usr/sbin'], + command => 'restorecon -Rv /data/cobbler', + refreshonly => true, + subscribe => Selinux::Fcontext['/data/cobbler'], + } + } +} diff --git a/site/profiles/manifests/cobbler/service.pp b/site/profiles/manifests/cobbler/service.pp new file mode 100644 index 0000000..63b2645 --- /dev/null +++ b/site/profiles/manifests/cobbler/service.pp @@ -0,0 +1,17 @@ +# profiles::cobbler::service +class profiles::cobbler::service inherits profiles::cobbler::params { + + # ensure cobblerd is running + service {'cobblerd': + ensure => 'running', + enable => true, + require => File['/etc/cobbler/settings.yaml'], + } + + # ensure httpd is running + service {'httpd': + ensure => 'running', + enable => true, + require => File['/etc/httpd/conf.d/ssl.conf'], + } +} diff --git a/site/profiles/manifests/consul/client.pp b/site/profiles/manifests/consul/client.pp new file mode 100644 index 0000000..4524b87 --- /dev/null +++ b/site/profiles/manifests/consul/client.pp @@ -0,0 +1,87 @@ +# profiles::consul::client +class profiles::consul::client ( + String $secret_id_salt = '', + Stdlib::Fqdn $consul_hostname = 'consul.service.consul', + Enum['http','https'] $consul_protocol = 'http', + Stdlib::Port $consul_port = 8500, + String $consul_api_token = lookup('profiles::consul::server::acl_tokens_initial_management'), + Boolean $members_lookup = false, + String $members_role = undef, + Array $consul_servers = [], + Stdlib::Absolutepath $data_dir = '/opt/consul', + Array[Hash] $node_rules = [], +) { + + if $facts['enc_role'] != $members_role { + + # set a datacentre/cluster name + $consul_cluster = "${::facts['country']}-${::facts['region']}" + + # if lookup is enabled, find all the hosts in the specified role and create the servers_array + if $members_lookup { + + # check that the role is also set + unless !($members_role == undef) { + fail("members_role must be provided for ${title} when members_lookup is True") + } + + # if it is, find hosts, sort them so they dont cause changes every run + $servers_array = sort(query_nodes("enc_role='${members_role}' and region='${::facts['region']}'", 'networking.fqdn')) + + # else use provided array from params + }else{ + $servers_array = $consul_servers + } + + # deploy the consul agent + class { 'consul': + config_hash => { + 'data_dir' => $data_dir, + 'datacenter' => $consul_cluster, + 'log_level' => 'INFO', + 'node_name' => $facts['networking']['fqdn'], + 'retry_join' => $servers_array, + 'bind_addr' => $::facts['networking']['ip'], + 'advertise_addr' => $::facts['networking']['ip'], + 'acl' => { + tokens => { + default => fqdn_uuid("${facts['networking']['fqdn']}-${secret_id_salt}") + } + } + }, + } + } + + # Create ACL policy that allows nodes to update themselves and read others + consul_policy { $facts['networking']['hostname']: + description => "${facts['networking']['fqdn']} puppet-generated-policy", + rules => $node_rules, + acl_api_token => $consul_api_token, + hostname => $consul_hostname, + protocol => $consul_protocol, + port => $consul_port, + } + + consul_token { $facts['networking']['hostname']: + accessor_id => fqdn_uuid($facts['networking']['fqdn']), + description => "${facts['networking']['fqdn']} puppet-generated-token", + policies_by_name => [$facts['networking']['hostname']], + acl_api_token => $consul_api_token, + secret_id => fqdn_uuid("${facts['networking']['fqdn']}-${secret_id_salt}"), + hostname => $consul_hostname, + protocol => $consul_protocol, + port => $consul_port, + + } + + # ensure the consul token is saved for the root user + file {'/root/.config/consul_node_token': + ensure => file, + owner => 'root', + group => 'root', + mode => '0600', + content => Sensitive(fqdn_uuid("${facts['networking']['fqdn']}-${secret_id_salt}")), + require => File['/root/.config'], + } + +} diff --git a/site/profiles/manifests/consul/policies.pp b/site/profiles/manifests/consul/policies.pp new file mode 100644 index 0000000..df1bf2a --- /dev/null +++ b/site/profiles/manifests/consul/policies.pp @@ -0,0 +1,23 @@ +# profiles::consul::policies +class profiles::consul::policies ( + String $root_api_token = lookup('profiles::consul::server::acl_tokens_initial_management'), +) { + + consul_policy { 'node_editor': + description => 'Policy to read/write all nodes puppet-generated-policy', + rules => [ + { + 'resource' => 'node', + 'segment' => '', + 'disposition' => 'write' + }, + { + 'resource' => 'node', + 'segment' => '', + 'disposition' => 'read' + } + ], + acl_api_token => $root_api_token, + hostname => $facts['networking']['ip'], + } +} diff --git a/site/profiles/manifests/consul/prepared_query.pp b/site/profiles/manifests/consul/prepared_query.pp new file mode 100644 index 0000000..16df79f --- /dev/null +++ b/site/profiles/manifests/consul/prepared_query.pp @@ -0,0 +1,14 @@ +# profile::consul::prepared_query +class profiles::consul::prepared_query ( + String $root_api_token = lookup('profiles::consul::server::acl_tokens_initial_management'), + Hash $rules = {}, +) { + + $rules.each | $rule, $data | { + consul_prepared_query { $rule: + acl_api_token => $root_api_token, + hostname => $facts['networking']['ip'], + * => $data, + } + } +} diff --git a/site/profiles/manifests/consul/server.pp b/site/profiles/manifests/consul/server.pp index 83dac9f..f71c567 100644 --- a/site/profiles/manifests/consul/server.pp +++ b/site/profiles/manifests/consul/server.pp @@ -1,10 +1,16 @@ # profiles::consul::server class profiles::consul::server ( - String $gossip_key, - String $primary_datacenter, - Hash $acl, - Hash $ports, - Hash $addresses, + Variant[ + Undef, + String + ] $gossip_key = undef, + Variant[ + Undef, + String + ] $primary_datacenter = undef, + Hash $acl = {}, + Hash $ports = {}, + Hash $addresses = {}, Boolean $members_lookup = false, String $members_role = undef, Array $consul_servers = [], @@ -37,65 +43,92 @@ class profiles::consul::server ( Stdlib::Absolutepath $bin_dir = '/usr/bin', Boolean $disable_remote_exec = true, Boolean $disable_update_check = true, + Boolean $join_remote_regions = false, + Array[String] $remote_regions = [], ) { - # set a datacentre/cluster name - $consul_cluster = "${::facts['country']}-${::facts['region']}" + # wait for all attributes to be ready + if $facts['enc_role'] == $members_role { - # if lookup is enabled, find all the hosts in the specified role and create the servers_array - if $members_lookup { + # set a datacentre/cluster name + $consul_cluster = "${::facts['country']}-${::facts['region']}" - # check that the role is also set - unless !($members_role == undef) { - fail("members_role must be provided for ${title} when members_lookup is True") + # if lookup is enabled, find all the hosts in the specified role and create the servers_array + if $members_lookup { + + # check that the role is also set + unless !($members_role == undef) { + fail("members_role must be provided for ${title} when members_lookup is True") + } + + # if it is, find hosts, sort them so they dont cause changes every run + $servers_array = sort(query_nodes("enc_role='${members_role}' and region='${::facts['region']}'", 'networking.fqdn')) + + if $join_remote_regions { + # get all nodes in the members_role for each other region + $region_to_servers = $remote_regions.reduce({}) |$memo, $region| { + $servers = sort(query_nodes("enc_role='${members_role}' and region='${region}'", 'networking.fqdn')) + $memo + { $region => $servers } + } + + # sort and flatten the regions into a single array of fqdns + $remote_servers_array = sort(flatten($region_to_servers.values)) + + } else { + # else just send an empty array + $remote_servers_array = [] + } + + # else use provided array from params + }else{ + $servers_array = $consul_servers } - # if it is, find hosts, sort them so they dont cause changes every run - $servers_array = sort(query_nodes("enc_role='${members_role}' and region='${::facts['region']}'", 'networking.fqdn')) + # if $data_dir starts with /data, ensure the data mount exists + if ($data_dir.stdlib::start_with('/data') and $::facts['mountpoints']['/data']) or ! $data_dir.stdlib::start_with('/data') { - # else use provided array from params - }else{ - $servers_array = $consul_servers - } - - # if $data_dir starts with /data, ensure the data mount exists - if ($data_dir.stdlib::start_with('/data') and $::facts['mountpoints']['/data']) or ! $data_dir.stdlib::start_with('/data') { - - # install consul - class { 'consul': - install_method => $install_method, - manage_repo => $manage_repo, - package_name => $package_name, - package_ensure => $package_ensure, - bin_dir => $bin_dir, - config_hash => { - 'primary_datacenter' => $primary_datacenter, - 'acl' => $acl, - 'ports' => $ports, - 'addresses' => $addresses, - 'disable_remote_exec' => $disable_remote_exec, - 'disable_update_check' => $disable_update_check, - 'domain' => $domain, - 'bootstrap_expect' => $bootstrap_count, - 'client_addr' => '0.0.0.0', - 'data_dir' => $data_dir, - 'datacenter' => $consul_cluster, - 'log_level' => 'INFO', - 'node_name' => $::facts['networking']['fqdn'], - 'server' => true, - 'ui' => $enable_ui, - 'ui_config' => { 'enabled' => $enable_ui_config }, - 'performance' => { 'raft_multiplier' => $raft_multiplier }, - 'bind_addr' => $::facts['networking']['ip'], - 'advertise_addr' => $::facts['networking']['ip'], - 'retry_join' => $servers_array - }, + # install consul + class { 'consul': + install_method => $install_method, + manage_repo => $manage_repo, + package_name => $package_name, + package_ensure => $package_ensure, + bin_dir => $bin_dir, + config_hash => { + 'primary_datacenter' => $primary_datacenter, + 'acl' => $acl, + 'ports' => $ports, + 'addresses' => $addresses, + 'disable_remote_exec' => $disable_remote_exec, + 'disable_update_check' => $disable_update_check, + 'domain' => $domain, + 'bootstrap_expect' => $bootstrap_count, + 'client_addr' => '0.0.0.0', + 'data_dir' => $data_dir, + 'datacenter' => $consul_cluster, + 'log_level' => 'INFO', + 'node_name' => $::facts['networking']['fqdn'], + 'server' => true, + 'ui' => $enable_ui, + 'ui_config' => { 'enabled' => $enable_ui_config }, + 'performance' => { 'raft_multiplier' => $raft_multiplier }, + 'bind_addr' => $::facts['networking']['ip'], + 'advertise_addr' => $::facts['networking']['ip'], + 'retry_join' => $servers_array, + 'retry_join_wan' => $remote_servers_array, + }, + } } } - - # consul before dnsmasq + # consul before extra services if defined(Class['consul']) { + # include nginx, policies and tokens + include profiles::nginx::simpleproxy + include profiles::consul::policies + include profiles::consul::tokens + include profiles::consul::prepared_query + # get the dns port from the $ports hash, otherwise use the default $dns_port = pick($ports['dns'], 8600) diff --git a/site/profiles/manifests/consul/tokens.pp b/site/profiles/manifests/consul/tokens.pp new file mode 100644 index 0000000..c471783 --- /dev/null +++ b/site/profiles/manifests/consul/tokens.pp @@ -0,0 +1,13 @@ +# profiles::consul::tokens +class profiles::consul::tokens ( + String $root_api_token = lookup('profiles::consul::server::acl_tokens_initial_management'), +){ + + consul_token { 'node_editor': + accessor_id => lookup('profiles::consul::token::node_editor::accessor_id'), + policies_by_name => ['node_editor'], + acl_api_token => $root_api_token, + secret_id => lookup('profiles::consul::token::node_editor::secret_id'), + hostname => $facts['networking']['ip'], + } +} diff --git a/site/profiles/manifests/defaults.pp b/site/profiles/manifests/defaults.pp index 5c72fb6..c0b94a8 100644 --- a/site/profiles/manifests/defaults.pp +++ b/site/profiles/manifests/defaults.pp @@ -8,7 +8,9 @@ class profiles::defaults { } Package { - ensure => present, + ensure => present, + require => Class['profiles::base::repos'] + } File { @@ -27,4 +29,13 @@ class profiles::defaults { ensure => present, shell => '/bin/bash', } + + Yumrepo { + ensure => 'present', + enabled => 1, + gpgcheck => 1, + mirrorlist => 'absent', + require => Class['profiles::pki::vaultca'], + notify => Exec['dnf_makecache'], + } } diff --git a/site/profiles/manifests/dhcp/server.pp b/site/profiles/manifests/dhcp/server.pp new file mode 100644 index 0000000..726ff19 --- /dev/null +++ b/site/profiles/manifests/dhcp/server.pp @@ -0,0 +1,39 @@ +# profiles::dhcp::server +class profiles::dhcp::server ( + Array[Stdlib::Host] $ntpservers = [ + '0.au.pool.ntp.org', + '1.au.pool.ntp.org', + '2.au.pool.ntp.org', + '3.au.pool.ntp.org' + ], + Array[String] $interfaces = ['eth0'], + Integer $default_lease_time = 86400, + Array[String] $globaloptions = [], + Hash $pools = {}, + Hash $classes = {}, +){ + + if $facts['enc_role'] == 'roles::infra::dhcp::server' { + class { 'dhcp': + service_ensure => running, + interfaces => $interfaces, + ntpservers => $ntpservers, + default_lease_time => $default_lease_time, + globaloptions => $globaloptions + } + + # if pools, import them + $pools.each | $name, $data | { + dhcp::pool { $name: + * => $data, + } + } + + # if classes, import them + $classes.each | $name, $data | { + dhcp::dhcp_class { $name: + * => $data, + } + } + } +} diff --git a/site/profiles/manifests/dns/base.pp b/site/profiles/manifests/dns/base.pp index 6bd2458..e22e964 100644 --- a/site/profiles/manifests/dns/base.pp +++ b/site/profiles/manifests/dns/base.pp @@ -3,16 +3,24 @@ class profiles::dns::base ( String $ns_role = undef, Array $search = [], Array $nameservers = ['8.8.8.8', '1.1.1.1'], + Enum[ + 'all', + 'region', + 'country' + ] $use_ns = 'all', ){ # install bind_utils include bind::updater # if ns_role is set, find all hosts matching that enc_role - if $ns_role == undef { - $nameserver_array = $nameservers - }else{ - $nameserver_array = query_nodes("enc_role='${ns_role}'", 'networking.ip') + $nameserver_array = $ns_role ? { + undef => $nameservers, + default => $use_ns ? { + 'all' => query_nodes("enc_role='${ns_role}'", 'networking.ip'), + 'region' => query_nodes("enc_role='${ns_role}' and region=${facts['region']}", 'networking.ip'), + 'country' => query_nodes("enc_role='${ns_role}' and country=${facts['country']}", 'networking.ip'), + } } # if search is undef, fallback to domainname from facts @@ -24,8 +32,8 @@ class profiles::dns::base ( # include resolvconf class class { 'profiles::dns::resolvconf': - nameservers => $nameserver_array, - search_domains => $search_array, + nameservers => sort($nameserver_array), + search_domains => sort($search_array), } # export dns records for client diff --git a/site/profiles/manifests/dns/master.pp b/site/profiles/manifests/dns/master.pp index a66b665..440325e 100644 --- a/site/profiles/manifests/dns/master.pp +++ b/site/profiles/manifests/dns/master.pp @@ -1,6 +1,5 @@ # profiles::dns::master authoritative service class profiles::dns::master ( - Array[String] $nameservers, Stdlib::AbsolutePath $basedir, Hash $acls = {}, Hash $zones = {}, @@ -13,8 +12,27 @@ class profiles::dns::master ( String $owner = 'root', String $group = 'named', Boolean $dnssec = false, + Variant[String, Undef] $ns_role = undef, + Enum['all', 'region', 'country'] $use_ns = 'all', ){ + # if ns_role is set, find all hosts matching that enc_role, otherwise use the current host + $nameservers_array = $ns_role ? { + undef => [$facts['networking']['fqdn']], + default => $use_ns ? { + 'all' => query_nodes("enc_role='${ns_role}'", 'networking.fqdn'), + 'region' => query_nodes("enc_role='${ns_role}' and region=${facts['region']}", 'networking.fqdn'), + 'country' => query_nodes("enc_role='${ns_role}' and country=${facts['country']}", 'networking.fqdn'), + } + } + + # if nameservers is empty, use the current host, otherwise use nameservers_array as nameservers + $nameservers = empty($nameservers_array) ? { + true => [$facts['networking']['fqdn']], + false => $nameservers_array, + default => [$facts['networking']['fqdn']], + } + class {'profiles::dns::server': acls => $acls, zones => $zones, @@ -37,7 +55,7 @@ class profiles::dns::master ( profiles::dns::zone { $name: zone => $data['domain'], basedir => $basedir, - nameservers => $nameservers, + nameservers => sort($nameservers), owner => $owner, group => $group, before => Bind::Zone[$name] diff --git a/site/profiles/manifests/edgecache/init.pp b/site/profiles/manifests/edgecache/init.pp new file mode 100644 index 0000000..1112530 --- /dev/null +++ b/site/profiles/manifests/edgecache/init.pp @@ -0,0 +1,12 @@ +# profiles::edgecache::init +class profiles::edgecache::init { + + if $facts['enc_role'] == 'roles::infra::storage::edgecache' { + + include profiles::edgecache::nginx + include profiles::edgecache::selinux + + Class['profiles::edgecache::nginx'] + -> Class['profiles::edgecache::selinux'] + } +} diff --git a/site/profiles/manifests/edgecache/nginx.pp b/site/profiles/manifests/edgecache/nginx.pp new file mode 100644 index 0000000..30e2c69 --- /dev/null +++ b/site/profiles/manifests/edgecache/nginx.pp @@ -0,0 +1,129 @@ +# profiles::edgecache::nginx +class profiles::edgecache::nginx { + + include profiles::edgecache::params + + $data_root = $profiles::edgecache::params::data_root + $nginx_vhost = $profiles::edgecache::params::nginx_vhost + $nginx_aliases = $profiles::edgecache::params::nginx_aliases + $nginx_port = $profiles::edgecache::params::nginx_port + $nginx_ssl_port = $profiles::edgecache::params::nginx_ssl_port + $nginx_listen_mode = $profiles::edgecache::params::nginx_listen_mode + $nginx_cert_type = $profiles::edgecache::params::nginx_cert_type + $nginx_resolvers_enable = $profiles::edgecache::params::nginx_resolvers_enable + $nginx_resolvers_ipv4only = $profiles::edgecache::params::nginx_resolvers_ipv4only + + # select the certificates to use based on cert type + case $nginx_cert_type { + 'puppet': { + $selected_ssl_cert = "/etc/pki/tls/puppet/${facts['networking']['fqdn']}.crt" + $selected_ssl_key = "/etc/pki/tls/puppet/${facts['networking']['fqdn']}.key" + } + 'vault': { + $selected_ssl_cert = '/etc/pki/tls/vault/certificate.crt' + $selected_ssl_key = '/etc/pki/tls/vault/private.key' + } + default: { + # enum param prevents this ever being reached + } + } + + # set variables based on the listen_mode + case $nginx_listen_mode { + 'http': { + $enable_ssl = false + $ssl_cert = undef + $ssl_key = undef + $listen_port = $nginx_port + $listen_ssl_port = undef + $extras_hash = {} + } + 'https': { + $enable_ssl = true + $ssl_cert = $selected_ssl_cert + $ssl_key = $selected_ssl_key + $listen_port = $nginx_ssl_port + $listen_ssl_port = $nginx_ssl_port + $extras_hash = { + 'subscribe' => [File[$ssl_cert], File[$ssl_key]], + } + } + 'both': { + $enable_ssl = true + $ssl_cert = $selected_ssl_cert + $ssl_key = $selected_ssl_key + $listen_port = $nginx_port + $listen_ssl_port = $nginx_ssl_port + $extras_hash = { + 'subscribe' => [File[$ssl_cert], File[$ssl_key]], + } + } + default: { + # enum param prevents this ever being reached + } + } + + if $nginx_resolvers_ipv4only and $nginx_resolvers_enable { + $resolvers = $facts['nameservers'].join(' ') + file { '/etc/nginx/conf.d/resolvers.conf': + ensure => file, + content => "resolver ${resolvers} ipv4=on;\n", + } + } + + # set the server_names + $server_names = unique([$facts['networking']['fqdn'], $nginx_vhost] + $nginx_aliases) + + # define the default parameters for the nginx server + $defaults = { + 'listen_port' => $listen_port, + 'server_name' => $server_names, + 'use_default_location' => true, + 'access_log' => "/var/log/nginx/${nginx_vhost}_access.log", + 'error_log' => "/var/log/nginx/${nginx_vhost}_error.log", + 'www_root' => "${data_root}/pub", + 'autoindex' => 'on', + 'ssl' => $enable_ssl, + 'ssl_cert' => $ssl_cert, + 'ssl_key' => $ssl_key, + 'ssl_port' => $listen_ssl_port, + } + + # ensure the requires directories exist + $profiles::edgecache::params::directories.each |$name,$data| { + file { $name: + ensure => 'directory', + before => Class['nginx'], + mode => '0775', + * => $data, + } + } + + # merge the hashes conditionally + $nginx_parameters = merge($defaults, $extras_hash) + + # manage the nginx class + class { 'nginx': + proxy_cache_path => { + "${data_root}/cache" => 'cache:128m', + }, + proxy_cache_levels => '1:2', + proxy_cache_keys_zone => 'cache:128m', + proxy_cache_max_size => '30000m', + proxy_cache_inactive => '60d', + proxy_temp_path => "${data_root}/cache_tmp", + } + + # create the nginx vhost with the merged parameters + create_resources('nginx::resource::server', { $nginx_vhost => $nginx_parameters }) + + # create location mirrors + $profiles::edgecache::params::mirrors.each |$name, $data| { + nginx::resource::location { "${nginx_vhost}_${name}": + server => $nginx_vhost, + ssl => true, + ssl_only => false, + * => $data, + } + } +} diff --git a/site/profiles/manifests/edgecache/params.pp b/site/profiles/manifests/edgecache/params.pp new file mode 100644 index 0000000..0766ea7 --- /dev/null +++ b/site/profiles/manifests/edgecache/params.pp @@ -0,0 +1,15 @@ +# profiles::edgecache::params +class profiles::edgecache::params ( + Stdlib::Absolutepath $data_root = '/data/edgecache', + Stdlib::Fqdn $nginx_vhost = $facts['networking']['fqdn'], + Array[Stdlib::Host] $nginx_aliases = [], + Stdlib::Port $nginx_port = 80, + Stdlib::Port $nginx_ssl_port = 443, + Enum['http','https','both'] $nginx_listen_mode = 'http', + Enum['puppet', 'vault'] $nginx_cert_type = 'vault', + Boolean $nginx_resolvers_enable = false, + Boolean $nginx_resolvers_ipv4only = false, + Hash $directories = {}, + Hash $mirrors = {}, +){ +} diff --git a/site/profiles/manifests/edgecache/selinux.pp b/site/profiles/manifests/edgecache/selinux.pp new file mode 100644 index 0000000..c3b502b --- /dev/null +++ b/site/profiles/manifests/edgecache/selinux.pp @@ -0,0 +1,56 @@ +# profiles::edgecache::selinux +class profiles::edgecache::selinux { + + include profiles::edgecache::params + + $data_root = $profiles::edgecache::params::data_root + + if $::facts['os']['selinux']['config_mode'] == 'enforcing' { + + # set httpd_sys_content_t to all files under the www_root + selinux::fcontext { "${data_root}/pub": + ensure => 'present', + seltype => 'httpd_sys_content_t', + pathspec => "${data_root}/pub(/.*)?", + } + + # set httpd_sys_rw_content_t to all files under the cache_root + selinux::fcontext { "${data_root}/cache": + ensure => 'present', + seltype => 'httpd_sys_rw_content_t', + pathspec => "${data_root}/cache(/.*)?", + } + selinux::fcontext { "${data_root}/cache_tmp": + ensure => 'present', + seltype => 'httpd_sys_rw_content_t', + pathspec => "${data_root}/cache_tmp(/.*)?", + } + + # make sure we can connect to other hosts + selboolean { 'httpd_can_network_connect': + persistent => true, + value => 'on', + } + + exec { "restorecon_${data_root}/pub": + path => ['/bin', '/usr/bin', '/sbin', '/usr/sbin'], + command => "restorecon -Rv ${data_root}/pub", + refreshonly => true, + subscribe => Selinux::Fcontext["${data_root}/pub"], + } + + exec { "restorecon_${data_root}/cache": + path => ['/bin', '/usr/bin', '/sbin', '/usr/sbin'], + command => "restorecon -Rv ${data_root}/cache", + refreshonly => true, + subscribe => Selinux::Fcontext["${data_root}/cache"], + } + + exec { "restorecon_${data_root}/cache_tmp": + path => ['/bin', '/usr/bin', '/sbin', '/usr/sbin'], + command => "restorecon -Rv ${data_root}/cache_tmp", + refreshonly => true, + subscribe => Selinux::Fcontext["${data_root}/cache_tmp"], + } + } +} diff --git a/site/profiles/manifests/firstrun/complete.pp b/site/profiles/manifests/firstrun/complete.pp new file mode 100644 index 0000000..b79eaf2 --- /dev/null +++ b/site/profiles/manifests/firstrun/complete.pp @@ -0,0 +1,19 @@ +# profiles::firstrun::complete +class profiles::firstrun::complete { + + file { '/root/.cache': + ensure => 'directory', + owner => 'root', + group => 'root', + mode => '0750', + } + + file {'/root/.cache/puppet_firstrun_complete': + ensure => 'file', + owner => 'root', + group => 'root', + mode => '0750', + content => 'firstrun completed', + require => File['/root/.cache'], + } +} diff --git a/site/profiles/manifests/firstrun/init.pp b/site/profiles/manifests/firstrun/init.pp new file mode 100644 index 0000000..c4845e1 --- /dev/null +++ b/site/profiles/manifests/firstrun/init.pp @@ -0,0 +1,20 @@ +# profiles::firstrun::init +class profiles::firstrun::init { + + # include the required CA certificates + include profiles::pki::vaultca + + # fast install packages on the first run + include profiles::base::repos + include profiles::firstrun::packages + + # mark the firstrun as done + include profiles::firstrun::complete + + + Class['profiles::defaults'] + -> Class['profiles::pki::vaultca'] + -> Class['profiles::base::repos'] + -> Class['profiles::firstrun::packages'] + -> Class['profiles::firstrun::complete'] +} diff --git a/site/profiles/manifests/firstrun/packages.pp b/site/profiles/manifests/firstrun/packages.pp new file mode 100644 index 0000000..5bcc6d4 --- /dev/null +++ b/site/profiles/manifests/firstrun/packages.pp @@ -0,0 +1,27 @@ +# profiles::firstrun::packages +class profiles::firstrun::packages { + # include the correct package repositories, define the install_packages exec + case $facts['os']['family'] { + 'RedHat': { + include profiles::yum::global + $install_command = 'dnf install -y' + } + 'Debian': { + include profiles::apt::global + $install_command = 'apt-get install -y' + } + default: { + fail("Unsupported OS family ${facts['os']['family']}") + } + } + + # get all the packages to install, and convert into a space separated list + $packages = hiera_array('profiles::packages::install', []) + $package_list = $packages.join(' ') + + # install all the packages + exec { 'install_packages': + command => "${install_command} ${package_list}", + path => ['/bin', '/usr/bin'], + } +} diff --git a/site/profiles/manifests/gitea/init.pp b/site/profiles/manifests/gitea/init.pp new file mode 100644 index 0000000..90e9e47 --- /dev/null +++ b/site/profiles/manifests/gitea/init.pp @@ -0,0 +1,55 @@ +# profiles::gitea::init +class profiles::gitea::init ( + String $mysql_pass = '', + String $lfs_jwt_secret = '', +) { + + include profiles::nginx::simpleproxy + + class { 'gitea': + ensure => '1.22.0', + checksum => 'a31086f073cb9592d28611394b2de3655db515d961e4fdcf5b549cb40753ef3d', + custom_configuration => { + '' => { + 'APP_NAME' => 'Gitea', + 'RUN_USER' => 'git', + 'RUN_MODE' => 'prod', + }, + 'repository' => { + 'ROOT' => '/data/gitea/repos', + 'FORCE_PRIVATE' => false, + 'MAX_CREATION_LIMIT' => -1, + 'DISABLE_HTTP_GIT' => false, + 'DEFAULT_BRANCH' => 'main', + 'DEFAULT_PRIVATE' => 'last', + }, + 'ui' => { + 'SHOW_USER_EMAIL' => false, + }, + 'server' => { + 'PROTOCOL' => 'http', + 'DOMAIN' => 'git.query.consul', + 'ROOT_URL' => 'https://git.query.consul', + 'HTTP_ADDR' => '0.0.0.0', + 'HTTP_PORT' => 3000, + 'START_SSH_SERVER' => false, + 'SSH_DOMAIN' => 'git.query.consul', + 'SSH_PORT' => 2222, + 'SSH_LISTEN_HOST' => '0.0.0.0', + 'OFFLINE_MODE' => true, + 'APP_DATA_PATH' => '/var/lib/gitea/data', + 'SSH_LISTEN_PORT' => 22, + }, + 'database' => { + 'DB_TYPE' => 'mysql', + 'HOST' => 'mariadb-prod.service.au-syd1.consul:3306', + 'NAME' => 'gitea', + 'USER' => 'gitea', + 'PASSWD' => Sensitive($mysql_pass), + 'SSL_MODE' => 'disable', + 'PATH' => '/var/lib/gitea/data/gitea.db', + 'LOG_SQL' => false, + }, + } + } +} diff --git a/site/profiles/manifests/haproxy/backends.pp b/site/profiles/manifests/haproxy/backends.pp new file mode 100644 index 0000000..a8d1294 --- /dev/null +++ b/site/profiles/manifests/haproxy/backends.pp @@ -0,0 +1,19 @@ +# profiles::haproxy::backends +class profiles::haproxy::backends { + # set location_environment + $location_environment = "${facts['country']}-${facts['region']}-${facts['environment']}" + + # for each backend: + $backends = lookup('profiles::haproxy::backends', Hash, 'deep', {}) + $backends.each |$backend, $data| { + + # create backend + haproxy::backend { $backend: + * => $data, + } + + # collect exported resources + $tag = "${backend}_${location_environment}" + Haproxy::Balancermember <<| tag == $tag |>> + } +} diff --git a/site/profiles/manifests/haproxy/balancemember.pp b/site/profiles/manifests/haproxy/balancemember.pp new file mode 100644 index 0000000..a477a91 --- /dev/null +++ b/site/profiles/manifests/haproxy/balancemember.pp @@ -0,0 +1,19 @@ +# profiles::haproxy::balancemember +define profiles::haproxy::balancemember ( + String $service, + Array[Stdlib::Port] $ports, + Array $options = ['check'], +) { + + $location_environment = "${facts['country']}-${facts['region']}-${facts['environment']}" + $balancemember_tag = "${service}_${location_environment}" + + @@haproxy::balancermember { $title: + listening_service => $service, + ports => $ports, + server_names => $facts['networking']['hostname'], + ipaddresses => $facts['networking']['ip'], + options => $options, + tag => $balancemember_tag, + } +} diff --git a/site/profiles/manifests/haproxy/certlist.pp b/site/profiles/manifests/haproxy/certlist.pp new file mode 100644 index 0000000..301bd8c --- /dev/null +++ b/site/profiles/manifests/haproxy/certlist.pp @@ -0,0 +1,18 @@ +# profiles::haproxy::certlist +class profiles::haproxy::certlist ( + Boolean $enabled = true, + Stdlib::Absolutepath $path = '/etc/haproxy/certificate.list', + Array[Stdlib::Absolutepath] $certificates = [] +) { + + if $enabled { + file { $path: + ensure => 'file', + owner => 'root', + group => 'root', + mode => '0600', + content => template('profiles/haproxy/certificate.list.erb') + } + } + +} diff --git a/site/profiles/manifests/haproxy/dns.pp b/site/profiles/manifests/haproxy/dns.pp new file mode 100644 index 0000000..af0e8ac --- /dev/null +++ b/site/profiles/manifests/haproxy/dns.pp @@ -0,0 +1,27 @@ +# profiles::haproxy::dns +class profiles::haproxy::dns ( + Array[Stdlib::Fqdn] $cnames = [], + Integer $order = 10, +){ + + # create an A record for each load balancer in a region + $location_environment = "${facts['country']}-${facts['region']}-${facts['environment']}" + profiles::dns::record { "${facts['networking']['fqdn']}_${location_environment}-halb_A": + value => $::facts['networking']['ip'], + type => 'A', + record => "${location_environment}-halb", + zone => $::facts['networking']['domain'], + order => $order, + } + + # export cnames for haproxy applications + $cnames.each |$cname| { + profiles::dns::record { "${::facts['networking']['fqdn']}_${cname}_CNAME": + value => "${location_environment}-halb", + type => 'CNAME', + record => "${cname}.", + zone => $::facts['networking']['domain'], + order => $order, + } + } +} diff --git a/site/profiles/manifests/haproxy/frontends.pp b/site/profiles/manifests/haproxy/frontends.pp new file mode 100644 index 0000000..10721db --- /dev/null +++ b/site/profiles/manifests/haproxy/frontends.pp @@ -0,0 +1,14 @@ +# profiles::haproxy::frontends +class profiles::haproxy::frontends { + + # for each frontend: + $frontends = lookup('profiles::haproxy::frontends', Hash, 'deep', {}) + $frontends.each |$frontend, $data| { + + # create frontends + haproxy::frontend { $frontend: + * => $data, + } + + } +} diff --git a/site/profiles/manifests/haproxy/listeners.pp b/site/profiles/manifests/haproxy/listeners.pp new file mode 100644 index 0000000..3fbe07e --- /dev/null +++ b/site/profiles/manifests/haproxy/listeners.pp @@ -0,0 +1,19 @@ +# profiles::haproxy::listeners +class profiles::haproxy::listeners { + # set location_environment + $location_environment = "${facts['country']}-${facts['region']}-${facts['environment']}" + + # for each listener: + $listeners = lookup('profiles::haproxy::listeners', Hash, 'deep', {}) + $listeners.each |$listen, $data| { + + # create listener + haproxy::listen { $listen: + * => $data, + } + + # collect exported resources + $tag = "${listen}_${location_environment}" + Haproxy::Balancermember <<| tag == $tag |>> + } +} diff --git a/site/profiles/manifests/haproxy/ls_stats.pp b/site/profiles/manifests/haproxy/ls_stats.pp new file mode 100644 index 0000000..7c8bc9d --- /dev/null +++ b/site/profiles/manifests/haproxy/ls_stats.pp @@ -0,0 +1,19 @@ +# the default status listener +class profiles::haproxy::ls_stats ( + Stdlib::IP::Address $bind_addr = $facts['networking']['ip'], + Stdlib::Port $bind_port = 9090, + Array $bind_opts = [], + String $user = 'admin', + String $pass = 'admin', +) { + haproxy::listen { 'stats': + bind => { "${bind_addr}:${bind_port}" => $bind_opts }, + options => { + 'mode' => 'http', + 'stats' => [ + 'uri /', + "auth ${user}:${pass}", + ], + }, + } +} diff --git a/site/profiles/manifests/haproxy/mappings.pp b/site/profiles/manifests/haproxy/mappings.pp new file mode 100644 index 0000000..df844df --- /dev/null +++ b/site/profiles/manifests/haproxy/mappings.pp @@ -0,0 +1,13 @@ +# profiles::haproxy::mappings +class profiles::haproxy::mappings { + + # for each mapping: + $mappings = lookup('profiles::haproxy::mappings') + $mappings.each |$mapping, $data| { + + # create mapping + haproxy::mapfile { $mapping: + * => $data, + } + } +} diff --git a/site/profiles/manifests/haproxy/selinux.pp b/site/profiles/manifests/haproxy/selinux.pp new file mode 100644 index 0000000..a5b7271 --- /dev/null +++ b/site/profiles/manifests/haproxy/selinux.pp @@ -0,0 +1,32 @@ +# profiles::haproxy::selinux +class profiles::haproxy::selinux ( + Array[String] $sebooleans = [], + Array[Stdlib::Port] $ports = [], +) { + + # manage enforcing mode + include profiles::selinux::setenforce + + # manage selinux requirements for haproxy + if $::facts['os']['selinux']['config_mode'] == 'enforcing' { + + # set context for ports + $ports.each |$port| { + selinux::port { "haproxy_port_${port}": + ensure => 'present', + seltype => 'http_port_t', + protocol => 'tcp', + port => $port, + } + } + + # enable sebooleans + $sebooleans.each |$bool| { + selboolean { $bool: + value => on, + persistent => true, + } + } + } +} + diff --git a/site/profiles/manifests/haproxy/server.pp b/site/profiles/manifests/haproxy/server.pp new file mode 100644 index 0000000..3ac313e --- /dev/null +++ b/site/profiles/manifests/haproxy/server.pp @@ -0,0 +1,63 @@ +# configure a haproxy server +class profiles::haproxy::server ( + Hash $globals = {}, + Hash $defaults = {}, +){ + + # default global/defaults arrays + $global_options = { + 'log' => "${facts['networking']['ip']} local0", + 'chroot' => '/var/lib/haproxy', + 'pidfile' => '/var/run/haproxy.pid', + 'maxconn' => '4000', + 'user' => 'haproxy', + 'group' => 'haproxy', + 'daemon' => '', + 'stats' => 'socket /var/lib/haproxy/stats', + } + $default_options = { + 'log' => 'global', + 'stats' => 'enable', + 'option' => ['redispatch'], + 'retries' => '3', + 'timeout' => [ + 'http-request 10s', + 'queue 1m', + 'connect 10s', + 'client 1m', + 'server 1m', + 'check 10s', + ], + 'maxconn' => '8000', + } + + # merge the default globals/defaults with those provided as params + $merged_global_options = merge($global_options, $globals) + $merged_default_options = merge($default_options, $defaults) + + # wait until enc_role matches haproxy enc_role + if $facts['enc_role'] == 'roles::infra::halb::haproxy' { + + # manage selinux + include profiles::haproxy::selinux + + # create the haproxy service/instance + class { 'haproxy': + global_options => $merged_global_options, + defaults_options => $merged_default_options, + require => Class['profiles::haproxy::selinux'] + } + + include profiles::haproxy::certlist # manage the certificate list file + include profiles::haproxy::mappings # manage the domain to backend mappings + include profiles::haproxy::ls_stats # default status listener + include profiles::haproxy::dns # manage dns for haproxy + include profiles::haproxy::frontends # create frontends + include profiles::haproxy::backends # create backends + include profiles::haproxy::listeners # create listeners + + Class['profiles::haproxy::certlist'] + -> Class['profiles::haproxy::dns'] + -> Class['profiles::haproxy::mappings'] + } +} diff --git a/site/profiles/manifests/helpers/certmanager.pp b/site/profiles/manifests/helpers/certmanager.pp new file mode 100644 index 0000000..41d1730 --- /dev/null +++ b/site/profiles/manifests/helpers/certmanager.pp @@ -0,0 +1,77 @@ +# profiles::helpers::certmanager +# +# wrapper class for python, pip and venv +class profiles::helpers::certmanager ( + String $script_name = 'certmanager', + Stdlib::AbsolutePath $base_path = "/opt/${script_name}", + Stdlib::AbsolutePath $venv_path = "${base_path}/venv", + Stdlib::AbsolutePath $config_path = "${base_path}/config.yaml", + Hash $vault_config = {}, + String $owner = 'root', + String $group = 'root', + Boolean $systempkgs = false, + String $version = 'system', + Array[String[1]] $packages = ['requests', 'pyyaml'], +){ + + if $::facts['python3_version'] { + + $python_version = $version ? { + 'system' => $::facts['python3_version'], + default => $version, + } + + # ensure the base_path exists + file { $base_path: + ensure => directory, + mode => '0755', + owner => $owner, + group => $group, + } + + # create a venv + python::pyvenv { $venv_path : + ensure => present, + version => $python_version, + systempkgs => $systempkgs, + venv_dir => $venv_path, + owner => $owner, + group => $group, + require => File[$base_path], + } + + # install the required pip packages + $packages.each |String $package| { + python::pip { "${venv_path}_${package}": + ensure => present, + pkgname => $package, + virtualenv => $venv_path, + } + } + + # create the script from a template + file { "${base_path}/${script_name}": + ensure => file, + mode => '0755', + content => template("profiles/helpers/${script_name}.erb"), + require => Python::Pyvenv[$venv_path], + } + + # create the config from a template + file { $config_path: + ensure => file, + mode => '0660', + owner => 'puppet', + group => 'root', + content => Sensitive(template("profiles/helpers/${script_name}_config.yaml.erb")), + require => Python::Pyvenv[$venv_path], + } + + # create symbolic link in $PATH + file { "/usr/local/bin/${script_name}": + ensure => 'link', + target => "${base_path}/${script_name}", + require => File["${base_path}/${script_name}"], + } + } +} diff --git a/site/profiles/manifests/nginx/simpleproxy.pp b/site/profiles/manifests/nginx/simpleproxy.pp new file mode 100644 index 0000000..28d6c1e --- /dev/null +++ b/site/profiles/manifests/nginx/simpleproxy.pp @@ -0,0 +1,116 @@ +# profiles::nginx:simpleproxy +# +# only one simpleproxy per host, for anything more advanced, use nginx class +class profiles::nginx::simpleproxy ( + Stdlib::Fqdn $nginx_vhost = 'localhost', + Array[Stdlib::Host] $nginx_aliases = [], + Stdlib::Port $nginx_port = 80, + Stdlib::Port $nginx_ssl_port = 443, + Enum['http','https','both'] $nginx_listen_mode = 'https', + Enum['puppet', 'vault'] $nginx_cert_type = 'vault', + Enum['http','https'] $proxy_scheme = 'http', + Stdlib::Port $proxy_port = 80, + Stdlib::Host $proxy_host = $facts['networking']['ip'], + String $proxy_path = '/', +) { + + # if nginx_version isnt set, install nginx + if ! $facts['nginx_version'] { + package {'nginx': + ensure => 'present', + } + + # else, configure simple proxy + }else{ + + # build the proxyurl from proxy_* variables + $proxyurl = "${proxy_scheme}://${proxy_host}:${proxy_port}${proxy_path}" + + # set the server_names + $server_names = unique([$facts['networking']['fqdn'], $nginx_vhost] + $nginx_aliases) + + # select the certificates to use based on cert type + case $nginx_cert_type { + 'puppet': { + $selected_ssl_cert = "/etc/pki/tls/puppet/${facts['networking']['fqdn']}.crt" + $selected_ssl_key = "/etc/pki/tls/puppet/${facts['networking']['fqdn']}.key" + } + 'vault': { + $selected_ssl_cert = '/etc/pki/tls/vault/certificate.crt' + $selected_ssl_key = '/etc/pki/tls/vault/private.key' + } + default: { + # enum param prevents this ever being reached + } + } + + # set variables based on the listen_mode + case $nginx_listen_mode { + 'http': { + $enable_ssl = false + $ssl_cert = undef + $ssl_key = undef + $listen_port = $nginx_port + $listen_ssl_port = undef + $extras_hash = {} + } + 'https': { + $enable_ssl = true + $ssl_cert = $selected_ssl_cert + $ssl_key = $selected_ssl_key + $listen_port = $nginx_ssl_port + $listen_ssl_port = $nginx_ssl_port + $extras_hash = { + 'subscribe' => [File[$ssl_cert], File[$ssl_key]], + } + } + 'both': { + $enable_ssl = true + $ssl_cert = $selected_ssl_cert + $ssl_key = $selected_ssl_key + $listen_port = $nginx_port + $listen_ssl_port = $nginx_ssl_port + $extras_hash = { + 'subscribe' => [File[$ssl_cert], File[$ssl_key]], + } + } + default: { + # enum param prevents this ever being reached + } + } + + # define the default parameters for the nginx server + $defaults = { + 'listen_port' => $listen_port, + 'server_name' => $server_names, + 'use_default_location' => true, + 'access_log' => "/var/log/nginx/${nginx_vhost}_access.log", + 'error_log' => "/var/log/nginx/${nginx_vhost}_error.log", + 'autoindex' => 'on', + 'ssl' => $enable_ssl, + 'ssl_cert' => $ssl_cert, + 'ssl_key' => $ssl_key, + 'ssl_port' => $listen_ssl_port, + 'proxy' => $proxyurl, + } + + # merge the hashes conditionally + $nginx_parameters = merge($defaults, $extras_hash) + + # manage the nginx class + include 'nginx' + + # create the nginx vhost with the merged parameters + create_resources('nginx::resource::server', { $nginx_vhost => $nginx_parameters }) + + # manage selinux + if $::facts['os']['selinux']['config_mode'] == 'enforcing' { + + # make sure nginx can reverse proxy + selboolean { 'httpd_can_network_connect': + persistent => true, + value => 'on', + } + } + } +} diff --git a/site/profiles/manifests/ntp/client.pp b/site/profiles/manifests/ntp/client.pp index e3c90a7..c09cff2 100644 --- a/site/profiles/manifests/ntp/client.pp +++ b/site/profiles/manifests/ntp/client.pp @@ -11,6 +11,11 @@ class profiles::ntp::client ( 'running', 'stopped' ] $wait_ensure = 'running', + Enum[ + 'all', + 'region', + 'country' + ] $use_ntp = 'all', Boolean $client_only = true, ) { @@ -18,23 +23,25 @@ class profiles::ntp::client ( # through the profiles::ntp::server class. if $client_only { - # if ntp_role is set, find all hosts matching that enc_role - if $ntp_role == undef { - $ntpserver_array = $peers - }else{ - $ntpserver_array = query_nodes("enc_role='${ntp_role}'", 'networking.fqdn') + $ntpserver_array = $ntp_role ? { + undef => $peers, + default => $use_ntp ? { + 'all' => query_nodes("enc_role='${ntp_role}'", 'networking.fqdn'), + 'region' => query_nodes("enc_role='${ntp_role}' and region=${facts['region']}", 'networking.fqdn'), + 'country' => query_nodes("enc_role='${ntp_role}' and country=${facts['country']}", 'networking.fqdn'), + } } # Define the client configuration based on OS family if $facts['os']['family'] == 'RedHat' { class { 'chrony': - servers => $ntpserver_array, + servers => sort($ntpserver_array), wait_enable => $wait_enable, wait_ensure => $wait_ensure, } } else { class { 'chrony': - servers => $ntpserver_array, + servers => sort($ntpserver_array), } } } diff --git a/site/profiles/manifests/ovirt/node.pp b/site/profiles/manifests/ovirt/node.pp new file mode 100644 index 0000000..9979c95 --- /dev/null +++ b/site/profiles/manifests/ovirt/node.pp @@ -0,0 +1,20 @@ +# profiles::ovirt::node +class profiles::ovirt::node { + # Define the DNF modules to be enabled + $dnf_modules_to_enable = { + 'javapackages-tools' => { 'ensure' => 'latest' }, + 'pki-deps' => { 'ensure' => 'latest' }, + 'postgresql' => { 'ensure' => '12' }, + 'mod_auth_openidc' => { 'ensure' => '2.3' }, + 'nodejs' => { 'ensure' => '14' }, + } + + # Enable the DNF modules + create_resources( + 'package', + $dnf_modules_to_enable, { + provider => dnfmodule, + enable_only => true + } + ) +} diff --git a/site/profiles/manifests/pki/vault.pp b/site/profiles/manifests/pki/vault.pp new file mode 100644 index 0000000..e680383 --- /dev/null +++ b/site/profiles/manifests/pki/vault.pp @@ -0,0 +1,141 @@ +# profiles::pki::vault +class profiles::pki::vault ( + Optional[Array[Stdlib::Host]] $alt_names = [], + Optional[Array[Stdlib::IP::Address]] $ip_sans = [], +){ + + # validate and prepare additional alt_names, if any + $default_alt_names = [$::facts['networking']['hostname'], $::facts['networking']['fqdn']] + $effective_alt_names = $alt_names ? { + [] => $default_alt_names, + default => concat($default_alt_names, $alt_names), + } + + # validate and prepare additional ip_sans, if any + $default_ip_sans = ['127.0.0.1', $::facts['networking']['ip']] + $effective_ip_sans = $ip_sans ? { + [] => $default_ip_sans, + default => concat($default_ip_sans, $ip_sans), + } + + # path for the alt names file + $base_path = '/etc/pki/tls/vault' + $alt_names_file = "${base_path}/alt_names" + + # ensure the base directory exists + file { '/etc/pki': + ensure => directory, + owner => 'root', + group => 'root', + mode => '0755', + } + file { '/etc/pki/tls': + ensure => directory, + owner => 'root', + group => 'root', + mode => '0755', + require => File['/etc/pki'] + } + file { $base_path: + ensure => directory, + owner => 'root', + group => 'root', + mode => '0755', + require => File['/etc/pki/tls'] + } + + # alt_names_file contents + $alt_names_content = concat($effective_alt_names, $effective_ip_sans) + + # manage the alt names file + file { $alt_names_file: + ensure => file, + owner => 'root', + group => 'root', + mode => '0644', + content => join($alt_names_content, "\n"), + require => File[$base_path] + } + + # compare the sorted arrays of altnames from disk (fact) vs what is intended (this run) + $alt_names_match = sort($::facts['vault_cert_altnames']) == sort($alt_names_content) + + # only renew certificate if its expiring or the alt names have changed + if $::facts['vault_cert_expiring'] or ! $alt_names_match { + + # certificate variables + $common_name = $::facts['networking']['fqdn'] + $valid_days = 90 + + # prepare alt_names and ip_sans arguments conditionally + $alt_names_string = $effective_alt_names.empty() ? { + true => '', + default => join($effective_alt_names, ','), + } + $ip_sans_string = $effective_ip_sans.empty() ? { + true => '', + default => join($effective_ip_sans, ','), + } + + # certmanager arguments + $cmd = '/usr/local/bin/certmanager' + $alt_names_arg = '--alt-names' + $ip_sans_arg = '--ip-sans' + $expiry_days_arg = '--expiry-days' + + # call the script with generate(), capturing json output + $json_output = generate( + $cmd, + $common_name, + $alt_names_arg, + $alt_names_string, + $ip_sans_arg, + $ip_sans_string, + $expiry_days_arg, + $valid_days, + '--json' + ) + $cert_data = parsejson($json_output) + + # manage certificate file resources based on script output + $certificate_files = { + "${base_path}/certificate.crt" => $cert_data['certificate'], + "${base_path}/private.key" => $cert_data['private_key'], + "${base_path}/full_chain.crt" => $cert_data['full_chain'], + "${base_path}/ca_certificate.crt" => $cert_data['ca_certificate'], + "${base_path}/certificate.pem" => "${cert_data['certificate']}\n${cert_data['private_key']}", + } + + # manage each file resources + $certificate_files.each |$file_path, $content| { + file { $file_path: + ensure => file, + content => $content, + owner => 'root', + group => 'root', + mode => '0644', + require => File[$base_path], + } + } + + }else{ + # manage each file resources, but dont change the content + $certificate_files = [ + "${base_path}/certificate.crt", + "${base_path}/private.key", + "${base_path}/full_chain.crt", + "${base_path}/ca_certificate.crt", + "${base_path}/certificate.pem" + ] + + $certificate_files.each |$file_path| { + file { $file_path: + ensure => file, + owner => 'root', + group => 'root', + mode => '0644', + require => File[$base_path], + } + } + } +} diff --git a/site/profiles/manifests/pki/vaultca.pp b/site/profiles/manifests/pki/vaultca.pp new file mode 100644 index 0000000..9ebc067 --- /dev/null +++ b/site/profiles/manifests/pki/vaultca.pp @@ -0,0 +1,37 @@ +# ensure the ca certificate for vault is installed everywhere +class profiles::pki::vaultca { + $root_cacert = 'vaultcaroot.pem' + + # Define the target path based on the operating system + case $facts['os']['family'] { + 'RedHat': { + $ca_cert_target_path = "/etc/pki/ca-trust/source/anchors/${root_cacert}" + $update_ca_cert_command = 'update-ca-trust extract' + } + 'Debian': { + $ca_cert_target_path = "/usr/local/share/ca-certificates/${root_cacert}" + $update_ca_cert_command = 'update-ca-certificates' + } + default: { + fail("Unsupported operating system: ${facts['os']['family']}") + } + } + + # Ensure the CA certificate is present and contains the content from the template + file { $ca_cert_target_path: + ensure => file, + owner => 'root', + group => 'root', + mode => '0644', + content => template('profiles/pki/vaultcaroot.pem.erb'), + notify => Exec['update_ca_trust_store'], + } + + # Execute the system command to update the CA trust store + exec { 'update_ca_trust_store': + command => $update_ca_cert_command, + path => ['/bin', '/usr/bin', 'sbin', '/usr/sbin'], + refreshonly => true, + require => File[$ca_cert_target_path], + } +} diff --git a/site/profiles/manifests/proxmox/ceph.pp b/site/profiles/manifests/proxmox/ceph.pp new file mode 100644 index 0000000..3bff1b0 --- /dev/null +++ b/site/profiles/manifests/proxmox/ceph.pp @@ -0,0 +1,50 @@ +# profiles::proxmox::ceph +class profiles::proxmox::ceph { + + # include params class + include profiles::proxmox::params + + # localise some vars + $network = $profiles::proxmox::params::pve_ceph_network + $size = $profiles::proxmox::params::pve_ceph_size + $min_size = $profiles::proxmox::params::pve_ceph_minsize + + # install ceph if it is enabled + if $profiles::proxmox::params::pve_ceph_install { + + # initialise the cluster, but only on the clusterinit node and only if its not already initialised + if $profiles::proxmox::params::pve_clusterinit_master and ! $facts['pve_ceph_initialised']{ + exec { 'pveceph_init': + command => "/usr/bin/pveceph init --network ${network} --size ${size} --min_size ${min_size}", + user => 'root', + } + } + + if $facts['pve_ceph_initialised'] { + + # create monitors + if $profiles::proxmox::params::pve_ceph_mon { + + # only when its not already a monitor + if ! $facts['is_pveceph_mon'] { + exec { 'pveceph_mon': + command => '/usr/bin/pveceph mon create', + user => 'root', + } + } + } + + # create managers + if $profiles::proxmox::params::pve_ceph_mgr { + + # only when its not already a manager + if ! $facts['is_pveceph_mgr'] { + exec { 'pveceph_mgr': + command => '/usr/bin/pveceph mgr create', + user => 'root', + } + } + } + } + } +} diff --git a/site/profiles/manifests/proxmox/clusterinit.pp b/site/profiles/manifests/proxmox/clusterinit.pp new file mode 100644 index 0000000..65189b3 --- /dev/null +++ b/site/profiles/manifests/proxmox/clusterinit.pp @@ -0,0 +1,41 @@ +# profiles::proxmox::clusterinit +class profiles::proxmox::clusterinit { + + # include params class + include profiles::proxmox::params + + # localise some vars + $clusterinit_master = $profiles::proxmox::params::pve_clusterinit_master + $clustername = $profiles::proxmox::params::pve_cluster + $membersrole = $profiles::proxmox::params::pve_members_role + + # if this is the cluster master + if $clusterinit_master { + + # and its not a member of a cluster yet + if ! $facts['pve_cluster_member'] { + + # initialise a cluster + exec {'pve_init_cluster': + command => "/usr/bin/pvecm create ${clustername}", + unless => 'pvecm status', + timeout => 60, + } + } + } + + $servers_array = sort(query_nodes( + "enc_role='${membersrole}' and country='${facts['country']}' and region='${facts['region']}'", + 'networking.fqdn' + )) + + if ! $profiles::proxmox::params::pve_clusterinit_master { + if !empty($servers_array) { + notify { "Cluster ${profiles::proxmox::params::pve_cluster} detected, proceeding to join...": + } + } else { + notify { "No cluster flag found for ${profiles::proxmox::params::pve_cluster}, not attempting to join": + } + } + } +} diff --git a/site/profiles/manifests/proxmox/clusterjoin.pp b/site/profiles/manifests/proxmox/clusterjoin.pp new file mode 100644 index 0000000..7ab3ea5 --- /dev/null +++ b/site/profiles/manifests/proxmox/clusterjoin.pp @@ -0,0 +1,74 @@ +# profiles::proxmox::clusterjoin +class profiles::proxmox::clusterjoin { + + # include params class + include profiles::proxmox::params + + # localise some vars + $clusterinit_master = $profiles::proxmox::params::pve_clusterinit_master + $clustername = $profiles::proxmox::params::pve_cluster + $membersrole = $profiles::proxmox::params::pve_members_role + $root_password = $profiles::proxmox::params::root_password + + # query puppetdb for list of cluster members + $members_array = sort(query_nodes( + "enc_role='${membersrole}' and \ + country='${facts['country']}' and \ + region='${facts['region']}' and \ + pve_cluster.cluster_name='${clustername}'", + 'networking.fqdn' + )) + + # check if the pve kernerl is running + if $facts['kernelrelease'] == $profiles::proxmox::params::pve_kernel_release { + + # if this is the cluster master + if $clusterinit_master { + + # there are no cluster members in puppetdb + if empty($members_array) { + + # and this host isnt already in a cluster by itself + if ! $facts['pve_cluster'] { + + # initialise a cluster + exec {'pve_init_cluster': + command => "/usr/bin/pvecm create ${clustername}", + unless => 'pvecm status', + timeout => 60, + } + } + } + } + + # for non-masters + if ! $clusterinit_master { + + # if there are already members of the cluster + if !empty($members_array) { + + # and this host isnt already in a cluster + if ! $facts['pve_cluster'] { + + # create an expect script to join the cluster + file { '/usr/local/bin/join_pvecluster.expect': + ensure => file, + owner => 'root', + mode => '0755', + content => template('profiles/proxmox/join_pvecluster.erb'), + } + + exec { 'pve_join_cluster': + command => "/usr/local/bin/join_pvecluster.expect '${root_password.unwrap}' '${members_array[0]}'", + require => [File['/usr/local/bin/join_pvecluster.expect'], Package['expect']], + unless => "/usr/bin/pvesh nodes | grep -q '${facts['networking']['hostname']}'", + user => 'root', + } + } + } else { + notify { "No initialised cluster found for ${clustername}, not attempting to join": + } + } + } + } +} diff --git a/site/profiles/manifests/proxmox/config.pp b/site/profiles/manifests/proxmox/config.pp new file mode 100644 index 0000000..0edc8d1 --- /dev/null +++ b/site/profiles/manifests/proxmox/config.pp @@ -0,0 +1,19 @@ +# profiles::proxmox::config +class profiles::proxmox::config { + + # include params class + include profiles::proxmox::params + + # localise some vars + $clusterinit_master = $profiles::proxmox::params::pve_clusterinit_master + + # create pve_facts file + file {'/opt/puppetlabs/facter/facts.d/pve_facts.yaml': + ensure => 'file', + owner => 'root', + group => 'root', + mode => '0600', + content => template('profiles/proxmox/pve_facts.yaml.erb') + } + +} diff --git a/site/profiles/manifests/proxmox/init.pp b/site/profiles/manifests/proxmox/init.pp new file mode 100644 index 0000000..1d90b3d --- /dev/null +++ b/site/profiles/manifests/proxmox/init.pp @@ -0,0 +1,17 @@ +# proxmox:: +class profiles::proxmox::init { + + #include profiles::proxmox::params + include profiles::proxmox::repos + include profiles::proxmox::install + include profiles::proxmox::clusterjoin + include profiles::proxmox::ceph + include profiles::proxmox::config + include profiles::proxmox::weblb + + Class['profiles::proxmox::repos'] + -> Class['profiles::proxmox::install'] + -> Class['profiles::proxmox::clusterjoin'] + -> Class['profiles::proxmox::ceph'] + -> Class['profiles::proxmox::config'] +} diff --git a/site/profiles/manifests/proxmox/install.pp b/site/profiles/manifests/proxmox/install.pp new file mode 100644 index 0000000..4cfdba2 --- /dev/null +++ b/site/profiles/manifests/proxmox/install.pp @@ -0,0 +1,58 @@ +# profiles::proxmox::install +class profiles::proxmox::install { + + # include params class + include profiles::proxmox::params + + # install the pve kernel + package { 'proxmox-default-kernel': + ensure => $profiles::proxmox::params::pve_kernel_version, + notify => Reboot['after_run'], + require => Apt::Source['proxmox'], + } + + # reboot into the new kernel + reboot { 'after_run': + apply => finished, + } + + if $facts['kernelrelease'] == $profiles::proxmox::params::pve_kernel_release { + + # install pve + ensure_packages($profiles::proxmox::params::pve_packages_install, { ensure => 'present', require => Apt::Source['proxmox']}) + + # remove the old linux kernel metapackage + ensure_packages($profiles::proxmox::params::pve_packages_remove, { ensure => 'absent' }) + + # install ceph package if requested + if $profiles::proxmox::params::pve_ceph_install { + ensure_packages($profiles::proxmox::params::pve_packages_ceph, { ensure => 'present', require => Apt::Source['ceph'] }) + } + + # cleanup the old kernel packages + exec { 'remove-linux-kernel-packages': + command => '/usr/bin/apt-get purge -y $(/usr/bin/dpkg --list | /bin/grep "linux-image-6.1" | /usr/bin/awk \'{ print $2 }\')', + onlyif => '/usr/bin/dpkg --list | /bin/grep -q "linux-image-6.1"', + path => ['/usr/bin', '/bin', '/sbin'], + refreshonly => true, + } + + # update grup + exec { 'update-grub': + command => '/usr/sbin/update-grub', + path => ['/usr/bin', '/bin', '/sbin'], + refreshonly => true, + } + + # update grub after removing kernel packages only + Exec['remove-linux-kernel-packages'] ~> Exec['update-grub'] + + # prepare for SDN + file_line { 'source-network-interfaces-d': + path => '/etc/network/interfaces', + line => 'source /etc/network/interfaces.d/*', + match => '^source /etc/network/interfaces.d/\*$', + append_on_no_match => true, + } + } +} diff --git a/site/profiles/manifests/proxmox/params.pp b/site/profiles/manifests/proxmox/params.pp new file mode 100644 index 0000000..17e69ce --- /dev/null +++ b/site/profiles/manifests/proxmox/params.pp @@ -0,0 +1,44 @@ +# profiles::proxmox::params +class profiles::proxmox::params ( + Sensitive[String] $root_password = Sensitive(lookup('profiles::accounts::root::password')), + String $pve_members_role = 'roles::infra::proxmox::node', + String $pve_kernel_version = '1.0.1', + String $pve_kernel_release = '6.5.13-5-pve', + String $pve_cluster = "${::facts['country']}-${::facts['region']}", + Boolean $pve_clusterinit_master = false, + Boolean $pve_ceph_repos = false, + Boolean $pve_ceph_install = false, + Boolean $pve_ceph_mon = false, + Boolean $pve_ceph_mgr = false, + Boolean $pve_ceph_osd = false, + String $pve_ceph_release = 'quincy', + Integer $pve_ceph_size = 3, + Integer $pve_ceph_minsize = 2, + Variant[ + Undef, + Stdlib::IP::Address::V4::CIDR + ] $pve_ceph_network = undef, + + Array $pve_packages_install = [ + 'proxmox-ve', + 'postfix', + 'open-iscsi', + 'frr-pythontools', + 'ksm-control-daemon' + ], + Array $pve_packages_remove = [ + 'os-prober', + 'linux-image-amd64' + ], + Array $pve_packages_ceph = [ + 'ceph', + 'ceph-common', + 'ceph-fuse', + 'ceph-mds', + 'ceph-volume', + 'gdisk', + 'nvme-cli' + ], + Stdlib::Port $pve_webport = 8006, +){ +} diff --git a/site/profiles/manifests/proxmox/repos.pp b/site/profiles/manifests/proxmox/repos.pp new file mode 100644 index 0000000..0378fa4 --- /dev/null +++ b/site/profiles/manifests/proxmox/repos.pp @@ -0,0 +1,37 @@ +# profiles::proxmox::repos +class profiles::proxmox::repos { + + # include params class + include profiles::proxmox::params + + $codename = $facts['os']['distro']['codename'] + + exec { 'download-proxmox-gpg-key': + command => "/usr/bin/wget https://enterprise.proxmox.com/debian/proxmox-release-${codename}.gpg -O /etc/apt/trusted.gpg.d/proxmox-release-${codename}.gpg", + creates => "/etc/apt/trusted.gpg.d/proxmox-release-${codename}.gpg", + path => ['/usr/bin', '/bin'], + require => File['/etc/apt/trusted.gpg.d/'], + } + + file { '/etc/apt/trusted.gpg.d/': + ensure => 'directory', + } + + apt::source { 'proxmox': + location => 'http://download.proxmox.com/debian/pve', + repos => 'pve-no-subscription', + include => { + src => false, + }, + } + + if $profiles::proxmox::params::pve_ceph_repos { + apt::source { 'ceph': + location => "http://download.proxmox.com/debian/ceph-${profiles::proxmox::params::pve_ceph_release}", + repos => 'no-subscription', + include => { + src => false, + }, + } + } +} diff --git a/site/profiles/manifests/proxmox/weblb.pp b/site/profiles/manifests/proxmox/weblb.pp new file mode 100644 index 0000000..a1bd2c0 --- /dev/null +++ b/site/profiles/manifests/proxmox/weblb.pp @@ -0,0 +1,33 @@ +# profiles::proxmox::weblb +class profiles::proxmox::weblb { + + # include params class + include profiles::proxmox::params + + # export haproxy balancemember + profiles::haproxy::balancemember { "${facts['networking']['fqdn']}_${profiles::proxmox::params::pve_webport}}": + service => "be_${facts['country']}${facts['region']}pve_web", + ports => [$profiles::proxmox::params::pve_webport], + options => [ + "cookie ${facts['networking']['hostname']}", + 'ssl', + 'verify none', + 'check', + 'inter 2s', + 'rise 3', + 'fall 2', + ] + } + profiles::haproxy::balancemember { "${facts['networking']['fqdn']}_${profiles::proxmox::params::pve_webport}_api2}": + service => "be_${facts['country']}${facts['region']}pve_api", + ports => [$profiles::proxmox::params::pve_webport], + options => [ + 'ssl', + 'verify none', + 'check', + 'inter 2s', + 'rise 3', + 'fall 2', + ] + } +} diff --git a/site/profiles/manifests/puppet/agent.pp b/site/profiles/manifests/puppet/agent.pp index 0c2122e..76164c1 100644 --- a/site/profiles/manifests/puppet/agent.pp +++ b/site/profiles/manifests/puppet/agent.pp @@ -4,11 +4,6 @@ class profiles::puppet::agent ( String $puppet_version = 'latest', ) { - # Ensure the puppet-agent package is installed and locked to a specific version - package { 'puppet-agent': - ensure => $puppet_version, - } - # if puppet-version is anything other than latest, set a versionlock $puppet_versionlock_ensure = $puppet_version ? { 'latest' => 'absent', @@ -18,9 +13,29 @@ class profiles::puppet::agent ( 'latest' => undef, default => $puppet_version, } - yum::versionlock{'puppet-agent': - ensure => $puppet_versionlock_ensure, - version => $puppet_versionlock_version, + + case $facts['os']['family'] { + 'RedHat': { + # Ensure the puppet-agent package is installed and locked to a specific version + package { 'puppet-agent': + ensure => $puppet_version, + require => Yumrepo['puppet'], + } + + # versionlock puppet-agent + yum::versionlock{'puppet-agent': + ensure => $puppet_versionlock_ensure, + version => $puppet_versionlock_version, + } + } + 'Debian': { + # Ensure the puppet-agent package is installed and locked to a specific version + package { 'puppet-agent': + ensure => $puppet_version, + require => Class['profiles::apt::puppet7'], + } + } + default: {} } # Ensure the puppet service is running diff --git a/site/profiles/manifests/puppet/autosign.pp b/site/profiles/manifests/puppet/autosign.pp index 0c75d25..b154aea 100644 --- a/site/profiles/manifests/puppet/autosign.pp +++ b/site/profiles/manifests/puppet/autosign.pp @@ -4,35 +4,6 @@ # based on specified subnet ranges and domain patterns. # It is useful in environments where nodes are dynamically provisioned and # require automatic certificate signing without manual intervention. -# -# Parameters: -# - `subnet_ranges`: An array of IP subnet ranges in CIDR notation. -# Nodes with IP addresses within these ranges will have their -# certificates autosigned. -# Default: [] -# Example: ['198.18.17.0/24'] -# -# - `domains`: An array of domain patterns. -# Nodes with hostnames matching these patterns will have their -# certificates autosigned. -# Default: [] -# Example: ['*.main.unkin.net', '*.secondary.unkin.net'] -# -# - `nodes`: An array of specific node names. -# Nodes with hostnames matching these will have their -# certificates autosigned. -# Default: [] -# Example: ['somenode.main.unkin.net', 'othernode.secondary.unkin.net'] -# Usage: -# -# To include this class with custom parameters: -# class { 'profiles::puppet::autosign': -# subnet_ranges => ['198.18.17.0/24', '198.18.18.0/24'], -# domains => ['*.main.unkin.net', '*.dev.unkin.net'], -# nodes => ['somenode.main.unkin.net', 'othernode.dev.unkin.net'], -# } -# -# Alternatively, configure subnet ranges and domains through Hiera. class profiles::puppet::autosign ( Array[Stdlib::IP::Address::V4::CIDR] $subnet_ranges = [], Array[String[1]] $domains = [], diff --git a/site/profiles/manifests/puppet/client.pp b/site/profiles/manifests/puppet/client.pp index 973f621..aa3444c 100644 --- a/site/profiles/manifests/puppet/client.pp +++ b/site/profiles/manifests/puppet/client.pp @@ -4,7 +4,7 @@ # # site/profile/manifests/puppet/client.pp class profiles::puppet::client ( - String $dns_alt_names = $trusted['certname'], + Array $dns_alt_names = [$trusted['certname']], String $server = 'puppetmaster', String $ca_server = 'puppetca', String $environment = 'develop', @@ -14,14 +14,21 @@ class profiles::puppet::client ( Boolean $usecacheonfailure = false, ) { - # Assuming you want to manage puppet.conf with this profile - file { '/etc/puppetlabs/puppet/puppet.conf': - ensure => 'present', - content => template('profiles/puppet/client/puppet.conf.erb'), - owner => 'root', - group => 'root', - mode => '0644', - notify => Service['puppet'], + # dont manage puppet.conf if this is a puppetmaster + if $facts['enc_role'] != 'roles::infra::puppet::master' { + + + $dns_alt_names_string = join(sort($dns_alt_names), ',') + + # Assuming you want to manage puppet.conf with this profile + file { '/etc/puppetlabs/puppet/puppet.conf': + ensure => 'present', + content => template('profiles/puppet/client/puppet.conf.erb'), + owner => 'root', + group => 'root', + mode => '0644', + notify => Service['puppet'], + } } } diff --git a/site/profiles/manifests/puppet/cobbler_enc.pp b/site/profiles/manifests/puppet/cobbler_enc.pp new file mode 100644 index 0000000..a3e9708 --- /dev/null +++ b/site/profiles/manifests/puppet/cobbler_enc.pp @@ -0,0 +1,76 @@ +# Class: profiles::puppet::cobbler_enc +# +# This will deploy the cobbler-enc tool for puppetmasters +# +# wrapper class for python, pip and venv +class profiles::puppet::cobbler_enc ( + Stdlib::Host $cobbler_hostname, + Enum['http','https'] $cobbler_scheme = 'https', + String $script_name = 'cobbler-enc', + Stdlib::AbsolutePath $base_path = "/opt/${script_name}", + Stdlib::AbsolutePath $venv_path = "${base_path}/venv", + String $owner = 'root', + String $group = 'root', + Boolean $systempkgs = false, + String $version = 'system', + Array[String[1]] $packages = ['sys','requests','pyyaml'], + Stdlib::AbsolutePath $trusted_ca_cert = '/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem' +){ + + # set the cobbler url, required for the erb template + $cobbler_base_url = "${cobbler_scheme}://${cobbler_hostname}" + + if $::facts['python3_version'] { + + $python_version = $version ? { + 'system' => $::facts['python3_version'], + default => $version, + } + + # ensure the base_path exists + file { $base_path: + ensure => directory, + mode => '0755', + owner => $owner, + group => $group, + } + + # create a venv + python::pyvenv { $venv_path : + ensure => present, + version => $python_version, + systempkgs => $systempkgs, + venv_dir => $venv_path, + owner => $owner, + group => $group, + require => File[$base_path], + } + + # install the required pip packages + $packages.each |String $package| { + python::pip { "${venv_path}_${package}": + ensure => present, + pkgname => $package, + virtualenv => $venv_path, + } + } + + # create the script from a template + file { "${base_path}/${script_name}": + ensure => file, + mode => '0755', + content => template("profiles/puppet/server/${script_name}.erb"), + require => [ + Python::Pyvenv[$venv_path], + Package['python3.11'] + ], + } + + # create symbolic link in $PATH + file { "/usr/local/bin/${script_name}": + ensure => 'link', + target => "${base_path}/${script_name}", + require => File["${base_path}/${script_name}"], + } + } +} diff --git a/site/profiles/manifests/puppet/enc.pp b/site/profiles/manifests/puppet/enc.pp index b0a4a49..fcfeec7 100644 --- a/site/profiles/manifests/puppet/enc.pp +++ b/site/profiles/manifests/puppet/enc.pp @@ -4,35 +4,6 @@ # systemd service and timer to keep the repository updated every minute. # The Git package is installed if not present, and the repository at the given # location will always reflect the state of the remote Git repository. -# -# Parameters: -# - enc_repo: The URL of the Git repository to clone. -# -# Actions: -# - Ensures the Git package is installed. -# - Ensures the /opt/puppetlabs/enc directory is a clone of the given Git repository. -# - Creates a helper script '/opt/puppetlabs/bin/git_update' for updating the Git repository. -# - Creates a systemd service and timer that runs the git update script every minute. -# -# Usage: -# Directly include the class in your node definitions or classify your nodes -# using an ENC or Hiera. -# Example: -# node 'puppet.example.com' { -# class { 'profiles::puppet::enc': -# enc_repo => 'https://github.com/user/repo.git', -# } -# } -# -# Requirements: -# - The 'puppet-vcsrepo' module should be installed on your puppetmaster. -# - The 'puppet-systemd' module should be installed on your puppetmaster. -# - '/opt/puppetlabs/bin/' directory must exist and be writable. -# - Puppet master must have access to the specified Git URL. -# -# Limitations: -# This is designed to work on Unix-like systems only. -# class profiles::puppet::enc ( String $repo, String $release = 'master', diff --git a/site/profiles/manifests/puppet/eyaml.pp b/site/profiles/manifests/puppet/eyaml.pp new file mode 100644 index 0000000..093e9c2 --- /dev/null +++ b/site/profiles/manifests/puppet/eyaml.pp @@ -0,0 +1,41 @@ +# profiles::puppet::eyaml +class profiles::puppet::eyaml ( + String $privatekey = '', + String $publickey = '', +) { + + # create the /var/lib/puppet/keys directory + file { '/var/lib/puppet': + ensure => 'directory', + owner => 'puppet', + group => 'root', + mode => '0755', + } + file { '/var/lib/puppet/keys': + ensure => 'directory', + owner => 'puppet', + group => 'root', + mode => '0755', + require => File['/var/lib/puppet'] + } + # manage the eyaml private key + file { '/var/lib/puppet/keys/private_key.pkcs7.pem': + ensure => 'file', + owner => 'puppet', + group => 'root', + mode => '0400', + content => Sensitive($privatekey), + before => Service['puppetserver'], + require => File['/var/lib/puppet/keys'], + } + # manage the eyaml private key + file { '/var/lib/puppet/keys/public_key.pkcs7.pem': + ensure => 'file', + owner => 'puppet', + group => 'root', + mode => '0400', + content => Sensitive($publickey), + before => Service['puppetserver'], + require => File['/var/lib/puppet/keys'], + } +} diff --git a/site/profiles/manifests/puppet/g10k.pp b/site/profiles/manifests/puppet/g10k.pp index eddb6f1..3a2af5e 100644 --- a/site/profiles/manifests/puppet/g10k.pp +++ b/site/profiles/manifests/puppet/g10k.pp @@ -5,31 +5,6 @@ # The latest release of g10k is downloaded from GitHub and placed into '/opt/puppetlabs/bin'. # Additionally, it creates a helper script to easily run g10k with the appropriate configuration. # It also creates a systemd service and timer that runs the g10k script every minute. -# -# Parameters: None -# -# Actions: -# - Downloads the latest g10k release from GitHub. -# - Extracts the download and places the executable in '/opt/puppetlabs/bin'. -# - Creates a helper script '/opt/puppetlabs/bin/puppet-g10k' for easy usage of g10k. -# - Creates a systemd service and timer that runs the g10k script every minute. -# -# Usage: -# Directly including the class in your node definitions or classify your nodes -# using an ENC or Hiera. -# Example: -# node 'puppet.example.com' { -# include profiles::puppet::g10k -# } -# -# Requirements: -# - The 'puppet-archive' module should be installed in your puppetmaster. -# - The 'puppet-systemd' module should be installed on your puppetmaster. -# - '/opt/puppetlabs/bin/' directory must exist and be writable. -# - Puppet master must have access to the GitHub URL. -# -# Limitations: -# This is designed to work on Unix-like systems only. class profiles::puppet::g10k ( String $bin_path, String $cfg_path, diff --git a/site/profiles/manifests/puppet/puppetboard.pp b/site/profiles/manifests/puppet/puppetboard.pp index ec6f164..08b49aa 100644 --- a/site/profiles/manifests/puppet/puppetboard.pp +++ b/site/profiles/manifests/puppet/puppetboard.pp @@ -8,7 +8,7 @@ class profiles::puppet::puppetboard ( Integer $reports_count = 40, Boolean $offline_mode = true, String $default_environment = '*', - String $puppetdb_host = lookup('profiles::puppet::puppetdb::puppetdb_host'), + String $puppetdb_host = lookup('puppetdbapi'), Stdlib::AbsolutePath $basedir = '/opt/puppetboard', Stdlib::Absolutepath $virtualenv_dir = "${basedir}/venv", Stdlib::Absolutepath $settings_file = "${basedir}/settings.py", @@ -18,8 +18,9 @@ class profiles::puppet::puppetboard ( String $gunicorn_bind_prefix = 'http://', Integer $gunicorn_workers = 1, Integer $gunicorn_threads = 4, - String $nginx_vhost = 'puppetboard.main.unkin.net', - Integer $nginx_port = 80, + Stdlib::Port $nginx_port = 80, + Stdlib::Host $nginx_vhost = 'puppetboard.main.unkin.net', + Array[Stdlib::Host] $nginx_aliases = [], #String[1] $secret_key = "${fqdn_rand_string(32)}", ) { @@ -98,10 +99,12 @@ class profiles::puppet::puppetboard ( # ensure the nginx service is managed class { 'nginx': } + $nginx_server_names = unique([$nginx_vhost] + $nginx_aliases) + # create the nginx vhost nginx::resource::server { $nginx_vhost: listen_port => $nginx_port, - server_name => [$nginx_vhost], + server_name => $nginx_server_names, proxy => "${gunicorn_bind_prefix}${gunicorn_bind}", proxy_set_header => [ 'Host $http_host', @@ -121,13 +124,38 @@ class profiles::puppet::puppetboard ( location_alias => "${virtualenv_dir}/lib/python${python_version}/site-packages/puppetboard/static", } + # export haproxy balancemember + profiles::haproxy::balancemember { "${facts['networking']['fqdn']}_${nginx_port}}": + service => 'be_puppetboard', + ports => [$nginx_port], + options => [ + "cookie ${facts['networking']['hostname']}", + 'check', + 'inter 2s', + 'rise 3', + 'fall 2', + ] + } + #@@haproxy::balancermember { "${facts['networking']['fqdn']}_${nginx_port}}": + # listening_service => 'be_puppetboard', + # ports => [$nginx_port], + # server_names => $facts['networking']['hostname'], + # ipaddresses => $facts['networking']['ip'], + # options => [ + # "cookie ${facts['networking']['hostname']}", + # 'check', + # 'inter 2s', + # 'rise 3', + # 'fall 2', + # ] + #} - # if selinux is defined, manage it - if $::facts['os']['selinux']['config_mode'] == 'enforcing' { + # if selinux is defined, manage it + if $::facts['os']['selinux']['config_mode'] == 'enforcing' { - # call the nginx selinux class - class { 'profiles::selinux::nginx': - require => Class['Nginx'], - } + # call the nginx selinux class + class { 'profiles::selinux::nginx': + require => Class['Nginx'], } + } } diff --git a/site/profiles/manifests/puppet/puppetca.pp b/site/profiles/manifests/puppet/puppetca.pp new file mode 100644 index 0000000..e94ecad --- /dev/null +++ b/site/profiles/manifests/puppet/puppetca.pp @@ -0,0 +1,56 @@ +# Class: profiles::puppet::puppetca +# +# This class manages Puppet CA +class profiles::puppet::puppetca ( + Boolean $allow_subject_alt_names = false, + Boolean $allow_authorization_extensions = false, + Boolean $enable_infra_crl = false, + Boolean $is_puppetca = false, +) { + + # manage the ca.cfg file + file { '/etc/puppetlabs/puppetserver/conf.d/ca.conf': + ensure => 'file', + owner => 'root', + group => 'root', + mode => '0644', + content => template('profiles/puppet/puppet_ca.cfg.erb'), + notify => Service['puppetserver'], + } + + # manage the crl file + if $is_puppetca { + # export the puppet crl.pem + @@file { '/etc/puppetlabs/puppet/ssl/crl.pem': + ensure => file, + content => file('/etc/puppetlabs/puppet/ssl/crl.pem'), + tag => 'crl_pem_export', + } + }else{ + # import the puppet crl.pem + File <<| tag == 'crl_pem_export' |>> { + require => Service['puppetserver'], + } + } + + # register the PuppetCA service with consul + if $is_puppetca { + consul::service { 'puppetca': + service_name => 'puppetca', + tags => ['ca', 'puppet', 'ssl'], + address => $facts['networking']['ip'], + port => 8140, + checks => [ + { + id => 'puppetca_https_check', + name => 'PuppetCA HTTPS Check', + http => "https://${facts['networking']['fqdn']}:8140/status/v1/simple", + method => 'GET', + tls_skip_verify => true, + interval => '10s', + timeout => '1s', + } + ], + } + } +} diff --git a/site/profiles/manifests/puppet/puppetdb_api.pp b/site/profiles/manifests/puppet/puppetdb_api.pp index fa51753..8c2177e 100644 --- a/site/profiles/manifests/puppet/puppetdb_api.pp +++ b/site/profiles/manifests/puppet/puppetdb_api.pp @@ -1,21 +1,45 @@ # configure the puppetdb api service class profiles::puppet::puppetdb_api ( - String $postgres_host = lookup('profiles::puppet::puppetdb::postgres_host'), + String $postgres_host = lookup('puppetdbsql'), String $listen_address = $facts['networking']['ip'], + Stdlib::Absolutepath $java_bin = '/usr/bin/java', + Hash $java_args = {}, ) { - class { 'puppetdb::server': - database_host => $postgres_host, - manage_firewall => false, - ssl_listen_address => $listen_address, - listen_address => $listen_address, + # wait for enc_role to match the required role + if $facts['enc_role'] == 'roles::infra::puppetdb::api' { + class { 'java': + package => 'java-11-openjdk-devel', + before => Class['puppetdb::server'], + } + + class { 'puppetdb::server': + database_host => $postgres_host, + manage_firewall => false, + ssl_listen_address => $listen_address, + listen_address => $listen_address, + java_bin => $java_bin, + java_args => $java_args, + } + + contain ::puppetdb::server + + class { 'prometheus::puppetdb_exporter': + puppetdb_url => "http://${listen_address}:8080/pdb/query", + export_scrape_job => true, + } + + # export haproxy balancemember + profiles::haproxy::balancemember { "${facts['networking']['fqdn']}_8080": + service => 'be_puppetdbapi', + ports => [8080], + options => [ + "cookie ${facts['networking']['hostname']}", + 'check', + 'inter 2s', + 'rise 3', + 'fall 2', + ] + } } - - contain ::puppetdb::server - - class { 'prometheus::puppetdb_exporter': - puppetdb_url => "http://${listen_address}:8080/pdb/query", - export_scrape_job => true, - } - } diff --git a/site/profiles/manifests/puppet/puppetdb_sql.pp b/site/profiles/manifests/puppet/puppetdb_sql.pp index 2d80d30..1765003 100644 --- a/site/profiles/manifests/puppet/puppetdb_sql.pp +++ b/site/profiles/manifests/puppet/puppetdb_sql.pp @@ -1,6 +1,6 @@ # configure the puppetdb sql service class profiles::puppet::puppetdb_sql ( - String $puppetdb_host = lookup('profiles::puppet::puppetdb::puppetdb_host'), + String $puppetdb_host = lookup('puppetdbsql'), String $listen_address = $facts['networking']['ip'], ) { @@ -24,4 +24,12 @@ class profiles::puppet::puppetdb_sql ( contain ::puppetdb::database::postgresql + # create the postgresql::server::config_entry resources + $pg_config_entries = lookup('postgresql_config_entries', Hash[String, Data], 'hash', {}) + $pg_config_entries.each |String $key, Data $value| { + postgresql::server::config_entry { $key: + ensure => 'present', + value => $value, + } + } } diff --git a/site/profiles/manifests/puppet/puppetmaster.pp b/site/profiles/manifests/puppet/puppetmaster.pp index 627f247..6ce7ca5 100644 --- a/site/profiles/manifests/puppet/puppetmaster.pp +++ b/site/profiles/manifests/puppet/puppetmaster.pp @@ -2,64 +2,37 @@ # # This class manages the puppetmaster using the ghoneycutt-puppet module. # It manages the server settings in the puppet.conf file. -# -# Parameters: None -# -# Actions: -# - Sets up the server, main, agent, and master sections in the puppet.conf file -# -# Usage: -# Directly include the class in your node definitions or classify your nodes -# using an ENC or Hiera. -# Example: -# node 'puppet.example.com' { -# include profiles::puppet::puppetmaster -# } -# -# Requirements: -# - The 'ghoneycutt/puppet' module should be installed in your Puppet master. -# - Puppet master must have access to the necessary directories. -# -# Limitations: -# This is designed to work on Unix-like systems. class profiles::puppet::puppetmaster ( - String $puppetdb_host = lookup('profiles::puppet::puppetdb::puppetdb_host'), + Optional[Stdlib::Fqdn] $puppetdb_host = lookup('puppetdbapi', Optional[Stdlib::Fqdn], 'first', undef), ) { - include profiles::puppet::r10k - include profiles::puppet::g10k - include profiles::puppet::enc - include profiles::puppet::autosign - include profiles::puppet::gems - class { 'puppetdb::master::config': - puppetdb_server => $puppetdb_host, - manage_storeconfigs => false, + if $facts['enc_role'] == 'roles::infra::puppet::master' { + + include profiles::puppet::r10k + include profiles::puppet::g10k + include profiles::puppet::enc + include profiles::puppet::cobbler_enc + include profiles::puppet::autosign + include profiles::puppet::gems + include profiles::helpers::certmanager + include profiles::puppet::server + include profiles::puppet::puppetca + include profiles::puppet::eyaml + + class { 'puppetdb::master::config': + puppetdb_server => $puppetdb_host, + manage_storeconfigs => false, + } + + Package['puppetserver'] + -> Class['profiles::puppet::gems'] + -> Class['profiles::puppet::r10k'] + -> Class['profiles::puppet::g10k'] + -> Class['profiles::puppet::enc'] + -> Class['profiles::puppet::cobbler_enc'] + -> Class['profiles::puppet::autosign'] + -> Class['puppetdb::master::config'] + -> Class['profiles::puppet::server'] } - class { 'profiles::puppet::server': - vardir => '/opt/puppetlabs/server/data/puppetserver', - logdir => '/var/log/puppetlabs/puppetserver', - rundir => '/var/run/puppetlabs/puppetserver', - pidfile => '/var/run/puppetlabs/puppetserver/puppetserver.pid', - codedir => '/etc/puppetlabs/code', - dns_alt_names => [ - 'prodinf01n01.main.unkin.net', - 'puppet.main.unkin.net', - 'puppetca.main.unkin.net', - 'puppetmaster.main.unkin.net', - 'puppet', - 'puppetca', - 'puppetmaster', - ], - server => 'prodinf01n01.main.unkin.net', - node_terminus => 'exec', - external_nodes => '/opt/puppetlabs/bin/enc', - autosign => '/etc/puppetlabs/puppet/autosign.conf', - default_manifest => '/etc/puppetlabs/code/environments/develop/manifests', - default_environment => 'develop', - storeconfigs => true, - storeconfigs_backend => 'puppetdb', - reports => 'puppetdb', - usecacheonfailure => false, - } } diff --git a/site/profiles/manifests/puppet/r10k.pp b/site/profiles/manifests/puppet/r10k.pp index baa16d5..e366953 100644 --- a/site/profiles/manifests/puppet/r10k.pp +++ b/site/profiles/manifests/puppet/r10k.pp @@ -4,35 +4,6 @@ # systemd service and timer to keep the repository updated every minute. # The Git package is installed if not present, and the repository at the given # location will always reflect the state of the remote Git repository. -# -# Parameters: -# - r10k_repo: The URL of the Git repository to clone. -# -# Actions: -# - Ensures the Git package is installed. -# - Ensures the /etc/puppetlabs/r10k directory is a clone of the given Git repository. -# - Creates a helper script '/opt/puppetlabs/bin/puppet-r10k' for updating the Git repository. -# - Creates a systemd service and timer that runs the git update script every minute. -# -# Usage: -# Directly include the class in your node definitions or classify your nodes -# using an enc or Hiera. -# Example: -# node 'puppet.example.com' { -# class { 'profiles::puppet::r10k': -# r10k_repo => 'https://github.com/user/repo.git', -# } -# } -# -# Requirements: -# - The 'puppet-vcsrepo' module should be installed on your puppetmaster. -# - The 'puppet-systemd' module should be installed on your puppetmaster. -# - '/opt/puppetlabs/bin/' directory must exist and be writable. -# - Puppet master must have access to the specified Git URL. -# -# Limitations: -# This is designed to work on Unix-like systems only. -# class profiles::puppet::r10k ( String $r10k_repo, ){ diff --git a/site/profiles/manifests/puppet/server.pp b/site/profiles/manifests/puppet/server.pp index 4930582..771d41a 100644 --- a/site/profiles/manifests/puppet/server.pp +++ b/site/profiles/manifests/puppet/server.pp @@ -1,36 +1,33 @@ # Class: profiles::puppet::server # # This class manages Puppet server's configuration and service. -# -# Parameters: -# vardir - Directory path for variable data. -# logdir - Directory path for logs. -# rundir - Directory path for run-time data. -# pidfile - File path for the PID file. -# codedir - Directory path for code data. -# dns_alt_names - Array of alternate DNS names for the server. -# server - Server's name. -# node_terminus - Node terminus. -# external_nodes - Path to the external node classifier script. -# autosign - Path to the autosign script. -# class profiles::puppet::server ( - String $vardir, - String $logdir, - String $rundir, - String $pidfile, - String $codedir, - Array[String[1]] $dns_alt_names, - String $server, - String $node_terminus, - String $external_nodes, - String $autosign, - String $default_manifest, - String $default_environment, - Boolean $storeconfigs, - String $storeconfigs_backend, - String $reports, - Boolean $usecacheonfailure, + Stdlib::Absolutepath $vardir = '/opt/puppetlabs/server/data/puppetserver', + Stdlib::Absolutepath $logdir = '/var/log/puppetlabs/puppetserver', + Stdlib::Absolutepath $rundir = '/var/run/puppetlabs/puppetserver', + Stdlib::Absolutepath $pidfile = '/var/run/puppetlabs/puppetserver/puppetserver.pid', + Stdlib::Absolutepath $codedir = '/etc/puppetlabs/code', + Array[String] $dns_alt_names = [ + $facts['networking']['fqdn'], + $facts['networking']['hostname'], + ], + Stdlib::Fqdn $agent_server = 'puppetmaster', + Stdlib::Fqdn $report_server = $agent_server, + Stdlib::Fqdn $ca_server = 'puppetca', + String $node_terminus = 'exec', + String $external_nodes = '/opt/cobbler-enc/cobbler-enc', + String $default_environment = 'develop', + String $environment = 'develop', + Stdlib::Absolutepath $autosign = '/etc/puppetlabs/puppet/autosign.conf', + Stdlib::Absolutepath $default_manifest = "${codedir}/environments/${default_environment}/manifests", + String $reports = 'puppetdb', + Boolean $storeconfigs = true, + String $storeconfigs_backend = 'puppetdb', + Boolean $usecacheonfailure = false, + Boolean $report = true, + Integer $runinterval = 1800, + Integer $runtimeout = 3600, + Boolean $show_diff = true, ) { file { '/etc/puppetlabs/puppet/puppet.conf': @@ -44,8 +41,15 @@ class profiles::puppet::server ( 'rundir' => $rundir, 'pidfile' => $pidfile, 'codedir' => $codedir, - 'dns_alt_names' => join($dns_alt_names, ','), - 'server' => $server, + 'dns_alt_names' => join(sort($dns_alt_names), ','), + 'server' => $agent_server, + 'ca_server' => $ca_server, + 'environment' => $environment, + 'report' => $report, + 'runinterval' => $runinterval, + 'runtimeout' => $runtimeout, + 'show_diff' => $show_diff, + 'report_server' => $report_server, 'node_terminus' => $node_terminus, 'external_nodes' => $external_nodes, 'autosign' => $autosign, diff --git a/site/profiles/manifests/reposync/repos.pp b/site/profiles/manifests/reposync/repos.pp index 046e404..0be17f7 100644 --- a/site/profiles/manifests/reposync/repos.pp +++ b/site/profiles/manifests/reposync/repos.pp @@ -4,7 +4,7 @@ define profiles::reposync::repos ( String $description, String $osname, String $release, - Stdlib::HTTPUrl $gpgkey, + Stdlib::Filesource $gpgkey, String $arch = 'x86_64', String $repo_owner = 'root', String $repo_group = 'root', diff --git a/site/profiles/manifests/reposync/webserver.pp b/site/profiles/manifests/reposync/webserver.pp index 789ce21..b75782d 100644 --- a/site/profiles/manifests/reposync/webserver.pp +++ b/site/profiles/manifests/reposync/webserver.pp @@ -1,22 +1,120 @@ # setup a reposync webserver class profiles::reposync::webserver ( String $www_root = '/data/repos/snap', + String $cache_root = '/data/repos/cache', String $nginx_vhost = 'repos.main.unkin.net', - Integer $nginx_port = 80, + Stdlib::Port $nginx_port = 80, + Stdlib::Port $nginx_ssl_port = 443, Boolean $favicon = true, + Enum['http','https','both'] $nginx_listen_mode = 'http', + Enum['puppet', 'vault'] $nginx_cert_type = 'vault' ) { - class { 'nginx': } + # select the certificates to use based on cert type + case $nginx_cert_type { + 'puppet': { + $selected_ssl_cert = "/etc/pki/tls/puppet/${facts['networking']['fqdn']}.crt" + $selected_ssl_key = "/etc/pki/tls/puppet/${facts['networking']['fqdn']}.key" + } + 'vault': { + $selected_ssl_cert = '/etc/pki/tls/vault/certificate.crt' + $selected_ssl_key = '/etc/pki/tls/vault/private.key' + } + default: { + # enum param prevents this ever being reached + } + } - # create the nginx vhost - nginx::resource::server { $nginx_vhost: - listen_port => $nginx_port, - server_name => [$nginx_vhost], - use_default_location => true, - access_log => "/var/log/nginx/${nginx_vhost}_access.log", - error_log => "/var/log/nginx/${nginx_vhost}_error.log", - www_root => $www_root, - autoindex => 'on', + # set variables based on the listen_mode + case $nginx_listen_mode { + 'http': { + $enable_ssl = false + $ssl_cert = undef + $ssl_key = undef + $listen_port = $nginx_port + $listen_ssl_port = undef + $extras_hash = {} + } + 'https': { + $enable_ssl = true + $ssl_cert = $selected_ssl_cert + $ssl_key = $selected_ssl_key + $listen_port = $nginx_ssl_port + $listen_ssl_port = $nginx_ssl_port + $extras_hash = { + 'subscribe' => [File[$ssl_cert], File[$ssl_key]], + } + } + 'both': { + $enable_ssl = true + $ssl_cert = $selected_ssl_cert + $ssl_key = $selected_ssl_key + $listen_port = $nginx_port + $listen_ssl_port = $nginx_ssl_port + $extras_hash = { + 'subscribe' => [File[$ssl_cert], File[$ssl_key]], + } + } + default: { + # enum param prevents this ever being reached + } + } + + # define the default parameters for the nginx server + $defaults = { + 'listen_port' => $listen_port, + 'server_name' => [$nginx_vhost], + 'use_default_location' => true, + 'access_log' => "/var/log/nginx/${nginx_vhost}_access.log", + 'error_log' => "/var/log/nginx/${nginx_vhost}_error.log", + 'www_root' => $www_root, + 'autoindex' => 'on', + 'ssl' => $enable_ssl, + 'ssl_cert' => $ssl_cert, + 'ssl_key' => $ssl_key, + 'ssl_port' => $listen_ssl_port, + } + + # merge the hashes conditionally + $nginx_parameters = merge($defaults, $extras_hash) + + # manage the nginx class + class { 'nginx': + proxy_cache_path => { + "${cache_root}/debian" => 'debian:128m', + }, + proxy_cache_levels => '1:2', + proxy_cache_keys_zone => 'debian:128m', + proxy_cache_max_size => '30000m', + proxy_cache_inactive => '60d', + proxy_temp_path => "${cache_root}/tmp", + } + + # create the nginx vhost with the merged parameters + create_resources('nginx::resource::server', { $nginx_vhost => $nginx_parameters }) + + # cache debian packages from upstream + nginx::resource::location { "${nginx_vhost}-debian": + ensure => present, + ssl => true, + ssl_only => false, + location => '/debian', + server => $nginx_vhost, + proxy => 'http://mirror.gsl.icu/debian', + } + + nginx::resource::location { "${nginx_vhost}-debian_pool": + ensure => present, + ssl => true, + ssl_only => false, + location => '/debian/pool', + server => $nginx_vhost, + proxy => 'http://mirror.gsl.icu/debian/pool', + proxy_cache => 'debian', + proxy_cache_valid => [ + '200 302 1440h', + '404 1m' + ], } if $favicon { @@ -47,6 +145,13 @@ class profiles::reposync::webserver ( pathspec => "${www_root}(/.*)?", } + # set httpd_sys_rw_content_t to all files under the cache_root + selinux::fcontext { $cache_root: + ensure => 'present', + seltype => 'httpd_sys_rw_content_t', + pathspec => "${cache_root}(/.*)?", + } + # make sure we can connect to port 80 selboolean { 'httpd_can_network_connect': persistent => true, @@ -59,5 +164,12 @@ class profiles::reposync::webserver ( refreshonly => true, subscribe => Selinux::Fcontext[$www_root], } + + exec { "restorecon_${cache_root}": + path => ['/bin', '/usr/bin', '/sbin', '/usr/sbin'], + command => "restorecon -Rv ${cache_root}", + refreshonly => true, + subscribe => Selinux::Fcontext[$cache_root], + } } } diff --git a/site/profiles/manifests/sql/galera_member.pp b/site/profiles/manifests/sql/galera_member.pp index 66f189c..24fab57 100644 --- a/site/profiles/manifests/sql/galera_member.pp +++ b/site/profiles/manifests/sql/galera_member.pp @@ -47,7 +47,7 @@ class profiles::sql::galera_member ( } # if it is, find hosts, sort them so they dont cause changes every run - $servers_array = sort(query_nodes("enc_role='${galera_members_role}'", 'networking.fqdn')) + $servers_array = sort(query_nodes("enc_role='${galera_members_role}' and region='${facts['region']}'", 'networking.fqdn')) # else use provided array from params }else{ @@ -103,7 +103,8 @@ class profiles::sql::galera_member ( 'binlog_format' => 'ROW', 'default-storage-engine' => 'innodb', 'query_cache_size' => '0', - 'query_cache_type' => '0' + 'query_cache_type' => '0', + 'bind-address' => $local_ip, } } $default_override_options_galera = { @@ -211,4 +212,5 @@ class profiles::sql::galera_member ( }else{ notice("${title} requires the servers_array to have 3 or more, currently it is ${length($servers_array)}.") } + } diff --git a/site/profiles/manifests/vault/server.pp b/site/profiles/manifests/vault/server.pp index a0e760a..d07e8ba 100644 --- a/site/profiles/manifests/vault/server.pp +++ b/site/profiles/manifests/vault/server.pp @@ -1,7 +1,10 @@ # profiles::vault::server class profiles::vault::server ( Boolean $members_lookup = false, - String $members_role = undef, + Variant[ + String, + Undef + ] $members_role = undef, Array $vault_servers = [], Enum[ 'archive', @@ -15,19 +18,11 @@ class profiles::vault::server ( Stdlib::Absolutepath $bin_dir = '/usr/bin', ){ - # use puppet certs as base - include profiles::pki::puppetcerts - # set a datacentre/cluster name $vault_cluster = "${::facts['country']}-${::facts['region']}" # if lookup is enabled, find all the hosts in the specified role and create the servers_array - if $members_lookup { - - # check that the role is also set - unless !($members_role == undef) { - fail("members_role must be provided for ${title} when members_lookup is True") - } + if $members_lookup and $members_role != undef { # if it is, find hosts, sort them so they dont cause changes every run $servers_array = sort(query_nodes("enc_role='${members_role}' and region='${::facts['region']}'", 'networking.fqdn')) @@ -37,54 +32,61 @@ class profiles::vault::server ( $servers_array = $vault_servers } - # set http scheme - $http_scheme = $tls_disable ? { - true => 'http', - false => 'https' - } + # configure vault if servers_array isnt empty + if ! $servers_array.empty() { - # create vault urls - $server_urls = $servers_array.map |$fqdn| { - { - leader_api_addr => "${http_scheme}://${fqdn}:${client_port}", - leader_client_cert_file => "/etc/pki/tls/puppet/${facts['networking']['fqdn']}.crt", - leader_client_key_file => "/etc/pki/tls/puppet/${facts['networking']['fqdn']}.key", - leader_ca_cert_file => '/etc/pki/tls/puppet/ca.pem', + # set http scheme + $http_scheme = $tls_disable ? { + true => 'http', + false => 'https' } - } - class { 'vault': - install_method => $install_method, - manage_storage_dir => $manage_storage_dir, - enable_ui => true, - storage => { - raft => { - node_id => $::facts['networking']['fqdn'], - path => $data_dir, - retry_join => $server_urls, - } - }, - api_addr => "${http_scheme}://${::facts['networking']['fqdn']}:${client_port}", - extra_config => { - cluster_addr => "${http_scheme}://${::facts['networking']['fqdn']}:${cluster_port}", - }, - listener => [ + # create vault urls + $server_urls = $servers_array.map |$fqdn| { { - tcp => { - address => "127.0.0.1:${client_port}", - cluster_address => "127.0.0.1:${cluster_port}", - tls_disable => true, + leader_api_addr => "${http_scheme}://${fqdn}:${client_port}", + leader_client_cert_file => '/etc/pki/tls/vault/certificate.crt', + leader_client_key_file => '/etc/pki/tls/vault/private.key', + leader_ca_cert_file => '/etc/pki/tls/certs/ca-bundle.crt', + } + } + + class { 'vault': + install_method => $install_method, + manage_storage_dir => $manage_storage_dir, + enable_ui => true, + storage => { + raft => { + node_id => $::facts['networking']['fqdn'], + path => $data_dir, + retry_join => $server_urls, } }, - { - tcp => { - address => "${::facts['networking']['ip']}:${client_port}", - cluster_address => "${::facts['networking']['ip']}:${cluster_port}", - tls_disable => $tls_disable, - tls_cert_file => "/etc/pki/tls/puppet/${facts['networking']['fqdn']}.crt", - tls_key_file => "/etc/pki/tls/puppet/${facts['networking']['fqdn']}.key", + api_addr => "${http_scheme}://${::facts['networking']['fqdn']}:${client_port}", + extra_config => { + cluster_addr => "${http_scheme}://${::facts['networking']['fqdn']}:${cluster_port}", + }, + listener => [ + { + tcp => { + address => "127.0.0.1:${client_port}", + cluster_address => "127.0.0.1:${cluster_port}", + tls_disable => true, + } + }, + { + tcp => { + address => "${::facts['networking']['ip']}:${client_port}", + cluster_address => "${::facts['networking']['ip']}:${cluster_port}", + tls_disable => $tls_disable, + tls_cert_file => '/etc/pki/tls/vault/certificate.crt', + tls_key_file => '/etc/pki/tls/vault/private.key', + } } - } - ] + ] + } + + # include classes to manage vault + include profiles::vault::unseal } } diff --git a/site/profiles/manifests/vault/unseal.pp b/site/profiles/manifests/vault/unseal.pp index 81ccb89..cff32a1 100644 --- a/site/profiles/manifests/vault/unseal.pp +++ b/site/profiles/manifests/vault/unseal.pp @@ -32,6 +32,6 @@ class profiles::vault::unseal ( active => true, enable => true, require => File['/usr/local/bin/vault-unseal.sh'], - subscribe => Service['vault'], + subscribe => [Service['vault'],File['/etc/vault/unseal_keys']], } } diff --git a/site/profiles/manifests/yum/base.pp b/site/profiles/manifests/yum/base.pp deleted file mode 100644 index df86cd0..0000000 --- a/site/profiles/manifests/yum/base.pp +++ /dev/null @@ -1,92 +0,0 @@ -# Class: profiles::yum::base -# -# This class manages the 'base', extras' and 'appstream' yum -# repositories for a system, based on the provided list of managed repositories. -# -# Parameters: -# ----------- -# - $managed_repos: An array containing the names of the repositories to be -# managed. This can include 'base', 'extras', -# and 'appstream'. -# -# - $baseurl: The base URL for the yum repositories. This should be the root -# URL of your yum mirror server. -# -# Actions: -# -------- -# - Sets up the 'base', extras', and 'appstream' yum repositories -# as specified in the $managed_repos parameter, all using the provided baseurl. -# -# - Each repo configuration includes the baseurl parameterized with the OS -# release version and architecture, and specifies the GPG key. -# -# Example usage: -# -------------- -# To use this class with the default parameters: -# class { 'profiles::yum::base': -# managed_repos => ['base', 'extras', 'appstream'], -# baseurl => 'http://mylocalmirror.com/yum', -# } -# -class profiles::yum::base ( - Array[String] $managed_repos, - String $baseurl, - Enum[ - 'daily', - 'weekly', - 'monthly' - ] $snapshot = 'daily', -) { - $release = $facts['os']['release']['full'] - $basearch = $facts['os']['architecture'] - - if 'base' in $managed_repos { - yumrepo { 'base': - name => 'base', - descr => 'base repository', - target => '/etc/yum.repos.d/base.repo', - baseurl => "${baseurl}/${release}/BaseOS-${snapshot}/${basearch}/os/", - gpgkey => "${baseurl}/${release}/BaseOS-${snapshot}/${basearch}/os/RPM-GPG-KEY-${facts['os']['name']}", - } - } - - if 'extras' in $managed_repos { - yumrepo { 'extras': - name => 'extras', - descr => 'extras repository', - target => '/etc/yum.repos.d/extras.repo', - baseurl => "${baseurl}/${release}/extras-${snapshot}/${basearch}/os/", - gpgkey => "${baseurl}/${release}/extras-${snapshot}/${basearch}/os/RPM-GPG-KEY-${facts['os']['name']}", - } - } - - if 'appstream' in $managed_repos { - yumrepo { 'appstream': - name => 'appstream', - descr => 'appstream repository', - target => '/etc/yum.repos.d/appstream.repo', - baseurl => "${baseurl}/${release}/AppStream-${snapshot}/${basearch}/os/", - gpgkey => "${baseurl}/${release}/AppStream-${snapshot}/${basearch}/os/RPM-GPG-KEY-${facts['os']['name']}", - } - } - - if 'powertools' in $managed_repos { - yumrepo { 'powertools': - name => 'powertools', - descr => 'powertools repository', - target => '/etc/yum.repos.d/powertools.repo', - baseurl => "${baseurl}/${release}/PowerTools-${snapshot}/${basearch}/os/", - gpgkey => "${baseurl}/${release}/PowerTools-${snapshot}/${basearch}/os/RPM-GPG-KEY-${facts['os']['name']}", - } - } - - if 'highavailability' in $managed_repos { - yumrepo { 'highavailability': - name => 'highavailability', - descr => 'highavailability repository', - target => '/etc/yum.repos.d/highavailability.repo', - baseurl => "${baseurl}/${release}/HighAvailability-${snapshot}/${basearch}/os/", - gpgkey => "${baseurl}/${release}/HighAvailability-${snapshot}/${basearch}/os/RPM-GPG-KEY-${facts['os']['name']}", - } - } -} diff --git a/site/profiles/manifests/yum/epel.pp b/site/profiles/manifests/yum/epel.pp deleted file mode 100644 index 575e099..0000000 --- a/site/profiles/manifests/yum/epel.pp +++ /dev/null @@ -1,48 +0,0 @@ -# Class: profiles::yum::epel -# -# This class manages the EPEL yum repository for the system. -# -# Parameters: -# ----------- -# - $baseurl: The base URL for the EPEL yum repository. This should be the root -# URL of your EPEL mirror server. -# -# Actions: -# -------- -# - Checks the OS release version. -# -# - If the release version is 7, 8, or 9, it sets up the 'epel' yum repository -# -# - If the release version is not supported, it raises an error. -# -# Example usage: -# -------------- -# To use this class with the default parameters: -# include profiles::yum::epel -# -# To specify a custom base URL: -# class { 'profiles::yum::epel': -# baseurl => 'http://mylocalmirror.com/yum', -# } -class profiles::yum::epel ( - Array[String] $managed_repos, - String $baseurl, - Enum[ - 'daily', - 'weekly', - 'monthly' - ] $snapshot = 'daily', -) { - $release = $facts['os']['release']['major'] - $basearch = $facts['os']['architecture'] - - if 'epel' in $managed_repos { - yumrepo { 'epel': - name => 'epel', - descr => 'epel repository', - target => '/etc/yum.repos.d/epel.repo', - baseurl => "${baseurl}/${release}/Everything-${snapshot}/${basearch}/os/", - gpgkey => "${baseurl}/${release}/Everything-${snapshot}/${basearch}/os/RPM-GPG-KEY-EPEL-${release}", - } - } -} diff --git a/site/profiles/manifests/yum/global.pp b/site/profiles/manifests/yum/global.pp index 796b491..a9fbef5 100644 --- a/site/profiles/manifests/yum/global.pp +++ b/site/profiles/manifests/yum/global.pp @@ -1,48 +1,7 @@ # Class: profiles::yum::global -# -# This class manages global YUM configurations and optionally includes the -# base and EPEL yum repository profiles based on the content of the -# $managed_repos parameter, which is an array of repository names. -# -# Parameters: -# ----------- -# - $managed_repos: An array of repository names that the Puppet agent should -# manage. This parameter is mandatory and the class will -# fail if it is not provided via hieradata. -# Example: ['base', 'updates', 'extras', 'appstream'] -# -# Actions: -# -------- -# - Configures global YUM settings, including keeping the kernel development -# packages and cleaning old kernels. -# -# - Establishes default parameters for any YUM repositories managed by Puppet. -# This includes the repository file location, the repository description, -# and enabling the repository and GPG checks. -# -# - Depending on the content of the $managed_repos parameter, it includes the -# profiles::yum::base and/or profiles::yum::epel classes. -# -# - Manages all .repo files under /etc/yum.repos.d. All the repositories listed -# in $managed_repos will have their corresponding .repo files preserved. Any -# .repo file that is not listed in $managed_repos will be removed. -# -# - Creates and maintains a /etc/yum.repos.d/.managed file that lists all the -# .repo files that should be managed by Puppet. -# -# Example usage: -# -------------- -# To use this class, include the class and configure hieradata: -# include profiles::yum::global -# -# profiles::yum::managed_repos: -# - 'base' -# - 'extras' -# - 'appstream' -# class profiles::yum::global ( - Array[String] $managed_repos = lookup('profiles::yum::managed_repos'), - Boolean $purge = true, + Hash $repos = {}, + Boolean $purge = true, ){ class { 'yum': keep_kernel_devel => true, @@ -52,44 +11,34 @@ class profiles::yum::global ( }, } - Yumrepo { - ensure => 'present', - enabled => 1, - gpgcheck => 1, - mirrorlist => 'absent', - } - + # purge all yum repos not defined by puppet resources { 'yumrepo': purge => $purge, } - # Generate the content for the .managed file - $managed_file_content = $managed_repos.map |$repo_name| { "${repo_name}.repo" }.join("\n") + # download all gpg keys if a repo defines it + $repos.each |$name, $repo| { + if $repo['gpgkey'] { + $key_url = $repo['gpgkey'] + $key_file = "/etc/pki/rpm-gpg/${name}-gpg-key" - # Create the .managed file - file { '/etc/yum.repos.d/.managed': - ensure => file, - content => $managed_file_content, + exec { "download_gpg_key_${name}": + command => "curl -s -o ${key_file} ${key_url} && rpm --import ${key_file}", + path => ['/bin', 'usr/bin'], + creates => $key_file, + before => Yumrepo[$name], + } + } } - # Setup base repos - class { 'profiles::yum::base': - managed_repos => $managed_repos, - } + # create repos + create_resources('yumrepo', $repos) - # Setup epel if included in managed_repos - class { 'profiles::yum::epel': - managed_repos => $managed_repos, - } - - # Setup puppet7 if included in managed_repos - class { 'profiles::yum::puppet7': - managed_repos => $managed_repos, - } - - # Setup unkin repo if included in managed_repos - class { 'profiles::yum::unkin': - managed_repos => $managed_repos, + # makecache if changes made to repos + exec {'dnf_makecache': + command => 'dnf makecache -q', + path => ['/usr/bin', '/bin'], + refreshonly => true, } # setup dnf-autoupdate diff --git a/site/profiles/manifests/yum/mariadb.pp b/site/profiles/manifests/yum/mariadb.pp deleted file mode 100644 index df3d71e..0000000 --- a/site/profiles/manifests/yum/mariadb.pp +++ /dev/null @@ -1,24 +0,0 @@ -# Class: profiles::yum::mariadb -# -# This class manages the mariadb yum repository for the system. -# -class profiles::yum::mariadb ( - String $baseurl = 'http://repos.main.unkin.net', - String $version = '11.2', - Enum[ - 'daily', - 'weekly', - 'monthly' - ] $snapshot = 'daily', -) { - $release = $facts['os']['release']['major'] - $basearch = $facts['os']['architecture'] - - yumrepo { 'mariadb': - name => 'mariadb', - descr => 'mariadb repository', - target => '/etc/yum.repos.d/mariadb.repo', - baseurl => "${baseurl}/mariadb/${version}/el${release}-${snapshot}/${basearch}/os/", - gpgkey => "${baseurl}/mariadb/${version}/el${release}-${snapshot}/${basearch}/os/RPM-GPG-KEY-MariaDB", - } -} diff --git a/site/profiles/manifests/yum/puppet7.pp b/site/profiles/manifests/yum/puppet7.pp deleted file mode 100644 index 2733ff2..0000000 --- a/site/profiles/manifests/yum/puppet7.pp +++ /dev/null @@ -1,58 +0,0 @@ -# Class: profiles::yum::epel -# -# This class manages the puppet7 yum repository for the system. -# -# Parameters: -# ----------- -# - $baseurl: The base URL for the puppet7 yum repository. This should be the root -# URL of your puppet7 mirror server. -# -# Actions: -# -------- -# - Checks the OS release version. -# -# - If the release version is 7, 8, or 9, it sets up the 'puppet7' yum repository -# and installs the puppet7 release RPM from the provided baseurl. -# -# - If the release version is not supported, it raises an error. -# -# - The repo configuration includes the baseurl parameterized with the OS -# release version and architecture, and specifies the GPG key. -# -# Example usage: -# -------------- -# To use this class with the default parameters: -# include profiles::yum::puppet7 -# -# To specify a custom base URL: -# class { 'profiles::yum::puppet7': -# baseurl => 'http://mylocalmirror.com/yum', -# } -class profiles::yum::puppet7 ( - Array[String] $managed_repos, - String $baseurl = 'http://yum.puppet.com', -) { - $releasever = $facts['os']['release']['major'] - $basearch = $facts['os']['architecture'] - - if 'puppet7' in $managed_repos { - if ($releasever in [7,8,9]) { - $source = "${baseurl}/puppet7-release-el-${releasever}.noarch.rpm" - - yum::install { 'puppet-release-el': - ensure => present, - source => $source, - } - } else { - err("Unsupported OS release ${releasever}") - } - - yumrepo { 'puppet7': - name => 'puppet7', - descr => 'puppet7 repository', - target => '/etc/yum.repos.d/puppet7.repo', - baseurl => "${baseurl}/puppet/el/${releasever}/${basearch}/", - gpgkey => "${baseurl}/RPM-GPG-KEY-puppet", - } - } -} diff --git a/site/profiles/manifests/yum/unkin.pp b/site/profiles/manifests/yum/unkin.pp deleted file mode 100644 index be5be37..0000000 --- a/site/profiles/manifests/yum/unkin.pp +++ /dev/null @@ -1,23 +0,0 @@ -# Class: profiles::yum::unkin -class profiles::yum::unkin ( - Array[String] $managed_repos, - String $baseurl, - Enum[ - 'daily', - 'weekly', - 'monthly' - ] $snapshot = 'daily', -) { - $release = $facts['os']['release']['major'] - $basearch = $facts['os']['architecture'] - - if 'unkin' in $managed_repos { - yumrepo { 'unkin': - name => 'unkin', - descr => 'unkin repository', - target => '/etc/yum.repos.d/unkin.repo', - baseurl => "${baseurl}/${::facts['os']['release']['major']}/${basearch}/os/", - gpgcheck => false, - } - } -} diff --git a/site/profiles/templates/base/facts/custom_facts.yaml.erb b/site/profiles/templates/base/facts/custom_facts.yaml.erb new file mode 100644 index 0000000..e4b3895 --- /dev/null +++ b/site/profiles/templates/base/facts/custom_facts.yaml.erb @@ -0,0 +1,3 @@ +--- +enc_role: <%= @enc_role[0] %> +enc_env: <%= @enc_env %> diff --git a/site/profiles/templates/base/hosts.erb b/site/profiles/templates/base/hosts.erb index 45bf0d2..c41ef08 100644 --- a/site/profiles/templates/base/hosts.erb +++ b/site/profiles/templates/base/hosts.erb @@ -1,15 +1,10 @@ # /etc/hosts file managed by Puppet # The following lines are desirable for IPv4 capable hosts -127.0.0.1 <%= @fqdn %> <%= @hostname %> +<%= @facts['networking']['ip'] %> <%= @fqdn %> <%= @hostname %> 127.0.0.1 localhost.localdomain localhost 127.0.0.1 localhost4.localdomain4 localhost4 -# The following lines are desirable for IPv6 capable hosts -::1 <%= @fqdn %> <%= @hostname %> -::1 localhost.localdomain localhost -::1 localhost6.localdomain6 localhost6 - <% @additional_hosts.each do |host| -%> <%= host['ip'] %> <%= host['hostname'] %> <%= host['aliases'].join(' ') if host['aliases'] %> <% end -%> diff --git a/site/profiles/templates/base/motd/motd.erb b/site/profiles/templates/base/motd/motd.erb index 7ca06df..6e2f7df 100644 --- a/site/profiles/templates/base/motd/motd.erb +++ b/site/profiles/templates/base/motd/motd.erb @@ -1,6 +1,6 @@ <% # calculate padding for the longest word -max_length = ['fqdn:', 'os:', 'role:', 'branch:', 'addr:', 'nic:'].max_by(&:length).length +max_length = ['fqdn:', 'os:', 'role:', 'branch:', 'addr:', 'nic:', 'location:', 'env:'].max_by(&:length).length # helper lambda to right-align text align = ->(word) { word.ljust(max_length) } %> @@ -10,4 +10,6 @@ align = ->(word) { word.ljust(max_length) } <%= align.call('branch:') %> <%= @enc_env %> <%= align.call('addr:') %> <%= @addr %> <%= align.call('nic:') %> <%= @nic %> +<%= align.call('location:') %> <%= @location %> +<%= align.call('env:') %> <%= @env %> diff --git a/site/profiles/templates/cobbler/debmirror.conf.erb b/site/profiles/templates/cobbler/debmirror.conf.erb new file mode 100644 index 0000000..9c66ca1 --- /dev/null +++ b/site/profiles/templates/cobbler/debmirror.conf.erb @@ -0,0 +1,79 @@ +# Puppet managed config for debmirror + +# The config file is a perl script so take care to follow perl syntax. +# Any setting in /etc/debmirror.conf overrides these defaults and +# ~/.debmirror.conf overrides those again. Take only what you need. +# +# The syntax is the same as on the command line and variable names +# loosely match option names. If you don't recognize something here +# then just stick to the command line. +# +# Options specified on the command line override settings in the config +# files. + +# Location of the local mirror (use with care) +# $mirrordir="/path/to/mirrordir" + +# Output options +$verbose=0; +$progress=0; +$debug=0; + +# Download options +$host="ftp.debian.org"; +$user="anonymous"; +$passwd="anonymous@"; +$remoteroot="debian"; +$download_method="ftp"; +# @dists="sid"; +@sections="main,main/debian-installer,contrib,non-free,non-free-firmware"; +# @arches="i386"; +# @ignores=""; +# @excludes=""; +# @includes=""; +# @excludes_deb_section=""; +# @limit_priority=""; +$omit_suite_symlinks=0; +$skippackages=0; +# @rsync_extra="doc,tools"; +$i18n=0; +$getcontents=0; +$do_source=1; +$max_batch=0; + +# @di_dists="dists"; +# @di_archs="arches"; + +# Save mirror state between runs; value sets validity of cache in days +$state_cache_days=0; + +# Security/Sanity options +$ignore_release_gpg=0; +$ignore_release=0; +$check_md5sums=0; +$ignore_small_errors=0; + +# Cleanup +$cleanup=0; +$post_cleanup=1; + +# Locking options +$timeout=300; + +# Rsync options +$rsync_batch=200; +$rsync_options="-aIL --partial"; + +# FTP/HTTP options +$passive=0; +# $proxy="http://proxy:port/"; + +# Dry run +$dry_run=0; + +# Don't keep diff files but use them +$diff_mode="use"; + +# The config file must return true or perl complains. +# Always copy this. +1; diff --git a/site/profiles/templates/cobbler/httpd_ssl.conf.erb b/site/profiles/templates/cobbler/httpd_ssl.conf.erb new file mode 100644 index 0000000..9b95ba5 --- /dev/null +++ b/site/profiles/templates/cobbler/httpd_ssl.conf.erb @@ -0,0 +1,203 @@ +# managed by puppet +# +# When we also provide SSL we have to listen to the +# standard HTTPS port in addition. +# +Listen 443 https + +## +## SSL Global Context +## +## All SSL configuration in this context applies both to +## the main server and all SSL-enabled virtual hosts. +## + +# Pass Phrase Dialog: +# Configure the pass phrase gathering process. +# The filtering dialog program (`builtin' is a internal +# terminal dialog) has to provide the pass phrase on stdout. +SSLPassPhraseDialog exec:/usr/libexec/httpd-ssl-pass-dialog + +# Inter-Process Session Cache: +# Configure the SSL Session Cache: First the mechanism +# to use and second the expiring timeout (in seconds). +SSLSessionCache shmcb:/run/httpd/sslcache(512000) +SSLSessionCacheTimeout 300 + +# +# Use "SSLCryptoDevice" to enable any supported hardware +# accelerators. Use "openssl engine -v" to list supported +# engine names. NOTE: If you enable an accelerator and the +# server does not start, consult the error logs and ensure +# your accelerator is functioning properly. +# +SSLCryptoDevice builtin +#SSLCryptoDevice ubsec + +## +## SSL Virtual Host Context +## + + + +# General setup for the virtual host, inherited from global configuration +#DocumentRoot "/var/www/html" +#ServerName www.example.com:443 + +# Use separate log files for the SSL virtual host; note that LogLevel +# is not inherited from httpd.conf. +ErrorLog logs/ssl_error_log +TransferLog logs/ssl_access_log +LogLevel warn + +# SSL Engine Switch: +# Enable/Disable SSL for this virtual host. +SSLEngine on + +# List the protocol versions which clients are allowed to connect with. +# The OpenSSL system profile is used by default. See +# update-crypto-policies(8) for more details. +#SSLProtocol all -SSLv3 +#SSLProxyProtocol all -SSLv3 + +# User agents such as web browsers are not configured for the user's +# own preference of either security or performance, therefore this +# must be the prerogative of the web server administrator who manages +# cpu load versus confidentiality, so enforce the server's cipher order. +SSLHonorCipherOrder on + +# SSL Cipher Suite: +# List the ciphers that the client is permitted to negotiate. +# See the mod_ssl documentation for a complete list. +# The OpenSSL system profile is configured by default. See +# update-crypto-policies(8) for more details. +SSLCipherSuite PROFILE=SYSTEM +SSLProxyCipherSuite PROFILE=SYSTEM + +# Point SSLCertificateFile at a PEM encoded certificate. If +# the certificate is encrypted, then you will be prompted for a +# pass phrase. Note that restarting httpd will prompt again. Keep +# in mind that if you have both an RSA and a DSA certificate you +# can configure both in parallel (to also allow the use of DSA +# ciphers, etc.) +# Some ECC cipher suites (http://www.ietf.org/rfc/rfc4492.txt) +# require an ECC certificate which can also be configured in +# parallel. +SSLCertificateFile <%= @httpd_ssl_certificate %> + +# Server Private Key: +# If the key is not combined with the certificate, use this +# directive to point at the key file. Keep in mind that if +# you've both a RSA and a DSA private key you can configure +# both in parallel (to also allow the use of DSA ciphers, etc.) +# ECC keys, when in use, can also be configured in parallel +SSLCertificateKeyFile <%= @httpd_ssl_privatekey %> + +# Server Certificate Chain: +# Point SSLCertificateChainFile at a file containing the +# concatenation of PEM encoded CA certificates which form the +# certificate chain for the server certificate. Alternatively +# the referenced file can be the same as SSLCertificateFile +# when the CA certificates are directly appended to the server +# certificate for convenience. +#SSLCertificateChainFile /etc/pki/tls/certs/server-chain.crt + +# Certificate Authority (CA): +# Set the CA certificate verification path where to find CA +# certificates for client authentication or alternatively one +# huge file containing all of them (file must be PEM encoded) +#SSLCACertificateFile /etc/pki/tls/certs/ca-bundle.crt + +# Client Authentication (Type): +# Client certificate verification type and depth. Types are +# none, optional, require and optional_no_ca. Depth is a +# number which specifies how deeply to verify the certificate +# issuer chain before deciding the certificate is not valid. +#SSLVerifyClient require +#SSLVerifyDepth 10 + +# Access Control: +# With SSLRequire you can do per-directory access control based +# on arbitrary complex boolean expressions containing server +# variable checks and other lookup directives. The syntax is a +# mixture between C and Perl. See the mod_ssl documentation +# for more details. +# +#SSLRequire ( %{SSL_CIPHER} !~ m/^(EXP|NULL)/ \ +# and %{SSL_CLIENT_S_DN_O} eq "Snake Oil, Ltd." \ +# and %{SSL_CLIENT_S_DN_OU} in {"Staff", "CA", "Dev"} \ +# and %{TIME_WDAY} >= 1 and %{TIME_WDAY} <= 5 \ +# and %{TIME_HOUR} >= 8 and %{TIME_HOUR} <= 20 ) \ +# or %{REMOTE_ADDR} =~ m/^192\.76\.162\.[0-9]+$/ +# + +# SSL Engine Options: +# Set various options for the SSL engine. +# o FakeBasicAuth: +# Translate the client X.509 into a Basic Authorisation. This means that +# the standard Auth/DBMAuth methods can be used for access control. The +# user name is the `one line' version of the client's X.509 certificate. +# Note that no password is obtained from the user. Every entry in the user +# file needs this password: `xxj31ZMTZzkVA'. +# o ExportCertData: +# This exports two additional environment variables: SSL_CLIENT_CERT and +# SSL_SERVER_CERT. These contain the PEM-encoded certificates of the +# server (always existing) and the client (only existing when client +# authentication is used). This can be used to import the certificates +# into CGI scripts. +# o StdEnvVars: +# This exports the standard SSL/TLS related `SSL_*' environment variables. +# Per default this exportation is switched off for performance reasons, +# because the extraction step is an expensive operation and is usually +# useless for serving static content. So one usually enables the +# exportation for CGI and SSI requests only. +# o StrictRequire: +# This denies access when "SSLRequireSSL" or "SSLRequire" applied even +# under a "Satisfy any" situation, i.e. when it applies access is denied +# and no other module can change it. +# o OptRenegotiate: +# This enables optimized SSL connection renegotiation handling when SSL +# directives are used in per-directory context. +#SSLOptions +FakeBasicAuth +ExportCertData +StrictRequire + + SSLOptions +StdEnvVars + + + SSLOptions +StdEnvVars + + +# SSL Protocol Adjustments: +# The safe and default but still SSL/TLS standard compliant shutdown +# approach is that mod_ssl sends the close notify alert but doesn't wait for +# the close notify alert from client. When you need a different shutdown +# approach you can use one of the following variables: +# o ssl-unclean-shutdown: +# This forces an unclean shutdown when the connection is closed, i.e. no +# SSL close notify alert is sent or allowed to be received. This violates +# the SSL/TLS standard but is needed for some brain-dead browsers. Use +# this when you receive I/O errors because of the standard approach where +# mod_ssl sends the close notify alert. +# o ssl-accurate-shutdown: +# This forces an accurate shutdown when the connection is closed, i.e. a +# SSL close notify alert is sent and mod_ssl waits for the close notify +# alert of the client. This is 100% SSL/TLS standard compliant, but in +# practice often causes hanging connections with brain-dead browsers. Use +# this only for browsers where you know that their SSL implementation +# works correctly. +# Notice: Most problems of broken clients are also related to the HTTP +# keep-alive facility, so you usually additionally want to disable +# keep-alive for those clients, too. Use variable "nokeepalive" for this. +# Similarly, one has to force some clients to use HTTP/1.0 to workaround +# their broken HTTP/1.1 implementation. Use variables "downgrade-1.0" and +# "force-response-1.0" for this. +BrowserMatch "MSIE [2-5]" \ + nokeepalive ssl-unclean-shutdown \ + downgrade-1.0 force-response-1.0 + +# Per-Server Logging: +# The home of a custom SSL log file. Use this when you want a +# compact non-error SSL logfile on a virtual host basis. +CustomLog logs/ssl_request_log \ + "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b" + + diff --git a/site/profiles/templates/cobbler/main.ipxe.erb b/site/profiles/templates/cobbler/main.ipxe.erb new file mode 100644 index 0000000..386d262 --- /dev/null +++ b/site/profiles/templates/cobbler/main.ipxe.erb @@ -0,0 +1,47 @@ +#!ipxe +dhcp + +# Some menu defaults +set menu-timeout 5000 +set submenu-timeout ${menu-timeout} +set menu-default cobbler + +:start +menu iPXE boot menu +item --gap -- ----------------------------- Cobbler ------------------------------------ +item cobbler Cobbler (kickstart or boot from disk) +item --gap -- ------------------------- Advanced options ------------------------------- +item --key s shell Drop to iPXE shell +item --key r reboot Reboot +item +item --key x exit Exit iPXE and continue BIOS boot +choose --timeout ${menu-timeout} --default ${menu-default} selected || goto cancel +set menu-timeout 0 +goto ${selected} + +:cancel +echo You cancelled the menu, dropping you to a shell + +:no_system +echo No system configuration found for MAC address ${mac} +goto exit + +:shell +echo Type 'exit' to get the back to the menu +shell +set menu-timeout 0 +set submenu-timeout 0 +goto start + +:reboot +reboot + +:exit +exit + +### +### Custom menu entries +### + +:cobbler +chain --autofree http://${next-server}/cblr/svc/op/gpxe/mac/${net0/mac} || goto no_system diff --git a/site/profiles/templates/cobbler/settings.yaml.erb b/site/profiles/templates/cobbler/settings.yaml.erb new file mode 100644 index 0000000..1869444 --- /dev/null +++ b/site/profiles/templates/cobbler/settings.yaml.erb @@ -0,0 +1,466 @@ +# Cobbler settings file + +# Restart cobblerd and run "cobbler sync" after making changes. +# This config file is in YAML 1.2 format; see "http://yaml.org". + +# If "true", Cobbler will allow insertions of system records that duplicate the "--dns-name" information of other system +# records. In general, this is undesirable and should be left "false". +allow_duplicate_hostnames: false + +# If "true", Cobbler will allow insertions of system records that duplicate the ip address information of other system +# records. In general, this is undesirable and should be left "false". +allow_duplicate_ips: false + +# If "true", Cobbler will allow insertions of system records that duplicate the MAC address information of other system +# records. In general, this is undesirable. +allow_duplicate_macs: false + +# If "true", Cobbler will allow settings to be changed dynamically without a restart of the cobblerd daemon. You can +# only change this variable by manually editing the settings file, and you MUST restart cobblerd after changing it. +allow_dynamic_settings: false + +# By default, installs are *not* set to send installation logs to the Cobbler server. With "anamon_enabled", automatic +# installation templates may use the "pre_anamon" snippet to allow remote live monitoring of their installations from +# the Cobbler server. Installation logs will be stored under "/var/log/cobbler/anamon/". +# NOTE: This does allow an xmlrpc call to send logs to this directory, without authentication, so enable only if you are +# ok with this limitation. +anamon_enabled: false + +# If using "authn_pam" in the "modules.conf", this can be configured to change the PAM service authentication will be +# tested against. +# The default value is "login". +authn_pam_service: "login" + +# How long the authentication token is valid for, in seconds. +auth_token_expiration: 3600 + +# This is a directory of files that Cobbler uses to make templating easier. See the Wiki for more information. Changing +# this directory should not be required. +autoinstall_snippets_dir: /var/lib/cobbler/snippets +autoinstall_templates_dir: /var/lib/cobbler/templates + +# location of templates used for boot loader config generation +boot_loader_conf_template_dir: "/etc/cobbler/boot_loader_conf" + +# Email out a report when Cobbler finishes installing a system. +# enabled: set to true to turn this feature on +# sender: optional +# email: which addresses to email +# smtp_server: used to specify another server for an MTA +# subject: use the default subject unless overridden +build_reporting_enabled: false +build_reporting_sender: "" +build_reporting_email: [ 'root@localhost' ] +build_reporting_smtp_server: "localhost" +build_reporting_subject: "" +build_reporting_ignorelist: [] + +# If cache_enabled is true, a cache will keep converted records in memory to make checking them faster. This helps with +# use cases like writing out large numbers of records. There is a known issue with cache and remote XMLRPC API calls. +# If you will use Cobbler with config management or infrastructure-as-code tools such as Terraform, it is recommended +# to disable by setting to false. +cache_enabled: true + +# Cheetah-language autoinstall templates can import Python modules. While this is a useful feature, it is not safe to +# allow them to import anything they want. This whitelists which modules can be imported through Cheetah. Users can +# expand this as needed but should never allow modules such as subprocess or those that allow access to the filesystem +# as Cheetah templates are evaluated by cobblerd as code. +cheetah_import_whitelist: + - "random" + - "re" + - "time" + - "netaddr" + +# Default "createrepo_flags" to use for new repositories. If you have createrepo >= 0.4.10, consider +# "-c cache --update -C", which can dramatically improve your "cobbler reposync" time. "-s sha" enables working with +# Fedora repos from F11/F12 from EL-4 or EL-5 without python-hashlib installed (which is not available on EL-4) +createrepo_flags: "-c cache -s sha" + +# if no autoinstall template is specified to profile add, use this template +default_autoinstall: /var/lib/cobbler/templates/default.ks + +# configure all installed systems to use these nameservers by default +# unless defined differently in the profile. For DHCP configurations +# you probably do /not/ want to supply this. +default_name_servers: [] +default_name_servers_search: [] + +# if using the authz_ownership module (see the Wiki), objects +# created without specifying an owner are assigned to this +# owner and/or group. Can be a comma seperated list. +default_ownership: + - "admin" + +# Cobbler has various sample automatic installation templates stored +# in /var/lib/cobbler/templates/. This controls +# what install (root) password is set up for those +# systems that reference this variable. The factory +# default is "cobbler" and Cobbler check will warn if +# this is not changed. +# The simplest way to change the password is to run +# openssl passwd -1 +# and put the output between the "" below. +default_password_crypted: "<%= @default_password_crypted %>" + +# the default template type to use in the absence of any +# other detected template. If you do not specify the template +# with '#template=' on the first line of your +# templates/snippets, Cobbler will assume try to use the +# following template engine to parse the templates. +# +# Current valid values are: cheetah, jinja2 +default_template_type: "cheetah" + +# for libvirt based installs in koan, if no virt bridge +# is specified, which bridge do we try? For EL 4/5 hosts +# this should be xenbr0, for all versions of Fedora, try +# "virbr0". This can be overriden on a per-profile +# basis or at the koan command line though this saves +# typing to just set it here to the most common option. +default_virt_bridge: xenbr0 + +# use this as the default disk size for virt guests (GB) +default_virt_file_size: 5 + +# use this as the default memory size for virt guests (MB) +default_virt_ram: 512 + +# if koan is invoked without --virt-type and no virt-type +# is set on the profile/system, what virtualization type +# should be assumed? Values: xenpv, xenfv, qemu, vmware +# (NOTE: this does not change what virt_type is chosen by import) +default_virt_type: xenpv + +# enable gPXE booting? Enabling this option will cause Cobbler +# to copy the undionly.kpxe file to the tftp root directory, +# and if a profile/system is configured to boot via gpxe it will +# chain load off pxelinux.0. +# Default: false +enable_gpxe: false + +# controls whether Cobbler will add each new profile entry to the default +# PXE boot menu. This can be over-ridden on a per-profile +# basis when adding/editing profiles with --enable-menu=false/true. Users +# should ordinarily leave this setting enabled unless they are concerned +# with accidental reinstalls from users who select an entry at the PXE +# boot menu. Adding a password to the boot menus templates +# may also be a good solution to prevent unwanted reinstallations +enable_menu: true + +# change this port if Apache is not running plaintext on port +# 80. Most people can leave this alone. +http_port: 80 + +# kernel options that should be present in every Cobbler installation. +# kernel options can also be applied at the distro/profile/system +# level. +kernel_options: {} + +# configuration options if using the authn_ldap module. See the +# the Wiki for details. This can be ignored if you are not using +# LDAP for WebUI/XMLRPC authentication. +ldap_server: "ldap.example.com" +ldap_base_dn: "DC=example,DC=com" +ldap_port: 389 +ldap_tls: true +ldap_anonymous_bind: true +ldap_search_bind_dn: '' +ldap_search_passwd: '' +ldap_search_prefix: 'uid=' +ldap_tls_cacertfile: '' +ldap_tls_keyfile: '' +ldap_tls_certfile: '' + +# Cobbler has a feature that allows for integration with config management +# systems such as Puppet. The following parameters work in conjunction with +# --mgmt-classes and are described in further detail at: +# https://github.com/cobbler/cobbler/wiki/Using-cobbler-with-a-configuration-management-system +mgmt_classes: [] +mgmt_parameters: + from_cobbler: true + +# if enabled, this setting ensures that puppet is installed during +# machine provision, a client certificate is generated and a +# certificate signing request is made with the puppet master server +puppet_auto_setup: false + +# when puppet starts on a system after installation it needs to have +# its certificate signed by the puppet master server. Enabling the +# following feature will ensure that the puppet server signs the +# certificate after installation if the puppet master server is +# running on the same machine as Cobbler. This requires +# puppet_auto_setup above to be enabled +sign_puppet_certs_automatically: false + +# location of the puppet executable, used for revoking certificates +puppetca_path: "/usr/bin/puppet" + +# when a puppet managed machine is reinstalled it is necessary to +# remove the puppet certificate from the puppet master server before a +# new certificate is signed (see above). Enabling the following +# feature will ensure that the certificate for the machine to be +# installed is removed from the puppet master server if the puppet +# master server is running on the same machine as Cobbler. This +# requires puppet_auto_setup above to be enabled +remove_old_puppet_certs_automatically: false + +# choose a --server argument when running puppetd/puppet agent during autoinstall +#puppet_server: 'puppet' + +# let Cobbler know that you're using a newer version of puppet +# choose version 3 to use: 'puppet agent'; version 2 uses status quo: 'puppetd' +#puppet_version: 2 + +# choose whether to enable puppet parameterized classes or not. +# puppet versions prior to 2.6.5 do not support parameters +puppet_parameterized_classes: true + +# set to true to enable Cobbler's DHCP management features. +# the choice of DHCP management engine is in /etc/cobbler/modules.conf +manage_dhcp: false + +# set to true to enable Cobbler's DNS management features. +# the choice of DNS mangement engine is in /etc/cobbler/modules.conf +manage_dns: false + +# set to path of bind chroot to create bind-chroot compatible bind +# configuration files. This should be automatically detected. +bind_chroot_path: "" + +# set to the ip address of the master bind DNS server for creating secondary +# bind configuration files +bind_master: 127.0.0.1 + +# set to true to enable Cobbler's TFTP management features. +# the choice of TFTP mangement engine is in /etc/cobbler/modules.conf +manage_tftpd: true + +# This variable contains the location of the tftpboot directory. If this directory is not present Cobbler does not +# start. +# Default: /var/lib/tftpboot +tftpboot_location: "/var/lib/tftpboot" + +# set to true to enable Cobbler's RSYNC management features. +manage_rsync: false + +# if using BIND (named) for DNS management in /etc/cobbler/modules.conf +# and manage_dns is enabled (above), this lists which zones are managed +# See the Wiki (https://github.com/cobbler/cobbler/wiki/Dns-management) for more info +manage_forward_zones: [] +manage_reverse_zones: [] + +# if using Cobbler with manage_dhcp, put the IP address +# of the Cobbler server here so that PXE booting guests can find it +# if you do not set this correctly, this will be manifested in TFTP open timeouts. +next_server: <%= @next_server %> + +# settings for power management features. optional. +# see https://github.com/cobbler/cobbler/wiki/Power-management to learn more +# choices (refer to codes.py): +# apc_snmp bladecenter bullpap drac ether_wake ilo integrity +# ipmilan lpar rsa virsh wti +power_management_default_type: 'ipmilan' + +# if this setting is set to true, Cobbler systems that pxe boot +# will request at the end of their installation to toggle the +# --netboot-enabled record in the Cobbler system record. This eliminates +# the potential for a PXE boot loop if the system is set to PXE +# first in it's BIOS order. Enable this if PXE is first in your BIOS +# boot order, otherwise leave this disabled. See the manpage +# for --netboot-enabled. +pxe_just_once: <%= @pxe_just_once %> + +# if this setting is set to one, triggers will be executed when systems +# will request to toggle the --netboot-enabled record at the end of their installation. +nopxe_with_triggers: true + +# This setting is only used by the code that supports using Spacewalk/Satellite +# authentication within Cobbler Web and Cobbler XMLRPC. +redhat_management_server: "xmlrpc.rhn.redhat.com" + +# if using authn_spacewalk in modules.conf to let Cobbler authenticate +# against Satellite/Spacewalk's auth system, by default it will not allow per user +# access into Cobbler Web and Cobbler XMLRPC. +# in order to permit this, the following setting must be enabled HOWEVER +# doing so will permit all Spacewalk/Satellite users of certain types to edit all +# of Cobbler's configuration. +# these roles are: config_admin and org_admin +# users should turn this on only if they want this behavior and +# do not have a cross-multi-org seperation concern. If you have +# a single org in your satellite, it's probably safe to turn this +# on and then you can use CobblerWeb alongside a Satellite install. +redhat_management_permissive: false + +# specify the default Red Hat authorization key to use to register +# system. If left blank, no registration will be attempted. Similarly +# you can set the --redhat-management-key to blank on any system to +# keep it from trying to register. +redhat_management_key: "" + +# if set to true, allows /usr/bin/cobbler-register (part of the koan package) +# to be used to remotely add new Cobbler system records to Cobbler. +# this effectively allows for registration of new hardware from system +# records. +register_new_installs: false + +# Flags to use for yum's reposync. If your version of yum reposync +# does not support -l, you may need to remove that option. +reposync_flags: "-l -n -d" + +# Flags to use for rysync's reposync. If flag 'a' is used then createrepo +# is not ran after the rsync +reposync_rsync_flags: "-rltDv --copy-unsafe-links" + +# when DHCP and DNS management are enabled, Cobbler sync can automatically +# restart those services to apply changes. The exception for this is +# if using ISC for DHCP, then omapi eliminates the need for a restart. +# omapi, however, is experimental and not recommended for most configurations. +# If DHCP and DNS are going to be managed, but hosted on a box that +# is not on this server, disable restarts here and write some other +# script to ensure that the config files get copied/rsynced to the destination +# box. This can be done by modifying the restart services trigger. +# Note that if manage_dhcp and manage_dns are disabled, the respective +# parameter will have no effect. Most users should not need to change +# this. +restart_dns: true +restart_dhcp: true + +# install triggers are scripts in /var/lib/cobbler/triggers/install +# that are triggered in autoinstall pre and post sections. Any +# executable script in those directories is run. They can be used +# to send email or perform other actions. They are currently +# run as root so if you do not need this functionality you can +# disable it, though this will also disable "cobbler status" which +# uses a logging trigger to audit install progress. +run_install_triggers: true + +# enables a trigger which version controls all changes to /var/lib/cobbler +# when add, edit, or sync events are performed. This can be used +# to revert to previous database versions, generate RSS feeds, or for +# other auditing or backup purposes. "git" and "hg" are currently suported, +# but git is the recommend SCM for use with this feature. +scm_track_enabled: false +scm_track_mode: "git" +scm_track_author: "cobbler " +scm_push_script: "/bin/true" + +# this is the address of the Cobbler server -- as it is used +# by systems during the install process, it must be the address +# or hostname of the system as those systems can see the server. +# if you have a server that appears differently to different subnets +# (dual homed, etc), you need to read the --server-override section +# of the manpage for how that works. +server: <%= @server %> + +# If set to true, all commands will be forced to use the localhost address +# instead of using the above value which can force commands like +# cobbler sync to open a connection to a remote address if one is in the +# configuration and would traceback. +client_use_localhost: false + +# If set to "true", all commands to the API (not directly to the XMLRPC server) will go over HTTPS instead of plaintext. +# Be sure to change the "http_port" setting to the correct value for the web server. +client_use_https: false + +# Should new profiles for virtual machines default to auto booting with the physical host when the physical host +# reboots? This can be overridden on each profile or system object. +virt_auto_boot: true + +# Cobbler's web directory. Don't change this setting -- see the Wiki on "Relocating your Cobbler install" if your "/var" +# partition is not large enough. +webdir: "/var/www/cobbler" + +# Directories that will not get wiped and recreated on a "cobbler sync". +webdir_whitelist: + - misc + - web + - webui + - localmirror + - repo_mirror + - distro_mirror + - images + - links + - pub + - repo_profile + - repo_system + - svc + - rendered + - .link_cache + +# Cobbler's public XMLRPC listens on this port. Change this only +# if absolutely needed, as you'll have to start supplying a new +# port option to koan if it is not the default. +xmlrpc_port: 25151 + +# "cobbler repo add" commands set Cobbler up with repository +# information that can be used during autoinstall and is automatically +# set up in the Cobbler autoinstall templates. By default, these +# are only available at install time. To make these repositories +# usable on installed systems (since Cobbler makes a very convenient +# mirror) set this to true. Most users can safely set this to true. Users +# who have a dual homed Cobbler server, or are installing laptops that +# will not always have access to the Cobbler server may wish to leave +# this as false. In that case, the Cobbler mirrored yum repos are still +# accessable at http://cobbler.example.org/cblr/repo_mirror and yum +# configuration can still be done manually. This is just a shortcut. +yum_post_install_mirror: true + +# the default yum priority for all the distros. This is only used if yum-priorities plugin is used. +# 1=maximum +# Tweak with caution! +yum_distro_priority: 1 + +# Flags to use for yumdownloader. Not all versions may support +# --resolve. +yumdownloader_flags: "--resolve" + +# sort and indent JSON output to make it more human-readable +serializer_pretty_json: false + +# replication rsync options for distros, autoinstalls, snippets set to override default value of "-avzH" +replicate_rsync_options: "-avzH" + +# replication rsync options for repos set to override default value of "-avzH" +replicate_repo_rsync_options: "-avzH" + +# always write DHCP entries, regardless if netboot is enabled +always_write_dhcp_entries: false + +# External proxy - used by: reposync", "signature update" +# Eg: "http://192.168.1.1:8080" (HTTP), "https://192.168.1.1:8443" (HTTPS) +proxy_url_ext: "" + +# Internal proxy - used by systems to reach Cobbler for templates +# Eg: proxy_url_int: "http://10.0.0.1:8080" +proxy_url_int: "" + +# This is a directory of files that Cobbler uses to include +# files into Jinja2 templates +jinja2_includedir: "/var/lib/cobbler/jinja2" + +# Up to now, cobblerd used $server's IP address instead of the DNS name in autoinstallation +# file settings (pxelinux.cfg files) to save bytes, which seemed required for S/390 systems. +# This behavior can have negative impact on installs with multi-homed Cobbler servers, because +# not all of the IP addresses may be reachable during system install. +# This behavior was now made conditional, with default being "off". +convert_server_to_ip: false + +# Leftover settings +bootloaders_dir: "/var/lib/cobbler/loaders" +buildisodir: "/var/cache/cobbler/buildiso" +cobbler_master: "" +default_virt_disk_driver: "raw" +grubconfig_dir: "/var/lib/cobbler/grub_config" +iso_template_dir: "/etc/cobbler/iso" + +# Puppet +puppet_server: "" +puppet_version: 2 + +# Signatures +signature_path: "/var/lib/cobbler/distro_signatures.json" +signature_url: "https://cobbler.github.io/signatures/3.0.x/latest.json" + +# Include other configuration snippets. Overwriting a key from this file in a childfile will overwrite the value from +# this file. +include: [ "/etc/cobbler/settings.d/*.settings" ] diff --git a/site/profiles/templates/haproxy/certificate.list.erb b/site/profiles/templates/haproxy/certificate.list.erb new file mode 100644 index 0000000..85c8efa --- /dev/null +++ b/site/profiles/templates/haproxy/certificate.list.erb @@ -0,0 +1,3 @@ +<% @certificates.each do |item| %> +<%= item %> +<% end %> diff --git a/site/profiles/templates/helpers/certmanager.erb b/site/profiles/templates/helpers/certmanager.erb new file mode 100644 index 0000000..7266fde --- /dev/null +++ b/site/profiles/templates/helpers/certmanager.erb @@ -0,0 +1,102 @@ +#!<%= @venv_path %>/bin/python + +import argparse +import requests +import json +import os +import yaml +from zipfile import ZipFile + +# remove this after certs are generated everywhere +requests.packages.urllib3.disable_warnings() + +def load_config(config_path): + with open(config_path, 'r') as file: + config = yaml.safe_load(file) + return config['vault'] + +def authenticate_approle(vault_config): + url = f"{vault_config['addr']}/v1/auth/{vault_config['approle_path']}/login" + payload = { + "role_id": vault_config['role_id'], + } + response = requests.post(url, json=payload, verify=False) + if response.status_code == 200: + auth_response = response.json() + return auth_response['auth']['client_token'] + else: + print(f"Error authenticating with AppRole: {response.text}") + return None + +def request_certificate(common_name, alt_names, ip_sans, expiry_days, vault_config): + # Authenticate using AppRole and get a token + client_token = authenticate_approle(vault_config) + if not client_token: + print("Failed to authenticate with Vault using AppRole.") + return None + + url = f"{vault_config['addr']}/v1/{vault_config['mount_point']}/issue/{vault_config['role_name']}" + headers = {'X-Vault-Token': client_token} + payload = { + "common_name": common_name, + "alt_names": ",".join(alt_names), + "ip_sans": ",".join(ip_sans), + "ttl": f"{expiry_days}d" + } + response = requests.post(url, headers=headers, json=payload, verify=False) + if response.status_code == 200: + return response.json() + else: + print(f"Error requesting certificate: {response.text}") + return None + +def save_cert_files(certificate_response, common_name, compress, config, json_output): + base_path = config.get('output_path', '.') + cert_dir = os.path.join(base_path, common_name) + if json_output: + import json + output = { + 'certificate': certificate_response['data']['certificate'], + 'private_key': certificate_response['data']['private_key'], + 'full_chain': certificate_response['data']['issuing_ca'] + "\n" + certificate_response['data']['certificate'], + } + print(json.dumps(output)) + elif not compress: + os.makedirs(cert_dir, exist_ok=True) + with open(os.path.join(cert_dir, "certificate.crt"), "w") as cert_file: + cert_file.write(certificate_response['data']['certificate']) + with open(os.path.join(cert_dir, "private.key"), "w") as key_file: + key_file.write(certificate_response['data']['private_key']) + with open(os.path.join(cert_dir, "full_chain.crt"), "w") as full_chain_file: + full_chain_file.write(certificate_response['data']['issuing_ca'] + "\n" + certificate_response['data']['certificate']) + else: + zip_name = f"{os.path.join(base_path, common_name)}.zip" + with ZipFile(zip_name, 'w') as zipf: + zipf.writestr("certificate.crt", certificate_response['data']['certificate']) + zipf.writestr("private.key", certificate_response['data']['private_key']) + zipf.writestr("full_chain.crt", certificate_response['data']['issuing_ca'] + "\n" + certificate_response['data']['certificate']) + +def main(config_file): + config = load_config(config_file) + parser = argparse.ArgumentParser(description='Request and retrieve a certificate from Vault.') + parser.add_argument('common_name', type=str, help='Common Name for the certificate') + parser.add_argument('-a', '--alt-names', type=str, default='', help='Comma-separated alternative names for the certificate') + parser.add_argument('-i', '--ip-sans', type=str, default='', help='Comma-separated IP Subject Alternative Names for the certificate') + parser.add_argument('-e', '--expiry-days', type=int, default=365, help='Validity of the certificate in days (default: 365)') + parser.add_argument('-c', '--compress', action='store_true', help='Compress the certificate, key, and full chain into a zip file') + parser.add_argument('--json', action='store_true', help='Output results in JSON format') + args = parser.parse_args() + alt_names = [name.strip() for name in args.alt_names.split(',') if name] + ip_sans = [ip.strip() for ip in args.ip_sans.split(',') if ip] + certificate_response = request_certificate(args.common_name, alt_names, ip_sans, args.expiry_days, config) + if certificate_response: + if args.json: + save_cert_files(certificate_response, args.common_name, args.compress, config, True) + else: + save_cert_files(certificate_response, args.common_name, args.compress, config, False) + else: + print("Failed to obtain certificate.") + +if __name__ == "__main__": + config_file = '<%= @config_path %>' + main(config_file) diff --git a/site/profiles/templates/helpers/certmanager_config.yaml.erb b/site/profiles/templates/helpers/certmanager_config.yaml.erb new file mode 100644 index 0000000..1b3e1ed --- /dev/null +++ b/site/profiles/templates/helpers/certmanager_config.yaml.erb @@ -0,0 +1,7 @@ +vault: + addr: '<%= @vault_config['addr'] %>' + role_id: '<%= @vault_config['role_id'] %>' + approle_path: '<%= @vault_config['approle_path'] %>' + mount_point: '<%= @vault_config['mount_point'] %>' + role_name: '<%= @vault_config['role_name'] %>' +output_path: '<%= @vault_config['output_path'] %>' diff --git a/site/profiles/templates/helpers/node_lookup.erb b/site/profiles/templates/helpers/node_lookup.erb index 7596821..deeb39e 100644 --- a/site/profiles/templates/helpers/node_lookup.erb +++ b/site/profiles/templates/helpers/node_lookup.erb @@ -3,6 +3,7 @@ import requests import sys import argparse import json +import os def build_query(node=None, fact_name=None, match=None, show_role=False): query_filters = [] @@ -23,14 +24,27 @@ def build_query(node=None, fact_name=None, match=None, show_role=False): return json.dumps(["and"] + query_filters) def query_puppetdb(query): - url = 'http://puppetdb:8080/pdb/query/v4/facts' + url = 'http://puppetdbapi.service.consul:8080/pdb/query/v4/facts' response = requests.get(url, params={'query': query}) process_response(response) -def process_response(response): +def process_response(response, count_only=False): if response.status_code == 200: - for fact in response.json(): - print(f"{fact['certname']} {fact['value']}") + try: + response_data = response.json() + except ValueError: + print("Error decoding JSON response") + return + + if count_only: + fact_counter = Counter(fact['value'] for fact in response_data) + for fact_value, count in fact_counter.items(): + print(f"{fact_value}: {count}") + else: + facts = [f"{fact['certname']} {fact['value']}" for fact in response_data] + facts.sort() + for fact in facts: + print(fact) else: print(f"Error querying PuppetDB: HTTP {response.status_code}") print("Response content:", response.text) @@ -45,6 +59,7 @@ def main(): parser.add_argument("-R", "--role", action="store_true", help="Show the role for matched hosts") parser.add_argument("-F", "--fact", help="Specify a fact name") parser.add_argument("-m", "--match", help="Simple pattern match for the value") + parser.add_argument("-C", "--count", action="store_true", help="Show count of rows with the same fact") args = parser.parse_args() diff --git a/site/profiles/templates/pki/vaultcaroot.pem.erb b/site/profiles/templates/pki/vaultcaroot.pem.erb new file mode 100644 index 0000000..8a92884 --- /dev/null +++ b/site/profiles/templates/pki/vaultcaroot.pem.erb @@ -0,0 +1,91 @@ +# unkin.net Intermediate Authority drw1 +-----BEGIN CERTIFICATE----- +MIIDrDCCApSgAwIBAgIUAyjDayxDtmvXzttcT1jUg9KU08swDQYJKoZIhvcNAQEL +BQAwFDESMBAGA1UEAxMJdW5raW4ubmV0MB4XDTI0MDIyNTExMDI0NloXDTI5MDIy +MzExMDMxNlowKzEpMCcGA1UEAxMgdW5raW4ubmV0IEludGVybWVkaWF0ZSBBdXRo +b3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCft5vNuV0S+WPN +qIm8N09yQcWUjK7S5LeWqFi2sYvxB3PZIsbGF4oB5QQKbHOvwSp+/70gQ0HeyBpq +yS3bVJK/OYMQXbYj+wpS8FXd1WeD5XphAEPV/vfWixQWOHLm4A+yjVbyFiaD4Z8e +0/cvi48WPp3uzyVFW12U/XRZ/eHF4psJ1tsNt8e1JcAsAmRXUr1R0JgKNDBJsu2Q +2EPa6MqRpJVKfI4cvOYM3XyXN5pCogAJaleg+TMdZ3wCQljTBpojzX947Ky1Yosa +GtZ2tNes8cpq3mzHqH8fms89H1JBPttOCVJXwK1sEdwkXYh6aktUDGkjppvaG013 +eSx/LDFvAgMBAAGjgd4wgdswDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMB +Af8wHQYDVR0OBBYEFEMfNj+VqQQF2XHJm1qK0RhCZxnRMB8GA1UdIwQYMBaAFCqI +QnrNBzDWmM1YryAlmIbAnwLPMEAGCCsGAQUFBwEBBDQwMjAwBggrBgEFBQcwAoYk +aHR0cDovLzEyNy4wLjAuMTo4MjAwL3YxL3BraV9yb290L2NhMDYGA1UdHwQvMC0w +K6ApoCeGJWh0dHA6Ly8xMjcuMC4wLjE6ODIwMC92MS9wa2lfcm9vdC9jcmwwDQYJ +KoZIhvcNAQELBQADggEBALMGlMJ7twlrBkBJLBgDmF7+Q5rpiHz9zBhLU8fh0HiR +dhqe3yJcO87o3CrCiQXqtWHGy4Ogl2QvastKKhFBIcwp8BBXxzp68HG+SIJAzWau +val0pncs/2V3TIk1iOXLY7YXDm6x4ND+iUz5rmILs/0q82S3iAbro4IckinfmGjI +7En8eg7VRv8z2FL51+giov5zqH7NT3TjvYZzf20EKHmOlyZhAboktNxVpoj4cAGl +iUW3GFSva8F6VS49I9pejBFJUQeIILz5jeTEdzG643DnujjjNqw8ad3ivakBYD1G +YxGhYmLfh5RmESCeAgBbLQgRa1vNz1YYWhjn4OP0KKs= +-----END CERTIFICATE----- + +# unkin.net Intermediate Authority syd1 +-----BEGIN CERTIFICATE----- +MIIDujCCAqKgAwIBAgIULZAR/QcvAnxdi04S6bXhNeazozYwDQYJKoZIhvcNAQEL +BQAwFDESMBAGA1UEAxMJdW5raW4ubmV0MB4XDTI0MDQyNzExMzcyMloXDTI5MDQy +NjExMzc1MlowKzEpMCcGA1UEAxMgdW5raW4ubmV0IEludGVybWVkaWF0ZSBBdXRo +b3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDDq0ZU2DnuYW5s +E3lPjVe2Ns6cPu64yx1GLVqB5VbOUs71ThRjPjvEwE98YtGMza8ok0CQSqS2qX8z +vnMbnVCaWKjCnem/dtQtB+8WCu5uQuNHhwqxgw1tD/klAkVLWGgTPDEgasvjDMkc +sW8in/BhtrV9YA/lQGpge+j9/MFXhlnvaLCPybFifPRX9Yc5CcnhSzLSzFPO4PJx +VH4Qu9eByyKHMTvgcCy6p9qjjzz+8dtAlxeIsgfTEdvtfCPowsF+v2XooutTsJt0 +xUDvUDu4xV6tVCEOYRA2cZHkLRBhV289M0hocHrsGqMmA1+j0skwwt/6UkVHqlCT +mitItX+RAgMBAAGjgewwgekwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMB +Af8wHQYDVR0OBBYEFEp/+grAdVqRSeb9xJjSeZYNW32MMB8GA1UdIwQYMBaAFBqc +v6Y+hfHt4EjgKa/uoQGEHTknMEcGCCsGAQUFBwEBBDswOTA3BggrBgEFBQcwAoYr +aHR0cHM6Ly92YXVsdC5zZXJ2dWNlLmNvbnN1bC92MS9wa2lfcm9vdC9jYTA9BgNV +HR8ENjA0MDKgMKAuhixodHRwczovL3ZhdWx0LnNlcnZpY2UuY29uc3VsL3YxL3Br +aV9yb290L2NybDANBgkqhkiG9w0BAQsFAAOCAQEAM0FS8tscZe7yly/gM7jO6lx5 +muMFusifjUIrcQGnZBkoECeuUVPNTs3e/Th+XaxjCnmSpqSNT3z9Irr6Hhxf7n03 +4+hpF3G0bf1yh4DRex/0ua3szvgo91RwyKVQM1BHIA1PwdF8csO+LT4FTMILzo4U +DdSVvDEIaxYYQCDNfAD81n+8lmFbabupfsKbkSTR+sNTS+TMnLpN8YwSXdB0e+RU +eEZRNVu0jKmbE8U/66Sc33YLe6cxbCclHA+G4giGwEP+lYZk+rFjmr6ci9bj5yyN +Sznr7xdW0ofOdACAQFFy5KTZqCDjIrvk12vUn4bSsXmWVIQEd+jPx6wuxD/rSw== +-----END CERTIFICATE----- + +# unkin.net drw1 +-----BEGIN CERTIFICATE----- +MIIDLzCCAhegAwIBAgIUeXJ+O/IJWu4Fl4+KdZl5r166SokwDQYJKoZIhvcNAQEL +BQAwFDESMBAGA1UEAxMJdW5raW4ubmV0MB4XDTI0MDIyNTExMDEwNVoXDTM0MDIy +MjExMDEzNFowFDESMBAGA1UEAxMJdW5raW4ubmV0MIIBIjANBgkqhkiG9w0BAQEF +AAOCAQ8AMIIBCgKCAQEAzKFwXIKAkavv5RgGUEzGQIgys1Uw97RBp4aE7glT++hs +60WSwKBRr+sk7zdL3LGMK/xClTIBt3eFJ2RMxEf/N/qLPoA1JqOzsHua1nXCR1sA +puP5HVfrS6YvfsXGpqJywX7tfaqk+7+Mq4Bbp22+JXmgBpfcQhCy9CNRd8gaLM67 +LaznQEcmeurdqvqeUxSMUsymeLLSi2+Fx+M9bPiYYXvK3Hu7k7VVsDPamglBsZaG +QC7Up7ZD1h+UaweK/lC5v8HkW6xZ8OWZBEm0F6XFRIRRbroFTZXniAUu60FpoCCD +Ga9AfUrAAIWFQjd0iJ2fgzbX1qeLozKn1T/oMAiKhQIDAQABo3kwdzAOBgNVHQ8B +Af8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUKohCes0HMNaYzViv +ICWYhsCfAs8wHwYDVR0jBBgwFoAUKohCes0HMNaYzVivICWYhsCfAs8wFAYDVR0R +BA0wC4IJdW5raW4ubmV0MA0GCSqGSIb3DQEBCwUAA4IBAQCBVjvJIAp3AtEhRO/V +wYtF/t6ntSKs8limCGnHHvJDvUJGkIP5ihCDQYviNyYIf7CrtRUmYzzOmwA4OEjq +cwxrdRynqkUz8jeRL2Ljc1kEs5A4rY2X8EtoUaCu4p55wm7Bh/m2lYASHHMpuza8 +CR2DtlSQR8/x9gFKzAZO6rOw89qqU34p/cf7DlymDACjJr0QmhLa5IQMSj8ObsbT +c9sb9NXMFTsFkuCrkF5iLmeDZgmgyJNXkzFEh3TPeL15jKBXSJOHsBe8j3E3VMWS +YOL0pDU1XzfJedKGzX3LxvK6aUuBbtgaf/PW3IYX3KToolqfB30H2AO6Q/3LBl8M +aN8H +-----END CERTIFICATE----- + +# unkin.net syd1 +-----BEGIN CERTIFICATE----- +MIIDLzCCAhegAwIBAgIUIDADwsHIrQ8dfncpechBdIUCQdIwDQYJKoZIhvcNAQEL +BQAwFDESMBAGA1UEAxMJdW5raW4ubmV0MB4XDTI0MDQyNzExMjcwMloXDTM0MDQy +NTExMjczMlowFDESMBAGA1UEAxMJdW5raW4ubmV0MIIBIjANBgkqhkiG9w0BAQEF +AAOCAQ8AMIIBCgKCAQEA3ENPv7R7gCUJAg8Q4hB2LEZSdvbK155YbcrguLDDnu6m +2fkJn8jYMMW3Z6/+Y04ouGwi6sKup8ggTb217sY+dC4IUZjotDPAhruxfXVQAh0v +Yr3RYoxVDrm4nRSFLo1RA4Qt+1KK299mHGQf9iAiwbsFp5mDrJT9uz15FE2uWmbK +8/onMyJC4fnkMihVN6NIgTtjpHYNm5aAJwxoWldTopgF0ucb7X3XVPNbKAmd3Avd +lsOo6m751zSZ0HvJOxgRSy7lvPzMuUfCQsOcmI4O4+Z2FL4Y7p+T9DvWkciC7L3i +tBiK30fPfGKNpWaof1ONCcPQNjMwWcEFXqSiWUOXkwIDAQABo3kwdzAOBgNVHQ8B +Af8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUGpy/pj6F8e3gSOAp +r+6hAYQdOScwHwYDVR0jBBgwFoAUGpy/pj6F8e3gSOApr+6hAYQdOScwFAYDVR0R +BA0wC4IJdW5raW4ubmV0MA0GCSqGSIb3DQEBCwUAA4IBAQA5xocILzuvD+R2Iub1 +UnTdcVpgNcxJmESz0eX4UrkcBmddtuFINXvDTv5//XTFs78LsVVSf00xZ+2C62Xe +xRdCdluHN8VDCAKulP4XJY1BiZ7im0v+iMgPDKhq4OXb86WFYI/8J6uRm7oIAwj1 +zhhKxMimkzli+yHB8ipL15W7l68CMUgmOjFA+EG6sbfadFpQTX/h6TVj3FQPkU/p +UJEm2XjlGNAKGJrNRU47PM4vRDv5Joyowp9zv/pHFXvUJladaJupMKRJQVWQz1US +EXE67rawG79s3vm8dDolnbli/IhPHtjDRIprxAwrMs5tt9cY0xsRkFBZVcAOjrpb +4gqd +-----END CERTIFICATE----- diff --git a/site/profiles/templates/proxmox/join_pvecluster.erb b/site/profiles/templates/proxmox/join_pvecluster.erb new file mode 100644 index 0000000..378b95d --- /dev/null +++ b/site/profiles/templates/proxmox/join_pvecluster.erb @@ -0,0 +1,11 @@ +#!/usr/bin/expect -f +set timeout -1 +set password [lindex $argv 0] +set ip [lindex $argv 1] + +spawn pvecm add $ip +expect "Please enter superuser (root) password for" +send "$password\r" +expect "The authenticity of host" +send "yes\r" +expect eof diff --git a/site/profiles/templates/proxmox/pve_facts.yaml.erb b/site/profiles/templates/proxmox/pve_facts.yaml.erb new file mode 100644 index 0000000..7b3362e --- /dev/null +++ b/site/profiles/templates/proxmox/pve_facts.yaml.erb @@ -0,0 +1,2 @@ +--- +pve_clusterinit_master: <%= @clusterinit_master %> diff --git a/site/profiles/templates/puppet/client/puppet.conf.erb b/site/profiles/templates/puppet/client/puppet.conf.erb index e7a86c6..40874c6 100644 --- a/site/profiles/templates/puppet/client/puppet.conf.erb +++ b/site/profiles/templates/puppet/client/puppet.conf.erb @@ -1,5 +1,5 @@ [main] -dns_alt_names = <%= @dns_alt_names %> +dns_alt_names = <%= @dns_alt_names_string %> [agent] server = <%= @server %> diff --git a/site/profiles/templates/puppet/puppet_ca.cfg.erb b/site/profiles/templates/puppet/puppet_ca.cfg.erb new file mode 100644 index 0000000..a119784 --- /dev/null +++ b/site/profiles/templates/puppet/puppet_ca.cfg.erb @@ -0,0 +1,10 @@ +certificate-authority: { + # allow CA to sign certificate requests that have subject alternative names. + allow-subject-alt-names: <%= @allow_subject_alt_names %> + + # allow CA to sign certificate requests that have authorization extensions. + allow-authorization-extensions: <%= @allow_authorization_extensions %> + + # enable the separate CRL for Puppet infrastructure nodes + enable-infra-crl: <%= @enable_infra_crl %> +} diff --git a/site/profiles/templates/puppet/server/cobbler-enc.erb b/site/profiles/templates/puppet/server/cobbler-enc.erb new file mode 100644 index 0000000..27dd30e --- /dev/null +++ b/site/profiles/templates/puppet/server/cobbler-enc.erb @@ -0,0 +1,46 @@ +#!<%= @venv_path %>/bin/python +""" +External Node Classifier (ENC) for Puppet. + +If the environment specified in the YAML file is 'testing', +the environment is not included in the output. +""" + +import sys +import yaml +import requests + +def fetch_enc_data(cobbler_url: str, hostname: str) -> str: + """ + Fetches and modifies ENC data from a given URL to ensure classes are in list format. + """ + url = f"{cobbler_url}/cblr/svc/op/puppet/hostname/{hostname}" + try: + response = requests.get(url, verify='<%= @trusted_ca_cert %>') + response.raise_for_status() + except requests.RequestException as e: + sys.exit(f"Request failed: {e}") + + data = yaml.safe_load(response.text) + data["parameters"] = data.get("parameters", {}) + + # Ensure 'classes' is in the desired list format + if "classes" in data: + if isinstance(data["classes"], dict): + data["parameters"]["enc_role"] = list(data["classes"].keys()) + data["classes"] = list(data["classes"].keys()) + else: + data["parameters"]["enc_role"] = list(data["classes"]) + data["classes"] = list(data["classes"]) + + if "environment" in data: + data["parameters"]["enc_env"] = data["environment"] + if data["environment"] == "testing": + del data["environment"] + + return yaml.dump(data) + +if __name__ == "__main__": + if len(sys.argv) != 2: + sys.exit(f"Usage: {sys.argv[0]} ") + print(fetch_enc_data("<%= @cobbler_base_url %>", sys.argv[1])) diff --git a/site/profiles/templates/puppet/server/puppet.conf.epp b/site/profiles/templates/puppet/server/puppet.conf.epp index 226346d..dbb93ee 100644 --- a/site/profiles/templates/puppet/server/puppet.conf.epp +++ b/site/profiles/templates/puppet/server/puppet.conf.epp @@ -10,9 +10,16 @@ dns_alt_names = <%= $dns_alt_names %> [agent] server = <%= $server %> +ca_server = <%= $ca_server %> +environment = <%= $environment %> +report = <%= $report %> +report_server = <%= $report_server %> +runinterval = <%= $runinterval %> +runtimeout = <%= $runtimeout %> +show_diff = <%= $show_diff %> [master] -node_terminus = exec +node_terminus = <%= $node_terminus %> external_nodes = <%= $external_nodes %> autosign = <%= $autosign %> default_manifest = <%= $default_manifest %> diff --git a/site/profiles/templates/reposync/autosyncer.erb b/site/profiles/templates/reposync/autosyncer.erb index 4f48e58..0cc2551 100644 --- a/site/profiles/templates/reposync/autosyncer.erb +++ b/site/profiles/templates/reposync/autosyncer.erb @@ -26,7 +26,7 @@ download_gpg_key() { local filename=$(basename "$gpgkeyurl") # Download GPG key to the specified path with the filename from the URL - wget -q -O "${basepath}/live/${reponame}/${filename}" "$gpgkeyurl" || { + curl -s --create-dirs -o "${basepath}/live/${reponame}/${filename}" "$gpgkeyurl" || { echo "Failed to download GPG key from $gpgkeyurl" } } diff --git a/site/roles/manifests/base.pp b/site/roles/manifests/base.pp index d6a7fa2..371974f 100644 --- a/site/roles/manifests/base.pp +++ b/site/roles/manifests/base.pp @@ -1,6 +1,11 @@ # a role to deploy the base system # work in progress class roles::base { - include profiles::defaults - include profiles::base + if $facts['firstrun'] { + include profiles::defaults + include profiles::firstrun::init + }else{ + include profiles::defaults + include profiles::base + } } diff --git a/site/roles/manifests/infra/cobbler/server.pp b/site/roles/manifests/infra/cobbler/server.pp new file mode 100644 index 0000000..5ffd2a6 --- /dev/null +++ b/site/roles/manifests/infra/cobbler/server.pp @@ -0,0 +1,11 @@ +# cobbler server profile +class roles::infra::cobbler::server { + if $facts['firstrun'] { + include profiles::defaults + include profiles::firstrun::init + }else{ + include profiles::base + include profiles::base::datavol + include profiles::cobbler::init + } +} diff --git a/site/roles/manifests/infra/db/redis.pp b/site/roles/manifests/infra/db/redis.pp new file mode 100644 index 0000000..af3bfce --- /dev/null +++ b/site/roles/manifests/infra/db/redis.pp @@ -0,0 +1,10 @@ +# a role to deploy a redis node +class roles::infra::db::redis { + if $facts['firstrun'] { + include profiles::defaults + include profiles::firstrun::init + }else{ + include profiles::defaults + include profiles::base + } +} diff --git a/site/roles/manifests/infra/dhcp/server.pp b/site/roles/manifests/infra/dhcp/server.pp new file mode 100644 index 0000000..1a27e17 --- /dev/null +++ b/site/roles/manifests/infra/dhcp/server.pp @@ -0,0 +1,11 @@ +# dhcp server profile +class roles::infra::dhcp::server { + if $facts['firstrun'] { + include profiles::defaults + include profiles::firstrun::init + }else{ + include profiles::defaults + include profiles::base + include profiles::dhcp::server + } +} diff --git a/site/roles/manifests/infra/dns/master.pp b/site/roles/manifests/infra/dns/master.pp index e5d50de..fbf5192 100644 --- a/site/roles/manifests/infra/dns/master.pp +++ b/site/roles/manifests/infra/dns/master.pp @@ -2,7 +2,12 @@ # defines a dns server with master-only zones # class roles::infra::dns::master { + if $facts['firstrun'] { + include profiles::defaults + include profiles::firstrun::init + }else{ include profiles::defaults include profiles::base include profiles::dns::master + } } diff --git a/site/roles/manifests/infra/dns/resolver.pp b/site/roles/manifests/infra/dns/resolver.pp index 606ca9f..3277cad 100644 --- a/site/roles/manifests/infra/dns/resolver.pp +++ b/site/roles/manifests/infra/dns/resolver.pp @@ -2,7 +2,12 @@ # defines a dns server with forward-only zones # class roles::infra::dns::resolver { + if $facts['firstrun'] { + include profiles::defaults + include profiles::firstrun::init + }else{ include profiles::defaults include profiles::base include profiles::dns::resolver + } } diff --git a/site/roles/manifests/infra/git/gitea.pp b/site/roles/manifests/infra/git/gitea.pp new file mode 100644 index 0000000..a11e842 --- /dev/null +++ b/site/roles/manifests/infra/git/gitea.pp @@ -0,0 +1,14 @@ +# a role to deploy the puppetboard +class roles::infra::git::gitea { + if $facts['firstrun'] { + include profiles::defaults + include profiles::firstrun::init + }else{ + include profiles::defaults + include profiles::base + include profiles::base::datavol + if $facts['enc_role'] == 'roles::infra::git::gitea' { + include profiles::gitea::init + } + } +} diff --git a/site/roles/manifests/infra/halb/haproxy.pp b/site/roles/manifests/infra/halb/haproxy.pp index 81c7455..87a2d41 100644 --- a/site/roles/manifests/infra/halb/haproxy.pp +++ b/site/roles/manifests/infra/halb/haproxy.pp @@ -1,5 +1,11 @@ # a role to deploy a haproxy node class roles::infra::halb::haproxy { - include profiles::defaults - include profiles::base + if $facts['firstrun'] { + include profiles::defaults + include profiles::firstrun::init + }else{ + include profiles::defaults + include profiles::base + include profiles::haproxy::server + } } diff --git a/site/roles/manifests/infra/metrics/grafana.pp b/site/roles/manifests/infra/metrics/grafana.pp index db6f757..2f99f8d 100644 --- a/site/roles/manifests/infra/metrics/grafana.pp +++ b/site/roles/manifests/infra/metrics/grafana.pp @@ -1,5 +1,10 @@ # a role to deploy a grafana service class roles::infra::metrics::grafana { - include profiles::defaults - include profiles::base + if $facts['firstrun'] { + include profiles::defaults + include profiles::firstrun::init + }else{ + include profiles::defaults + include profiles::base + } } diff --git a/site/roles/manifests/infra/metrics/prometheus.pp b/site/roles/manifests/infra/metrics/prometheus.pp index d3dd8ea..1b2ee1c 100644 --- a/site/roles/manifests/infra/metrics/prometheus.pp +++ b/site/roles/manifests/infra/metrics/prometheus.pp @@ -1,7 +1,12 @@ # a role to deploy a prometheus server class roles::infra::metrics::prometheus { - include profiles::defaults - include profiles::base - include profiles::base::datavol - include profiles::metrics::server + if $facts['firstrun'] { + include profiles::defaults + include profiles::firstrun::init + }else{ + include profiles::defaults + include profiles::base + include profiles::base::datavol + include profiles::metrics::server + } } diff --git a/site/roles/manifests/infra/ntp/server.pp b/site/roles/manifests/infra/ntp/server.pp index cfc685d..4ff34f3 100644 --- a/site/roles/manifests/infra/ntp/server.pp +++ b/site/roles/manifests/infra/ntp/server.pp @@ -1,6 +1,11 @@ # a role to deploy a ntp server class roles::infra::ntp::server { - include profiles::defaults - include profiles::base - include profiles::ntp::server + if $facts['firstrun'] { + include profiles::defaults + include profiles::firstrun::init + }else{ + include profiles::defaults + include profiles::base + include profiles::ntp::server + } } diff --git a/site/roles/manifests/infra/ovirt/engine.pp b/site/roles/manifests/infra/ovirt/engine.pp new file mode 100644 index 0000000..1e998f3 --- /dev/null +++ b/site/roles/manifests/infra/ovirt/engine.pp @@ -0,0 +1,10 @@ +# role to manage ovirt management engine nodes +class roles::infra::ovirt::engine { + if $facts['firstrun'] { + include profiles::defaults + include profiles::firstrun::init + }else{ + include profiles::defaults + include profiles::base + } +} diff --git a/site/roles/manifests/infra/ovirt/node.pp b/site/roles/manifests/infra/ovirt/node.pp new file mode 100644 index 0000000..026a25f --- /dev/null +++ b/site/roles/manifests/infra/ovirt/node.pp @@ -0,0 +1,11 @@ +# role to manage ovirt hypervisor nodes +class roles::infra::ovirt::node { + if $facts['firstrun'] { + include profiles::defaults + include profiles::firstrun::init + }else{ + include profiles::defaults + include profiles::base + include profiles::ovirt::node + } +} diff --git a/site/roles/manifests/infra/proxmox/node.pp b/site/roles/manifests/infra/proxmox/node.pp new file mode 100644 index 0000000..ccf41b6 --- /dev/null +++ b/site/roles/manifests/infra/proxmox/node.pp @@ -0,0 +1,11 @@ +# manage the installation of a proxmox node +class roles::infra::proxmox::node { + if $facts['firstrun'] { + include profiles::defaults + include profiles::firstrun::init + }else{ + include profiles::defaults + include profiles::base + include profiles::proxmox::init + } +} diff --git a/site/roles/manifests/infra/puppet/master.pp b/site/roles/manifests/infra/puppet/master.pp index 01e8877..c29ab7a 100644 --- a/site/roles/manifests/infra/puppet/master.pp +++ b/site/roles/manifests/infra/puppet/master.pp @@ -1,7 +1,12 @@ # a role to deploy the puppetmaster # work in progress class roles::infra::puppet::master { + if $facts['firstrun'] { + include profiles::defaults + include profiles::firstrun::init + }else{ include profiles::defaults include profiles::base include profiles::puppet::puppetmaster } +} diff --git a/site/roles/manifests/infra/puppetboard/server.pp b/site/roles/manifests/infra/puppetboard/server.pp index 4742810..e2d772d 100644 --- a/site/roles/manifests/infra/puppetboard/server.pp +++ b/site/roles/manifests/infra/puppetboard/server.pp @@ -1,6 +1,11 @@ # a role to deploy the puppetboard class roles::infra::puppetboard::server { + if $facts['firstrun'] { + include profiles::defaults + include profiles::firstrun::init + }else{ include profiles::defaults include profiles::base include profiles::puppet::puppetboard } +} diff --git a/site/roles/manifests/infra/puppetdb/api.pp b/site/roles/manifests/infra/puppetdb/api.pp index 65bee4c..7d50c47 100644 --- a/site/roles/manifests/infra/puppetdb/api.pp +++ b/site/roles/manifests/infra/puppetdb/api.pp @@ -1,6 +1,11 @@ # a role to deploy the puppetdb api service class roles::infra::puppetdb::api { + if $facts['firstrun'] { + include profiles::defaults + include profiles::firstrun::init + }else{ include profiles::defaults include profiles::base include profiles::puppet::puppetdb_api } +} diff --git a/site/roles/manifests/infra/puppetdb/sql.pp b/site/roles/manifests/infra/puppetdb/sql.pp index 97ebc96..7f13859 100644 --- a/site/roles/manifests/infra/puppetdb/sql.pp +++ b/site/roles/manifests/infra/puppetdb/sql.pp @@ -1,6 +1,11 @@ # a role to deploy the puppetdb postgresql service class roles::infra::puppetdb::sql { + if $facts['firstrun'] { + include profiles::defaults + include profiles::firstrun::init + }else{ include profiles::defaults include profiles::base include profiles::puppet::puppetdb_sql } +} diff --git a/site/roles/manifests/infra/reposync/syncer.pp b/site/roles/manifests/infra/reposync/syncer.pp index 8c5a613..9c41fe3 100644 --- a/site/roles/manifests/infra/reposync/syncer.pp +++ b/site/roles/manifests/infra/reposync/syncer.pp @@ -1,7 +1,12 @@ # a role to deploy a packagerepo class roles::infra::reposync::syncer { - include profiles::defaults - include profiles::base - include profiles::base::datavol - include profiles::reposync::syncer + if $facts['firstrun'] { + include profiles::defaults + include profiles::firstrun::init + }else{ + include profiles::defaults + include profiles::base + include profiles::base::datavol + include profiles::reposync::syncer + } } diff --git a/site/roles/manifests/infra/sql/galera.pp b/site/roles/manifests/infra/sql/galera.pp index a116c8c..2628f81 100644 --- a/site/roles/manifests/infra/sql/galera.pp +++ b/site/roles/manifests/infra/sql/galera.pp @@ -1,7 +1,15 @@ # a role to deploy a mariadb galera node class roles::infra::sql::galera { - include profiles::defaults - include profiles::base - include profiles::base::datavol - include profiles::sql::galera_member + if $facts['firstrun'] { + include profiles::defaults + include profiles::firstrun::init + }else{ + include profiles::defaults + include profiles::base + include profiles::base::datavol + + if $facts['enc_role'] == 'roles::infra::sql::galera' { + include profiles::sql::galera_member + } + } } diff --git a/site/roles/manifests/infra/storage/consul.pp b/site/roles/manifests/infra/storage/consul.pp index e47a108..143b167 100644 --- a/site/roles/manifests/infra/storage/consul.pp +++ b/site/roles/manifests/infra/storage/consul.pp @@ -1,8 +1,12 @@ - # a role to deploy a consul node class roles::infra::storage::consul { - include profiles::defaults - include profiles::base - include profiles::base::datavol - include profiles::consul::server + if $facts['firstrun'] { + include profiles::defaults + include profiles::firstrun::init + }else{ + include profiles::defaults + include profiles::base + include profiles::base::datavol + include profiles::consul::server + } } diff --git a/site/roles/manifests/infra/storage/edgecache.pp b/site/roles/manifests/infra/storage/edgecache.pp new file mode 100644 index 0000000..7d9d655 --- /dev/null +++ b/site/roles/manifests/infra/storage/edgecache.pp @@ -0,0 +1,12 @@ +# a role to deploy an edgecache +class roles::infra::storage::edgecache { + if $facts['firstrun'] { + include profiles::defaults + include profiles::firstrun::init + }else{ + include profiles::defaults + include profiles::base + include profiles::base::datavol + include profiles::edgecache::init + } +} diff --git a/site/roles/manifests/infra/storage/minio.pp b/site/roles/manifests/infra/storage/minio.pp index 72411e8..d436e8e 100644 --- a/site/roles/manifests/infra/storage/minio.pp +++ b/site/roles/manifests/infra/storage/minio.pp @@ -1,6 +1,11 @@ # a role to deploy a minio node class roles::infra::storage::minio { - include profiles::defaults - include profiles::base - include profiles::minio::server + if $facts['firstrun'] { + include profiles::defaults + include profiles::firstrun::init + }else{ + include profiles::defaults + include profiles::base + include profiles::minio::server + } } diff --git a/site/roles/manifests/infra/storage/vault.pp b/site/roles/manifests/infra/storage/vault.pp index b6afe40..9e11b14 100644 --- a/site/roles/manifests/infra/storage/vault.pp +++ b/site/roles/manifests/infra/storage/vault.pp @@ -1,8 +1,12 @@ # a role to deploy a vault node class roles::infra::storage::vault { - include profiles::defaults - include profiles::base - include profiles::base::datavol - include profiles::vault::server - include profiles::vault::unseal + if $facts['firstrun'] { + include profiles::defaults + include profiles::firstrun::init + }else{ + include profiles::defaults + include profiles::base + include profiles::base::datavol + include profiles::vault::server + } }