Skip to content
1 change: 0 additions & 1 deletion aws/infrastructure.tf
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ module "configuration" {
cloud_provider = local.cloud_provider
cloud_region = local.cloud_region
skip_upgrade = var.skip_upgrade
puppetfile = var.puppetfile
}

module "provision" {
Expand Down
1 change: 0 additions & 1 deletion azure/infrastructure.tf
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ module "configuration" {
cloud_provider = local.cloud_provider
cloud_region = local.cloud_region
skip_upgrade = var.skip_upgrade
puppetfile = var.puppetfile
}

module "provision" {
Expand Down
5 changes: 3 additions & 2 deletions common/configuration/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ variable "guest_passwd" {}
variable "public_keys" {}

variable "skip_upgrade" {}
variable "puppetfile" {}
variable "bastion_tags" {}

resource "tls_private_key" "ssh" {
Expand Down Expand Up @@ -84,6 +83,7 @@ locals {
domain_name = var.domain_name
guest_passwd = local.guest_passwd
nb_users = var.nb_users
bastion_tags = var.bastion_tags
}
}
})
Expand Down Expand Up @@ -112,7 +112,8 @@ locals {
tf_ssh_public_key = chomp(tls_private_key.ssh.public_key_openssh)
terraform_facts = local.terraform_facts
skip_upgrade = var.skip_upgrade
puppetfile = var.puppetfile
module_path = path.module
user_tf_required = contains(values.tags, "puppet") || length(setintersection(values.tags, var.bastion_tags)) > 0
hostkeys = {
rsa = {
private = chomp(tls_private_key.rsa[values.prefix].private_key_openssh)
Expand Down
120 changes: 44 additions & 76 deletions common/configuration/puppet.yaml.tftpl
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ mounts:
- [ ephemeral0, /mnt/ephemeral0, auto, "defaults,nofail" ]

users:
%{ if contains(tags, "puppet") || length(setintersection(tags, bastion_tags)) > 0 ~}
%{ if user_tf_required ~}
- name: tf
system: true
passwd: '*'
no_user_group: true
homedir: /tmp
%{ if contains(tags, "puppet") }
%{ if contains(tags, "puppet") ~}
sudo: "ALL = NOPASSWD: /usr/sbin/update_etc_puppetlabs.sh *.zip"
%{ endif ~}
%{ endif ~}
Expand All @@ -21,10 +21,10 @@ users:
passwd: '*'
homedir: /${sudoer_username}
sudo: ALL=(ALL) NOPASSWD:ALL
%{ if cloud_provider != "incus" }
%{ if cloud_provider != "incus" ~}
# most container images do not have selinux pre-installed
selinux_user: unconfined_u
%{ endif }
%{ endif ~}
ssh_authorized_keys:
%{ for key in ssh_authorized_keys ~}
- ${key}
Expand All @@ -35,18 +35,10 @@ runcmd:
- trap 'flag_cloud_init_failed' ERR
- chmod 755 /etc # avoid issue with Rocky 9.4
- test ! -d /${sudoer_username} && userdel -f -r ${sudoer_username} && cloud-init clean -r
%{ if cloud_provider != "incus" }
# most container images do not have selinux pre-installed
%{ if cloud_provider != "incus" ~}
# most container images do not have selinux pre-installed
- restorecon -R /${sudoer_username}
%{ endif }
# Make sure puppet server can be reached by name early in the process if we need to debug.
# For some provider, the ip address of the puppetserver is not known in advance, so we make
# sure it is not empty before adding it to /etc/hosts
%{ for host, ip in puppetservers ~}
%{ if ip != "" ~}
- echo "${ip} ${host}" >> /etc/hosts
%{ endif ~}
%{ endfor ~}
# Install package and configure kernel only if building from a "vanilla" linux image
- |
if ! test -f /etc/magic-castle-release; then
Expand Down Expand Up @@ -84,9 +76,16 @@ runcmd:
systemctl disable kdump
grubby --update-kernel=ALL --args="rd.driver.blacklist=nouveau nouveau.modeset=0 crashkernel=0M initcall_blacklist=algif_aead_init"
grub2-mkconfig -o /boot/grub2/grub.cfg
%{ endif ~}
%{ if cloud_provider == "gcp" ~}
# Google Cloud user-data fact generates a warning because its size is greater than what is allowed (<4096 bytes).
# We have no use for it, so we remove startup-script, user-data and user-data-encoding when running in GCE.
sed -i "/gce_data\['instance'\] = instance_data/i \ \ \ \ \ \ \ \ \ \ instance_data['attributes'].delete('startup-script')" /opt/puppetlabs/puppet/lib/ruby/vendor_ruby/facter/resolvers/gce.rb
sed -i "/gce_data\['instance'\] = instance_data/i \ \ \ \ \ \ \ \ \ \ instance_data['attributes'].delete('user-data')" /opt/puppetlabs/puppet/lib/ruby/vendor_ruby/facter/resolvers/gce.rb
sed -i "/gce_data\['instance'\] = instance_data/i \ \ \ \ \ \ \ \ \ \ instance_data['attributes'].delete('user-data-encoding')" /opt/puppetlabs/puppet/lib/ruby/vendor_ruby/facter/resolvers/gce.rb
%{ endif ~}
fi
%{ if contains(tags, "puppet") }
%{ if contains(tags, "puppet") ~}
# Install puppetserver
- dnf -y install openvox-server-8.11.0
# Configure puppet-agent to start after puppetserver when on puppetserver
Expand Down Expand Up @@ -127,20 +126,13 @@ runcmd:
- ln -sf /etc/puppetlabs/facts/terraform_facts.yaml /etc/puppetlabs/code/environments/production/site/profile/facts.d
# We use r10k solely to install the modules of the production puppet environment.
- /opt/puppetlabs/puppet/bin/r10k puppetfile install --moduledir=/etc/puppetlabs/code/environments/production/modules --puppetfile=/etc/puppetlabs/code/environments/production/Puppetfile
%{ if puppetfile != "" ~}
- /opt/puppetlabs/puppet/bin/r10k puppetfile install --moduledir=/etc/puppetlabs/code/modules --puppetfile=/etc/puppetlabs/code/Puppetfile
%{ endif ~}
# Backport stdlib patch to support Puppet 8 json parsing until we update to stdlib >= 8.5.0
# Patch origin: https://github.com/puppetlabs/puppetlabs-stdlib/commit/53a8ccf869aa49de7a77c8a35d89dd5aac8fa52d.patch
- sed -i -e 's/PSON/Puppet::Util::Json/' -e "/module Puppet/i require 'puppet/util/json'" /etc/puppetlabs/code/environments/production/modules/stdlib/lib/puppet/parser/functions/parsejson.rb
# Wait for Terraform to scp its YAML data
- while [ ! -e "/etc/puppetlabs/data/terraform_data.yaml" ]; do echo "$(date -I'seconds') Waiting for terraform to scp terraform_data.yaml"; sleep 5; done
%{ if node_name != keys(puppetservers)[0] }
- test -f /etc/puppetlabs/code/Puppetfile && /opt/puppetlabs/puppet/bin/r10k puppetfile install --moduledir=/etc/puppetlabs/code/modules --puppetfile=/etc/puppetlabs/code/Puppetfile
%{ if node_name != keys(puppetservers)[0] ~}
- sed -e '/certificate-authority-service/ s/^/#/' -i /etc/puppetlabs/puppetserver/services.d/ca.cfg
- sed -e '/certificate-authority-disabled-service/ s/^#//' -i /etc/puppetlabs/puppetserver/services.d/ca.cfg
%{ endif }
%{ endif ~}
- chgrp puppet /etc/puppetlabs/puppet/csr_attributes.yaml
%{ endif }
%{ endif ~}
%{ if length(puppetservers) > 0 ~}
- /opt/puppetlabs/bin/puppet config set server ${keys(puppetservers)[0]}
%{ endif ~}
Expand All @@ -151,41 +143,44 @@ runcmd:
- systemctl enable puppet
# Remove all ifcfg configuration files that have no corresponding network interface in ip link show.
- for i in /etc/sysconfig/network-scripts/ifcfg-*; do if ! ip link show | grep -q "$${i##*-}:"; then rm -f $i; fi; done
%{ if cloud_provider == "gcp" }
# Google Cloud user-data fact generates a warning because its size is greater than what is allowed (<4096 bytes).
# We have no use for it, so we remove startup-script, user-data and user-data-encoding when running in GCE.
- sed -i "/gce_data\['instance'\] = instance_data/i \ \ \ \ \ \ \ \ \ \ instance_data['attributes'].delete('startup-script')" /opt/puppetlabs/puppet/lib/ruby/vendor_ruby/facter/resolvers/gce.rb
- sed -i "/gce_data\['instance'\] = instance_data/i \ \ \ \ \ \ \ \ \ \ instance_data['attributes'].delete('user-data')" /opt/puppetlabs/puppet/lib/ruby/vendor_ruby/facter/resolvers/gce.rb
- sed -i "/gce_data\['instance'\] = instance_data/i \ \ \ \ \ \ \ \ \ \ instance_data['attributes'].delete('user-data-encoding')" /opt/puppetlabs/puppet/lib/ruby/vendor_ruby/facter/resolvers/gce.rb
%{ endif }
%{ if contains(tags, "puppet") }
%{ if contains(tags, "puppet") ~}
# Wait for Terraform to scp its YAML data
- while [ ! -e "/etc/puppetlabs/data/terraform_data.yaml" ]; do echo "$(date -I'seconds') Waiting for terraform to scp terraform_data.yaml"; sleep 5; done
# Bootstrap services that are essential to the puppet repo
- (cd /etc/puppetlabs/code/environments/production; test -e bootstrap.sh && ./bootstrap.sh)
%{ endif }
%{ endif ~}
# If the current image has already been configured with Magic Castle Puppet environment,
# we can start puppet and skip reboot, reducing the delay for bringing the node up.
- test -f /etc/magic-castle-release && systemctl start puppet || true
- test -f /run/cloud-init-failed && echo 'WARNING - some steps cloud-init runcmd failed, listed in /run/cloud-init-failed. Manual fixing and rebooting required. ' | tee /etc/motd || true

write_files:
%{ if contains(tags, "puppet") || length(setintersection(tags, bastion_tags)) > 0 ~}
- content: |
%{ for host, ip in puppetservers ~}
%{ if ip != "" ~}
${ip} ${host}
%{ endif ~}
%{ endfor ~}
path: /etc/hosts
append: true
%{ if user_tf_required ~}
- path: /etc/ssh/sshd_config.d/50-authenticationmethods.conf
permissions: "0600"
content: |
Match User tf
AuthorizedKeysFile /etc/ssh/authorized_keys.%u
AuthenticationMethods publickey
path: /etc/ssh/sshd_config.d/50-authenticationmethods.conf
permissions: "0600"
%{ endif ~}
%{ if contains(tags, "puppet") ~}
- content: restrict,pty ${tf_ssh_public_key}
path: /etc/ssh/authorized_keys.tf
- path: /etc/ssh/authorized_keys.tf
permissions: "0644"
content: |
%{ if contains(tags, "puppet") ~}
restrict,pty ${tf_ssh_public_key}
%{ else ~}
%{ if length(setintersection(tags, bastion_tags)) > 0 ~}
# If the ip addresses of the puppet servers are not known in advance, we cannot restrict the ssh connection to them.
- content: restrict,%{if length(compact(values(puppetservers))) == length(keys(puppetservers)) }%{ for host, ip in puppetservers }permitopen="${ip}:22"%{ endfor }%{ else }pty%{ endif },port-forwarding,command="/sbin/nologin" ${tf_ssh_public_key}
path: /etc/ssh/authorized_keys.tf
permissions: "0644"
%{ if length(compact(values(puppetservers))) != length(keys(puppetservers)) ~}
restrict,pty,port-forwarding,command="/sbin/nologin" ${tf_ssh_public_key}
%{ else ~}
restrict,%{ for host, ip in puppetservers }permitopen="${ip}:22",%{ endfor }port-forwarding,command="/sbin/nologin" ${tf_ssh_public_key}
%{ endif ~}
%{ endif ~}
%{ endif ~}
- content: |
Expand All @@ -207,29 +202,8 @@ write_files:
path: /etc/puppetlabs/facter/facts.d/prefix.yaml
permissions: "0644"
%{ if contains(tags, "puppet") ~}
- content: |
#!/bin/bash
ZIP_FILE=$${1}
ZIP_DIR=$${ZIP_FILE%.zip}

# unzip is not necessarily installed when connecting, but python is.
/usr/libexec/platform-python -c "import zipfile; zipfile.ZipFile('$${ZIP_FILE}').extractall()"

chmod g-w,o-rwx $(find $${ZIP_DIR}/ -type f ! -path $${ZIP_DIR}/code/*)
chown -R root:52 $${ZIP_DIR}
mkdir -p -m 755 /etc/puppetlabs/
rsync -avh --no-t --exclude 'data' $${ZIP_DIR}/ /etc/puppetlabs/
rsync -avh --no-t --del $${ZIP_DIR}/data/ /etc/puppetlabs/data/
rm -rf $${ZIP_DIR}/

if [ -f /opt/puppetlabs/puppet/bin/r10k ] && [ /etc/puppetlabs/code/Puppetfile -nt /etc/puppetlabs/code/modules ]; then
/opt/puppetlabs/puppet/bin/r10k puppetfile install --moduledir=/etc/puppetlabs/code/modules --puppetfile=/etc/puppetlabs/code/Puppetfile
touch /etc/puppetlabs/code/modules
fi

if [ -f /usr/local/bin/consul ] && [ -f /usr/bin/jq ]; then
/usr/local/bin/consul event -token=$(jq -r .acl.tokens.agent /etc/consul/config.json) -name=puppet $(date +%s)
fi
- content: ${filebase64("${module_path}/update_etc_puppetlabs.sh")}
encoding: b64
permissions: "0755"
path: /usr/sbin/update_etc_puppetlabs.sh
- content: |
Expand All @@ -245,12 +219,6 @@ write_files:
permissions: "0640"
- path: /var/log/autosign.log
permissions: "0640"
%{ if puppetfile != "" ~}
- path: /etc/puppetlabs/code/Puppetfile
content: |
${indent(6, puppetfile)}
permissions: "0644"
%{ endif ~}
%{ endif ~}
- content: |
---
Expand Down
22 changes: 22 additions & 0 deletions common/configuration/update_etc_puppetlabs.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#!/bin/bash
ZIP_FILE=${1}
ZIP_DIR=${ZIP_FILE%.zip}

# unzip is not necessarily installed when connecting, but python is.
/usr/libexec/platform-python -c "import zipfile; zipfile.ZipFile('${ZIP_FILE}').extractall()"

chmod g-w,o-rwx $(find ${ZIP_DIR}/ -type f ! -path ${ZIP_DIR}/code/*)
chown -R root:52 ${ZIP_DIR}
mkdir -p -m 755 /etc/puppetlabs/
rsync -avh --no-t --exclude 'data' ${ZIP_DIR}/ /etc/puppetlabs/
rsync -avh --no-t --del ${ZIP_DIR}/data/ /etc/puppetlabs/data/
rm -rf ${ZIP_DIR}/

if [ -f /opt/puppetlabs/puppet/bin/r10k ] && [ /etc/puppetlabs/code/Puppetfile -nt /etc/puppetlabs/code/modules ]; then
/opt/puppetlabs/puppet/bin/r10k puppetfile install --moduledir=/etc/puppetlabs/code/modules --puppetfile=/etc/puppetlabs/code/Puppetfile
touch /etc/puppetlabs/code/modules
fi

if [ -f /usr/local/bin/consul ] && [ -f /usr/bin/jq ]; then
/usr/local/bin/consul event -token=$(jq -r .acl.tokens.agent /etc/consul/config.json) -name=puppet $(date +%s)
fi
1 change: 0 additions & 1 deletion gcp/infrastructure.tf
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ module "configuration" {
cloud_provider = local.cloud_provider
cloud_region = local.cloud_region
skip_upgrade = var.skip_upgrade
puppetfile = var.puppetfile
}

module "provision" {
Expand Down
1 change: 0 additions & 1 deletion incus/infrastructure.tf
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ module "configuration" {
cloud_provider = "incus"
cloud_region = "local"
skip_upgrade = var.skip_upgrade
puppetfile = var.puppetfile
}

module "provision" {
Expand Down
1 change: 0 additions & 1 deletion openstack/infrastructure.tf
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ module "configuration" {
cloud_provider = local.cloud_provider
cloud_region = local.cloud_region
skip_upgrade = var.skip_upgrade
puppetfile = var.puppetfile
}

module "provision" {
Expand Down
Loading