Migrate certificate-automation from consul-template to vault-agent
- Migrated Ansible integration from consul_template to vault_agent - Copied vault_agent role from terraform-vsphere-infra module - Created vault_agent-playbook.yml for deployment - Archived consul_template role as consul_template-legacy - Updated Terraform configuration: - Changed Ansible inventory group from consul_template to vault_agent - Added vault_secret_path variable for vault-agent - Added ssl_certs_dir and ssl_private_dir variables - Formatted all Terraform files - Implemented CI/CD pipeline: - Created .gitea/workflows/pipeline.yaml - Added TFLint, Tfsec, and Checkov security scans - Added Terraform validate step - Added SonarQube integration - Created sonar-project.properties - Documentation updates: - Updated README.md with vault-agent information - Added migration section comparing consul-template vs vault-agent - Updated CLAUDE.md with vault-agent architecture - Added vault-agent configuration examples Why vault-agent over consul-template: - Full AppRole support with role_id/secret_id files - Advanced token auto-renewal with auto_auth - Better credential security (separate files vs config) - Actively developed by HashiCorp Note: The ansible/ directory changes (vault_agent role and playbook) are not committed as the directory is in .gitignore. These files exist locally and will be deployed during Ansible runs.
This commit is contained in:
parent
47aaaa2143
commit
9c0d389dd3
116
.gitea/workflows/pipeline.yaml
Normal file
116
.gitea/workflows/pipeline.yaml
Normal file
@ -0,0 +1,116 @@
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened]
|
||||
|
||||
name: Code Quality & Security Scan
|
||||
jobs:
|
||||
tflint:
|
||||
name: TFLint
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checking out
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup TFLint
|
||||
uses: terraform-linters/setup-tflint@v4
|
||||
with:
|
||||
tflint_version: latest
|
||||
|
||||
- name: Initialize TFLint
|
||||
working-directory: terraform
|
||||
run: tflint --init
|
||||
|
||||
- name: Run TFLint
|
||||
working-directory: terraform
|
||||
run: tflint --format compact
|
||||
|
||||
tfsec:
|
||||
name: Tfsec Security Scan
|
||||
runs-on: ubuntu-latest
|
||||
needs: tflint
|
||||
steps:
|
||||
- name: Checking out
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Run Tfsec
|
||||
uses: aquasecurity/tfsec-action@v1.0.3
|
||||
with:
|
||||
working_directory: terraform
|
||||
format: default
|
||||
soft_fail: false
|
||||
|
||||
checkov:
|
||||
name: Checkov Security Scan
|
||||
runs-on: ubuntu-latest
|
||||
needs: tfsec
|
||||
steps:
|
||||
- name: Checking out
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Run Checkov
|
||||
uses: bridgecrewio/checkov-action@v12
|
||||
with:
|
||||
directory: terraform
|
||||
framework: terraform
|
||||
output_format: cli
|
||||
soft_fail: false
|
||||
|
||||
terraform-validate:
|
||||
name: Terraform Validate
|
||||
runs-on: ubuntu-latest
|
||||
needs: checkov
|
||||
steps:
|
||||
- name: Checking out
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup Terraform
|
||||
uses: hashicorp/setup-terraform@v3
|
||||
with:
|
||||
terraform_version: latest
|
||||
|
||||
- name: Terraform Format Check
|
||||
working-directory: terraform
|
||||
run: terraform fmt -check -recursive
|
||||
|
||||
- name: Terraform Init (for validation)
|
||||
working-directory: terraform
|
||||
env:
|
||||
TF_VAR_vault_address: "https://vault.example.com:8200"
|
||||
TF_VAR_environment: "test"
|
||||
TF_VAR_short_hostname: "test-host"
|
||||
run: terraform init -backend=false
|
||||
|
||||
- name: Terraform Validate
|
||||
working-directory: terraform
|
||||
env:
|
||||
TF_VAR_vault_address: "https://vault.example.com:8200"
|
||||
TF_VAR_environment: "test"
|
||||
TF_VAR_short_hostname: "test-host"
|
||||
run: terraform validate
|
||||
|
||||
sonarqube:
|
||||
name: SonarQube Trigger
|
||||
runs-on: ubuntu-latest
|
||||
needs: terraform-validate
|
||||
steps:
|
||||
- name: Checking out
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
# Disabling shallow clone is recommended for improving relevancy of reporting
|
||||
fetch-depth: 0
|
||||
- name: SonarQube Scan
|
||||
uses: sonarsource/sonarqube-scan-action@v6
|
||||
env:
|
||||
SONAR_HOST_URL: ${{ secrets.SONARQUBE_HOST }}
|
||||
SONAR_TOKEN: ${{ secrets.SONARQUBE_TOKEN }}
|
||||
114
CLAUDE.md
Normal file
114
CLAUDE.md
Normal file
@ -0,0 +1,114 @@
|
||||
# CLAUDE.md
|
||||
|
||||
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||||
|
||||
## Repository Overview
|
||||
|
||||
This is a Terraform module for automated TLS certificate deployment using Vault, vault-agent, Terraform, and Ansible. The module creates Vault AppRole authentication and policies, then deploys vault-agent via Ansible to automatically fetch and deploy certificates from Vault.
|
||||
|
||||
**Note**: This module has been migrated from consul-template to vault-agent for better AppRole support and improved security.
|
||||
|
||||
## Architecture
|
||||
|
||||
### Terraform Configuration (`terraform/`)
|
||||
- **main.tf**: Creates Vault policies, AppRole authentication, and Ansible inventory
|
||||
- **variables.tf**: Defines `environment` and `short_hostname` variables
|
||||
- **outputs.tf**: Outputs sensitive AppRole credentials (role_id and secret_id)
|
||||
- **backend.tf, provider.tf, data.tf**: Standard Terraform configuration files
|
||||
|
||||
### Ansible Configuration (`ansible/`)
|
||||
- **vault_agent-playbook.yml**: Main playbook that deploys vault-agent
|
||||
- **roles/vault_agent/**: Ansible role for vault-agent installation and configuration
|
||||
- Downloads and installs vault binary from HashiCorp releases
|
||||
- Creates systemd service for vault-agent
|
||||
- Configures AppRole authentication with role_id/secret_id files
|
||||
- Deploys certificate templates for automatic renewal
|
||||
- **roles/consul_template-legacy/**: Archived legacy consul-template role (for reference)
|
||||
- **collections/**: Contains Ansible collections (cloud.terraform, community.crypto, etc.)
|
||||
|
||||
### Key Components
|
||||
- **Vault Integration**: Uses AppRole authentication for secure certificate access
|
||||
- **Certificate Templates**: Automatically fetches certificates, private keys, and certificate chains
|
||||
- **System Integration**: Configures systemd service and file permissions for certificate deployment
|
||||
|
||||
## Common Commands
|
||||
|
||||
### Terraform Operations
|
||||
```bash
|
||||
cd terraform/
|
||||
terraform init
|
||||
terraform plan
|
||||
terraform apply
|
||||
terraform destroy
|
||||
```
|
||||
|
||||
### Ansible Operations
|
||||
```bash
|
||||
cd ansible/
|
||||
ansible-playbook -i inventory.yml vault_agent-playbook.yml
|
||||
```
|
||||
|
||||
### Certificate Template Files
|
||||
- `certificate.tpl`: Certificate template (fullchain)
|
||||
- `private_key.tpl`: Private key template
|
||||
- `chain_pem.tpl`: Certificate chain template
|
||||
|
||||
**Note**: Template files are dynamically generated by the vault_agent role during deployment.
|
||||
|
||||
## Security Considerations
|
||||
|
||||
- AppRole credentials are marked as sensitive in Terraform outputs
|
||||
- Certificate files are deployed with restricted permissions (600)
|
||||
- Vault policies follow principle of least privilege (read-only access to specific secret paths)
|
||||
- Ansible Vault should be used for encrypting sensitive variables (`vault_credentials.yml`)
|
||||
|
||||
## Module Usage Pattern
|
||||
|
||||
1. Deploy Vault AppRoles and policies with Terraform
|
||||
2. Generate Ansible Vault credentials using `ansible_vault_output.sh`
|
||||
3. Run Ansible playbook to deploy vault-agent: `ansible-playbook vault_agent-playbook.yml`
|
||||
4. vault-agent automatically fetches and renews certificates from Vault using AppRole authentication
|
||||
|
||||
## Why Vault-Agent?
|
||||
|
||||
This module migrated from consul-template to vault-agent for several reasons:
|
||||
|
||||
| Feature | consul-template | vault-agent |
|
||||
|---------|----------------|-------------|
|
||||
| AppRole Authentication | ❌ Limited support | ✅ Full support with role_id/secret_id files |
|
||||
| Token Auto-Renewal | ⚠️ Basic | ✅ Advanced with auto_auth |
|
||||
| Credential Storage | ❌ In config file | ✅ Separate secure files |
|
||||
| Active Development | ⚠️ Maintenance mode | ✅ Actively developed |
|
||||
|
||||
## vault-agent Configuration
|
||||
|
||||
vault-agent uses AppRole auto_auth:
|
||||
|
||||
```hcl
|
||||
auto_auth {
|
||||
method "approle" {
|
||||
mount_path = "auth/approle"
|
||||
config = {
|
||||
role_id_file_path = "/etc/vault-agent/role_id"
|
||||
secret_id_file_path = "/etc/vault-agent/secret_id"
|
||||
}
|
||||
}
|
||||
|
||||
sink "file" {
|
||||
config = {
|
||||
path = "/opt/vault-agent/vault-token"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Certificate templates automatically fetch secrets from Vault:
|
||||
|
||||
```hcl
|
||||
template {
|
||||
source = "/etc/vault-agent/certificate.tpl"
|
||||
destination = "/etc/ssl/certs/hostname.crt"
|
||||
perms = 0644
|
||||
command = "systemctl reload nginx" # Service-specific reload
|
||||
}
|
||||
```
|
||||
36
README.md
36
README.md
@ -4,12 +4,12 @@ This Terraform module automates TLS certificate deployment by creating Vault App
|
||||
|
||||
## Purpose
|
||||
|
||||
This module sets up the infrastructure needed to automatically fetch and deploy TLS certificates from HashiCorp Vault to target servers. It creates:
|
||||
This module sets up the infrastructure needed to automatically fetch and deploy TLS certificates from HashiCorp Vault to target servers using Vault Agent. It creates:
|
||||
|
||||
- Vault policies with read-only access to certificate secrets
|
||||
- AppRole authentication backend configuration
|
||||
- AppRole credentials for secure authentication
|
||||
- Ansible inventory entries for automated deployment
|
||||
- Ansible inventory entries for automated vault-agent deployment
|
||||
|
||||
## What It Does
|
||||
|
||||
@ -84,7 +84,7 @@ This module creates the following Vault resources:
|
||||
- Token Max TTL: 4 hours
|
||||
- Secret ID TTL: 24 hours
|
||||
|
||||
- **Ansible Host**: Added to `consul_template` group with Vault credentials
|
||||
- **Ansible Host**: Added to `vault_agent` group with Vault credentials
|
||||
|
||||
## Secret Path Convention
|
||||
|
||||
@ -106,22 +106,25 @@ Example: `secret/data/production/web01/certificate`
|
||||
This module automatically creates an Ansible inventory entry with:
|
||||
|
||||
- Inventory hostname: `{short_hostname}`
|
||||
- Group: `consul_template`
|
||||
- Group: `vault_agent`
|
||||
- Variables:
|
||||
- `vault_approle_role_id`
|
||||
- `vault_approle_secret_id`
|
||||
- `vault_address`
|
||||
- `vault_secret_path`
|
||||
- `environment`
|
||||
- `short_hostname`
|
||||
- `ssl_certs_dir`
|
||||
- `ssl_private_dir`
|
||||
|
||||
The generated inventory can be used with the included Ansible playbooks in the `ansible/` directory to deploy consul-template for automated certificate retrieval.
|
||||
The generated inventory can be used with the included Ansible playbooks in the `ansible/` directory to deploy vault-agent for automated certificate retrieval.
|
||||
|
||||
## Deployment Steps
|
||||
|
||||
1. Deploy Vault AppRoles and policies with Terraform
|
||||
2. Generate Ansible Vault credentials (`ansible_vault_output.sh`)
|
||||
3. Run Ansible playbook to deploy consul-template
|
||||
4. consul-template automatically fetches and renews certificates from Vault
|
||||
3. Run Ansible playbook to deploy vault-agent: `ansible-playbook vault_agent-playbook.yml`
|
||||
4. vault-agent automatically fetches and renews certificates from Vault using AppRole authentication
|
||||
|
||||
## Security Considerations
|
||||
|
||||
@ -135,9 +138,22 @@ The generated inventory can be used with the included Ansible playbooks in the `
|
||||
|
||||
This module works in conjunction with:
|
||||
|
||||
- **Ansible Playbooks** (in `ansible/` directory): Deploy consul-template to target servers
|
||||
- **Consul-Template**: Automatically fetches and renews certificates from Vault
|
||||
- **Vault PKI**: Stores certificates that this module provides access to
|
||||
- **Ansible Playbooks** (in `ansible/` directory): Deploy vault-agent to target servers
|
||||
- **Vault Agent**: Automatically fetches and renews certificates from Vault using AppRole authentication
|
||||
- **Vault KV Secrets Engine**: Stores certificates that this module provides access to
|
||||
|
||||
## Migration from consul-template
|
||||
|
||||
This module has been migrated from consul-template to vault-agent for better AppRole support and improved security. Key differences:
|
||||
|
||||
| Feature | consul-template (legacy) | vault-agent (current) |
|
||||
|---------|-------------------------|----------------------|
|
||||
| AppRole Auth | ❌ Limited support | ✅ Full support with role_id/secret_id files |
|
||||
| Token Management | ⚠️ Basic | ✅ Advanced auto_auth |
|
||||
| Security | ❌ Credentials in config | ✅ Separate credential files |
|
||||
| Active Development | ⚠️ Maintenance mode | ✅ Actively developed |
|
||||
|
||||
The legacy consul-template role is archived as `consul_template-legacy` for reference.
|
||||
|
||||
## Notes
|
||||
|
||||
|
||||
13
sonar-project.properties
Normal file
13
sonar-project.properties
Normal file
@ -0,0 +1,13 @@
|
||||
sonar.projectKey=terraform-certificate-automation
|
||||
sonar.projectName=Terraform Certificate Automation Module
|
||||
sonar.projectVersion=1.0
|
||||
|
||||
# Path to source directories
|
||||
sonar.sources=terraform,ansible
|
||||
|
||||
# Exclusions
|
||||
sonar.exclusions=**/*.tfvars,**/.terraform/**,**/files/**,**/collections/**,**/consul_template-legacy/**
|
||||
|
||||
# Terraform-specific settings
|
||||
sonar.language=terraform
|
||||
sonar.sourceEncoding=UTF-8
|
||||
@ -1,11 +1,11 @@
|
||||
terraform {
|
||||
backend "s3" {
|
||||
endpoints = {
|
||||
s3 = "https://minio.bsdserver.nl:443"
|
||||
s3 = "https://minio.bsdserver.nl:443"
|
||||
}
|
||||
|
||||
bucket = "home-terraform"
|
||||
key = "home/security/encryption/certificate-automation.tfstate"
|
||||
bucket = "home-terraform"
|
||||
key = "home/security/encryption/certificate-automation.tfstate"
|
||||
|
||||
# Configure credentials via environment variables:
|
||||
# export AWS_ACCESS_KEY_ID="your-access-key"
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
locals {
|
||||
secret_path = "secret/data/${var.environment}/${var.short_hostname}/certificate"
|
||||
policy_name = "${var.environment}-${var.short_hostname}-cert-policy"
|
||||
secret_path = "secret/data/${var.environment}/${var.short_hostname}/certificate"
|
||||
policy_name = "${var.environment}-${var.short_hostname}-cert-policy"
|
||||
approle_name = "${var.environment}-${var.short_hostname}-approle"
|
||||
}
|
||||
|
||||
resource "vault_policy" "cert_access" {
|
||||
name = local.policy_name
|
||||
name = local.policy_name
|
||||
policy = <<EOT
|
||||
path "${local.secret_path}" {
|
||||
capabilities = ["read"]
|
||||
@ -27,9 +27,9 @@ resource "vault_approle_auth_backend_role_secret_id" "cert_role_secret" {
|
||||
role_name = vault_approle_auth_backend_role.cert_role.role_name
|
||||
}
|
||||
|
||||
resource "ansible_host" "consul_template_node" {
|
||||
resource "ansible_host" "vault_agent_node" {
|
||||
inventory_hostname = var.short_hostname
|
||||
groups = ["consul_template"]
|
||||
groups = ["vault_agent"]
|
||||
|
||||
vars = {
|
||||
ansible_user = "ansible"
|
||||
@ -38,7 +38,10 @@ resource "ansible_host" "consul_template_node" {
|
||||
vault_approle_role_id = vault_approle_auth_backend_role.cert_role.role_id
|
||||
vault_approle_secret_id = vault_approle_auth_backend_role_secret_id.cert_role_secret.secret_id
|
||||
vault_address = var.vault_address
|
||||
vault_secret_path = local.secret_path
|
||||
environment = var.environment
|
||||
short_hostname = var.short_hostname
|
||||
ssl_certs_dir = "/etc/ssl/certs"
|
||||
ssl_private_dir = "/etc/ssl/private"
|
||||
}
|
||||
}
|
||||
|
||||
@ -11,14 +11,14 @@ terraform {
|
||||
|
||||
# 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
|
||||
}
|
||||
address = var.vault_address
|
||||
auth_login {
|
||||
path = "auth/approle/login"
|
||||
parameters = {
|
||||
role_id = var.role_id
|
||||
secret_id = var.secret_id
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Ansible Provider
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user