diff --git a/Puppetfile b/Puppetfile index c197bde..f29fb47 100644 --- a/Puppetfile +++ b/Puppetfile @@ -7,14 +7,17 @@ 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-lvm', '2.0.3' +mod 'puppetlabs-apt', '9.4.0' +mod 'puppetlabs-lvm', '2.1.0' mod 'puppetlabs-puppetdb', '7.13.0' mod 'puppetlabs-postgresql', '9.1.0' 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' @@ -27,13 +30,23 @@ mod 'puppet-nginx', '5.0.0' mod 'puppet-selinux', '4.1.0' 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/doc/vault/setup.md b/doc/vault/setup.md new file mode 100644 index 0000000..1ec2ca2 --- /dev/null +++ b/doc/vault/setup.md @@ -0,0 +1,48 @@ +# root ca + vault secrets enable -path=pki_root pki + + vault write -field=certificate pki_root/root/generate/internal \ + common_name="unkin.net" \ + issuer_name="unkinroot-2024" \ + ttl=87600h > unkinroot_2024_ca.crt + + vault read pki_root/issuer/$(vault list -format=json pki_root/issuers/ | jq -r '.[]') | tail -n 6 + + vault write pki_root/roles/2024-servers allow_any_name=true + + vault write pki_root/config/urls \ + issuing_certificates="$VAULT_ADDR/v1/pki_root/ca" \ + crl_distribution_points="$VAULT_ADDR/v1/pki_root/crl" + +# intermediate + vault secrets enable -path=pki_int pki + vault secrets tune -max-lease-ttl=43800h pki_int + + vault write -format=json pki_int/intermediate/generate/internal \ + common_name="unkin.net Intermediate Authority" \ + issuer_name="unkin-dot-net-intermediate" \ + | jq -r '.data.csr' > pki_intermediate.csr + + vault write -format=json pki_root/root/sign-intermediate \ + issuer_ref="unkinroot-2024" \ + csr=@pki_intermediate.csr \ + format=pem_bundle ttl="43800h" \ + | jq -r '.data.certificate' > intermediate.cert.pem + + vault write pki_int/intermediate/set-signed certificate=@intermediate.cert.pem + +# create role + vault write pki_int/roles/unkin-dot-net \ + issuer_ref="$(vault read -field=default pki_int/config/issuers)" \ + allowed_domains="unkin.net" \ + allow_subdomains=true \ + max_ttl="2160h" + +# test generating a domain cert + vault write pki_int/issue/unkin-dot-net common_name="test.unkin.net" ttl="24h" + vault write pki_int/issue/unkin-dot-net common_name="test.main.unkin.net" ttl="24h" + vault write pki_int/issue/unkin-dot-net common_name="*.test.main.unkin.net" ttl="24h" + + +# remove expired certificates + vault write pki_int/tidy tidy_cert_store=true tidy_revoked_certs=true diff --git a/environment.conf b/environment.conf index 19e7e87..0368a47 100644 --- a/environment.conf +++ b/environment.conf @@ -1,3 +1,3 @@ manifest = manifests/site.pp -modulepath = external_modules:site +modulepath = external_modules:modules:site config_version = '/usr/bin/grep signature /etc/puppetlabs/code/environments/$environment/.g10k-deploy.json | /usr/bin/cut -d \" -f 4' diff --git a/hiera.yaml b/hiera.yaml index 3097474..d46d2ee 100644 --- a/hiera.yaml +++ b/hiera.yaml @@ -7,14 +7,29 @@ hierarchy: - name: Consolidated Data paths: - "nodes/%{trusted.certname}.yaml" + - "country/%{::country}/region/%{::region}/%{::enc_role_tier1}/%{::enc_role_tier2}/%{::enc_role_tier3}.eyaml" + - "country/%{::country}/region/%{::region}/%{::enc_role_tier1}/%{::enc_role_tier2}/%{::enc_role_tier3}.yaml" + - "country/%{::country}/region/%{::region}/%{::enc_role_tier1}/%{::enc_role_tier2}.eyaml" + - "country/%{::country}/region/%{::region}/%{::enc_role_tier1}/%{::enc_role_tier2}.yaml" + - "country/%{::country}/region/%{::region}/%{::enc_role_tier1}.eyaml" + - "country/%{::country}/region/%{::region}/%{::enc_role_tier1}.yaml" + - "country/%{::country}/roles/%{::enc_role_tier1}/%{::enc_role_tier2}/%{::enc_role_tier3}.eyaml" + - "country/%{::country}/roles/%{::enc_role_tier1}/%{::enc_role_tier2}/%{::enc_role_tier3}.yaml" + - "country/%{::country}/roles/%{::enc_role_tier1}/%{::enc_role_tier2}.eyaml" + - "country/%{::country}/roles/%{::enc_role_tier1}/%{::enc_role_tier2}.yaml" + - "country/%{::country}/roles/%{::enc_role_tier1}.eyaml" + - "country/%{::country}/roles/%{::enc_role_tier1}.yaml" + - "country/%{::country}/region/%{::region}.eyaml" + - "country/%{::country}/region/%{::region}.yaml" + - "country/%{::country}.eyaml" + - "country/%{::country}.yaml" + - "roles/%{::enc_role_tier1}/%{::enc_role_tier2}/%{::enc_role_tier3}.eyaml" + - "roles/%{::enc_role_tier1}/%{::enc_role_tier2}/%{::enc_role_tier3}.yaml" + - "roles/%{::enc_role_tier1}/%{::enc_role_tier2}.eyaml" + - "roles/%{::enc_role_tier1}/%{::enc_role_tier2}.yaml" - "roles/%{::enc_role_tier1}.eyaml" - "roles/%{::enc_role_tier1}.yaml" - - "roles/${::enc_role_tier1}/%{::enc_role_tier2}.eyaml" - - "roles/${::enc_role_tier1}/%{::enc_role_tier2}.yaml" - - "roles/${::enc_role_tier1}/%{::enc_role_tier2}/%{::enc_role_tier3}.eyaml" - - "roles/${::enc_role_tier1}/%{::enc_role_tier2}/%{::enc_role_tier3}.yaml" - - "%{::enc_role_path}.eyaml" - - "%{::enc_role_path}.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 79f8edb..eda0ea1 100644 --- a/hieradata/common.yaml +++ b/hieradata/common.yaml @@ -1,13 +1,121 @@ --- lookup_options: - profiles::packages::base::add: + hiera_classes: merge: strategy: deep - profiles::packages::base::remove: + profiles::packages::install: + merge: + strategy: deep + profiles::packages::install_exclude: + merge: + strategy: deep + profiles::packages::remove: + merge: + strategy: deep + 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 @@ -19,20 +127,36 @@ 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::base::add: +profiles::packages::install: - bash-completion - bzip2 - ccze - curl - dstat + - expect - gzip + - git - htop - inotify-tools - iotop - jq - lz4 - - lzo - mtr - ncdu - neovim @@ -40,6 +164,7 @@ profiles::packages::base::add: - pbzip2 - pigz - pv + - python3.11 - rsync - screen - socat @@ -47,14 +172,14 @@ profiles::packages::base::add: - sysstat - tmux - traceroute + - unzip - vim - vnstat - wget - - xz - zsh - zstd -profiles::packages::base::remove: +profiles::packages::remove: - iwl100-firmware - iwl1000-firmware - iwl105-firmware @@ -73,15 +198,36 @@ profiles::packages::base::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 @@ -97,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 new file mode 100644 index 0000000..33b5046 --- /dev/null +++ b/hieradata/country/au/region/drw1/infra/storage/consul.eyaml @@ -0,0 +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=] diff --git a/hieradata/country/au/region/drw1/infra/storage/consul.yaml b/hieradata/country/au/region/drw1/infra/storage/consul.yaml new file mode 100644 index 0000000..b44e321 --- /dev/null +++ b/hieradata/country/au/region/drw1/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: + - syd1 diff --git a/hieradata/country/au/region/drw1/infra/storage/minio.yaml b/hieradata/country/au/region/drw1/infra/storage/minio.yaml new file mode 100644 index 0000000..1b428c1 --- /dev/null +++ b/hieradata/country/au/region/drw1/infra/storage/minio.yaml @@ -0,0 +1,6 @@ +--- +profiles::minio::server::minio_members: 5 +profiles::minio::server::blockdev: + - /dev/sda + - /dev/sdb +profiles::minio::server::minio_storage_class: 'EC:2' 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 ef48076..7861fca 100644 --- a/hieradata/os/AlmaLinux/AlmaLinux8.yaml +++ b/hieradata/os/AlmaLinux/AlmaLinux8.yaml @@ -1,10 +1,2 @@ # hieradata/os/AlmaLinux/AlmaLinux8.yaml --- -profiles::yum::managed_repos: - - 'base' - - 'appstream' - - 'epel' - - 'powertools' - - 'highavailability' - - 'puppet7' - - 'yum.postgresql.org' 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 6592ae6..c383966 100644 --- a/hieradata/os/AlmaLinux/all_releases.yaml +++ b/hieradata/os/AlmaLinux/all_releases.yaml @@ -1,9 +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::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 b2164e7..8c2ae06 100644 --- a/hieradata/roles/infra.yaml +++ b/hieradata/roles/infra.yaml @@ -1,5 +1,6 @@ --- -profiles::puppet::puppetdb::puppetdb_host: prodinf01n04.main.unkin.net -profiles::puppet::puppetdb::postgres_host: prodinf01n05.main.unkin.net +profiles::packages::install: + - policycoreutils + 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 5a5f87c..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,9 +12,64 @@ 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' profiles::puppet::g10k::default_environment: 'develop' +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 e6a341e..f893a5b 100644 --- a/hieradata/roles/infra/reposync/syncer.yaml +++ b/hieradata/roles/infra/reposync/syncer.yaml @@ -1,40 +1,13 @@ --- +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_8_baseos: - repository: 'BaseOS' - description: 'AlmaLinux 8.8 - BaseOS' - osname: 'almalinux' - release: '8.8' - mirrorlist: https://mirrors.almalinux.org/mirrorlist/8.8/baseos - gpgkey: 'http://mirror.aarnet.edu.au/pub/almalinux/RPM-GPG-KEY-AlmaLinux' - almalinux_8_8_appstream: - repository: 'AppStream' - description: 'AlmaLinux 8.8 - AppStream' - osname: 'almalinux' - release: '8.8' - mirrorlist: https://mirrors.almalinux.org/mirrorlist/8.8/appstream - gpgkey: 'http://mirror.aarnet.edu.au/pub/almalinux/RPM-GPG-KEY-AlmaLinux' - almalinux_8_8_highavailability: - repository: 'HighAvailability' - description: 'AlmaLinux 8.8 - HighAvailability' - osname: 'almalinux' - release: '8.8' - mirrorlist: https://mirrors.almalinux.org/mirrorlist/8.8/ha - gpgkey: 'http://mirror.aarnet.edu.au/pub/almalinux/RPM-GPG-KEY-AlmaLinux' - almalinux_8_8_powertools: - repository: 'PowerTools' - description: 'AlmaLinux 8.8 - PowerTools' - osname: 'almalinux' - release: '8.8' - mirrorlist: https://mirrors.almalinux.org/mirrorlist/8.8/powertools - gpgkey: 'http://mirror.aarnet.edu.au/pub/almalinux/RPM-GPG-KEY-AlmaLinux' - almalinux_8_8_extras: - repository: 'extras' - description: 'AlmaLinux 8.8 - extras' - osname: 'almalinux' - release: '8.8' - mirrorlist: https://mirrors.almalinux.org/mirrorlist/8.8/extras - gpgkey: 'http://mirror.aarnet.edu.au/pub/almalinux/RPM-GPG-KEY-AlmaLinux' almalinux_8_9_baseos: repository: 'BaseOS' description: 'AlmaLinux 8.9 - BaseOS' @@ -70,12 +43,67 @@ 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' osname: 'epel' release: '8' - # baseurl: 'https://dl.fedoraproject.org/pub/epel/8/Everything/x86_64/' mirrorlist: 'https://mirrors.fedoraproject.org/mirrorlist?repo=epel-8&arch=x86_64' gpgkey: 'https://dl.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-8' mariadb_11_2_el8: @@ -91,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.eyaml b/hieradata/roles/infra/storage/consul.eyaml new file mode 100644 index 0000000..4182583 --- /dev/null +++ b/hieradata/roles/infra/storage/consul.eyaml @@ -0,0 +1,2 @@ +--- +profiles::consul::server::acl_master_token: ENC[PKCS7,MIIBmQYJKoZIhvcNAQcDoIIBijCCAYYCAQAxggEhMIIBHQIBADAFMAACAQEwDQYJKoZIhvcNAQEBBQAEggEAFCDnJyImf/X8f6WGqt37XbuuSg5hCeC5Uhdd0u1/Jjlz4AzMyhF41Vs6iVrV6irlsMDziSQrcEvGumTPmYShRQiRv0GvkhHUpn2XROKd63KolsWRj2K2S5FhgwolgtQc05DLmGaQ6FIUMVk3aKU/v8IGSDopcjdhwTJtheOLgiiEjv8TsjWKOOIa0H7caa6ZiZxcf2Y99Wv9gIZdt+LnXGdlDuO88+gkYTpRM07RY21nr4VS821y0MwFcYx2SyzMDk60RvgCmvA6RdoyHBUYAu07IX6IjP5LZwpAkcPcA4gADVP7vOPT2WhVAtkzpg+RwNxkuWYA5roO2r1UhERixjBcBgkqhkiG9w0BBwEwHQYJYIZIAWUDBAEqBBC9TM/c8nXJswHAUSU6kFCDgDBob2r0tFLq1Jw313Ys8jUtKsetsrc5x7uIDYzOqr7ulEM9B0VOD2ekR9IRYZMsBCg=] diff --git a/hieradata/roles/infra/storage/consul.yaml b/hieradata/roles/infra/storage/consul.yaml new file mode 100644 index 0000000..a3ea581 --- /dev/null +++ b/hieradata/roles/infra/storage/consul.yaml @@ -0,0 +1,79 @@ +--- +profiles::consul::server::members_lookup: true +profiles::consul::server::data_dir: /data/consul +profiles::consul::server::addresses: + dns: "%{::networking.ip}" + http: "%{::networking.ip}" + https: "%{::networking.ip}" + grpc: "%{::networking.ip}" + grpc_tls: "%{::networking.ip}" +profiles::consul::server::ports: + dns: 8600 + http: 8500 + https: -1 +profiles::consul::server::acl: + enabled: true + default_policy: 'deny' + down_policy: 'extend-cache' + 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/minio.eyaml b/hieradata/roles/infra/storage/minio.eyaml new file mode 100644 index 0000000..08e0b2d --- /dev/null +++ b/hieradata/roles/infra/storage/minio.eyaml @@ -0,0 +1,2 @@ +--- +profiles::minio::server::minio_root_pass: ENC[PKCS7,MIIBmQYJKoZIhvcNAQcDoIIBijCCAYYCAQAxggEhMIIBHQIBADAFMAACAQEwDQYJKoZIhvcNAQEBBQAEggEAcAGh4K8P/bOwHs7FEAssBcYgtT+FlkMW4/jpJf230sbOh0jswvCl0woQMMw+AIpkXNJ//YcmDBkhdE92RCK8C4Xi/2nkdWjPt9FQwuT47BhAKISjunRs9R61dKj5aOwAlTQ3lNtsQsknGz17AMTyPEGQC9SnPxYirLRr9VgJX/EKPjl7M2LbkZTJChwIE6IiT+LSzye7YgpkJ7O6h4jNIp5ryWaUqSUfooYjqHc1zl4Bs9ZfyY1K/CWCTIbtd4hY1ZlskRlVa9yA0cWhsufV0gw43RA/bCAJPowLc64bZ4XlLx9Fy0qHKjTCDRLzysUoq0QjIR2Ulf1TkcCJAVLwFDBcBgkqhkiG9w0BBwEwHQYJYIZIAWUDBAEqBBC3+P+RW/JoQemkVJE/mpAngDAw1JpFkBvLj4AlbJePvpnG+fFN8coOE+5N94NgGd9Gtl2NZt/g5x/7xFHS28cSlIg=] diff --git a/hieradata/roles/infra/storage/minio.yaml b/hieradata/roles/infra/storage/minio.yaml new file mode 100644 index 0000000..62505fb --- /dev/null +++ b/hieradata/roles/infra/storage/minio.yaml @@ -0,0 +1,9 @@ +--- +profiles::minio::server::minio_members_role: roles::infra::storage::minio +profiles::minio::server::minio_root_user: admin +profiles::minio::server::minio_opts: + - '--anonymous' +profiles::minio::server::minio_members_lookup: true +profiles::minio::server::version: 'RELEASE.2023-12-20T01-00-02Z' +profiles::minio::server::checksum: '09fafaf399885b4912bafda6fa03fc4ccbc39ec45e17239677217317915d6aeb' +profiles::minio::server::checksum_type: 'sha256' diff --git a/hieradata/roles/infra/storage/vault.eyaml b/hieradata/roles/infra/storage/vault.eyaml new file mode 100644 index 0000000..11fff31 --- /dev/null +++ b/hieradata/roles/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/roles/infra/storage/vault.yaml b/hieradata/roles/infra/storage/vault.yaml new file mode 100644 index 0000000..7d5cc42 --- /dev/null +++ b/hieradata/roles/infra/storage/vault.yaml @@ -0,0 +1,24 @@ +--- +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::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/site/profiles/lib/facter/arpa.rb b/modules/libs/lib/facter/arpa.rb similarity index 100% rename from site/profiles/lib/facter/arpa.rb rename to modules/libs/lib/facter/arpa.rb 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/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/site/profiles/lib/facter/enc_role_path.rb b/modules/libs/lib/facter/enc_role_path.rb similarity index 100% rename from site/profiles/lib/facter/enc_role_path.rb rename to modules/libs/lib/facter/enc_role_path.rb diff --git a/site/profiles/lib/facter/enc_role_tier1.rb b/modules/libs/lib/facter/enc_role_tier1.rb similarity index 100% rename from site/profiles/lib/facter/enc_role_tier1.rb rename to modules/libs/lib/facter/enc_role_tier1.rb diff --git a/site/profiles/lib/facter/enc_role_tier2.rb b/modules/libs/lib/facter/enc_role_tier2.rb similarity index 100% rename from site/profiles/lib/facter/enc_role_tier2.rb rename to modules/libs/lib/facter/enc_role_tier2.rb diff --git a/site/profiles/lib/facter/enc_role_tier3.rb b/modules/libs/lib/facter/enc_role_tier3.rb similarity index 100% rename from site/profiles/lib/facter/enc_role_tier3.rb rename to modules/libs/lib/facter/enc_role_tier3.rb 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/site/profiles/lib/facter/mariadb_active.rb b/modules/libs/lib/facter/mariadb_active.rb similarity index 100% rename from site/profiles/lib/facter/mariadb_active.rb rename to modules/libs/lib/facter/mariadb_active.rb diff --git a/site/profiles/lib/facter/mariadb_datapath.rb b/modules/libs/lib/facter/mariadb_datapath.rb similarity index 100% rename from site/profiles/lib/facter/mariadb_datapath.rb rename to modules/libs/lib/facter/mariadb_datapath.rb diff --git a/site/profiles/lib/facter/mariadb_galera_active.rb b/modules/libs/lib/facter/mariadb_galera_active.rb similarity index 100% rename from site/profiles/lib/facter/mariadb_galera_active.rb rename to modules/libs/lib/facter/mariadb_galera_active.rb diff --git a/site/profiles/lib/facter/mariadb_installed.rb b/modules/libs/lib/facter/mariadb_installed.rb similarity index 100% rename from site/profiles/lib/facter/mariadb_installed.rb rename to modules/libs/lib/facter/mariadb_installed.rb diff --git a/modules/libs/lib/facter/minio_datadirs_initialised.rb b/modules/libs/lib/facter/minio_datadirs_initialised.rb new file mode 100644 index 0000000..17180ab --- /dev/null +++ b/modules/libs/lib/facter/minio_datadirs_initialised.rb @@ -0,0 +1,26 @@ +# frozen_string_literal: true + +# check all datadirs for minio are initialised + +require 'yaml' +Facter.add('minio_datadirs_initialised') do + setcode do + yaml_file_path = '/opt/puppetlabs/facter/facts.d/minio_facts.yaml' + + # check if the YAML file exists first + next false unless File.exist?(yaml_file_path) + + minio_facts = YAML.load_file(yaml_file_path) + dev_count = minio_facts['minio_blockdev_count'] + datadir = minio_facts['minio_datadir'] + + # check datadir if no blockdevices are used, otherwise check the store locations + if dev_count.zero? + Dir.exist?(datadir) + else + (1..dev_count).all? do |number| + Dir.exist?("#{datadir}/store#{number}") + end + end + end +end diff --git a/modules/libs/lib/facter/minio_group_exists.rb b/modules/libs/lib/facter/minio_group_exists.rb new file mode 100644 index 0000000..14c322a --- /dev/null +++ b/modules/libs/lib/facter/minio_group_exists.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true + +# check that the minio group exists + +require 'yaml' +Facter.add('minio_group_exists') do + setcode do + yaml_file_path = '/opt/puppetlabs/facter/facts.d/minio_facts.yaml' + + # check if the YAML file exists first + next false unless File.exist?(yaml_file_path) + + minio_facts = YAML.load_file(yaml_file_path) + group_name = minio_facts['minio_group'] + + group_exists = system("getent group #{group_name} >/dev/null 2>&1") + + group_exists + end +end diff --git a/modules/libs/lib/facter/minio_pool_dns.rb b/modules/libs/lib/facter/minio_pool_dns.rb new file mode 100644 index 0000000..6ccf804 --- /dev/null +++ b/modules/libs/lib/facter/minio_pool_dns.rb @@ -0,0 +1,35 @@ +# frozen_string_literal: true + +require 'facter' +require 'yaml' + +Facter.add('minio_pool_dns') do + setcode do + yaml_file_path = '/opt/puppetlabs/facter/facts.d/minio_facts.yaml' + + # check if the YAML file exists + next {} unless File.exist?(yaml_file_path) + + # load data from YAML + data = YAML.load_file(yaml_file_path) + minio_members = data['minio_members'] + minio_region = data['minio_region'] + minio_pool = data['minio_pool'] + domain = Facter.value(:networking)['domain'] + + # create result hash + result = {} + + # Check CNAME for each node_id from 1 to minio_members + (1..minio_members).each do |node_id| + cname_target = "#{minio_region}-#{minio_pool}-#{node_id}.#{domain}" + command = "host #{cname_target} > /dev/null 2>&1" + + # Using system method to execute the command + # It returns true if the command gives exit status 0 (success), otherwise false + result[cname_target] = system(command) + end + + result + end +end diff --git a/modules/libs/lib/facter/minio_user_exists.rb b/modules/libs/lib/facter/minio_user_exists.rb new file mode 100644 index 0000000..e1b3ef2 --- /dev/null +++ b/modules/libs/lib/facter/minio_user_exists.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true + +# check that the minio user exists + +require 'yaml' +Facter.add('minio_user_exists') do + setcode do + yaml_file_path = '/opt/puppetlabs/facter/facts.d/minio_facts.yaml' + + # check if the YAML file exists first + next false unless File.exist?(yaml_file_path) + + minio_facts = YAML.load_file(yaml_file_path) + user_name = minio_facts['minio_user'] + + user_exists = system("id #{user_name} >/dev/null 2>&1") + + user_exists + end +end diff --git a/site/profiles/lib/facter/mysql_wsrep.rb b/modules/libs/lib/facter/mysql_wsrep.rb similarity index 100% rename from site/profiles/lib/facter/mysql_wsrep.rb rename to modules/libs/lib/facter/mysql_wsrep.rb 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/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 607136b..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::base - 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/datavol.pp b/site/profiles/manifests/base/datavol.pp index 4384bb6..5cb2a12 100644 --- a/site/profiles/manifests/base/datavol.pp +++ b/site/profiles/manifests/base/datavol.pp @@ -11,6 +11,7 @@ # class profiles::base::datavol ( Enum['present', 'absent'] $ensure = 'present', + Enum['present', 'absent', 'mounted'] $mountstate = 'mounted', Enum['ext2', 'ext3', 'ext4', 'xfs', 'btrfs'] $fstype = 'xfs', String $vg = 'datavg', String $pv = '/dev/vdb', @@ -63,7 +64,7 @@ class profiles::base::datavol ( # Ensure the logical volume is mounted at the desired location mount { $mount: - ensure => $ensure, + ensure => $mountstate, device => "/dev/${vg}/${lv}", fstype => $fstype, options => $mount_options.join(','), 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 new file mode 100644 index 0000000..f71c567 --- /dev/null +++ b/site/profiles/manifests/consul/server.pp @@ -0,0 +1,158 @@ +# profiles::consul::server +class profiles::consul::server ( + 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 = [], + Boolean $enable_ui = true, + Boolean $enable_ui_config = true, + Boolean $manage_repo = false, + String $package_ensure = 'latest', + String $package_name = 'consul', + Integer $bootstrap_count = 1, + String $domain = 'consul', + Integer $raft_multiplier = 1, + Enum[ + 'allow', + 'deny', + 'extend-cache', + 'async-cache' + ] $acl_down_policy = 'extend-cache', + Enum[ + 'allow', + 'deny' + ] $acl_default_policy = 'deny', + Enum[ + 'url', + 'package', + 'docker', + 'none' + ] $install_method = 'package', + Stdlib::IP::Address $client_addr = '0.0.0.0', + Stdlib::Absolutepath $data_dir = '/opt/consul', + 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 = [], +) { + + # wait for all attributes to be ready + 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')) + + 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 $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, + 'retry_join_wan' => $remote_servers_array, + }, + } + } + } + # 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) + + # install dnsmasq + package { 'dnsmasq': + ensure => installed, + } + + # create the 10-consul.conf file + file { '/etc/dnsmasq.d/10-consul.conf': + ensure => file, + owner => 'root', + group => 'root', + mode => '0644', + content => "server=/${domain}/${::facts['networking']['ip']}#${dns_port}\n", + require => Package['dnsmasq'], + notify => Service['dnsmasq'], + } + + # ensure dnsmasq service is running and enabled at boot + service { 'dnsmasq': + ensure => running, + enable => true, + subscribe => File['/etc/dnsmasq.d/10-consul.conf'], # Restart dnsmasq if the consul config changes + } + } +} 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 6510453..e22e964 100644 --- a/site/profiles/manifests/dns/base.pp +++ b/site/profiles/manifests/dns/base.pp @@ -3,13 +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 @@ -21,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/helpers/node_lookup.pp b/site/profiles/manifests/helpers/node_lookup.pp index b155f6c..4e6ee01 100644 --- a/site/profiles/manifests/helpers/node_lookup.pp +++ b/site/profiles/manifests/helpers/node_lookup.pp @@ -12,45 +12,54 @@ class profiles::helpers::node_lookup ( Array[String[1]] $packages = ['requests'], ){ - # 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 => $version, - systempkgs => $systempkgs, - venv_dir => $venv_path, - owner => $owner, - group => $group, - require => File[$base_path], - } + if $::facts['python3_version'] { - # install the required pip packages - $packages.each |String $package| { - python::pip { "${venv_path}_${package}": + $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, - pkgname => $package, - virtualenv => $venv_path, + 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 symbolic link in $PATH + file { "/usr/local/bin/${script_name}": + ensure => 'link', + target => "${base_path}/${script_name}", + require => File["${base_path}/${script_name}"], } } - - # 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 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/minio/server.pp b/site/profiles/manifests/minio/server.pp new file mode 100644 index 0000000..3fdec43 --- /dev/null +++ b/site/profiles/manifests/minio/server.pp @@ -0,0 +1,208 @@ +# profiles::minio::server +class profiles::minio::server ( + String $minio_root_user, + String $minio_root_pass, + Array $minio_opts = [], + Boolean $minio_members_lookup = false, + String $minio_members_role = undef, + Integer $minio_members = undef, + Array $minio_servers = [], + String $minio_storage_class = 'EC:2', + String $version = 'RELEASE.2023-12-20T01-00-02Z', + String $checksum = '09fafaf399885b4912bafda6fa03fc4ccbc39ec45e17239677217317915d6aeb', + String $checksum_type = 'sha256', + String $owner = 'minio', + String $group = 'minio', + Stdlib::Fqdn $url_domain = $::facts['networking']['domain'], + Enum['http', 'https'] $url_scheme = 'http', + Array[String[0]] $blockdev = [], + Stdlib::Port $listen_port = 9000, + Stdlib::IP::Address $listen_addr = $::facts['networking']['ip'], + Stdlib::AbsolutePath $datadir = '/data/minio', + Stdlib::AbsolutePath $confdir = '/etc/minio', + Stdlib::AbsolutePath $homedir = '/var/lib/minio', + Stdlib::AbsolutePath $bindir = '/opt/minio', + Optional[Enum['puppet']] $cert_type = 'puppet', +) { + + # create the region string + $minio_region = "${::facts['country']}-${::facts['region']}" + + # count the block devices + $blockdev_count = count($blockdev) + + # create minio static facts, which are used by pre-compile facts + file { "${lookup('facts_path')}/minio_facts.yaml": + ensure => file, + content => template('profiles/minio/minio_facts.yaml.erb'), + } + + # create the user if its not yet initialised, if it is initialised, let the minio::server class manage + # manage the resource. This is done so that the user/group exist before attempting to create the data- + # directories. + if ! $::facts['minio_user_exists'] { + class {'minio::server::user': + manage_user => true, + manage_group => true, + manage_home => true, + owner => $owner, + group => $group, + home => $homedir, + } + } + + # create the datadir + if ! $::facts['minio_datadirs_initialised'] { + + # create the datadir root + exec { "mkdir_p_${datadir}": + command => "mkdir -p '${datadir}'", + unless => "test -d '${datadir}'", + path => '/bin:/usr/bin', + } + + # create te datavol's if blockdev's are listed + $blockdev.each |Integer $index, String $device| { + $id = $index + 1 + profiles::storage::datavol {"${::facts['networking']['fqdn']}_${device}": + fstype => 'xfs', + vg => "minio_vg${id}", + pv => $device, + lv => "store${id}", + owner => $owner, + group => $group, + mount => "${datadir}/store${id}", + require => Exec["mkdir_p_${datadir}"], + } + } + } + + # copy puppet certs to /etc/pki/tls/puppet + include profiles::pki::puppetcerts + + # create the cert configuration hash + if $cert_type == 'puppet' { + $cert_conf = { + 'source_path' => '/etc/pki/tls/puppet', + 'source_cert_name' => $::facts['networking']['fqdn'], + 'source_key_name' => $::facts['networking']['fqdn'], + } + } + + # if lookup is enabled, find all the hosts in the specified role and create the servers_array + if $minio_members_lookup { + + # check that the role is also set + unless !($minio_members_role == undef) { + fail("minio_members_role must be provided for ${title} when minio_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='${minio_members_role}'", 'networking.fqdn')) + $servers_array = sort(query_nodes("enc_role='${minio_members_role}' and minio_region='${minio_region}'", 'networking.fqdn')) + + # else use provided array from params + }else{ + $servers_array = $minio_servers + } + + # iterate through the servers_array and find the nodeid for each host + $servers_array.each |Integer $index, String $server| { + $id = $index + 1 + if $::facts['networking']['fqdn'] == $server { + $nodeid = $id + if $::facts['minio_pool'] != undef { + + # create a cname which is used to create a sequential group of names for distributed minio pool + profiles::dns::record { "${minio_region}-${::facts['minio_pool']}-${nodeid}.${::facts['networking']['domain']}_CNAME": + value => $::facts['networking']['hostname'], + type => 'CNAME', + record => "${minio_region}-${::facts['minio_pool']}-${nodeid}.${::facts['networking']['domain']}.", + zone => $::facts['networking']['domain'], + order => 10, + } + } + } + } + + # wait until all expected servers in the pool have reported into puppet + if count($servers_array) == $::facts['minio_members'] and $::facts['minio_pool'] != undef { + + # if datadirs and user have been initialised, prepare configuration. + if $::facts['minio_datadirs_initialised'] and $::facts['minio_user_exists'] { + + # join the minio_opts + $options = join($minio_opts, ' ') + + # create vars for $deployment_definition, others used below are params + $url_location = "${minio_region}-${::facts['minio_pool']}" + $url_servers = "1...${count($servers_array)}" + + # create the deployment definition line + # >= 1 : https://au-somewhere-1-pool1-{1...5}.example.domain/var/minio/store{1...4} + # == 1 : https://au-somewhere-1-pool1-{1...5}.example.domain/var/minio/store1 + # else : https://au-somewhere-1-pool1-{1...5}.example.domain/var/minio + if $blockdev_count >= 1 { + $deployment_definition = "${url_scheme}://${url_location}-{${url_servers}}.${url_domain}:${listen_port}${datadir}/store{1...${blockdev_count}}" + }elsif $blockdev_count == 1 { + $deployment_definition = "${url_scheme}://${url_location}-{${url_servers}}.${url_domain}:${listen_port}${datadir}/store1" + }else{ + $deployment_definition = "${url_scheme}://${url_location}-{${url_servers}}.${url_domain}:${listen_port}${datadir}" + } + + # create the configuration hash + $configuration = { + 'MINIO_ROOT_USER' => $minio_root_user, + 'MINIO_ROOT_PASSWORD' => $minio_root_pass.unwrap, + 'MINIO_REGION_NAME' => $minio_region, + 'MINIO_OPTS' => "\'${options}\'", + 'MINIO_DEPLOYMENT_DEFINITION' => $deployment_definition, + 'MINIO_STORAGE_CLASS_STANDARD' => $minio_storage_class, + } + } + } + + # check all the expected DNS CNAME records do not exist + $all_dns_exist = $::facts['minio_pool_dns'].all |String $cname, Boolean $exists| { $exists } + + # create the minio server if all dns records exist + if $all_dns_exist { + class { 'minio::server::install': + package_ensure => 'present', + owner => $owner, + group => $group, + base_url => 'https://dl.minio.io/server/minio/release', + version => $version, + checksum => $checksum, + checksum_type => $checksum_type, + configuration_directory => $confdir, + installation_directory => $bindir, + storage_root => $datadir, + listen_ip => $listen_addr, + listen_port => $listen_port, + manage_service => true, + service_template => 'profiles/minio/minio.service.erb', + service_provider => 'systemd', + cert_directory => "${confdir}/certs", + custom_configuration_file_path => '/etc/default/minio', + } + + class { 'minio::server::config': + owner => $owner, + group => $group, + configuration_directory => $confdir, + installation_directory => $bindir, + storage_root => $datadir, + configuration => $configuration, + custom_configuration_file_path => '/etc/default/minio', + require => Class['Minio::Server::Install'], + } + + class { 'minio::server::service': + manage_service => true, + service_provider => 'systemd', + service_ensure => 'running', + require => Class['Minio::Server::Config'], + } + } +} 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/packages.pp b/site/profiles/manifests/packages.pp new file mode 100644 index 0000000..ca43908 --- /dev/null +++ b/site/profiles/manifests/packages.pp @@ -0,0 +1,23 @@ +# This class manages the installation of packages for the base profile +# +# Parameters: +# - $install: An array of package names to be installed +# - $remove: An array of package names to be removed +# +class profiles::packages ( + Array $install = [], + Array $install_exclude = [], + Array $remove = [], + Array $remove_exclude = [], +) { + + # Filter out excluded packages + $install_real = $install.filter |$item| { !$install_exclude.any |$exclude_item| { $exclude_item == $item } } + $remove_real = $remove.filter |$item| { !$remove_exclude.any |$exclude_item| { $exclude_item == $item } } + + # Ensure packages to install are installed + ensure_packages($install_real, {'ensure' => 'present'}) + + # Ensure packages to remove are absent + ensure_packages($remove_real, {'ensure' => 'absent'}) +} diff --git a/site/profiles/manifests/packages/base.pp b/site/profiles/manifests/packages/base.pp deleted file mode 100644 index f7d51cf..0000000 --- a/site/profiles/manifests/packages/base.pp +++ /dev/null @@ -1,21 +0,0 @@ -# This class manages the installation of packages for the base profile -# -# Parameters: -# - $add: An array of package names to be installed -# - $remove: An array of package names to be removed -# -class profiles::packages::base ( - Array $add = [], - Array $remove = [], -) { - - # Ensure packages to add are installed - ensure_packages($add, {'ensure' => 'present'}) - - # Ensure packages to remove are absent - $remove.each |String $package| { - package { $package: - ensure => 'absent', - } - } -} diff --git a/site/profiles/manifests/packages/git.pp b/site/profiles/manifests/packages/git.pp deleted file mode 100644 index 578aca7..0000000 --- a/site/profiles/manifests/packages/git.pp +++ /dev/null @@ -1,11 +0,0 @@ -# installs git related packages -# -class profiles::packages::git ( - Array[String] $packages = lookup('profiles::packages::git', Array, 'first', ['git']), -) { - $packages.each |String $package| { - package { $package: - ensure => installed, - } - } -} diff --git a/site/profiles/manifests/packages/reposync.pp b/site/profiles/manifests/packages/reposync.pp deleted file mode 100644 index f6525a5..0000000 --- a/site/profiles/manifests/packages/reposync.pp +++ /dev/null @@ -1,11 +0,0 @@ -# installs reposync related packages -# -class profiles::packages::reposync ( - Array[String] $packages = lookup('profiles::packages::reposync', Array, 'first', ['createrepo']), -) { - $packages.each |String $package| { - package { $package: - ensure => installed, - } - } -} diff --git a/site/profiles/manifests/packages/selinux.pp b/site/profiles/manifests/packages/selinux.pp deleted file mode 100644 index 1bbd457..0000000 --- a/site/profiles/manifests/packages/selinux.pp +++ /dev/null @@ -1,11 +0,0 @@ -# installs selinux related packages -# -class profiles::packages::selinux ( - Array[String] $packages = lookup('profiles::packages::selinux', Array, 'first', ['policycoreutils']), -) { - $packages.each |String $package| { - package { $package: - ensure => installed, - } - } -} diff --git a/site/profiles/manifests/pki/puppetcerts.pp b/site/profiles/manifests/pki/puppetcerts.pp new file mode 100644 index 0000000..bf02ecd --- /dev/null +++ b/site/profiles/manifests/pki/puppetcerts.pp @@ -0,0 +1,42 @@ +# profiles::pki::puppetcerts +class profiles::pki::puppetcerts { + + # Define the directory + file { '/etc/pki/tls/puppet': + ensure => 'directory', + owner => 'root', + group => 'root', + mode => '0755', + } + + # Copy the CA certificate + file { '/etc/pki/tls/puppet/ca.pem': + ensure => 'file', + owner => 'root', + group => 'root', + mode => '0644', + source => '/etc/puppetlabs/puppet/ssl/certs/ca.pem', + require => File['/etc/pki/tls/puppet'], + } + + # Copy the private key + file { "/etc/pki/tls/puppet/${facts['networking']['fqdn']}.key": + ensure => 'file', + owner => 'root', + group => 'root', + mode => '0644', + source => "/etc/puppetlabs/puppet/ssl/private_keys/${facts['networking']['fqdn']}.pem", + require => File['/etc/pki/tls/puppet'], + } + + # Copy the certificate + $cert = "/etc/puppetlabs/puppet/ssl/certs/${facts['networking']['fqdn']}.pem" + file { "/etc/pki/tls/puppet/${facts['networking']['fqdn']}.crt": + ensure => 'file', + owner => 'root', + group => 'root', + mode => '0644', + source => "/etc/puppetlabs/puppet/ssl/certs/${facts['networking']['fqdn']}.pem", + require => File['/etc/pki/tls/puppet'], + } +} 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 dad9d11..fcfeec7 100644 --- a/site/profiles/manifests/puppet/enc.pp +++ b/site/profiles/manifests/puppet/enc.pp @@ -4,43 +4,12 @@ # 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', Boolean $force = false, ) { - include profiles::packages::git - vcsrepo { '/opt/puppetlabs/enc': ensure => latest, provider => git, 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 617190b..3a2af5e 100644 --- a/site/profiles/manifests/puppet/g10k.pp +++ b/site/profiles/manifests/puppet/g10k.pp @@ -5,40 +5,12 @@ # 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, String $environments_path, String $default_environment, ){ - package { 'unzip': - ensure => installed, - } archive { '/tmp/g10k.zip': ensure => present, @@ -47,6 +19,7 @@ class profiles::puppet::g10k ( extract_path => '/opt/puppetlabs/bin', creates => '/opt/puppetlabs/bin/g10k', cleanup => true, + require => Package['unzip'] } file { '/opt/puppetlabs/bin/puppet-g10k': diff --git a/site/profiles/manifests/puppet/gems.pp b/site/profiles/manifests/puppet/gems.pp new file mode 100644 index 0000000..b7a9369 --- /dev/null +++ b/site/profiles/manifests/puppet/gems.pp @@ -0,0 +1,12 @@ +# profiles::puppet::gems +class profiles::puppet::gems ( + Array $puppet = [], +){ + # install puppetmaster gems + $puppet.each | $pgem | { + package { $pgem: + ensure => installed, + provider => 'puppet_gem', + } + } +} diff --git a/site/profiles/manifests/puppet/puppetboard.pp b/site/profiles/manifests/puppet/puppetboard.pp index 0085eb5..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', @@ -120,4 +123,39 @@ class profiles::puppet::puppetboard ( server => $nginx_vhost, 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' { + + # 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 9819d5e..6ce7ca5 100644 --- a/site/profiles/manifests/puppet/puppetmaster.pp +++ b/site/profiles/manifests/puppet/puppetmaster.pp @@ -2,63 +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 - 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 402f49a..e366953 100644 --- a/site/profiles/manifests/puppet/r10k.pp +++ b/site/profiles/manifests/puppet/r10k.pp @@ -4,41 +4,10 @@ # 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, ){ - include profiles::packages::git - vcsrepo { '/etc/puppetlabs/r10k': ensure => latest, provider => git, diff --git a/site/profiles/manifests/puppet/server.pp b/site/profiles/manifests/puppet/server.pp index 7f0aec5..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, @@ -66,4 +70,3 @@ class profiles::puppet::server ( hasrestart => true, } } - diff --git a/site/profiles/manifests/reposync/autosyncer.pp b/site/profiles/manifests/reposync/autosyncer.pp index 04393cd..5271ec2 100644 --- a/site/profiles/manifests/reposync/autosyncer.pp +++ b/site/profiles/manifests/reposync/autosyncer.pp @@ -10,7 +10,7 @@ class profiles::reposync::autosyncer ( group => 'root', mode => '0755', content => template('profiles/reposync/autosyncer.erb'), - require => Class['profiles::packages::reposync'], + require => Package['createrepo'], } # daily autosyncr service/timer 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/syncer.pp b/site/profiles/manifests/reposync/syncer.pp index 6f20996..3be81d8 100644 --- a/site/profiles/manifests/reposync/syncer.pp +++ b/site/profiles/manifests/reposync/syncer.pp @@ -1,7 +1,6 @@ # setup a reposync syncer class profiles::reposync::syncer { - include profiles::packages::reposync include profiles::reposync::autosyncer include profiles::reposync::autopromoter include profiles::reposync::webserver @@ -14,10 +13,13 @@ class profiles::reposync::syncer { mode => '0755', } file { '/etc/reposync/conf.d': - ensure => directory, - owner => 'root', - group => 'root', - mode => '0755', + ensure => directory, + owner => 'root', + group => 'root', + mode => '0755', + purge => true, + recurse => true, + force => true, } # get a list of repos as a hash, and iterate through them diff --git a/site/profiles/manifests/reposync/webserver.pp b/site/profiles/manifests/reposync/webserver.pp index 9321db1..b75782d 100644 --- a/site/profiles/manifests/reposync/webserver.pp +++ b/site/profiles/manifests/reposync/webserver.pp @@ -1,23 +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, - Boolean $selinux = 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 { @@ -39,10 +136,7 @@ class profiles::reposync::webserver ( order => 10, } - if $selinux { - - # include packages that are required - include profiles::packages::selinux + if $::facts['os']['selinux']['config_mode'] == 'enforcing' { # set httpd_sys_content_t to all files under the www_root selinux::fcontext { $www_root: @@ -51,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, @@ -63,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/selinux/mysqld.pp b/site/profiles/manifests/selinux/mysqld.pp index 2c31e82..8a5d3b0 100644 --- a/site/profiles/manifests/selinux/mysqld.pp +++ b/site/profiles/manifests/selinux/mysqld.pp @@ -7,8 +7,6 @@ class profiles::selinux::mysqld ( Boolean $selinuxuser_mysql_connect_enabled = true, String $selinux_mode = 'enforcing', ){ - # include packages that are required - include profiles::packages::selinux # setenforce class { 'profiles::selinux::setenforce': diff --git a/site/profiles/manifests/selinux/nginx.pp b/site/profiles/manifests/selinux/nginx.pp new file mode 100644 index 0000000..25d47f6 --- /dev/null +++ b/site/profiles/manifests/selinux/nginx.pp @@ -0,0 +1,20 @@ +# profiles::selinux::nginx +# selinux settings for nginx +class profiles::selinux::nginx ( + Boolean $persistent = true, + Boolean $httpd_can_network_connect = true, + String $selinux_mode = 'enforcing', +){ + + # setenforce + class { 'profiles::selinux::setenforce': + mode => $selinux_mode, + } + + # make sure we can connect to network resources + selboolean { 'httpd_can_network_connect': + persistent => $persistent, + value => $httpd_can_network_connect, + } +} + diff --git a/site/profiles/manifests/selinux/setenforce.pp b/site/profiles/manifests/selinux/setenforce.pp index fa2c753..309ea71 100644 --- a/site/profiles/manifests/selinux/setenforce.pp +++ b/site/profiles/manifests/selinux/setenforce.pp @@ -3,7 +3,8 @@ class profiles::selinux::setenforce ( Enum['enforcing', 'permissive', 'disabled'] $mode = 'enforcing', ) { class { 'selinux': - mode => $mode, + mode => $mode, + require => Package['policycoreutils'] } } diff --git a/site/profiles/manifests/sql/galera_member.pp b/site/profiles/manifests/sql/galera_member.pp index d79c28a..24fab57 100644 --- a/site/profiles/manifests/sql/galera_member.pp +++ b/site/profiles/manifests/sql/galera_member.pp @@ -30,7 +30,6 @@ class profiles::sql::galera_member ( Boolean $package_manage = true, String $package_name = 'mariadb-server', Boolean $epel_needed = false, - Boolean $selinux = true, Boolean $manage_repo = true, ) { @@ -48,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{ @@ -59,10 +58,10 @@ class profiles::sql::galera_member ( if length($servers_array) >= 3 { # if selinux is defined, manage it - if $selinux { + if $::facts['os']['selinux']['config_mode'] == 'enforcing' { # set permissive on first run, as we need mariadb installed/started at a custom path before adding fcontext - if $::facts['mariadb_acti'] { $selinux_mode = 'enforcing' }else{ $selinux_mode = 'permissive' } + if $::facts['mariadb_active'] { $selinux_mode = 'enforcing' }else{ $selinux_mode = 'permissive' } # call the mysqld selinux class class { 'profiles::selinux::mysqld': @@ -104,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 = { @@ -212,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/storage/datavol.pp b/site/profiles/manifests/storage/datavol.pp new file mode 100644 index 0000000..ecc9a9d --- /dev/null +++ b/site/profiles/manifests/storage/datavol.pp @@ -0,0 +1,75 @@ +# profiles::storage::datavol +# +# This define manages the creation of a logical volume using the `lvm::volume` definition. +# +# Parameters: +# $ensure - Ensure whether the logical volume is present or not. Defaults to 'present'. +# $vg - Volume group name. No default. +# $pv - Physical volume, typically the disk or partition device path. No default. +# $fstype - Filesystem type for the logical volume. Defaults to 'ext3'. +# $size - Size of the logical volume. undef = 100%FREE. Changing $size to cause a resize. +# +define profiles::storage::datavol ( + Enum['present', 'absent'] $ensure = 'present', + Enum['ext2', 'ext3', 'ext4', 'xfs', 'btrfs'] $fstype = 'xfs', + String $vg = 'datavg', + String $pv = '/dev/vdb', + String $lv = 'data', + String $owner = 'root', + String $group = 'root', + Stdlib::Filemode $mode = '0755', + Stdlib::Absolutepath $mount = '/data', + Optional[Variant[Pattern[/^\d+(M|G|T|P)$/], Integer]] $size = undef, + Array[Enum[ + 'defaults', 'ro', 'rw', 'sync', 'async', + 'noatime', 'nodiratime', 'noexec', 'nosuid', + 'nodev', 'remount', 'auto', 'noauto' + ]] $mount_options = ['noatime', 'nodiratime'], +) { + + # Ensure the physical volume exists + physical_volume { $pv: + ensure => $ensure, + before => Volume_group[$vg], + } + + # Ensure the volume group exists + volume_group { $vg: + ensure => $ensure, + physical_volumes => [$pv], + before => Logical_volume[$lv], + } + + # Ensure the logical volume exists + logical_volume { $lv: + ensure => $ensure, + volume_group => $vg, + size => $size, + before => Filesystem["/dev/${vg}/${lv}"], + } + + # Ensure the filesystem is created on the logical volume + filesystem { "/dev/${vg}/${lv}": + ensure => $ensure, + fs_type => $fstype, + require => Logical_volume[$lv], + before => Mount[$mount], + } + + # Ensure the mountpath exists + file { $mount: + ensure => directory, + owner => $owner, + group => $group, + mode => $mode, + } + + # Ensure the logical volume is mounted at the desired location + mount { $mount: + ensure => $ensure, + device => "/dev/${vg}/${lv}", + fstype => $fstype, + options => $mount_options.join(','), + require => Filesystem["/dev/${vg}/${lv}"], + } +} diff --git a/site/profiles/manifests/vault/server.pp b/site/profiles/manifests/vault/server.pp new file mode 100644 index 0000000..d07e8ba --- /dev/null +++ b/site/profiles/manifests/vault/server.pp @@ -0,0 +1,92 @@ +# profiles::vault::server +class profiles::vault::server ( + Boolean $members_lookup = false, + Variant[ + String, + Undef + ] $members_role = undef, + Array $vault_servers = [], + Enum[ + 'archive', + 'repo' + ] $install_method = 'archive', + Boolean $tls_disable = false, + Stdlib::Port $client_port = 8200, + Stdlib::Port $cluster_port = 8201, + Boolean $manage_storage_dir = false, + Stdlib::Absolutepath $data_dir = '/opt/vault', + Stdlib::Absolutepath $bin_dir = '/usr/bin', +){ + + # 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 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')) + + # else use provided array from params + }else{ + $servers_array = $vault_servers + } + + # configure vault if servers_array isnt empty + if ! $servers_array.empty() { + + # set http scheme + $http_scheme = $tls_disable ? { + true => 'http', + false => 'https' + } + + # create vault urls + $server_urls = $servers_array.map |$fqdn| { + { + 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, + } + }, + 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 new file mode 100644 index 0000000..cff32a1 --- /dev/null +++ b/site/profiles/manifests/vault/unseal.pp @@ -0,0 +1,37 @@ +# profiles::vault::unseal +class profiles::vault::unseal ( + Array[String] $unseal_keys = lookup('vault::unseal_keys', Array[String], 'first', []), + Variant[ + Stdlib::HTTPSUrl, + Stdlib::HTTPUrl + ] $vault_address = 'http://127.0.0.1:8200', +){ + + # deploy the unseal keys file + file { '/etc/vault/unseal_keys': + ensure => file, + owner => 'root', + group => 'root', + mode => '0600', + content => Sensitive(template('profiles/vault/unseal_keys.erb')), + require => Class['vault'], + } + + # deploy the unseal script + file { '/usr/local/bin/vault-unseal.sh': + ensure => file, + owner => 'root', + group => 'root', + mode => '0750', + content => template('profiles/vault/vault_unseal.sh.erb'), + } + + # create systemd service unit + systemd::unit_file { 'vault-unseal.service': + content => template('profiles/vault/vault-unseal.service.erb'), + active => true, + enable => true, + require => File['/usr/local/bin/vault-unseal.sh'], + 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 119230e..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,39 +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, + # 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/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/base/scripts/puppetwrapper.py.erb b/site/profiles/templates/base/scripts/puppetwrapper.py.erb index 57ca8b1..809fd71 100644 --- a/site/profiles/templates/base/scripts/puppetwrapper.py.erb +++ b/site/profiles/templates/base/scripts/puppetwrapper.py.erb @@ -11,7 +11,7 @@ def main(): if index + 1 < len(args): # Check if there's another argument after "-E" environment_value = args[index + 1] # Replace \ and - with _ - modified_environment_value = environment_value.replace("\\", "_").replace("-", "_").replace("/","_") + modified_environment_value = environment_value.replace("\\", "_").replace("-", "_").replace("/","_").replace(".","_") args[index + 1] = modified_environment_value # Construct the full puppet command with the modified args 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/minio/minio.service.erb b/site/profiles/templates/minio/minio.service.erb new file mode 100644 index 0000000..efaddbe --- /dev/null +++ b/site/profiles/templates/minio/minio.service.erb @@ -0,0 +1,38 @@ +[Unit] +Description=Minio +Documentation=https://docs.minio.io +Wants=network-online.target +After=network-online.target +After=syslog.target network.target +AssertFileIsExecutable=<%= @installation_directory %>/minio + +[Service] +WorkingDirectory=<%= @installation_directory %> + +User=<%= @owner %> +Group=<%= @group %> + +PermissionsStartOnly=true + +EnvironmentFile=<%= @configuration_file_path %> +ExecStart=<%= @installation_directory %>/minio server $MINIO_OPTS --address <%= @listen_ip %>:<%= @listen_port %> $MINIO_DEPLOYMENT_DEFINITION + +StandardOutput=journal +StandardError=inherit + +# Specifies the maximum file descriptor number that can be opened by this process +LimitNOFILE=65536 + +# Disable timeout logic and wait until process is stopped +TimeoutStopSec=0 + +# SIGTERM signal is used to stop Minio +KillSignal=SIGTERM + +SendSIGKILL=no + +SuccessExitStatus=0 + +[Install] +WantedBy=multi-user.target + diff --git a/site/profiles/templates/minio/minio_facts.yaml.erb b/site/profiles/templates/minio/minio_facts.yaml.erb new file mode 100644 index 0000000..bc205b0 --- /dev/null +++ b/site/profiles/templates/minio/minio_facts.yaml.erb @@ -0,0 +1,17 @@ +# minio_facts.yaml +minio_user: '<%= @owner %>' +minio_group: '<%= @group %>' +minio_pool: '<%= @minio_pool %>' +minio_datadir: '<%= @datadir %>' +minio_confdir: '<%= @confdir %>' +minio_homedir: '<%= @homedir %>' +minio_bindir: '<%= @bindir %>' +minio_region: '<%= @minio_region %>' +minio_members: <%= @minio_members %> +minio_blockdev_count: <%= @blockdev_count %> +<% unless @blockdev.empty? -%> +minio_blockdevs: +<% @blockdev.each do |device| -%> + - '<%= device %>' +<% end -%> +<% end -%> 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 cd6c963..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" } } @@ -89,6 +89,6 @@ for conf in /etc/reposync/conf.d/*.conf; do create_repo_metadata "${snap_path}" # Update selinux - restorecon <%= @basepath %> + restorecon -R ${snap_path} done diff --git a/site/profiles/templates/vault/unseal_keys.erb b/site/profiles/templates/vault/unseal_keys.erb new file mode 100644 index 0000000..0ee4751 --- /dev/null +++ b/site/profiles/templates/vault/unseal_keys.erb @@ -0,0 +1,3 @@ +<% @unseal_keys.each do |key| -%> +<%= key %> +<% end -%> diff --git a/site/profiles/templates/vault/vault-unseal.service.erb b/site/profiles/templates/vault/vault-unseal.service.erb new file mode 100644 index 0000000..83b0e1a --- /dev/null +++ b/site/profiles/templates/vault/vault-unseal.service.erb @@ -0,0 +1,14 @@ +[Unit] +Description=Unseal Vault Service +After=vault.service network.target +Requires=vault.service +PartOf=vault.service + +[Service] +Type=oneshot +ExecStart=/usr/local/bin/vault-unseal.sh +RemainAfterExit=yes +User=root + +[Install] +WantedBy=multi-user.target diff --git a/site/profiles/templates/vault/vault_unseal.sh.erb b/site/profiles/templates/vault/vault_unseal.sh.erb new file mode 100644 index 0000000..5e4d5aa --- /dev/null +++ b/site/profiles/templates/vault/vault_unseal.sh.erb @@ -0,0 +1,23 @@ +#!/bin/bash + +# Script to unseal Vault + +VAULT_ADDR='<%= @vault_address %>' +UNSEAL_KEYS_FILE='/etc/vault/unseal_keys' + +# Check if Vault is sealed +is_sealed=$(curl -s ${VAULT_ADDR}/v1/sys/seal-status | jq -r '.sealed') +if [ "$is_sealed" != "true" ]; then + echo "Vault is already unsealed." + exit 0 +fi + +# Retrieve unseal keys from plaintext file +unseal_keys=$(cat "$UNSEAL_KEYS_FILE") + +# Loop through the unseal keys and use them to unseal Vault +for key in $unseal_keys; do + curl --request PUT --data '{"key": "'$key'"}' $VAULT_ADDR/v1/sys/unseal +done + +echo "Vault has been unsealed." 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 new file mode 100644 index 0000000..87a2d41 --- /dev/null +++ b/site/roles/manifests/infra/halb/haproxy.pp @@ -0,0 +1,11 @@ +# a role to deploy a haproxy node +class roles::infra::halb::haproxy { + 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 4d9176a..a73d7a5 100644 --- a/site/roles/manifests/infra/metrics/grafana.pp +++ b/site/roles/manifests/infra/metrics/grafana.pp @@ -1,6 +1,11 @@ # a role to deploy a grafana service class roles::infra::metrics::grafana { - include profiles::defaults - include profiles::base - include profiles::metrics::grafana + if $facts['firstrun'] { + include profiles::defaults + include profiles::firstrun::init + }else{ + include profiles::defaults + include profiles::base + include profiles::metrics::grafana + } } 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 new file mode 100644 index 0000000..143b167 --- /dev/null +++ b/site/roles/manifests/infra/storage/consul.pp @@ -0,0 +1,12 @@ +# a role to deploy a consul node +class roles::infra::storage::consul { + 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 new file mode 100644 index 0000000..d436e8e --- /dev/null +++ b/site/roles/manifests/infra/storage/minio.pp @@ -0,0 +1,11 @@ +# a role to deploy a minio node +class roles::infra::storage::minio { + 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 new file mode 100644 index 0000000..9e11b14 --- /dev/null +++ b/site/roles/manifests/infra/storage/vault.pp @@ -0,0 +1,12 @@ +# a role to deploy a vault node +class roles::infra::storage::vault { + 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 + } +}