From 9e90c3e27288a207b0faf4882c780352f2e2b563 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix-Antoine=20Fortin?= Date: Thu, 18 Jul 2024 16:27:15 -0400 Subject: [PATCH 01/24] Replace generate_ssh_key by a tf user with limited permissions --- aws/infrastructure.tf | 2 -- azure/infrastructure.tf | 2 -- common/configuration/main.tf | 5 ++--- common/configuration/puppet.yaml | 29 ++++++++++++++++++++++++++++ common/provision/main.tf | 16 +++++----------- common/variables.tf | 6 ------ docs/README.md | 33 -------------------------------- docs/design.md | 2 -- docs/terraform_cloud.md | 5 +---- gcp/infrastructure.tf | 2 -- openstack/infrastructure.tf | 2 -- 11 files changed, 37 insertions(+), 67 deletions(-) diff --git a/aws/infrastructure.tf b/aws/infrastructure.tf index 78132ebf..87682bfd 100644 --- a/aws/infrastructure.tf +++ b/aws/infrastructure.tf @@ -19,7 +19,6 @@ module "configuration" { config_git_url = var.config_git_url config_version = var.config_version sudoer_username = var.sudoer_username - generate_ssh_key = var.generate_ssh_key public_keys = var.public_keys domain_name = module.design.domain_name bastion_tag = module.design.bastion_tag @@ -42,7 +41,6 @@ module "provision" { terraform_facts = module.configuration.terraform_facts hieradata = var.hieradata hieradata_dir = var.hieradata_dir - sudoer_username = var.sudoer_username eyaml_key = var.eyaml_key puppetfile = var.puppetfile depends_on = [aws_instance.instances, aws_eip.public_ip] diff --git a/azure/infrastructure.tf b/azure/infrastructure.tf index f9827e50..615a7023 100644 --- a/azure/infrastructure.tf +++ b/azure/infrastructure.tf @@ -19,7 +19,6 @@ module "configuration" { config_git_url = var.config_git_url config_version = var.config_version sudoer_username = var.sudoer_username - generate_ssh_key = var.generate_ssh_key public_keys = var.public_keys domain_name = module.design.domain_name bastion_tag = module.design.bastion_tag @@ -42,7 +41,6 @@ module "provision" { terraform_facts = module.configuration.terraform_facts hieradata = var.hieradata hieradata_dir = var.hieradata_dir - sudoer_username = var.sudoer_username eyaml_key = var.eyaml_key puppetfile = var.puppetfile depends_on = [ azurerm_linux_virtual_machine.instances ] diff --git a/common/configuration/main.tf b/common/configuration/main.tf index 6fea5e9f..d9040032 100644 --- a/common/configuration/main.tf +++ b/common/configuration/main.tf @@ -12,7 +12,6 @@ variable "domain_name" { } variable "cluster_name" { } variable "guest_passwd" { } -variable "generate_ssh_key" { } variable "public_keys" { } variable "skip_upgrade" { } @@ -20,7 +19,6 @@ variable "puppetfile" { } variable "bastion_tag" { } resource "tls_private_key" "ssh" { - count = var.generate_ssh_key ? 1 : 0 algorithm = "ED25519" } @@ -56,7 +54,7 @@ locals { tag => [for key, values in var.inventory : values.local_ip if contains(values.tags, tag)] } - ssh_authorized_keys = var.generate_ssh_key ? concat(var.public_keys, ["${chomp(tls_private_key.ssh[0].public_key_openssh)} terraform@localhost"]) : var.public_keys + ssh_authorized_keys = var.public_keys # add openssh public key to inventory inventory = { for host, values in var.inventory: @@ -103,6 +101,7 @@ locals { puppetserver_password = local.puppet_passwd, sudoer_username = var.sudoer_username, ssh_authorized_keys = local.ssh_authorized_keys + tf_ssh_public_key = tls_private_key.ssh.public_key_openssh # If there is no bastion, the terraform data has to be packed with the user_data of the puppetserver. # We do not packed it systematically because it increases the user-data size to a value that can be # near or exceeds the cloud provider limit - AWS 16KB, Azure and OpenStack 64KB, GCP 256 KB. diff --git a/common/configuration/puppet.yaml b/common/configuration/puppet.yaml index 099ac2a6..17053026 100644 --- a/common/configuration/puppet.yaml +++ b/common/configuration/puppet.yaml @@ -6,6 +6,10 @@ mounts: - [ ephemeral0, /mnt/ephemeral0 ] users: + - name: tf + ssh_authorized_keys: + - ${tf_ssh_public_key} + sudo: tf ALL = NOPASSWD: /usr/sbin/update_etc_puppetlabs.sh /tmp/*.zip - name: ${sudoer_username} groups: adm, wheel, systemd-journal homedir: /${sudoer_username} @@ -144,6 +148,31 @@ 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 + permissions: 0755 + path: /usr/sbin/update_etc_puppetlabs.sh - content: | --- general: diff --git a/common/provision/main.tf b/common/provision/main.tf index f4b7e441..efe25344 100644 --- a/common/provision/main.tf +++ b/common/provision/main.tf @@ -4,7 +4,6 @@ variable "terraform_data" { } variable "terraform_facts" { } variable "hieradata" { } variable "hieradata_dir" { } -variable "sudoer_username" { } variable "tf_ssh_key" { } variable "eyaml_key" { } variable "puppetfile" { } @@ -65,9 +64,9 @@ resource "terraform_data" "deploy_puppetserver_files" { connection { type = "ssh" bastion_host = var.bastions[keys(var.bastions)[0]].public_ip - bastion_user = var.sudoer_username + bastion_user = "tf" bastion_private_key = var.tf_ssh_key.private - user = var.sudoer_username + user = "tf" host = each.value private_key = var.tf_ssh_key.private } @@ -78,18 +77,13 @@ resource "terraform_data" "deploy_puppetserver_files" { provisioner "file" { source = "${path.module}/files/${local.provision_folder}.zip" - destination = "${local.provision_folder}.zip" - } - - provisioner "file" { - content = file("${path.module}/update_etc_puppetlabs.sh") - destination = "update_etc_puppetlabs.sh" + destination = "/tmp/${local.provision_folder}.zip" } provisioner "remote-exec" { inline = [ - "sudo bash update_etc_puppetlabs.sh ${local.provision_folder}.zip", - "rm ${local.provision_folder}.zip update_etc_puppetlabs.sh" + "sudo /usr/bin/update_etc_puppetlabs.sh /tmp/${local.provision_folder}.zip", + "rm /tmp/${local.provision_folder}.zip" ] } } diff --git a/common/variables.tf b/common/variables.tf index 8989e336..cbb8381b 100644 --- a/common/variables.tf +++ b/common/variables.tf @@ -133,12 +133,6 @@ variable "firewall_rules" { description = "Map of ingress firewall rules. Rules are defined as object({from_port, to_port, tag, cidr, ethertype, protocol})." } -variable "generate_ssh_key" { - type = bool - default = false - description = "If set to true, Terraform will generate an ssh key pair to connect to the cluster. Default: false" -} - variable "software_stack" { type = string default = "alliance" diff --git a/docs/README.md b/docs/README.md index ecf789d7..ab97eaef 100644 --- a/docs/README.md +++ b/docs/README.md @@ -243,12 +243,6 @@ To learn how to start ssh-agent and add keys, refer to ssh-agent corresponds to the public key that will be granted access to your cluster (refer to [section 4.9 public_keys](#49-public_keys)). -**Note 2**: If you have no wish to use ssh-agent, you can configure Magic Castle to -generate a key pair specific to your cluster. The public key will be written in -the sudoer `authorized_keys` and Terraform will be able to connect the cluster -using the corresponding private key. For more information, -refer to [section 4.17 - generate_ssh_key](#417-generate_ssh_key-optional). - ## 2. Cloud Cluster Architecture Overview ![Magic Castle Service Architecture](https://docs.google.com/drawings/d/e/2PACX-1vRGFtPevjgM0_ZrkIBQY881X73eQGaXDJ1Fb48Z0DyOe61h2dYdw0urWF2pQZWUTdcNSAM868sQ2Sii/pub?w=1259&h=960) @@ -658,12 +652,6 @@ exist following modifications, the volumes will be deleted. List of SSH public keys that will have access to your cluster sudoer account. -**Note 1**: You need to add the private key associated with one of the public -keys to your local authentication agent (i.e: `ssh-add`) for Terraform to be -able to copy Puppet configuration files with scp on the cluster. Otherwise, -Magic Castle can create a key pair for unique to this cluster, see section -[4.17 - generate_ssh_key](#417-generate_ssh_key-optional). - **Post build modification effect**: trigger scp of hieradata files at next `terraform apply`. The sudoer account `authorized_keys` file will be updated by each instance's Puppet agent following the copy of the hieradata files. @@ -905,27 +893,6 @@ about this requirement, refer to Magic Castle's **Post build modification effect**: modify the cloud provider firewall rules at next `terraform apply`. -### 4.17 generate_ssh_key (optional) - -**default_value**: `false` - -If true, Terraform will generate an ssh key pair that would then be used when copying file with Terraform -file-provisioner. The public key will be added to the sudoer account authorized keys. - -This parameter is useful when Terraform does not have access to one of the private key associated with the -public keys provided in `public_keys`. - -**Post build modification effect**: - -- `false` -> `true`: will cause Terraform failure. -Terraform will try to use the newly created private SSH key -to connect to the cluster, while the corresponding public SSH -key is yet registered with the sudoer account. -- `true` -> `false`: will trigger a scp of terraform_data.yaml at -next terraform apply. The Terraform public SSH key will be removed -from the sudoer account `authorized_keys` file at next -Puppet agent run. - ### 4.18 software_stack (optional) **default_value**: `"alliance"` diff --git a/docs/design.md b/docs/design.md index 2229cbfc..06fb5928 100644 --- a/docs/design.md +++ b/docs/design.md @@ -221,7 +221,6 @@ the `module.design.instances` map. config_git_url = var.config_git_url config_version = var.config_version sudoer_username = var.sudoer_username - generate_ssh_key = var.generate_ssh_key public_keys = var.public_keys domain_name = module.design.domain_name cluster_name = var.cluster_name @@ -386,7 +385,6 @@ Alibaba cloud has an answer for each resource, so we will use this provider in t config_git_url = var.config_git_url config_version = var.config_version sudoer_username = var.sudoer_username - generate_ssh_key = var.generate_ssh_key public_keys = var.public_keys domain_name = module.design.domain_name cluster_name = var.cluster_name diff --git a/docs/terraform_cloud.md b/docs/terraform_cloud.md index 5cafc859..403bf268 100644 --- a/docs/terraform_cloud.md +++ b/docs/terraform_cloud.md @@ -291,10 +291,7 @@ To enable this feature: 4. On the right-hand-side of `public_keys = `, replace `[file("~/.ssh/id_rsa.pub")]` by a list of SSH public keys that will have admin access to the cluster. 5. After the line `public_keys = ...`, add `hieradata = file("data.yaml")`. - 6. After the line `hieradata = ...`, add `generate_ssh_key = true`. This will provide - Terraform Cloud SSH admin access to the cluster and it will be used to upload configuration - files. - 7. Stage changes, commit and push to git repo. + 6. Stage changes, commit and push to git repo. 9. Go to your workspace in TFE, click on Actions -> Start a new run -> Plan and apply -> Start run. Then, click on "Confirm & Apply" and "Confirm Plan". diff --git a/gcp/infrastructure.tf b/gcp/infrastructure.tf index 1583897d..c621a439 100644 --- a/gcp/infrastructure.tf +++ b/gcp/infrastructure.tf @@ -19,7 +19,6 @@ module "configuration" { config_git_url = var.config_git_url config_version = var.config_version sudoer_username = var.sudoer_username - generate_ssh_key = var.generate_ssh_key public_keys = var.public_keys domain_name = module.design.domain_name bastion_tag = module.design.bastion_tag @@ -42,7 +41,6 @@ module "provision" { terraform_facts = module.configuration.terraform_facts hieradata = var.hieradata hieradata_dir = var.hieradata_dir - sudoer_username = var.sudoer_username eyaml_key = var.eyaml_key puppetfile = var.puppetfile depends_on = [ google_compute_instance.instances ] diff --git a/openstack/infrastructure.tf b/openstack/infrastructure.tf index ffb4225c..ec40ebd3 100644 --- a/openstack/infrastructure.tf +++ b/openstack/infrastructure.tf @@ -14,7 +14,6 @@ module "configuration" { config_git_url = var.config_git_url config_version = var.config_version sudoer_username = var.sudoer_username - generate_ssh_key = var.generate_ssh_key public_keys = var.public_keys domain_name = module.design.domain_name bastion_tag = module.design.bastion_tag @@ -37,7 +36,6 @@ module "provision" { terraform_facts = module.configuration.terraform_facts hieradata = var.hieradata hieradata_dir = var.hieradata_dir - sudoer_username = var.sudoer_username eyaml_key = var.eyaml_key puppetfile = var.puppetfile depends_on = [ From 965cde2f13562624a6dacb67663cf0708f4dbd9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix-Antoine=20Fortin?= Date: Thu, 18 Jul 2024 16:31:01 -0400 Subject: [PATCH 02/24] Fix --- common/configuration/main.tf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/common/configuration/main.tf b/common/configuration/main.tf index d9040032..e159263b 100644 --- a/common/configuration/main.tf +++ b/common/configuration/main.tf @@ -152,8 +152,8 @@ output "inventory" { output "ssh_key" { value = { - public = try("${chomp(tls_private_key.ssh[0].public_key_openssh)} terraform@localhost", null) - private = try(tls_private_key.ssh[0].private_key_pem, null) + public = try("${chomp(tls_private_key.ssh.public_key_openssh)} terraform@localhost", null) + private = try(tls_private_key.ssh.private_key_pem, null) } } From 412da53b99536b440373cd25265a70e3231b5054 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix-Antoine=20Fortin?= Date: Thu, 18 Jul 2024 16:36:50 -0400 Subject: [PATCH 03/24] Fix sudo for tf user --- common/configuration/puppet.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/configuration/puppet.yaml b/common/configuration/puppet.yaml index 17053026..b6798a05 100644 --- a/common/configuration/puppet.yaml +++ b/common/configuration/puppet.yaml @@ -9,7 +9,7 @@ users: - name: tf ssh_authorized_keys: - ${tf_ssh_public_key} - sudo: tf ALL = NOPASSWD: /usr/sbin/update_etc_puppetlabs.sh /tmp/*.zip + sudo: "tf ALL = NOPASSWD: /usr/sbin/update_etc_puppetlabs.sh /tmp/*.zip" - name: ${sudoer_username} groups: adm, wheel, systemd-journal homedir: /${sudoer_username} From cb3915dbb54f6f08c23fbda23d2bb6acc42bf01f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix-Antoine=20Fortin?= Date: Thu, 18 Jul 2024 16:44:08 -0400 Subject: [PATCH 04/24] Fix tf sudo line --- common/configuration/puppet.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/configuration/puppet.yaml b/common/configuration/puppet.yaml index b6798a05..6e0c841a 100644 --- a/common/configuration/puppet.yaml +++ b/common/configuration/puppet.yaml @@ -9,7 +9,7 @@ users: - name: tf ssh_authorized_keys: - ${tf_ssh_public_key} - sudo: "tf ALL = NOPASSWD: /usr/sbin/update_etc_puppetlabs.sh /tmp/*.zip" + sudo: "ALL = NOPASSWD: /usr/sbin/update_etc_puppetlabs.sh /tmp/*.zip" - name: ${sudoer_username} groups: adm, wheel, systemd-journal homedir: /${sudoer_username} From eb07e455bb446f6243622095d548cbf7faa4a6ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix-Antoine=20Fortin?= Date: Thu, 18 Jul 2024 16:52:00 -0400 Subject: [PATCH 05/24] Fix provision command --- common/provision/main.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/provision/main.tf b/common/provision/main.tf index efe25344..7918977a 100644 --- a/common/provision/main.tf +++ b/common/provision/main.tf @@ -82,7 +82,7 @@ resource "terraform_data" "deploy_puppetserver_files" { provisioner "remote-exec" { inline = [ - "sudo /usr/bin/update_etc_puppetlabs.sh /tmp/${local.provision_folder}.zip", + "cd tmp && sudo /usr/sbin/update_etc_puppetlabs.sh /tmp/${local.provision_folder}.zip", "rm /tmp/${local.provision_folder}.zip" ] } From dc5d919553b9dd422a62d8489dc3255ee4c052a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix-Antoine=20Fortin?= Date: Thu, 18 Jul 2024 16:56:58 -0400 Subject: [PATCH 06/24] Fix --- common/provision/main.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/provision/main.tf b/common/provision/main.tf index 7918977a..40bfb4a3 100644 --- a/common/provision/main.tf +++ b/common/provision/main.tf @@ -82,7 +82,7 @@ resource "terraform_data" "deploy_puppetserver_files" { provisioner "remote-exec" { inline = [ - "cd tmp && sudo /usr/sbin/update_etc_puppetlabs.sh /tmp/${local.provision_folder}.zip", + "cd /tmp && sudo /usr/sbin/update_etc_puppetlabs.sh /tmp/${local.provision_folder}.zip", "rm /tmp/${local.provision_folder}.zip" ] } From 772b354decfa569bcf1ef3c3a159a4121985f033 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix-Antoine=20Fortin?= Date: Thu, 18 Jul 2024 17:16:30 -0400 Subject: [PATCH 07/24] Move tf homedir --- common/configuration/puppet.yaml | 3 ++- common/provision/main.tf | 4 ++-- common/provision/update_etc_puppetlabs.sh | 23 ----------------------- 3 files changed, 4 insertions(+), 26 deletions(-) delete mode 100644 common/provision/update_etc_puppetlabs.sh diff --git a/common/configuration/puppet.yaml b/common/configuration/puppet.yaml index 6e0c841a..7d0611ef 100644 --- a/common/configuration/puppet.yaml +++ b/common/configuration/puppet.yaml @@ -7,9 +7,10 @@ mounts: users: - name: tf + homedir: /tf ssh_authorized_keys: - ${tf_ssh_public_key} - sudo: "ALL = NOPASSWD: /usr/sbin/update_etc_puppetlabs.sh /tmp/*.zip" + sudo: "ALL = NOPASSWD: /usr/sbin/update_etc_puppetlabs.sh /tf/*.zip" - name: ${sudoer_username} groups: adm, wheel, systemd-journal homedir: /${sudoer_username} diff --git a/common/provision/main.tf b/common/provision/main.tf index 40bfb4a3..115d539c 100644 --- a/common/provision/main.tf +++ b/common/provision/main.tf @@ -82,8 +82,8 @@ resource "terraform_data" "deploy_puppetserver_files" { provisioner "remote-exec" { inline = [ - "cd /tmp && sudo /usr/sbin/update_etc_puppetlabs.sh /tmp/${local.provision_folder}.zip", - "rm /tmp/${local.provision_folder}.zip" + "sudo /usr/sbin/update_etc_puppetlabs.sh /tf/${local.provision_folder}.zip", + "rm ${local.provision_folder}.zip" ] } } diff --git a/common/provision/update_etc_puppetlabs.sh b/common/provision/update_etc_puppetlabs.sh deleted file mode 100644 index e117289e..00000000 --- a/common/provision/update_etc_puppetlabs.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/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 From 086cc113acdb3ffb1671263f8fed1eabdcb0da46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix-Antoine=20Fortin?= Date: Fri, 19 Jul 2024 11:29:17 -0400 Subject: [PATCH 08/24] Move home directory for user tf and sudoer --- common/configuration/puppet.yaml | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/common/configuration/puppet.yaml b/common/configuration/puppet.yaml index 7d0611ef..dfd84d12 100644 --- a/common/configuration/puppet.yaml +++ b/common/configuration/puppet.yaml @@ -7,13 +7,11 @@ mounts: users: - name: tf - homedir: /tf ssh_authorized_keys: - ${tf_ssh_public_key} - sudo: "ALL = NOPASSWD: /usr/sbin/update_etc_puppetlabs.sh /tf/*.zip" + sudo: "ALL = NOPASSWD: /usr/sbin/update_etc_puppetlabs.sh /localhome/tf/*.zip" - name: ${sudoer_username} groups: adm, wheel, systemd-journal - homedir: /${sudoer_username} selinux_user: unconfined_u sudo: ALL=(ALL) NOPASSWD:ALL ssh_authorized_keys: @@ -22,12 +20,9 @@ users: %{ endfor ~} runcmd: - # Verify ${sudoer_username} was created with the right homedir. If it wasn't - # the user with the corresponding username is entirely removed, cloud-init is - # cleaned and the system is rebooted. This happens when configuring from images - # that were customized. - - test ! -d /${sudoer_username} && userdel -f -r ${sudoer_username} && cloud-init clean -r - - restorecon -R /${sudoer_username} + - mkdir /localhome + - usermod -m -d /localhome/tf tf + - usermod -m -d /localhome/${sudoer_username} ${sudoer_username} - sed -i '/HostKey \/etc\/ssh\/ssh_host_ecdsa_key/ s/^#*/#/' /etc/ssh/sshd_config - chmod 644 /etc/ssh/ssh_host_*_key.pub - chgrp ssh_keys /etc/ssh/ssh_host_*_key.pub From 290f579374902633a341a0c09ed56341ca1a397f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix-Antoine=20Fortin?= Date: Fri, 19 Jul 2024 11:34:26 -0400 Subject: [PATCH 09/24] Fix provision --- common/provision/main.tf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/common/provision/main.tf b/common/provision/main.tf index 115d539c..78c671d4 100644 --- a/common/provision/main.tf +++ b/common/provision/main.tf @@ -77,12 +77,12 @@ resource "terraform_data" "deploy_puppetserver_files" { provisioner "file" { source = "${path.module}/files/${local.provision_folder}.zip" - destination = "/tmp/${local.provision_folder}.zip" + destination = "/localhome/tf/${local.provision_folder}.zip" } provisioner "remote-exec" { inline = [ - "sudo /usr/sbin/update_etc_puppetlabs.sh /tf/${local.provision_folder}.zip", + "sudo /usr/sbin/update_etc_puppetlabs.sh /localhome/tf/${local.provision_folder}.zip", "rm ${local.provision_folder}.zip" ] } From 35d2b5f0f00fab04f7ffa28322bad3da5a1f7244 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix-Antoine=20Fortin?= Date: Fri, 19 Jul 2024 14:10:54 -0400 Subject: [PATCH 10/24] Remove need for a home folder for user tf --- common/configuration/puppet.yaml | 14 ++++++++++---- common/provision/main.tf | 6 +++--- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/common/configuration/puppet.yaml b/common/configuration/puppet.yaml index dfd84d12..ce53a201 100644 --- a/common/configuration/puppet.yaml +++ b/common/configuration/puppet.yaml @@ -7,9 +7,11 @@ mounts: users: - name: tf - ssh_authorized_keys: - - ${tf_ssh_public_key} - sudo: "ALL = NOPASSWD: /usr/sbin/update_etc_puppetlabs.sh /localhome/tf/*.zip" + no_create_home: true + no_create_group: true +%{ if contains(tags, "puppet") } + sudo: "ALL = NOPASSWD: /usr/sbin/update_etc_puppetlabs.sh /tmp/*.zip" +%{ endif ~} - name: ${sudoer_username} groups: adm, wheel, systemd-journal selinux_user: unconfined_u @@ -20,8 +22,9 @@ users: %{ endfor ~} runcmd: + - echo -e "match User tf\n AuthorizedKeysFile /etc/ssh/authorized_keys.%u\n AuthenticationMethods publickey" >> /etc/ssh/sshd_config - mkdir /localhome - - usermod -m -d /localhome/tf tf + - chcon -t home_root_t /localhome - usermod -m -d /localhome/${sudoer_username} ${sudoer_username} - sed -i '/HostKey \/etc\/ssh\/ssh_host_ecdsa_key/ s/^#*/#/' /etc/ssh/sshd_config - chmod 644 /etc/ssh/ssh_host_*_key.pub @@ -126,6 +129,9 @@ runcmd: - test -f /etc/magic-castle-release && systemctl start puppet || true write_files: + - content: ${tf_ssh_public_key} + path: /etc/ssh/authorized_keys.tf + permissions: "0644" - content: | facts : { blocklist : [ diff --git a/common/provision/main.tf b/common/provision/main.tf index 78c671d4..40bfb4a3 100644 --- a/common/provision/main.tf +++ b/common/provision/main.tf @@ -77,13 +77,13 @@ resource "terraform_data" "deploy_puppetserver_files" { provisioner "file" { source = "${path.module}/files/${local.provision_folder}.zip" - destination = "/localhome/tf/${local.provision_folder}.zip" + destination = "/tmp/${local.provision_folder}.zip" } provisioner "remote-exec" { inline = [ - "sudo /usr/sbin/update_etc_puppetlabs.sh /localhome/tf/${local.provision_folder}.zip", - "rm ${local.provision_folder}.zip" + "cd /tmp && sudo /usr/sbin/update_etc_puppetlabs.sh /tmp/${local.provision_folder}.zip", + "rm /tmp/${local.provision_folder}.zip" ] } } From d02fee7e07cff0f115e8ae4123f054a58b3e808e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix-Antoine=20Fortin?= Date: Fri, 19 Jul 2024 14:19:37 -0400 Subject: [PATCH 11/24] Set tf homedir to /tmp --- common/configuration/puppet.yaml | 3 ++- common/provision/main.tf | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/common/configuration/puppet.yaml b/common/configuration/puppet.yaml index ce53a201..360ef17f 100644 --- a/common/configuration/puppet.yaml +++ b/common/configuration/puppet.yaml @@ -9,8 +9,9 @@ users: - name: tf no_create_home: true no_create_group: true + homedir: /tmp %{ if contains(tags, "puppet") } - sudo: "ALL = NOPASSWD: /usr/sbin/update_etc_puppetlabs.sh /tmp/*.zip" + sudo: "ALL = NOPASSWD: /usr/sbin/update_etc_puppetlabs.sh *.zip" %{ endif ~} - name: ${sudoer_username} groups: adm, wheel, systemd-journal diff --git a/common/provision/main.tf b/common/provision/main.tf index 40bfb4a3..17db99b8 100644 --- a/common/provision/main.tf +++ b/common/provision/main.tf @@ -77,13 +77,13 @@ resource "terraform_data" "deploy_puppetserver_files" { provisioner "file" { source = "${path.module}/files/${local.provision_folder}.zip" - destination = "/tmp/${local.provision_folder}.zip" + destination = "${local.provision_folder}.zip" } provisioner "remote-exec" { inline = [ - "cd /tmp && sudo /usr/sbin/update_etc_puppetlabs.sh /tmp/${local.provision_folder}.zip", - "rm /tmp/${local.provision_folder}.zip" + "sudo /usr/sbin/update_etc_puppetlabs.sh ${local.provision_folder}.zip", + "rm ${local.provision_folder}.zip" ] } } From 648eae3ed57d4e9a9657e406d31cad121033c8c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix-Antoine=20Fortin?= Date: Fri, 19 Jul 2024 15:00:16 -0400 Subject: [PATCH 12/24] Delay moving /centos to another folder --- common/configuration/puppet.yaml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/common/configuration/puppet.yaml b/common/configuration/puppet.yaml index 360ef17f..74fb495f 100644 --- a/common/configuration/puppet.yaml +++ b/common/configuration/puppet.yaml @@ -15,6 +15,7 @@ users: %{ endif ~} - name: ${sudoer_username} groups: adm, wheel, systemd-journal + homedir: /${sudoer_username} selinux_user: unconfined_u sudo: ALL=(ALL) NOPASSWD:ALL ssh_authorized_keys: @@ -24,9 +25,6 @@ users: runcmd: - echo -e "match User tf\n AuthorizedKeysFile /etc/ssh/authorized_keys.%u\n AuthenticationMethods publickey" >> /etc/ssh/sshd_config - - mkdir /localhome - - chcon -t home_root_t /localhome - - usermod -m -d /localhome/${sudoer_username} ${sudoer_username} - sed -i '/HostKey \/etc\/ssh\/ssh_host_ecdsa_key/ s/^#*/#/' /etc/ssh/sshd_config - chmod 644 /etc/ssh/ssh_host_*_key.pub - chgrp ssh_keys /etc/ssh/ssh_host_*_key.pub From 1cb7934c6b0b7b7ec71d193dc7b0fbe76f295207 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix-Antoine=20Fortin?= Date: Fri, 19 Jul 2024 15:03:38 -0400 Subject: [PATCH 13/24] Simplify --- common/configuration/main.tf | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/common/configuration/main.tf b/common/configuration/main.tf index e159263b..6a4586c7 100644 --- a/common/configuration/main.tf +++ b/common/configuration/main.tf @@ -54,8 +54,6 @@ locals { tag => [for key, values in var.inventory : values.local_ip if contains(values.tags, tag)] } - ssh_authorized_keys = var.public_keys - # add openssh public key to inventory inventory = { for host, values in var.inventory: host => merge(values, { @@ -72,7 +70,7 @@ locals { tag_ip = local.tag_ip data = { sudoer_username = var.sudoer_username - public_keys = local.ssh_authorized_keys + public_keys = var.public_keys cluster_name = lower(var.cluster_name) domain_name = var.domain_name guest_passwd = local.guest_passwd @@ -100,7 +98,7 @@ locals { puppetservers = local.puppetservers, puppetserver_password = local.puppet_passwd, sudoer_username = var.sudoer_username, - ssh_authorized_keys = local.ssh_authorized_keys + ssh_authorized_keys = var.public_keys tf_ssh_public_key = tls_private_key.ssh.public_key_openssh # If there is no bastion, the terraform data has to be packed with the user_data of the puppetserver. # We do not packed it systematically because it increases the user-data size to a value that can be From f7f6f7e797ec9e30f771b4d8d804f5387f4d9faf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix-Antoine=20Fortin?= Date: Fri, 19 Jul 2024 15:38:15 -0400 Subject: [PATCH 14/24] Reinstate lines in puppet.yaml --- common/configuration/puppet.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/common/configuration/puppet.yaml b/common/configuration/puppet.yaml index 74fb495f..14b46b13 100644 --- a/common/configuration/puppet.yaml +++ b/common/configuration/puppet.yaml @@ -24,6 +24,8 @@ users: %{ endfor ~} runcmd: + - test ! -d /${sudoer_username} && userdel -f -r ${sudoer_username} && cloud-init clean -r + - restorecon -R /${sudoer_username} - echo -e "match User tf\n AuthorizedKeysFile /etc/ssh/authorized_keys.%u\n AuthenticationMethods publickey" >> /etc/ssh/sshd_config - sed -i '/HostKey \/etc\/ssh\/ssh_host_ecdsa_key/ s/^#*/#/' /etc/ssh/sshd_config - chmod 644 /etc/ssh/ssh_host_*_key.pub From 538ab310563edb927326ae26394202070dee48fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix-Antoine=20Fortin?= Date: Fri, 19 Jul 2024 15:44:43 -0400 Subject: [PATCH 15/24] Fix documentation --- docs/README.md | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/docs/README.md b/docs/README.md index ab97eaef..9960aeb9 100644 --- a/docs/README.md +++ b/docs/README.md @@ -10,7 +10,6 @@ To use Magic Castle you will need: 2. Authenticated access to a cloud 3. Ability to communicate with the cloud provider API from your computer 4. A project with operational limits meeting the requirements described in _Quotas_ subsection. -5. ssh-agent running and tracking your SSH key ### 1.1 Terraform @@ -230,18 +229,6 @@ OVH examples. To increase the limits, or request access to special resources like GPUs, refer to [OVHcloud - Increasing Public Cloud quotas](https://docs.ovh.com/ca/en/public-cloud/increase-public-cloud-quota/). -### 1.5 ssh-agent - -To transfer configuration files, Terraform will connect to your cluster using SSH. -To avoid providing your private key to Terraform directly, you will have to -add it to the authentication agent, ssh-agent. - -To learn how to start ssh-agent and add keys, refer to -[ssh-agent - How to configure, forwarding, protocol](https://www.ssh.com/academy/ssh/agent). - -**Note 1**: If you own more than one key pair, make sure the private key added to -ssh-agent corresponds to the public key that will be granted access to your cluster -(refer to [section 4.9 public_keys](#49-public_keys)). ## 2. Cloud Cluster Architecture Overview From d0ea1887e53946ce050cc77895c9f4feae0534fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix-Antoine=20Fortin?= Date: Mon, 22 Jul 2024 09:47:43 -0400 Subject: [PATCH 16/24] Restrict key for user tf --- common/configuration/puppet.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/common/configuration/puppet.yaml b/common/configuration/puppet.yaml index 14b46b13..0996ac1b 100644 --- a/common/configuration/puppet.yaml +++ b/common/configuration/puppet.yaml @@ -26,7 +26,7 @@ users: runcmd: - test ! -d /${sudoer_username} && userdel -f -r ${sudoer_username} && cloud-init clean -r - restorecon -R /${sudoer_username} - - echo -e "match User tf\n AuthorizedKeysFile /etc/ssh/authorized_keys.%u\n AuthenticationMethods publickey" >> /etc/ssh/sshd_config + - echo -e "match User tf\n\tAuthorizedKeysFile /etc/ssh/authorized_keys.%u\n\tAuthenticationMethods publickey" >> /etc/ssh/sshd_config - sed -i '/HostKey \/etc\/ssh\/ssh_host_ecdsa_key/ s/^#*/#/' /etc/ssh/sshd_config - chmod 644 /etc/ssh/ssh_host_*_key.pub - chgrp ssh_keys /etc/ssh/ssh_host_*_key.pub @@ -130,7 +130,7 @@ runcmd: - test -f /etc/magic-castle-release && systemctl start puppet || true write_files: - - content: ${tf_ssh_public_key} + - content: restrict ${tf_ssh_public_key} path: /etc/ssh/authorized_keys.tf permissions: "0644" - content: | From bcb671c8d5ed369621ba80f95a9178a47d37604f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix-Antoine=20Fortin?= Date: Mon, 22 Jul 2024 10:00:11 -0400 Subject: [PATCH 17/24] Enable agent-forwarding for user tf --- common/configuration/puppet.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/configuration/puppet.yaml b/common/configuration/puppet.yaml index 0996ac1b..16455626 100644 --- a/common/configuration/puppet.yaml +++ b/common/configuration/puppet.yaml @@ -130,7 +130,7 @@ runcmd: - test -f /etc/magic-castle-release && systemctl start puppet || true write_files: - - content: restrict ${tf_ssh_public_key} + - content: restrict,agent-forwarding ${tf_ssh_public_key} path: /etc/ssh/authorized_keys.tf permissions: "0644" - content: | From 32e4bc20f73d111b418c607d50e38f3c31ac822f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix-Antoine=20Fortin?= Date: Mon, 22 Jul 2024 13:17:35 -0400 Subject: [PATCH 18/24] Restrict tf user in sshd --- common/configuration/puppet.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/configuration/puppet.yaml b/common/configuration/puppet.yaml index 16455626..088a1f34 100644 --- a/common/configuration/puppet.yaml +++ b/common/configuration/puppet.yaml @@ -130,7 +130,7 @@ runcmd: - test -f /etc/magic-castle-release && systemctl start puppet || true write_files: - - content: restrict,agent-forwarding ${tf_ssh_public_key} + - content: restrict%{ if contains(tags, "puppet") },pty%{ else }%{ for host, ip in puppetservers },permitopen="${ip}:22"%{ endfor },port-forwarding,command="/sbin/nologin"%{ endif } ${tf_ssh_public_key} path: /etc/ssh/authorized_keys.tf permissions: "0644" - content: | From bfcde3ad27fb82821f7ca07ca06be86c637f31c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix-Antoine=20Fortin?= Date: Mon, 22 Jul 2024 14:03:00 -0400 Subject: [PATCH 19/24] Remove wildcard certificate generation --- dns/acme/main.tf | 135 ------------------ dns/acme/versions.tf | 11 -- dns/cloudflare/main.tf | 15 -- dns/cloudflare/variables.tf | 30 ---- dns/gcloud/main.tf | 18 --- dns/gcloud/variables.tf | 30 ---- dns/txt/variables.tf | 2 +- .../advanced/basic_puppet/openstack/main.tf | 6 - examples/advanced/k8s/openstack/main.tf | 6 - examples/advanced/lustre/openstack/main.tf | 6 - examples/advanced/spot_instances/aws/main.tf | 6 - .../advanced/spot_instances/azure/main.tf | 6 - examples/advanced/spot_instances/gcp/main.tf | 6 - examples/aws/main.tf | 6 - examples/azure/main.tf | 6 - examples/gcp/main.tf | 6 - examples/openstack/main.tf | 6 - examples/ovh/main.tf | 6 - 18 files changed, 1 insertion(+), 306 deletions(-) delete mode 100644 dns/acme/main.tf delete mode 100644 dns/acme/versions.tf diff --git a/dns/acme/main.tf b/dns/acme/main.tf deleted file mode 100644 index 7d2a24fc..00000000 --- a/dns/acme/main.tf +++ /dev/null @@ -1,135 +0,0 @@ -variable "name" { -} - -variable "domain" { -} - -variable "email" { -} - -variable "sudoer_username" { -} - -variable "dns_provider" { -} - -variable "dns_provider_config" { - default = {} -} - -variable "ssl_tags" { } - -variable "bastions" { } - -variable "public_instances" {} - -variable "ssh_private_key" { - type = string -} - -variable "acme_key_pem" { - type = string - default = "" -} - -resource "tls_private_key" "private_key" { - count = var.acme_key_pem == "" ? 1 : 0 - algorithm = "RSA" -} - -resource "acme_registration" "reg" { - count = var.acme_key_pem == "" ? 1 : 0 - account_key_pem = tls_private_key.private_key[0].private_key_pem - email_address = var.email -} - -resource "acme_certificate" "certificate" { - account_key_pem = var.acme_key_pem == "" ? acme_registration.reg[0].account_key_pem : var.acme_key_pem - common_name = "${var.name}.${var.domain}" - subject_alternative_names = ["*.${var.name}.${var.domain}"] - - dns_challenge { - provider = var.dns_provider - config = var.dns_provider_config - } -} - -resource "terraform_data" "deploy_certs" { - for_each = length(var.bastions) > 0 ? { for key, values in var.public_instances: key => values if length(setintersection(var.ssl_tags, values.tags)) > 0 } : { } - - triggers_replace = { - instance_id = each.value["id"] - certificate_id = acme_certificate.certificate.id - } - - connection { - type = "ssh" - - bastion_host = var.bastions[keys(var.bastions)[0]].public_ip - bastion_user = var.sudoer_username - bastion_private_key = var.ssh_private_key - - user = var.sudoer_username - host = each.value.local_ip - private_key = var.ssh_private_key - } - - provisioner "file" { - content = acme_certificate.certificate.private_key_pem - destination = "privkey.pem" - } - - provisioner "file" { - content = "${acme_certificate.certificate.certificate_pem}${acme_certificate.certificate.issuer_pem}" - destination = "fullchain.pem" - } - - provisioner "file" { - content = acme_certificate.certificate.certificate_pem - destination = "cert.pem" - } - - provisioner "file" { - content = acme_certificate.certificate.issuer_pem - destination = "chain.pem" - } - - provisioner "file" { - destination = "renewal.conf" - content = < /dev/null && sudo chgrp caddy /etc/letsencrypt/archive/${var.name}.${var.domain}/privkey1.pem", - "test -f /usr/lib/systemd/system/caddy.service && sudo systemctl restart caddy || true", - ] - } -} \ No newline at end of file diff --git a/dns/acme/versions.tf b/dns/acme/versions.tf deleted file mode 100644 index 4fe0926f..00000000 --- a/dns/acme/versions.tf +++ /dev/null @@ -1,11 +0,0 @@ -terraform { - required_version = ">= 1.4.0" - required_providers { - acme = { - source = "vancluever/acme" - } - tls = { - source = "hashicorp/tls" - } - } -} diff --git a/dns/cloudflare/main.tf b/dns/cloudflare/main.tf index 9fe4fa24..64dc3dfe 100644 --- a/dns/cloudflare/main.tf +++ b/dns/cloudflare/main.tf @@ -35,21 +35,6 @@ resource "cloudflare_record" "records" { } } -module "acme" { - count = var.issue_wildcard_cert ? 1 : 0 - source = "../acme" - dns_provider = "cloudflare" - name = lower(var.name) - domain = var.domain - email = var.email - sudoer_username = var.sudoer_username - bastions = var.bastions - public_instances = var.public_instances - ssh_private_key = var.ssh_private_key - ssl_tags = var.ssl_tags - acme_key_pem = var.acme_key_pem -} - output "hostnames" { value = distinct(compact([for record in module.record_generator.records : join(".", [record.name, var.domain]) if record.type == "A" ])) } diff --git a/dns/cloudflare/variables.tf b/dns/cloudflare/variables.tf index 74d56d84..f021da3b 100644 --- a/dns/cloudflare/variables.tf +++ b/dns/cloudflare/variables.tf @@ -4,25 +4,6 @@ variable "name" { variable "domain" { } -variable "email" { - description = "Define the email address used to issue the wildcard certificate. This address will get certificate expiration reminder." - type = string - default = "" -} - -variable "issue_wildcard_cert" { - description = "Use DNS-01 challenge to generate a wildcard certificate *.name.domain_name" - default = false -} - -variable "acme_key_pem" { - type = string - default = "" -} - -variable "sudoer_username" { -} - variable "vhosts" { description = "List of vhost dns records to create as vhost.name.domain_name." type = list(string) @@ -39,15 +20,4 @@ variable "vhost_tag" { default = "proxy" } -variable "ssl_tags" { - description = "Define a list of tags the instances that will receive a copy of the wildcard SSL certificate can have." - default = ["proxy", "ssl"] -} - variable "public_instances" { } - -variable "bastions" { } - -variable "ssh_private_key" { - type = string -} \ No newline at end of file diff --git a/dns/gcloud/main.tf b/dns/gcloud/main.tf index 3d64559f..b81d6cf6 100644 --- a/dns/gcloud/main.tf +++ b/dns/gcloud/main.tf @@ -31,24 +31,6 @@ resource "google_dns_record_set" "records" { ttl = 300 } -module "acme" { - count = var.issue_wildcard_cert ? 1 : 0 - source = "../acme" - dns_provider = "gcloud" - dns_provider_config = { - GCE_PROJECT = var.project - } - name = lower(var.name) - domain = var.domain - email = var.email - sudoer_username = var.sudoer_username - bastions = var.bastions - public_instances = var.public_instances - ssh_private_key = var.ssh_private_key - ssl_tags = var.ssl_tags - acme_key_pem = var.acme_key_pem -} - output "hostnames" { value = distinct(compact([for record in module.record_generator.records : join(".", [record.name, var.domain]) if record.type == "A" ])) } diff --git a/dns/gcloud/variables.tf b/dns/gcloud/variables.tf index 15058eb9..d4794b6b 100644 --- a/dns/gcloud/variables.tf +++ b/dns/gcloud/variables.tf @@ -10,25 +10,6 @@ variable "name" { variable "domain" { } -variable "email" { - description = "Define the email address used to issue the wildcard certificate. This address will get certificate expiration reminder." - type = string - default = "" -} - -variable "issue_wildcard_cert" { - description = "Use DNS-01 challenge to generate a wildcard certificate *.name.domain_name" - default = false -} - -variable "acme_key_pem" { - type = string - default = "" -} - -variable "sudoer_username" { -} - variable "vhosts" { description = "List of vhost dns records to create as vhost.name.domain_name." type = list(string) @@ -45,15 +26,4 @@ variable "vhost_tag" { default = "proxy" } -variable "ssl_tags" { - description = "Define a list of tags the instances that will receive a copy of the wildcard SSL certificate can have." - default = ["proxy", "ssl"] -} - variable "public_instances" { } - -variable "bastions" { } - -variable "ssh_private_key" { - type = string -} \ No newline at end of file diff --git a/dns/txt/variables.tf b/dns/txt/variables.tf index b5cc33e7..2cf32424 100644 --- a/dns/txt/variables.tf +++ b/dns/txt/variables.tf @@ -20,4 +20,4 @@ variable "vhosts" { description = "List of vhost records A to create." type = list(string) default = ["ipa", "jupyter", "mokey", "explore"] -} \ No newline at end of file +} diff --git a/examples/advanced/basic_puppet/openstack/main.tf b/examples/advanced/basic_puppet/openstack/main.tf index f3977871..23654e77 100644 --- a/examples/advanced/basic_puppet/openstack/main.tf +++ b/examples/advanced/basic_puppet/openstack/main.tf @@ -35,10 +35,7 @@ output "sudoer" { # source = "git::https://github.com/ComputeCanada/magic_castle.git//dns/cloudflare" # name = module.openstack.cluster_name # domain = module.openstack.domain -# bastions = module.openstack.bastions # public_instances = module.openstack.public_instances -# ssh_private_key = module.openstack.ssh_private_key -# sudoer_username = module.openstack.accounts.sudoer.username # } ## Uncomment to register your domain name with Google Cloud @@ -48,10 +45,7 @@ output "sudoer" { # zone_name = "you-zone-name" # name = module.openstack.cluster_name # domain = module.openstack.domain -# bastions = module.openstack.bastions # public_instances = module.openstack.public_instances -# ssh_private_key = module.openstack.ssh_private_key -# sudoer_username = module.openstack.accounts.sudoer.username # } # output "hostnames" { diff --git a/examples/advanced/k8s/openstack/main.tf b/examples/advanced/k8s/openstack/main.tf index 9a856f7f..b3321362 100644 --- a/examples/advanced/k8s/openstack/main.tf +++ b/examples/advanced/k8s/openstack/main.tf @@ -35,10 +35,7 @@ output "public_ip" { # source = "git::https://github.com/ComputeCanada/magic_castle.git//dns/cloudflare" # name = module.openstack.cluster_name # domain = module.openstack.domain -# bastions = module.openstack.bastions # public_instances = module.openstack.public_instances -# ssh_private_key = module.openstack.ssh_private_key -# sudoer_username = module.openstack.accounts.sudoer.username # } ## Uncomment to register your domain name with Google Cloud @@ -48,10 +45,7 @@ output "public_ip" { # zone_name = "you-zone-name" # name = module.openstack.cluster_name # domain = module.openstack.domain -# bastions = module.openstack.bastions # public_instances = module.openstack.public_instances -# ssh_private_key = module.openstack.ssh_private_key -# sudoer_username = module.openstack.accounts.sudoer.username # } # output "hostnames" { diff --git a/examples/advanced/lustre/openstack/main.tf b/examples/advanced/lustre/openstack/main.tf index 6d85547b..1e22d20c 100644 --- a/examples/advanced/lustre/openstack/main.tf +++ b/examples/advanced/lustre/openstack/main.tf @@ -44,10 +44,7 @@ output "sudoer" { # source = "git::https://github.com/ComputeCanada/magic_castle.git//dns/cloudflare" # name = module.openstack.cluster_name # domain = module.openstack.domain -# bastions = module.openstack.bastions # public_instances = module.openstack.public_instances -# ssh_private_key = module.openstack.ssh_private_key -# sudoer_username = module.openstack.accounts.sudoer.username # } ## Uncomment to register your domain name with Google Cloud @@ -57,10 +54,7 @@ output "sudoer" { # zone_name = "you-zone-name" # name = module.openstack.cluster_name # domain = module.openstack.domain -# bastions = module.openstack.bastions # public_instances = module.openstack.public_instances -# ssh_private_key = module.openstack.ssh_private_key -# sudoer_username = module.openstack.accounts.sudoer.username # } # output "hostnames" { diff --git a/examples/advanced/spot_instances/aws/main.tf b/examples/advanced/spot_instances/aws/main.tf index 8437dcab..d5e84721 100644 --- a/examples/advanced/spot_instances/aws/main.tf +++ b/examples/advanced/spot_instances/aws/main.tf @@ -53,10 +53,7 @@ output "public_ip" { # source = "git::https://github.com/ComputeCanada/magic_castle.git//dns/cloudflare" # name = module.aws.cluster_name # domain = module.aws.domain -# bastions = module.aws.bastions # public_instances = module.aws.public_instances -# ssh_private_key = module.aws.ssh_private_key -# sudoer_username = module.aws.accounts.sudoer.username # } ## Uncomment to register your domain name with Google Cloud @@ -66,10 +63,7 @@ output "public_ip" { # zone_name = "you-zone-name" # name = module.aws.cluster_name # domain = module.aws.domain -# bastions = module.aws.bastions # public_instances = module.aws.public_instances -# ssh_private_key = module.aws.ssh_private_key -# sudoer_username = module.aws.accounts.sudoer.username # } # output "hostnames" { diff --git a/examples/advanced/spot_instances/azure/main.tf b/examples/advanced/spot_instances/azure/main.tf index 06cddb35..c5b84c02 100644 --- a/examples/advanced/spot_instances/azure/main.tf +++ b/examples/advanced/spot_instances/azure/main.tf @@ -57,10 +57,7 @@ output "public_ip" { # source = "git::https://github.com/ComputeCanada/magic_castle.git//dns/cloudflare" # name = module.azure.cluster_name # domain = module.azure.domain -# bastions = module.azure.bastions # public_instances = module.azure.public_instances -# ssh_private_key = module.azure.ssh_private_key -# sudoer_username = module.azure.accounts.sudoer.username # } ## Uncomment to register your domain name with Google Cloud @@ -70,10 +67,7 @@ output "public_ip" { # zone_name = "you-zone-name" # name = module.azure.cluster_name # domain = module.azure.domain -# bastions = module.azure.bastions # public_instances = module.azure.public_instances -# ssh_private_key = module.azure.ssh_private_key -# sudoer_username = module.azure.accounts.sudoer.username # } # output "hostnames" { diff --git a/examples/advanced/spot_instances/gcp/main.tf b/examples/advanced/spot_instances/gcp/main.tf index edb780a1..d69f1a9a 100644 --- a/examples/advanced/spot_instances/gcp/main.tf +++ b/examples/advanced/spot_instances/gcp/main.tf @@ -53,10 +53,7 @@ output "public_ip" { # source = "git::https://github.com/ComputeCanada/magic_castle.git//dns/cloudflare" # name = module.gcp.cluster_name # domain = module.gcp.domain -# bastions = module.gcp.bastions # public_instances = module.gcp.public_instances -# ssh_private_key = module.gcp.ssh_private_key -# sudoer_username = module.gcp.accounts.sudoer.username # } ## Uncomment to register your domain name with Google Cloud @@ -66,10 +63,7 @@ output "public_ip" { # zone_name = "you-zone-name" # name = module.gcp.cluster_name # domain = module.gcp.domain -# bastions = module.gcp.bastions # public_instances = module.gcp.public_instances -# ssh_private_key = module.gcp.ssh_private_key -# sudoer_username = module.gcp.accounts.sudoer.username # } # output "hostnames" { diff --git a/examples/aws/main.tf b/examples/aws/main.tf index c3035362..ce504cc5 100644 --- a/examples/aws/main.tf +++ b/examples/aws/main.tf @@ -61,10 +61,7 @@ output "public_ip" { # source = "git::https://github.com/ComputeCanada/magic_castle.git//dns/cloudflare" # name = module.aws.cluster_name # domain = module.aws.domain -# bastions = module.aws.bastions # public_instances = module.aws.public_instances -# ssh_private_key = module.aws.ssh_private_key -# sudoer_username = module.aws.accounts.sudoer.username # } ## Uncomment to register your domain name with Google Cloud @@ -74,10 +71,7 @@ output "public_ip" { # zone_name = "you-zone-name" # name = module.aws.cluster_name # domain = module.aws.domain -# bastions = module.aws.bastions # public_instances = module.aws.public_instances -# ssh_private_key = module.aws.ssh_private_key -# sudoer_username = module.aws.accounts.sudoer.username # } # output "hostnames" { diff --git a/examples/azure/main.tf b/examples/azure/main.tf index 136b4ab9..d471d911 100644 --- a/examples/azure/main.tf +++ b/examples/azure/main.tf @@ -72,10 +72,7 @@ output "public_ip" { # source = "git::https://github.com/ComputeCanada/magic_castle.git//dns/cloudflare" # name = module.azure.cluster_name # domain = module.azure.domain -# bastions = module.azure.bastions # public_instances = module.azure.public_instances -# ssh_private_key = module.azure.ssh_private_key -# sudoer_username = module.azure.accounts.sudoer.username # } ## Uncomment to register your domain name with Google Cloud @@ -85,10 +82,7 @@ output "public_ip" { # zone_name = "you-zone-name" # name = module.azure.cluster_name # domain = module.azure.domain -# bastions = module.azure.bastions # public_instances = module.azure.public_instances -# ssh_private_key = module.azure.ssh_private_key -# sudoer_username = module.azure.accounts.sudoer.username # } # output "hostnames" { diff --git a/examples/gcp/main.tf b/examples/gcp/main.tf index 2dd37738..e431ab50 100644 --- a/examples/gcp/main.tf +++ b/examples/gcp/main.tf @@ -67,10 +67,7 @@ output "public_ip" { # source = "git::https://github.com/ComputeCanada/magic_castle.git//dns/cloudflare" # name = module.gcp.cluster_name # domain = module.gcp.domain -# bastions = module.gcp.bastions # public_instances = module.gcp.public_instances -# ssh_private_key = module.gcp.ssh_private_key -# sudoer_username = module.gcp.accounts.sudoer.username # } ## Uncomment to register your domain name with Google Cloud @@ -80,10 +77,7 @@ output "public_ip" { # zone_name = "you-zone-name" # name = module.gcp.cluster_name # domain = module.gcp.domain -# bastions = module.gcp.bastions # public_instances = module.gcp.public_instances -# ssh_private_key = module.gcp.ssh_private_key -# sudoer_username = module.gcp.accounts.sudoer.username # } # output "hostnames" { diff --git a/examples/openstack/main.tf b/examples/openstack/main.tf index 76a39f1a..b815ab1e 100644 --- a/examples/openstack/main.tf +++ b/examples/openstack/main.tf @@ -56,10 +56,7 @@ output "public_ip" { # source = "git::https://github.com/ComputeCanada/magic_castle.git//dns/cloudflare" # name = module.openstack.cluster_name # domain = module.openstack.domain -# bastions = module.openstack.bastions # public_instances = module.openstack.public_instances -# ssh_private_key = module.openstack.ssh_private_key -# sudoer_username = module.openstack.accounts.sudoer.username # } ## Uncomment to register your domain name with Google Cloud @@ -69,10 +66,7 @@ output "public_ip" { # zone_name = "you-zone-name" # name = module.openstack.cluster_name # domain = module.openstack.domain -# bastions = module.openstack.bastions # public_instances = module.openstack.public_instances -# ssh_private_key = module.openstack.ssh_private_key -# sudoer_username = module.openstack.accounts.sudoer.username # } # output "hostnames" { diff --git a/examples/ovh/main.tf b/examples/ovh/main.tf index f36f5c2c..61c1a142 100644 --- a/examples/ovh/main.tf +++ b/examples/ovh/main.tf @@ -56,10 +56,7 @@ output "public_ip" { # source = "git::https://github.com/ComputeCanada/magic_castle.git//dns/cloudflare" # name = module.ovh.cluster_name # domain = module.ovh.domain -# bastions = module.ovh.bastions # public_instances = module.ovh.public_instances -# ssh_private_key = module.ovh.ssh_private_key -# sudoer_username = module.ovh.accounts.sudoer.username # } ## Uncomment to register your domain name with Google Cloud @@ -69,10 +66,7 @@ output "public_ip" { # zone_name = "you-zone-name" # name = module.ovh.cluster_name # domain = module.ovh.domain -# bastions = module.ovh.bastions # public_instances = module.ovh.public_instances -# ssh_private_key = module.ovh.ssh_private_key -# sudoer_username = module.ovh.accounts.sudoer.username # } # output "hostnames" { From 8fab7f42165150707dce4f688204f77c83283c85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix-Antoine=20Fortin?= Date: Mon, 22 Jul 2024 14:06:16 -0400 Subject: [PATCH 20/24] Remove ssl wildcard certificate generation documentation --- docs/README.md | 98 ++------------------------------------------------ 1 file changed, 2 insertions(+), 96 deletions(-) diff --git a/docs/README.md b/docs/README.md index 9960aeb9..98cb8d0c 100644 --- a/docs/README.md +++ b/docs/README.md @@ -364,7 +364,7 @@ Defines Optional modules following the current module in the example `main.tf` can be used to register DNS records in relation to your cluster if the DNS zone of this domain is administered by one of the supported providers. -Refer to section [6. DNS Configuration and SSL Certificates](#6-dns-configuration-and-wildcard-ssl-certificate) +Refer to section [6. DNS Configuration](#6-dns-configuration) for more details. **Requirements**: @@ -499,7 +499,6 @@ Terraform tags: - `spot`: identify instances that are to be spawned as spot/preemptible instances. This tag is supported in AWS, Azure and GCP. It is ignored by OpenStack and OVH. - `efa`: attach an Elastic Fabric Adapter network interface to the instance. This tag is supported in AWS. -- `ssl`: identify instances that receive a copy of the SSL wildcard certificate for the domain Puppet tags expected by the [puppet-magic_castle](https://www.github.com/ComputeCanada/puppet-magic_castle) environment. @@ -1076,7 +1075,7 @@ find it automatically. Can be used to force a v4 subnet when both v4 and v6 exis **Post build modification effect**: rebuild of all instances at next `terraform apply`. -## 6. DNS Configuration and Wildcard SSL Certificate +## 6. DNS Configuration Some functionalities in Magic Castle require the registration of DNS records under the [cluster name](#44-cluster_name) in the selected [domain](#45-domain). This includes @@ -1089,12 +1088,6 @@ DNS records created and tracked by Magic Castle. If your DNS provider is not supported, you can manually create the records. Refer to the subsection [6.3](#63-unsupported-providers) for more details. -Optionally, Magic Castle can issue with [Let's encrypt DNS-01 challenge](https://letsencrypt.org/docs/challenge-types/#dns-01-challenge) -a wildcard certificate of the form `*.${cluster_name}.${domain_name}`. Refer to -the subsection [6.4](#64-wildcard-ssl-certificate) for more information. If no wildcard certificate is issued, -the reverse proxy server Caddy will automatically issue one certificate per virtual -host. - ### 6.1 Cloudflare 1. Uncomment the `dns` module for Cloudflare in your `main.tf`. @@ -1146,93 +1139,6 @@ if not OpenStack (i.e: `aws`, `gcp`, etc.). The file will be created after the `terraform apply` in the same folder as your `main.tf` and will be named as `${name}.${domain}.txt`. -### 6.4 Wildcard SSL Certificate - -**Requirement**: A private key associated with one of the -[public keys](#49-public_keys) needs to be tracked (i.e: `ssh-add`) by the local -[authentication agent](https://www.ssh.com/ssh/agent) (i.e: `ssh-agent`). -This module uses the ssh-agent tracked SSH keys to authenticate and -to copy SSL certificate files to the proxy nodes after their creation. - -To issue a wildcard SSL certificate with Magic Castle, modify the dns module call -in your `main.tf` like this: - -1. add the input: `issue_wildcard_cert = true` -2. add the input: `email = "replace.by@your.email"` - -#### 6.4.1 ACME Account Private Key - -To create the wildcard SSL certificate associated with the domain name, Magic Castle -creates a private key and register a new ACME account with this key. This account -registration process is done for each new cluster. However, ACME limits the number of -new accounts that can be created to a maximum of 10 per IP Address per 3 hours. - -If you plan to create more than 10 clusters per 3 hours, we recommend registering an -ACME account first and then provide its private key in PEM format to Magic Castle DNS -module, using the `acme_key_pem` variable. - -##### How to Generate an ACME Account Private Key - -In a separate folder, create a file with the following content -```hcl -terraform { - required_version = ">= 1.2.1" - required_providers { - acme = { - source = "vancluever/acme" - } - tls = { - source = "hashicorp/tls" - } - } -} - -variable "email" {} - -provider "acme" { - server_url = "https://acme-v02.api.letsencrypt.org/directory" -} -resource "tls_private_key" "private_key" { - algorithm = "RSA" -} -resource "acme_registration" "reg" { - account_key_pem = tls_private_key.private_key.private_key_pem - email_address = var.email -} -resource "local_file" "acme_key_pem" { - content = tls_private_key.private_key.private_key_pem - filename = "acme_key.pem" -} -``` - -In the same folder, enter the following commands and follow the instructions: -``` -terraform init -terraform apply -``` - -Once done, copy the file named `acme_key.pem` somewhere safe, and where you will be able -to refer to later on. Then, when the time comes to create a new cluster, add the following -variable to the DNS module in your `main.tf`: -```hcl -acme_key_pem = file("path/to/your/acme_key.pem") -``` - -#### 6.4.2 Issuing the wildcard SSL certificate manually - -Magic Castle generates with Let's Encrypt a wildcard certificate for `*.cluster_name.domain`. -You can use [certbot](https://certbot.eff.org/docs/using.html#dns-plugins) DNS-01 challenge -plugin to generate the wildcard certificate. - -You will then need to copy the certificate files in the proper location on each proxy node. -The reverse proxy configuration expects the following files to exist: - -- `/etc/letsencrypt/live/${domain_name}/fullchain.pem` -- `/etc/letsencrypt/live/${domain_name}/privkey.pem` -- `/etc/letsencrypt/live/${domain_name}/chain.pem` - -Refer to the [reverse proxy configuration](https://github.com/ComputeCanada/puppet-magic_castle/blob/main/site/profile/manifests/reverse_proxy.pp) for more details. - ### 6.5 SSHFP records and DNSSEC Magic Castle DNS module creates SSHFP records for all instances with a public ip address. From 8c699b81b9b7fc3f526aa971bfa718c8696c8a67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix-Antoine=20Fortin?= Date: Mon, 22 Jul 2024 14:08:34 -0400 Subject: [PATCH 21/24] Remove acme provider --- dns/cloudflare/main.tf | 4 ---- dns/cloudflare/versions.tf | 3 --- dns/gcloud/main.tf | 4 ---- dns/gcloud/versions.tf | 4 ---- 4 files changed, 15 deletions(-) diff --git a/dns/cloudflare/main.tf b/dns/cloudflare/main.tf index 64dc3dfe..aec8e036 100644 --- a/dns/cloudflare/main.tf +++ b/dns/cloudflare/main.tf @@ -1,7 +1,3 @@ -provider "acme" { - server_url = "https://acme-v02.api.letsencrypt.org/directory" -} - data "cloudflare_zones" "domain" { filter { name = var.domain diff --git a/dns/cloudflare/versions.tf b/dns/cloudflare/versions.tf index d44c99f5..13f44a60 100644 --- a/dns/cloudflare/versions.tf +++ b/dns/cloudflare/versions.tf @@ -5,9 +5,6 @@ terraform { cloudflare = { source = "cloudflare/cloudflare" } - acme = { - source = "vancluever/acme" - } tls = { source = "hashicorp/tls" } diff --git a/dns/gcloud/main.tf b/dns/gcloud/main.tf index b81d6cf6..acd67610 100644 --- a/dns/gcloud/main.tf +++ b/dns/gcloud/main.tf @@ -1,7 +1,3 @@ -provider "acme" { - server_url = "https://acme-v02.api.letsencrypt.org/directory" -} - data "google_dns_managed_zone" "domain" { name = var.zone_name project = var.project diff --git a/dns/gcloud/versions.tf b/dns/gcloud/versions.tf index d7f510e7..582096c4 100644 --- a/dns/gcloud/versions.tf +++ b/dns/gcloud/versions.tf @@ -1,13 +1,9 @@ - terraform { required_version = ">= 1.4.0" required_providers { google = { source = "hashicorp/google" } - acme = { - source = "vancluever/acme" - } tls = { source = "hashicorp/tls" } From 74c8f08313bf6255dd28a32062bf18d0db21c51a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix-Antoine=20Fortin?= Date: Mon, 22 Jul 2024 14:17:49 -0400 Subject: [PATCH 22/24] Remove ssh_private_key output from common --- common/configuration/main.tf | 2 +- common/outputs.tf | 5 ----- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/common/configuration/main.tf b/common/configuration/main.tf index 6a4586c7..7592d6b6 100644 --- a/common/configuration/main.tf +++ b/common/configuration/main.tf @@ -150,7 +150,7 @@ output "inventory" { output "ssh_key" { value = { - public = try("${chomp(tls_private_key.ssh.public_key_openssh)} terraform@localhost", null) + public = try("${chomp(tls_private_key.ssh.public_key_openssh)} tf@localhost", null) private = try(tls_private_key.ssh.private_key_pem, null) } } diff --git a/common/outputs.tf b/common/outputs.tf index e28d1b89..ef59d658 100644 --- a/common/outputs.tf +++ b/common/outputs.tf @@ -37,8 +37,3 @@ output "accounts" { } } } - -output "ssh_private_key" { - value = module.configuration.ssh_key.private - sensitive = true -} \ No newline at end of file From c0a4e20f876b5dfc917d75c17b3c61533f4c2c5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix-Antoine=20Fortin?= Date: Mon, 22 Jul 2024 15:46:17 -0400 Subject: [PATCH 23/24] Remove instructions on ssl certificate --- docs/README.md | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/docs/README.md b/docs/README.md index 98cb8d0c..0b4b3af9 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1516,25 +1516,6 @@ then call : terraform apply ``` -### 10.10 Generate a new SSL certificate - -The SSL certificate configured by the dns module is valid for [90 days](https://letsencrypt.org/docs/faq/#what-is-the-lifetime-for-let-s-encrypt-certificates-for-how-long-are-they-valid). -If you plan to use your cluster for more than 90 days, you will need to generate a -new SSL certificate before the one installed on the cluster expires. - -To generate a new certificate, use the following command on your computer: -``` -terraform taint 'module.dns.module.acme.acme_certificate.certificate' -``` - -Then apply the modification: -``` -terraform apply -``` - -The apply generates a new certificate, uploads it on the nodes that need it -and reloads the reverse proxy if it is configured. - ### 10.11 Set SELinux in permissive mode SELinux can be set in permissive mode to debug new workflows that would be From ba65c909e95c6fde0944c50987edb98ce5009e3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix-Antoine=20Fortin?= Date: Tue, 20 Aug 2024 11:29:04 -0400 Subject: [PATCH 24/24] Update design.md --- docs/design.md | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/design.md b/docs/design.md index 06fb5928..2a5fd395 100644 --- a/docs/design.md +++ b/docs/design.md @@ -432,7 +432,6 @@ that contains the attributes of instances that are publicly accessible from Inte terraform_data = module.configuration.terraform_data terraform_facts = module.configuration.terraform_facts hieradata = var.hieradata - sudoer_username = var.sudoer_username } ```