Skip to content

You are viewing documentation for Instruqt 2.0 Labs. For Tracks documentation, please visit docs.instruqt.com.

Certificate Leaf


Defined incertificates.hcl

The certificate_leaf resource generates leaf certificates signed by a Certificate Authority (CA). These are end-entity certificates used for servers, clients, or other applications that require TLS/SSL certificates signed by a trusted authority.

As a lab author, you can use certificate_leaf resources to:

  • Server Certificate Generation: Create TLS certificates for web servers, APIs, and other network services
  • Client Certificate Authentication: Generate client certificates for mutual TLS authentication scenarios
  • Service-to-Service Communication: Enable secure communication between microservices using signed certificates

Certificate leaf resources provide signed certificates for specific services while maintaining the certificate chain of trust.

resource "certificate_leaf" "name" {
ca_key = resource.certificate_ca.root.private_key.path
ca_cert = resource.certificate_ca.root.certificate.path
output = "./server-certs"
}
resource "certificate_leaf" "name" {
ca_key = resource.certificate_ca.root.private_key.path
ca_cert = resource.certificate_ca.root.certificate.path
output = "./server-certs"
dns_names = [
"localhost",
"api.example.com",
"www.example.com"
]
ip_addresses = [
"127.0.0.1",
"192.168.1.100",
"10.0.0.5"
]
}

Fields

FieldTypeRequiredDescription
ca_keystring✓Path to the private key for the root CA
ca_certstring✓Path to the root CA certificate
ip_addresseslist(string)—IP addresses to add to the certificate
dns_nameslist(string)—DNS names to add to the certificate
outputstring✓Output location for the certificate

Private Key

certificate_leaf→Private Key

Private key output

FieldTypeRequiredDescription
filenamestring—Filename of the private key
directorystring—Directory containing the private key
pathstring—Full path to the private key
contentsstring—Contents of the private key

Public Key PEM

certificate_leaf→Public Key PEM

Public key PEM output

FieldTypeRequiredDescription
filenamestring—Filename of the public key
directorystring—Directory containing the public key
pathstring—Full path to the public key
contentsstring—Contents of the public key

Public Key SSH

certificate_leaf→Public Key SSH

Public key SSH output

FieldTypeRequiredDescription
filenamestring—Filename of the SSH public key
directorystring—Directory containing the SSH public key
pathstring—Full path to the SSH public key
contentsstring—Contents of the SSH public key

Certificate

certificate_leaf→Certificate

Certificate output

FieldTypeRequiredDescription
filenamestring—Filename of the certificate
directorystring—Directory containing the certificate
pathstring—Full path to the certificate
contentsstring—Contents of the certificate

The File object contains information about generated certificate files:

FieldTypeDescription
filenamestringThe name of the generated file
directorystringThe directory where the file is written
pathstringThe full absolute path to the file
contentsstringThe contents of the generated file
resource "certificate_ca" "root" {
output = "./ca"
}
resource "certificate_leaf" "server" {
ca_key = resource.certificate_ca.root.private_key.path # e.g., "./ca/private_key.pem"
ca_cert = resource.certificate_ca.root.certificate.path # e.g., "./ca/certificate.pem"
output = "./server-certs"
dns_names = ["localhost"]
ip_addresses = ["127.0.0.1"]
}
output "server_cert_path" {
value = resource.certificate_leaf.server.certificate.path # e.g., "./server-certs/certificate.pem"
}
resource "certificate_leaf" "web" {
ca_key = resource.certificate_ca.root.private_key.path
ca_cert = resource.certificate_ca.root.certificate.path
output = "./web-certs"
dns_names = [
"example.com",
"www.example.com",
"api.example.com",
"admin.example.com"
]
ip_addresses = [
"192.168.1.10",
"10.0.0.100"
]
}
resource "container" "web_server" {
image {
name = "nginx:alpine"
}
volume {
source = resource.certificate_leaf.web.certificate.path # e.g., "./web-certs/certificate.pem"
destination = "/etc/ssl/certs/server.crt"
type = "bind"
read_only = true
}
volume {
source = resource.certificate_leaf.web.private_key.path # e.g., "./web-certs/private_key.pem"
destination = "/etc/ssl/private/server.key"
type = "bind"
read_only = true
}
port {
local = "443"
host = "8443"
}
}
resource "certificate_leaf" "client" {
ca_key = resource.certificate_ca.root.private_key.path
ca_cert = resource.certificate_ca.root.certificate.path
output = "./client-certs"
dns_names = ["client.internal"]
}
resource "template" "client_config" {
source = <<-EOF
client:
certificate: ${resource.certificate_leaf.client.certificate.path} # e.g., "./client-certs/certificate.pem"
private_key: ${resource.certificate_leaf.client.private_key.path} # e.g., "./client-certs/private_key.pem"
ca_certificate: ${resource.certificate_ca.root.certificate.path} # e.g., "./ca/certificate.pem"
tls:
verify_peer: true
verify_host: true
EOF
destination = "./client-config.yaml"
}
resource "certificate_ca" "service_mesh_ca" {
output = "./mesh-ca"
}
# API service certificate
resource "certificate_leaf" "api_service" {
ca_key = resource.certificate_ca.service_mesh_ca.private_key.path
ca_cert = resource.certificate_ca.service_mesh_ca.certificate.path
output = "./api-service-certs"
dns_names = [
"api-service",
"api-service.default.svc.cluster.local"
]
}
# Database service certificate
resource "certificate_leaf" "database_service" {
ca_key = resource.certificate_ca.service_mesh_ca.private_key.path
ca_cert = resource.certificate_ca.service_mesh_ca.certificate.path
output = "./database-service-certs"
dns_names = [
"database-service",
"database-service.default.svc.cluster.local"
]
}
resource "container" "api" {
image {
name = "api:latest"
}
environment = {
TLS_CERT_FILE = resource.certificate_leaf.api_service.certificate.path # e.g., "./api-service-certs/certificate.pem"
TLS_KEY_FILE = resource.certificate_leaf.api_service.private_key.path # e.g., "./api-service-certs/private_key.pem"
CA_CERT_FILE = resource.certificate_ca.service_mesh_ca.certificate.path # e.g., "./mesh-ca/certificate.pem"
}
}
resource "certificate_leaf" "load_balancer" {
ca_key = resource.certificate_ca.root.private_key.path
ca_cert = resource.certificate_ca.root.certificate.path
output = "./lb-certs"
dns_names = [
"lb.example.com",
"loadbalancer.internal",
"*.apps.example.com" # Wildcard certificate
]
ip_addresses = [
"192.168.1.50", # Load balancer IP
"10.0.0.50" # Internal IP
]
}
resource "template" "nginx_ssl_config" {
source = <<-EOF
server {
listen 443 ssl;
server_name lb.example.com *.apps.example.com;
ssl_certificate ${resource.certificate_leaf.load_balancer.certificate.path}; # e.g., "./lb-certs/certificate.pem"
ssl_certificate_key ${resource.certificate_leaf.load_balancer.private_key.path}; # e.g., "./lb-certs/private_key.pem"
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
location / {
proxy_pass http://backend;
}
}
EOF
destination = "./nginx-ssl.conf"
}
resource "certificate_leaf" "app_cert" {
ca_key = resource.certificate_ca.root.private_key.path
ca_cert = resource.certificate_ca.root.certificate.path
output = "./app-certs"
dns_names = ["app.local"]
}
resource "container" "secure_app" {
image {
name = "myapp:latest"
}
environment = {
# Pass certificate contents directly as environment variables
TLS_CERTIFICATE = resource.certificate_leaf.app_cert.certificate.contents
TLS_PRIVATE_KEY = resource.certificate_leaf.app_cert.private_key.contents
TLS_CA_CERT = resource.certificate_ca.root.certificate.contents
# Certificate metadata
CERT_FILENAME = resource.certificate_leaf.app_cert.certificate.filename # e.g., "certificate.pem"
CERT_DIRECTORY = resource.certificate_leaf.app_cert.certificate.directory # e.g., "./app-certs"
}
}
  1. Subject Alternative Names: Always include relevant DNS names and IP addresses for proper certificate validation
  2. Certificate Organization: Use descriptive output directories to organize certificates by service or purpose
  3. File References: Use .path for file system operations and .contents for inline certificate data
  4. Security: Protect private keys and limit access to certificate files
  5. Validation: Include all hostnames and IPs that clients will use to connect to your services
  6. Certificate Chain: Ensure CA certificates are properly distributed to clients for validation
  7. Naming Conventions: Use clear naming that indicates the certificate’s purpose and scope
  8. Environment Separation: Generate separate certificates for different environments (dev, staging, prod)