Compare commits

...

5 Commits
master ... main

Author SHA1 Message Date
9c31f9ce4c
Remove backend.tf from child module
Some checks failed
Code Quality & Security Scan / Tfsec Security Scan (push) Has been skipped
Code Quality & Security Scan / Checkov Security Scan (push) Has been skipped
Code Quality & Security Scan / Terraform Validate (push) Has been skipped
Code Quality & Security Scan / SonarQube Trigger (push) Has been skipped
Code Quality & Security Scan / TFLint (push) Failing after 22s
- backend.tf should only exist in root modules, not child modules
- Removes warning: Backend configuration ignored
- This module is only used as a child module via git source
2025-11-10 23:02:30 +01:00
6db178e6ba
Fix TFLint setup timeout by pinning version
Some checks failed
Code Quality & Security Scan / Tfsec Security Scan (push) Has been skipped
Code Quality & Security Scan / Checkov Security Scan (push) Has been skipped
Code Quality & Security Scan / Terraform Validate (push) Has been skipped
Code Quality & Security Scan / SonarQube Trigger (push) Has been skipped
Code Quality & Security Scan / TFLint (push) Failing after 29s
- Changed tflint_version from 'latest' to 'v0.50.3'
- Avoids GitHub API timeout when fetching latest release
- Fixes: Connect Timeout Error in Setup TFLint step
2025-11-10 22:15:45 +01:00
003572082e
Remove provider blocks from child module to support for_each
Some checks failed
Code Quality & Security Scan / TFLint (push) Failing after 36s
Code Quality & Security Scan / Tfsec Security Scan (push) Has been skipped
Code Quality & Security Scan / Checkov Security Scan (push) Has been skipped
Code Quality & Security Scan / Terraform Validate (push) Has been skipped
Code Quality & Security Scan / SonarQube Trigger (push) Has been skipped
- Removed provider blocks for Vault and Ansible from provider.tf
- Module now accepts provider configuration from parent module
- Updated Vault provider version from ~> 4.0 to ~> 5.3 for compatibility
- Fixes: Module is incompatible with count, for_each, and depends_on error
2025-11-10 22:04:31 +01:00
3af1102377
Add consul_template role files from master branch
Some checks failed
Code Quality & Security Scan / TFLint (push) Failing after 38s
Code Quality & Security Scan / Tfsec Security Scan (push) Has been skipped
Code Quality & Security Scan / Checkov Security Scan (push) Has been skipped
Code Quality & Security Scan / Terraform Validate (push) Has been skipped
Code Quality & Security Scan / SonarQube Trigger (push) Has been skipped
- Added all files from consul_template-legacy and consul_template-org roles
- These roles are now regular directories instead of submodules
2025-11-10 22:01:17 +01:00
381e1086a3
Convert consul_template submodules to regular directories
Some checks failed
Code Quality & Security Scan / TFLint (push) Failing after 38s
Code Quality & Security Scan / Tfsec Security Scan (push) Has been skipped
Code Quality & Security Scan / Checkov Security Scan (push) Has been skipped
Code Quality & Security Scan / Terraform Validate (push) Has been skipped
Code Quality & Security Scan / SonarQube Trigger (push) Has been skipped
- Removed gitlink entries for consul_template-legacy and consul_template-org
- Converted from git submodules to regular directories
- Fixes: 'fatal: No url found for submodule path' error when downloading module
- Required for using module with git::https:// source in parent modules
2025-11-10 22:00:26 +01:00
24 changed files with 330 additions and 41 deletions

View File

@ -20,7 +20,7 @@ jobs:
- name: Setup TFLint - name: Setup TFLint
uses: terraform-linters/setup-tflint@v4 uses: terraform-linters/setup-tflint@v4
with: with:
tflint_version: latest tflint_version: v0.50.3
- name: Initialize TFLint - name: Initialize TFLint
working-directory: terraform working-directory: terraform

@ -1 +0,0 @@
Subproject commit 011db9074813e45da783f410592c31a0f31c482e

View File

@ -0,0 +1,49 @@
#consul_template
An Ansible role to install and configure HashiCorps consul-template, securely fetching TLS certificates and private keys\
from HashiCorp Vault using AppRole authentication, rendering them to disk, and reloading services when certificates change.
### Requirements
• consul-template binary downloaded from HashiCorp releases.
• Network connectivity from the target host to the Vault instance (vault_address).
• Appropriate Vault AppRole credentials (vault_approle_role_id, vault_approle_secret_id) provisioned by Terraform or other automation.
### Role Variables
The following variables are required and should be set either through inventory or as role parameters:
| Variable | Description | Default |
| vault_address | URL of your HashiCorp Vault instance | None (required) |
| vault_approle_role_id | Vault AppRole Role ID for consul-template authentication | None (required) |
| vault_approle_secret_id | Vault AppRole Secret ID for consul-template authentication | None (required) |
| environment | Environment identifier (e.g., prod, nonprod) | None (required) |
| short_hostname | Short hostname of the target server (used in file naming) | None (required) |
### Dependencies
No direct Ansible Galaxy role dependencies. However, it relies on Terraform to provision AppRole credentials and Vault secrets.
### Example Playbook
Example playbook demonstrating basic role usage:
```yml
- hosts: webservers
become: true
roles:
- role: consul_template
vars:
vault_address: "https://vault.example.com:8200"
vault_approle_role_id: "{{ vault_approle_role_id }}"
vault_approle_secret_id: "{{ vault_approle_secret_id }}"
environment: "prod"
short_hostname: "web01"
```
### License
BSD
### Author Information
Created by Patrick De Ruiter.

View File

@ -0,0 +1,3 @@
#SPDX-License-Identifier: MIT-0
---
# defaults file for consul_template

View File

@ -0,0 +1,5 @@
{{ with secret "secret/data/{{ environment }}/{{ short_hostname }}/certificate" }}
{{ .Data.data.certificate }}
{{ .Data.data.chain_pem }}
{{ end }}

View File

@ -0,0 +1,3 @@
{{ with secret "secret/data/{{ environment }}/{{ short_hostname }}/certificate" }}
{{ .Data.data.chain_pem }}
{{ end }}

View File

@ -0,0 +1,3 @@
{{ with secret "secret/data/{{ environment }}/{{ short_hostname }}/certificate" }}
{{ .Data.data.private_key }}
{{ end }}

View File

@ -0,0 +1,9 @@
#SPDX-License-Identifier: MIT-0
---
# handlers file for consul_template
- name: restart consul-template
systemd:
name: consul-template
state: restarted
daemon_reload: yes

View File

@ -0,0 +1,20 @@
#SPDX-License-Identifier: BSD-3-Clause
galaxy_info:
author: Patrick De Ruiter
description: An Ansible role to install and configure consul-template, fetching TLS certificates from HashiCorp Vault using AppRole authentication.
company: “Benerail N.V.”
license: BSD-3-Clause
min_ansible_version: 2.10
galaxy_tags:
- vault
- consul
- consultemplate
- tls
- certificates
- security
- automation
dependencies: []

View File

@ -0,0 +1,86 @@
- name: Determine architecture
set_fact:
consul_template_arch: "{{ arch_mapping[ansible_architecture] | default('amd64') }}"
- name: Download consul-template checksum file
get_url:
url: "https://releases.hashicorp.com/consul-template/{{ consul_template.version }}/consul-template_{{ consul_template.version }}_SHA256SUMS"
dest: "/tmp/consul-template_{{ consul_template.version }}_SHA256SUMS"
mode: '0644'
- name: Extract expected checksum
shell: |
grep "consul-template_{{ consul_template.version }}_linux_{{ consul_template_arch }}.zip" \
/tmp/consul-template_{{ consul_template.version }}_SHA256SUMS | cut -d' ' -f1
register: expected_checksum
changed_when: false
- name: Install consul-template
unarchive:
src: "https://releases.hashicorp.com/consul-template/{{ consul_template.version }}/consul-template_{{ consul_template.version }}_linux_{{ consul_template_arch }}.zip"
dest: "{{ consul_template.install_dir }}"
remote_src: yes
owner: root
group: root
mode: '0755'
checksum: "sha256:{{ expected_checksum.stdout }}"
- name: Create consul-template user
user:
name: "{{ consul_template.user }}"
group: "{{ consul_template.group }}"
system: yes
shell: /bin/false
home: "{{ consul_template.config_dir }}"
create_home: no
- name: Create consul-template group
group:
name: "{{ consul_template.group }}"
system: yes
- name: Create consul-template directories
file:
path: "{{ item.path }}"
state: directory
mode: "{{ item.mode }}"
owner: "{{ item.owner | default('root') }}"
group: "{{ item.group | default('root') }}"
loop:
- { path: "{{ consul_template.config_dir }}", mode: '0755', owner: "{{ consul_template.user }}", group: "{{ consul_template.group }}" }
- { path: "{{ certificate_paths.cert_dir }}", mode: '0755' }
- { path: "{{ certificate_paths.private_dir }}", mode: '0700' }
- name: Deploy consul-template template files
copy:
src: "{{ item }}"
dest: "{{ consul_template.config_dir }}/{{ item }}"
mode: '0644'
owner: "{{ consul_template.user }}"
group: "{{ consul_template.group }}"
loop:
- certificate.ctmpl
- private_key.ctmpl
- chain_pem.ctmpl
notify: restart consul-template
- name: Deploy consul-template config
template:
src: consul-template-config.hcl.j2
dest: "{{ consul_template.config_dir }}/config.hcl"
mode: '0600'
owner: "{{ consul_template.user }}"
group: "{{ consul_template.group }}"
notify: restart consul-template
- name: Deploy consul-template systemd unit
template:
src: consul-template.service.j2
dest: /etc/systemd/system/consul-template.service
- name: Enable and start consul-template
systemd:
name: consul-template
enabled: true
state: started
daemon_reload: yes

View File

@ -0,0 +1,35 @@
vault {
address = "{{ vault_address }}"
auth {
method "approle" {
config = {
role_id = "{{ vault_approle_role_id }}"
secret_id = "{{ vault_approle_secret_id }}"
}
}
}
renew_token = true
}
log_level = "{{ consul_template.log_level | default('INFO') }}"
template {
source = "{{ consul_template.config_dir }}/certificate.ctmpl"
destination = "{{ certificate_paths.cert_dir }}/{{ certificate_paths.cert_file }}"
command = "{{ service_reload_commands[certificate_service | default('default')] }}"
perms = 0644
}
template {
source = "{{ consul_template.config_dir }}/private_key.ctmpl"
destination = "{{ certificate_paths.private_dir }}/{{ certificate_paths.private_key_file }}"
command = "chmod 600 {{ certificate_paths.private_dir }}/{{ certificate_paths.private_key_file }}"
perms = 0600
}
template {
source = "{{ consul_template.config_dir }}/chain_pem.ctmpl"
destination = "{{ certificate_paths.private_dir }}/{{ certificate_paths.chain_file }}"
command = "chmod 600 {{ certificate_paths.private_dir }}/{{ certificate_paths.chain_file }}"
perms = 0600
}

View File

@ -0,0 +1,18 @@
[Unit]
Description=consul-template TLS Certificate
After=network-online.target
Wants=network-online.target
[Service]
Type=notify
User={{ consul_template.user }}
Group={{ consul_template.group }}
ExecStart={{ consul_template.install_dir }}/consul-template \
-config={{ consul_template.config_dir }}/config.hcl
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
Restart=on-failure
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target

View File

@ -0,0 +1,3 @@
#SPDX-License-Identifier: MIT-0
localhost

View File

@ -0,0 +1,6 @@
#SPDX-License-Identifier: MIT-0
---
- hosts: localhost
remote_user: root
roles:
- consul_template

View File

@ -0,0 +1,3 @@
#SPDX-License-Identifier: MIT-0
---
# vars file for consul_template

@ -1 +0,0 @@
Subproject commit 7c00f1e5e059869c33291948282e7772e5427562

View File

@ -0,0 +1,5 @@
{{ with secret "secret/data/{{ environment }}/{{ short_hostname }}/certificate" }}
{{ .Data.data.certificate }}
{{ .Data.data.chain_pem }}
{{ end }}

View File

@ -0,0 +1,3 @@
{{ with secret "secret/data/{{ environment }}/{{ short_hostname }}/certificate" }}
{{ .Data.data.chain_pem }}
{{ end }}

View File

@ -0,0 +1,3 @@
{{ with secret "secret/data/{{ environment }}/{{ short_hostname }}/certificate" }}
{{ .Data.data.private_key }}
{{ end }}

View File

@ -0,0 +1,33 @@
- name: Install consul-template
unarchive:
src: "https://releases.hashicorp.com/consul-template/0.37.4/consul-template_0.37.4_linux_amd64.zip"
dest: /usr/local/bin
remote_src: yes
- name: Create consul-template directories
file:
path: "{{ item }}"
state: directory
mode: '0755'
loop:
- /etc/consul-template
- /etc/ssl/certs
- /etc/ssl/private
- name: Deploy consul-template config
template:
src: consul-template-config.hcl.j2
dest: /etc/consul-template/config.hcl
mode: '0600'
- name: Deploy consul-template systemd unit
template:
src: consul-template.service.j2
dest: /etc/systemd/system/consul-template.service
- name: Enable and start consul-template
systemd:
name: consul-template
enabled: true
state: restarted
daemon_reload: yes

View File

@ -0,0 +1,30 @@
vault {
address = "{{ vault_address }}"
auth {
method "approle" {
config = {
role_id = "{{ vault_approle_role_id }}"
secret_id = "{{ vault_approle_secret_id }}"
}
}
}
renew_token = true
}
template {
source = "/etc/consul-template/certificate.ctmpl"
destination = "/etc/ssl/certs/{{ short_hostname }}.pem"
command = "systemctl reload nginx"
}
template {
source = "/etc/consul-template/private_key.ctmpl"
destination = "/etc/ssl/private/{{ short_hostname }}.key"
command = "chmod 600 /etc/ssl/private/{{ short_hostname }}.key"
}
template {
source = "/etc/consul-template/chain_pem.ctmpl"
destination = "/etc/ssl/private/le-chaincert.pem"
command = "chmod 600 /etc/ssl/private/le-chaincert.pem"
}

View File

@ -0,0 +1,11 @@
[Unit]
Description=consul-template TLS Certificate
After=network-online.target
[Service]
ExecStart=/usr/local/bin/consul-template \
-config=/etc/consul-template/config.hcl
Restart=always
[Install]
WantedBy=multi-user.target

View File

@ -1,21 +0,0 @@
terraform {
backend "s3" {
endpoints = {
s3 = "https://minio.bsdserver.nl:443"
}
bucket = "home-terraform"
key = "home/security/encryption/certificate-automation.tfstate"
# Configure credentials via environment variables:
# export AWS_ACCESS_KEY_ID="your-access-key"
# export AWS_SECRET_ACCESS_KEY="your-secret-key"
region = "main"
skip_credentials_validation = true
skip_metadata_api_check = true
skip_requesting_account_id = true
skip_region_validation = true
use_path_style = true
}
}

View File

@ -8,23 +8,7 @@ terraform {
} }
vault = { vault = {
source = "hashicorp/vault" source = "hashicorp/vault"
version = "~> 4.0" version = "~> 5.3"
} }
} }
} }
# Configure the Vault provider
provider "vault" {
address = var.vault_address
auth_login {
path = "auth/approle/login"
parameters = {
role_id = var.role_id
secret_id = var.secret_id
}
}
}
# Ansible Provider
provider "ansible" {
}