From 5253d4dd4152a61722895c0a1ca57a85cf8bd22c Mon Sep 17 00:00:00 2001 From: Alexandre Pires Date: Thu, 24 Apr 2025 19:15:04 +0200 Subject: [PATCH] Refactor CI/CD setup: streamline Python package installations and add bcrypt hashing for email credentials --- .github/actions/setup-ansible-env/action.yml | 6 ++-- .github/actions/setup-env/action.yml | 6 ++++ .../actions/setup-terraform-env/action.yml | 5 +++ lib/bcrypt_hash.py | 27 ++++++++++++++++ requirements.txt => requirements/ansible.txt | 0 requirements-dev.txt => requirements/dev.txt | 0 requirements/terraform.txt | 1 + terraform/iac/.vault | 1 - terraform/k8sapps/mail.tf | 32 ++++++++++++++----- terraform/k8sapps/resources/mail/run.config | 8 ++--- 10 files changed, 69 insertions(+), 17 deletions(-) create mode 100644 lib/bcrypt_hash.py rename requirements.txt => requirements/ansible.txt (100%) rename requirements-dev.txt => requirements/dev.txt (100%) create mode 100644 requirements/terraform.txt delete mode 100644 terraform/iac/.vault diff --git a/.github/actions/setup-ansible-env/action.yml b/.github/actions/setup-ansible-env/action.yml index e2f4d44..49ca91d 100644 --- a/.github/actions/setup-ansible-env/action.yml +++ b/.github/actions/setup-ansible-env/action.yml @@ -30,12 +30,10 @@ outputs: runs: using: "composite" steps: - - name: Install Python and required packages + - name: Install required python packages shell: bash run: | - sudo apt-get update - sudo apt-get install -y python3-pip - python3 -m pip install -r requirements.txt + python3 -m pip install -r requirements/ansible.txt - name: Prepare SSH key shell: bash diff --git a/.github/actions/setup-env/action.yml b/.github/actions/setup-env/action.yml index f500462..2fb5fed 100644 --- a/.github/actions/setup-env/action.yml +++ b/.github/actions/setup-env/action.yml @@ -17,3 +17,9 @@ runs: - name: Setup Sectool uses: a13labs/setup-sectool@v1 + + - name: Install Python and required packages + shell: bash + run: | + sudo apt-get update + sudo apt-get install -y python3-pip diff --git a/.github/actions/setup-terraform-env/action.yml b/.github/actions/setup-terraform-env/action.yml index 17ea03b..9979e62 100644 --- a/.github/actions/setup-terraform-env/action.yml +++ b/.github/actions/setup-terraform-env/action.yml @@ -8,3 +8,8 @@ runs: uses: hashicorp/setup-terraform@v1 with: terraform_version: 1.10.5 + + - name: Install required python packages + shell: bash + run: | + python3 -m pip install -r requirements/terraform.txt diff --git a/lib/bcrypt_hash.py b/lib/bcrypt_hash.py new file mode 100644 index 0000000..b8bbd07 --- /dev/null +++ b/lib/bcrypt_hash.py @@ -0,0 +1,27 @@ +import sys +import json +import bcrypt +import binascii + +# Read input JSON from stdin +input_data = json.load(sys.stdin) +password = input_data.get("password") +cost = int(input_data.get("cost", "10")) # Default cost 10 + +if not password: + print(json.dumps({"error": "Password is required"}), file=sys.stderr) + sys.exit(1) + +# Generate bcrypt hash +hashed_bytes = bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt(rounds=cost)) +hashed_string = hashed_bytes.decode('utf-8') + +# Hex encode for Glauth +hex_encoded_hash = binascii.hexlify(hashed_string.encode('utf-8')).decode('utf-8') + +# Output JSON to stdout +output_data = { + "bcrypt_hash": hashed_string, + "hex_encoded_bcrypt_hash": hex_encoded_hash +} +print(json.dumps(output_data)) \ No newline at end of file diff --git a/requirements.txt b/requirements/ansible.txt similarity index 100% rename from requirements.txt rename to requirements/ansible.txt diff --git a/requirements-dev.txt b/requirements/dev.txt similarity index 100% rename from requirements-dev.txt rename to requirements/dev.txt diff --git a/requirements/terraform.txt b/requirements/terraform.txt new file mode 100644 index 0000000..441145a --- /dev/null +++ b/requirements/terraform.txt @@ -0,0 +1 @@ +bcrypt \ No newline at end of file diff --git a/terraform/iac/.vault b/terraform/iac/.vault deleted file mode 100644 index 7007d14..0000000 --- a/terraform/iac/.vault +++ /dev/null @@ -1 +0,0 @@ -../../repository.vault \ No newline at end of file diff --git a/terraform/k8sapps/mail.tf b/terraform/k8sapps/mail.tf index 3adc301..56dd7ce 100644 --- a/terraform/k8sapps/mail.tf +++ b/terraform/k8sapps/mail.tf @@ -1,9 +1,10 @@ locals { - mail_path = "${local.persistent_folder}/mail" - mailboxes_path = "${local.mail_path}/mailboxes" - getmail_path = "${local.mail_path}/getmail" - postfix_path = "${local.mail_path}/postfix" - mail_backup_path = "${local.persistent_folder}/backup.mail" + mail_path = "${local.persistent_folder}/mail" + mailboxes_path = "${local.mail_path}/mailboxes" + getmail_path = "${local.mail_path}/getmail" + postfix_path = "${local.mail_path}/postfix" + mail_backup_path = "${local.persistent_folder}/backup.mail" + email_domain_name = "alexpires.me" email_accounts = [ { @@ -44,7 +45,8 @@ locals { # Email configuration SMTP_HOST = local.scaleway_smtp_host SMTP_PORT = 465 - MY_DESTINATION = "alexpires.me" + MY_PRIMARY_DOMAIN = local.email_domain_name + MY_DESTINATION = join(",", [for account in local.email_accounts : account.domain]) MY_NETWORKS = "127.0.0.0/8" MAILNAME = "smtp.alexpires.me" DOVECOT_AUTH_ADDRESS = "dovecot-auth.mail.svc.cluster.local" @@ -54,6 +56,10 @@ locals { LOG_TO_STDOUT = 1 } + password_hashes = { + for account in local.email_accounts : account.username => data.external.password_hasher[account.username].result.hex_encoded_bcrypt_hash + } + postfix_secrets = { SMTP_USER = { key = "username" @@ -67,6 +73,16 @@ locals { } } +data "external" "password_hasher" { + for_each = { for account in local.email_accounts : account.username => account } + program = ["python3", "${path.module}/../../lib/bcrypt_hash.py"] + + query = { + password = each.value.password + cost = "10" + } +} + resource "kubernetes_namespace" "mail" { metadata { annotations = { @@ -85,7 +101,7 @@ resource "kubernetes_secret" "dovecot_users" { namespace = kubernetes_namespace.mail.metadata[0].name } data = { - "users" = join("\n", [for account in local.email_accounts : "${account.username}:{plain}${account.password}:1000:1000::/var/mail/${account.username}::"]) + "users" = join("\n", [for account in local.email_accounts : "${account.username}:{BLF-CRYPT.HEX}${local.password_hashes[account.username]}:1000:1000::/var/mail/${account.username}::"]) } } @@ -419,7 +435,7 @@ resource "kubernetes_deployment" "dovecot" { ignore_changes = [spec[0].template[0].metadata[0].annotations] replace_triggered_by = [ kubernetes_config_map.dovecot_config, - kubernetes_secret.dovecot_users, + # kubernetes_secret.dovecot_users, kubernetes_config_map.dovecot_sieve, ] } diff --git a/terraform/k8sapps/resources/mail/run.config b/terraform/k8sapps/resources/mail/run.config index af95b44..33be523 100644 --- a/terraform/k8sapps/resources/mail/run.config +++ b/terraform/k8sapps/resources/mail/run.config @@ -25,9 +25,10 @@ if [ -z "$DOVECOT_AUTH_PORT" ]; then fi postconf -e "myhostname=$MAILNAME" -postconf -e "mydomain=$MY_DESTINATION" -postconf -e "myorigin=$MY_DESTINATION" -postconf -e "smtpd_banner = \$myhostname ESMTP \$mail_name" +postconf -e "mydomain=$MY_PRIMARY_DOMAIN" +postconf -e "myorigin=$MY_PRIMARY_DOMAIN" +postconf -e "smtpd_banner=\$myhostname ESMTP \$mail_name" +postconf -e "mydestination=$MY_DESTINATION" # Relay configuration postconf -e "relayhost=[$SMTP_HOST]:$SMTP_PORT" @@ -47,7 +48,6 @@ postconf -e "smtpd_recipient_restrictions=permit_sasl_authenticated, reject" postconf -e "smtpd_relay_restrictions=permit_sasl_authenticated, reject_unauth_destination" postconf -e "smtpd_sasl_authenticated_header=yes" postconf -e "smtpd_tls_wrappermode=yes" -postconf -e "smtpd_sasl_local_domain=$MY_DESTINATION" # TLS configuration postconf -e "smtpd_tls_cert_file=/etc/letsencrypt/tls.crt"