zoobzio February 17, 2025 Edit this page

Certificates

Aegis requires mTLS for all node-to-node communication. This guide explains certificate management for development and production.

Development Mode

For local development, aegis generates certificates automatically:

node, _ := aegis.NewNodeBuilder().
    WithID("dev-node").
    WithName("Development Node").
    WithAddress("localhost:8443").
    WithCertDir("./certs").
    Build()

On first run:

  • Generates CA certificate (ca-cert.pem, ca-key.pem)
  • Generates node certificate (dev-node-cert.pem, dev-node-key.pem)
certs/
├── ca-cert.pem         # CA certificate (365-day validity)
├── ca-key.pem          # CA private key
├── dev-node-cert.pem   # Node certificate (90-day validity)
└── dev-node-key.pem    # Node private key

This is for development only. For production, use external certificates.

Production Configuration

Certificate Sources

Aegis supports three certificate sources:

SourceUse Case
CertSourceFileFiles on disk
CertSourceEnvEnvironment variables
CertSourceVaultHashiCorp Vault (future)

File-Based Certificates

opts := &aegis.TLSOptions{
    Source:   aegis.CertSourceFile,
    CertFile: "/etc/aegis/certs/node.crt",
    KeyFile:  "/etc/aegis/certs/node.key",
    CAFile:   "/etc/aegis/certs/ca.crt",
}

node, _ := aegis.NewNodeBuilder().
    WithID("prod-node").
    WithName("Production Node").
    WithAddress("node.example.com:8443").
    WithTLSOptions(opts).
    Build()

File permissions: Ensure key files are readable only by the node process (mode 0600).

Environment Variables

For containers and orchestrated deployments:

opts := &aegis.TLSOptions{
    Source:    aegis.CertSourceEnv,
    CertEnvVar: "AEGIS_TLS_CERT",
    KeyEnvVar:  "AEGIS_TLS_KEY",
    CAEnvVar:   "AEGIS_TLS_CA",
}

Set environment variables with PEM-encoded certificates:

export AEGIS_TLS_CERT="-----BEGIN CERTIFICATE-----
MIIDXTCCAkWgAwIBAgIJAKl...
-----END CERTIFICATE-----"

export AEGIS_TLS_KEY="-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAvLYcyu8f3...
-----END RSA PRIVATE KEY-----"

export AEGIS_TLS_CA="-----BEGIN CERTIFICATE-----
MIIDXTCCAkWgAwIBAgIJAKl1...
-----END CERTIFICATE-----"

Kubernetes Secrets

apiVersion: v1
kind: Secret
metadata:
  name: aegis-tls
type: Opaque
data:
  cert: LS0tLS1CRUdJTi...  # base64 encoded
  key: LS0tLS1CRUdJTi...
  ca: LS0tLS1CRUdJTi...
# Pod spec
env:
  - name: AEGIS_TLS_CERT
    valueFrom:
      secretKeyRef:
        name: aegis-tls
        key: cert
  - name: AEGIS_TLS_KEY
    valueFrom:
      secretKeyRef:
        name: aegis-tls
        key: key
  - name: AEGIS_TLS_CA
    valueFrom:
      secretKeyRef:
        name: aegis-tls
        key: ca

Certificate Validation

Chain Verification

Enable full chain verification:

opts := &aegis.TLSOptions{
    Source:      aegis.CertSourceFile,
    CertFile:    "/path/to/node.crt",
    KeyFile:     "/path/to/node.key",
    CAFile:      "/path/to/ca.crt",
    VerifyChain: true,
}

Required SANs

Enforce Subject Alternative Name validation:

opts := &aegis.TLSOptions{
    Source:       aegis.CertSourceFile,
    CertFile:     "/path/to/node.crt",
    KeyFile:      "/path/to/node.key",
    CAFile:       "/path/to/ca.crt",
    RequiredSANs: []string{"*.aegis.internal", "node.example.com"},
}

Expiry Handling

By default, expired certificates are rejected. For testing or migration, this can be disabled:

opts := &aegis.TLSOptions{
    AllowExpired: true,  // NOT FOR PRODUCTION
}

Generating Certificates

Using OpenSSL

Generate a CA:

# Generate CA key
openssl genrsa -out ca.key 4096

# Generate CA certificate
openssl req -new -x509 -days 365 -key ca.key -out ca.crt \
    -subj "/CN=Aegis CA/O=My Organization"

Generate a node certificate:

# Generate node key
openssl genrsa -out node.key 2048

# Generate CSR
openssl req -new -key node.key -out node.csr \
    -subj "/CN=node-1/O=Aegis Network"

# Create SAN config
cat > san.cnf << EOF
[req]
distinguished_name = req_distinguished_name
req_extensions = v3_req

[req_distinguished_name]
CN = node-1

[v3_req]
subjectAltName = @alt_names

[alt_names]
DNS.1 = node-1
DNS.2 = localhost
IP.1 = 127.0.0.1
EOF

# Sign with CA
openssl x509 -req -days 90 -in node.csr -CA ca.crt -CAkey ca.key \
    -CAcreateserial -out node.crt -extfile san.cnf -extensions v3_req

Using cfssl

# Generate CA
cfssl gencert -initca ca-csr.json | cfssljson -bare ca

# Generate node certificate
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem \
    -config=cfssl.json -profile=client-server \
    node-csr.json | cfssljson -bare node

Security Best Practices

  1. Use external CA — Never generate CA certificates on application nodes in production
  2. Rotate certificates — Node certificates should be rotated before expiry
  3. Secure key storage — Use hardware security modules (HSM) or key management services
  4. Monitor expiration — Alert on certificates approaching expiry
  5. Audit failures — Log all certificate validation failures
  6. Minimum key size — Use 2048-bit RSA or 256-bit ECDSA minimum

Debugging

View Certificate Details

openssl x509 -in node.crt -text -noout

Verify Chain

openssl verify -CAfile ca.crt node.crt

Test mTLS Connection

openssl s_client -connect localhost:8443 \
    -cert client.crt \
    -key client.key \
    -CAfile ca.crt

Next Steps