diff --git a/terraform-vault-pki/.gitignore b/terraform-vault-pki/.gitignore new file mode 100644 index 0000000..b992b4b --- /dev/null +++ b/terraform-vault-pki/.gitignore @@ -0,0 +1,4 @@ +*.tfstate +*.plan +.terraform/* +*.backup diff --git a/terraform-vault-pki/.terraform.lock.hcl b/terraform-vault-pki/.terraform.lock.hcl new file mode 100644 index 0000000..234d8fc --- /dev/null +++ b/terraform-vault-pki/.terraform.lock.hcl @@ -0,0 +1,22 @@ +# This file is maintained automatically by "terraform init". +# Manual edits may be lost in future updates. + +provider "registry.terraform.io/hashicorp/vault" { + version = "4.8.0" + constraints = "~> 4.0" + hashes = [ + "h1:aHqgWQhDBMeZO9iUKwJYMlh4q+xNMUlMIcjRbF4d02Y=", + "zh:269ab13433f67684012ae7e15876532b0312f5d0d2002a9cf9febb1279ce5ea6", + "zh:4babc95bf0c40eb85005db1dc2ca403c46be4a71dd3e409db3711a56f7a5ca0e", + "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", + "zh:86e27c1c625ecc24446a11eeffc3ac319b36c2b4e51251db8579256a0dbcf136", + "zh:a32f31da94824009e26b077374440b52098aecb93c92ff55dc3d31dd37c4ea25", + "zh:be0a18c6c0425518bab4fbffd82078b82036a88503b5d76064de551c9f646cbf", + "zh:be5a77fdfd36863ebeec79cd12b1d13322ffad6821d157a0b279789fa06b5937", + "zh:be8317d142a3caad74c7d936039ae27076a1b2b8312ef5208e2871a5f525977c", + "zh:c94a84895a3d9954b80e983eed4603330a5cdbbd8eef5b3c99278c2d1402ef3c", + "zh:de1fb712784dd8415f011ca5346a34f87fab6046c730557615247e511dbc7d98", + "zh:e3eafae7da550f86cae395d6660b2a0e93ec8d2b0e0e5ef982ec762e961fc952", + "zh:ff35fb1ab6add288f0f368981e56f780b50405accd1937131cba1137999c8d83", + ] +} diff --git a/terraform-vault-pki/README.md b/terraform-vault-pki/README.md new file mode 100644 index 0000000..d3fb18e --- /dev/null +++ b/terraform-vault-pki/README.md @@ -0,0 +1,199 @@ +# Terraform Vault PKI Playground + +This playground demonstrates how to use Terraform to manage HashiCorp Vault's PKI (Public Key Infrastructure) secrets engine for certificate management. + +## What's Included + +This playground sets up: +- **PKI Secrets Engine**: Enables Vault's PKI capabilities +- **Root Certificate Authority**: Creates an internal root CA +- **Certificate Roles**: Defines policies for certificate issuance +- **Example Certificate**: Issues a sample server certificate +- **URL Configuration**: Sets up CA and CRL distribution points + +## Prerequisites + +1. **HashiCorp Vault**: Running Vault server (dev mode is fine for testing) +2. **Terraform**: Version 1.0 or later +3. **Vault CLI**: For initial setup and verification (optional) + +## Getting Started + +### 1. Start Vault Server + +For development/testing, you can run Vault in dev mode: + +```bash +vault server -dev +``` + +This starts Vault at `http://127.0.0.1:8200` with a root token displayed in the output. + +### 2. Configure Variables + +Copy the example variables file and update with your values: + +```bash +cp terraform.tfvars.example terraform.tfvars +``` + +Edit `terraform.tfvars`: +```hcl +vault_address = "http://127.0.0.1:8200" +vault_token = "your-root-token-here" +ca_common_name = "mycompany.com" +``` + +### 3. Initialize and Apply + +```bash +# Initialize Terraform +terraform init + +# Plan the deployment +terraform plan + +# Apply the configuration +terraform apply +``` + +### 4. Verify Setup + +Check that the PKI engine is mounted: +```bash +vault secrets list +``` + +View the root CA certificate: +```bash +vault read pki/cert/ca +``` + +## What Gets Created + +1. **PKI Mount**: Secrets engine at `/pki` path +2. **Root CA**: Self-signed root certificate (10-year TTL) +3. **Server Role**: Certificate role for server certificates +4. **Example Certificate**: Sample certificate for `test.example.com` + +## Using the PKI + +### Issue New Certificates + +Once deployed, you can issue certificates using the `server` role: + +```bash +vault write pki/issue/server common_name="app.example.com" ttl="24h" +``` + +### Revoke Certificates + +```bash +vault write pki/revoke serial_number="39:dd:2e:90:b7:f8:95:00:2f:9b:37:f6:32:8d:2a:01:09:48:03:a5" +``` + +### View Certificate Revocation List + +```bash +vault read pki/crl +``` + +## Configuration Options + +### Variables + +| Variable | Description | Default | +|----------|-------------|---------| +| `vault_address` | Vault server URL | `http://127.0.0.1:8200` | +| `vault_token` | Vault authentication token | - | +| `pki_path` | PKI mount path | `pki` | +| `ca_common_name` | Root CA common name | `example.com` | +| `ca_ttl` | Root CA certificate TTL | `87600h` (10 years) | + +### Outputs + +The configuration provides these outputs: +- `root_ca_certificate`: Root CA certificate (PEM format) +- `example_certificate`: Example server certificate +- `example_private_key`: Example private key +- `pki_mount_path`: PKI secrets engine path +- `ca_issuing_url`: CA certificate download URL +- `crl_url`: Certificate revocation list URL + +## Security Considerations + +⚠️ **For Production Use:** + +1. Use proper Vault authentication (not root tokens) +2. Configure appropriate certificate policies and roles +3. Set up proper CA certificate chain management +4. Implement certificate rotation strategies +5. Monitor certificate expiration +6. Secure private key storage + +## Advanced Usage + +### Multiple PKI Engines + +You can create multiple PKI engines for different purposes: + +```hcl +# Intermediate CA +resource "vault_mount" "intermediate_pki" { + path = "intermediate-pki" + type = "pki" +} +``` + +### Custom Certificate Roles + +Create roles with specific constraints: + +```hcl +resource "vault_pki_secret_backend_role" "client_role" { + backend = vault_mount.pki.path + name = "client" + client_flag = true + server_flag = false + allow_any_name = false + allowed_domains = ["client.example.com"] +} +``` + +## Cleanup + +To destroy all resources: + +```bash +terraform destroy +``` + +## Troubleshooting + +### Common Issues + +1. **Connection refused**: Ensure Vault server is running +2. **Permission denied**: Verify your Vault token has sufficient privileges +3. **Path already in use**: Check if PKI engine is already mounted + +### Useful Commands + +```bash +# Check Vault status +vault status + +# List all secrets engines +vault secrets list + +# View PKI configuration +vault read pki/config/urls + +# List certificate roles +vault list pki/roles +``` + +## Resources + +- [Vault PKI Secrets Engine](https://www.vaultproject.io/docs/secrets/pki) +- [Terraform Vault Provider](https://registry.terraform.io/providers/hashicorp/vault/latest/docs) +- [PKI Best Practices](https://www.vaultproject.io/docs/secrets/pki/considerations) \ No newline at end of file diff --git a/terraform-vault-pki/install-terraform.sh b/terraform-vault-pki/install-terraform.sh new file mode 100755 index 0000000..b6d7170 --- /dev/null +++ b/terraform-vault-pki/install-terraform.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash +wget -O - https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg +echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(grep -oP '(?<=UBUNTU_CODENAME=).*' /etc/os-release || lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list +sudo apt update && sudo apt install terraform diff --git a/terraform-vault-pki/main.tf b/terraform-vault-pki/main.tf new file mode 100644 index 0000000..a8ed9ed --- /dev/null +++ b/terraform-vault-pki/main.tf @@ -0,0 +1,43 @@ +terraform { + required_providers { + vault = { + source = "hashicorp/vault" + version = "~> 4.0" + } + } +} + +provider "vault" { + address = var.vault_address + token = var.vault_token +} + +variable "vault_address" { + description = "Vault server address" + type = string + default = "http://127.0.0.1:8200" +} + +variable "vault_token" { + description = "Vault authentication token" + type = string + sensitive = true +} + +variable "pki_path" { + description = "Path where PKI secrets engine will be mounted" + type = string + default = "pki" +} + +variable "ca_common_name" { + description = "Common name for the root CA certificate" + type = string + default = "example.com" +} + +variable "ca_ttl" { + description = "TTL for the root CA certificate" + type = string + default = "87600h" # 10 years +} \ No newline at end of file diff --git a/terraform-vault-pki/outputs.tf b/terraform-vault-pki/outputs.tf new file mode 100644 index 0000000..cddfa7d --- /dev/null +++ b/terraform-vault-pki/outputs.tf @@ -0,0 +1,32 @@ +output "root_ca_certificate" { + description = "Root CA certificate" + value = vault_pki_secret_backend_root_cert.root_ca.certificate + sensitive = true +} + +output "example_certificate" { + description = "Example server certificate" + value = vault_pki_secret_backend_cert.example_cert.certificate + sensitive = true +} + +output "example_private_key" { + description = "Example server private key" + value = vault_pki_secret_backend_cert.example_cert.private_key + sensitive = true +} + +output "pki_mount_path" { + description = "PKI secrets engine mount path" + value = vault_mount.pki.path +} + +output "ca_issuing_url" { + description = "CA certificate issuing URL" + value = "${var.vault_address}/v1/${var.pki_path}/ca" +} + +output "crl_url" { + description = "Certificate Revocation List URL" + value = "${var.vault_address}/v1/${var.pki_path}/crl" +} \ No newline at end of file diff --git a/terraform-vault-pki/pki.tf b/terraform-vault-pki/pki.tf new file mode 100644 index 0000000..34345a3 --- /dev/null +++ b/terraform-vault-pki/pki.tf @@ -0,0 +1,71 @@ +# Enable PKI secrets engine +resource "vault_mount" "pki" { + path = var.pki_path + type = "pki" + description = "PKI secrets engine for certificate management" + + default_lease_ttl_seconds = 3600 + max_lease_ttl_seconds = 315360000 # 10 years +} + +# Generate root CA certificate +resource "vault_pki_secret_backend_root_cert" "root_ca" { + backend = vault_mount.pki.path + type = "internal" + common_name = var.ca_common_name + ttl = var.ca_ttl + format = "pem" + key_type = "rsa" + key_bits = 4096 + + exclude_cn_from_sans = true +} + +# Configure CA and CRL URLs +resource "vault_pki_secret_backend_config_urls" "config_urls" { + backend = vault_mount.pki.path + issuing_certificates = [ + "${var.vault_address}/v1/${var.pki_path}/ca" + ] + crl_distribution_points = [ + "${var.vault_address}/v1/${var.pki_path}/crl" + ] +} + +# Create a role for issuing certificates +resource "vault_pki_secret_backend_role" "server_role" { + backend = vault_mount.pki.path + name = "server" + ttl = 3600 + max_ttl = 86400 + allow_localhost = true + allow_ip_sans = true + allow_any_name = true + enforce_hostnames = false + key_type = "rsa" + key_bits = 2048 + key_usage = [ + "DigitalSignature", + "KeyAgreement", + "KeyEncipherment" + ] + ext_key_usage = [ + "ServerAuth" + ] +} + +# Example: Issue a certificate +resource "vault_pki_secret_backend_cert" "example_cert" { + backend = vault_mount.pki.path + name = vault_pki_secret_backend_role.server_role.name + common_name = "test.${var.ca_common_name}" + + alt_names = [ + "localhost", + "test-server.${var.ca_common_name}" + ] + + ip_sans = [ + "127.0.0.1" + ] +} \ No newline at end of file diff --git a/terraform-vault-pki/terraform.tfvars.example b/terraform-vault-pki/terraform.tfvars.example new file mode 100644 index 0000000..056ebc6 --- /dev/null +++ b/terraform-vault-pki/terraform.tfvars.example @@ -0,0 +1,8 @@ +# Example Terraform variables file +# Copy this to terraform.tfvars and update with your values + +vault_address = "http://127.0.0.1:8200" +vault_token = "your-vault-token-here" +pki_path = "pki" +ca_common_name = "example.com" +ca_ttl = "87600h" \ No newline at end of file