Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions terraform-vault-pki/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
*.tfstate
*.plan
.terraform/*
*.backup
22 changes: 22 additions & 0 deletions terraform-vault-pki/.terraform.lock.hcl

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

199 changes: 199 additions & 0 deletions terraform-vault-pki/README.md
Original file line number Diff line number Diff line change
@@ -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)
4 changes: 4 additions & 0 deletions terraform-vault-pki/install-terraform.sh
Original file line number Diff line number Diff line change
@@ -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
43 changes: 43 additions & 0 deletions terraform-vault-pki/main.tf
Original file line number Diff line number Diff line change
@@ -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
}
32 changes: 32 additions & 0 deletions terraform-vault-pki/outputs.tf
Original file line number Diff line number Diff line change
@@ -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"
}
71 changes: 71 additions & 0 deletions terraform-vault-pki/pki.tf
Original file line number Diff line number Diff line change
@@ -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"
]
}
8 changes: 8 additions & 0 deletions terraform-vault-pki/terraform.tfvars.example
Original file line number Diff line number Diff line change
@@ -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"