Python API Guide¶
This guide shows you how to use Certica programmatically through its Python API. This is perfect for automation, integration with other tools, or building custom workflows.
Why Use the Python API?¶
While the CLI is great for manual operations, the Python API allows you to:
Automate certificate generation in deployment scripts
Integrate with configuration management tools (Ansible, Puppet, etc.)
Build custom workflows that combine certificate management with other operations
Create web interfaces or APIs that manage certificates
Implement certificate rotation and renewal automation
Getting Started¶
Import the necessary modules:
from certica.ca_manager import CAManager
from certica.cert_manager import CertManager
from certica.template_manager import TemplateManager
from certica.system_cert import SystemCertManager
Initialize the managers:
# All managers use the same base directory
base_dir = "output" # or any custom path
ca_manager = CAManager(base_dir)
cert_manager = CertManager(base_dir)
template_manager = TemplateManager(base_dir)
system_cert_manager = SystemCertManager()
Note
All managers share the same base directory structure. Certificates are automatically organized by CA, making it easy to manage relationships between CAs and their certificates.
Working with CAs¶
Creating a CA¶
Create a root CA certificate:
try:
result = ca_manager.create_root_ca(
ca_name="myca",
organization="My Company Inc.",
country="US",
state="California",
city="San Francisco",
validity_days=3650, # 10 years
key_size=2048
)
print(f"CA created successfully!")
print(f"Key: {result['ca_key']}")
print(f"Cert: {result['ca_cert']}")
except FileExistsError:
print("CA already exists!")
except Exception as e:
print(f"Error creating CA: {e}")
Return Value:
The method returns a dictionary with:
- ca_name: Name of the CA
- ca_key: Path to the private key file
- ca_cert: Path to the certificate file
- key_size: Key size used
- validity_days: Validity period
Listing CAs¶
Get a list of all available CAs:
cas = ca_manager.list_cas()
for ca in cas:
print(f"CA: {ca['name']}")
print(f" Key: {ca['key']}")
print(f" Cert: {ca['cert']}")
Return Value:
Returns a list of dictionaries, each containing:
- name: CA name
- key: Path to private key
- cert: Path to certificate
Getting CA Information¶
Get information about a specific CA:
ca_info = ca_manager.get_ca("myca")
if ca_info:
print(f"Found CA: {ca_info['name']}")
print(f"Key: {ca_info['key']}")
print(f"Cert: {ca_info['cert']}")
else:
print("CA not found")
Getting CA Details¶
Get detailed information about a CA certificate:
ca_info = ca_manager.get_ca("myca")
if ca_info:
details = ca_manager.get_ca_info(ca_info['cert'])
print(details['info']) # OpenSSL certificate text output
Getting Certificates by CA¶
List all certificates signed by a specific CA:
certs = ca_manager.get_certs_by_ca("myca")
for cert in certs:
print(f"Certificate: {cert['name']}")
print(f" Key: {cert['key']}")
print(f" Cert: {cert['cert']}")
Deleting a CA¶
Delete a CA and all its certificates:
if ca_manager.delete_ca("myca"):
print("CA and all its certificates deleted successfully")
else:
print("Failed to delete CA")
Warning
Deleting a CA will also delete all certificates signed by that CA. This operation cannot be undone. Make sure you have backups if needed.
Working with Certificates¶
Signing a Certificate¶
Sign a certificate using an existing CA:
# First, get the CA information
ca_info = ca_manager.get_ca("myca")
if not ca_info:
print("CA not found!")
exit(1)
# Sign a server certificate
try:
result = cert_manager.sign_certificate(
ca_key=ca_info["key"],
ca_cert=ca_info["cert"],
ca_name=ca_info["name"],
cert_name="web-server",
cert_type="server", # or "client"
common_name="web-server.example.com",
dns_names=["web-server.example.com", "www.example.com"],
ip_addresses=["192.168.1.100"],
organization="My Company Inc.",
country="US",
state="California",
city="San Francisco",
validity_days=365,
key_size=2048
)
print(f"Certificate signed successfully!")
print(f"Key: {result['key']}")
print(f"Cert: {result['cert']}")
except Exception as e:
print(f"Error signing certificate: {e}")
Parameters:
ca_key: Path to CA private key (required)ca_cert: Path to CA certificate (required)ca_name: Name of the CA (for directory organization)cert_name: Name for the certificate (required)cert_type:"server"or"client"(default:"server")common_name: Common Name for the certificate (defaults to cert_name if empty)dns_names: List of DNS names (optional)ip_addresses: List of IP addresses (optional)organization: Organization name (optional)country: Country code (default:"CN")state: State/Province (default:"Beijing")city: City (default:"Beijing")validity_days: Validity in days (default:365)key_size: Key size in bits (default:2048)
Return Value:
Returns a dictionary with:
- cert_name: Name of the certificate
- key: Path to the private key file
- cert: Path to the certificate file
- type: Certificate type
- validity_days: Validity period
Note
The common_name parameter is optional. If not provided, Certica will use:
1. First DNS name (if available)
2. First IP address (if available)
3. Certificate name (as fallback)
Listing Certificates¶
List all certificates:
certs = cert_manager.list_certificates()
for cert in certs:
print(f"Certificate: {cert['name']}")
print(f" CA: {cert['ca_name']}")
print(f" Key: {cert['key']}")
print(f" Cert: {cert['cert']}")
Return Value:
Returns a list of dictionaries, each containing:
- name: Certificate name
- ca_name: Name of the CA that signed it
- key: Path to private key
- cert: Path to certificate
Getting Certificate Information¶
Get detailed information about a certificate:
cert_path = "output/certs/myca/web-server/cert.pem"
info = cert_manager.get_certificate_info(cert_path)
print(info['info']) # OpenSSL certificate text output
Deleting a Certificate¶
Delete a specific certificate:
if cert_manager.delete_certificate("myca", "web-server"):
print("Certificate deleted successfully")
else:
print("Failed to delete certificate")
Working with Templates¶
Creating Templates¶
Create a template for reuse:
template_path = template_manager.create_template(
template_name="myorg",
organization="My Company Inc.",
country="US",
state="California",
city="San Francisco",
default_validity_days=730, # 2 years
default_key_size=2048
)
print(f"Template created: {template_path}")
Loading Templates¶
Load a template to get default values:
template_data = template_manager.load_template("myorg")
print(f"Organization: {template_data['organization']}")
print(f"Country: {template_data['country']}")
print(f"Default validity: {template_data['default_validity_days']} days")
Note
If a template doesn’t exist, load_template() returns default values instead
of raising an error. This makes it safe to use templates that may not exist yet.
Listing Templates¶
List all available templates:
templates = template_manager.list_templates()
for template in templates:
print(f"Template: {template}")
Deleting Templates¶
Delete a template:
if template_manager.delete_template("myorg"):
print("Template deleted successfully")
else:
print("Template not found")
System Certificate Management¶
Installing CAs to System¶
Install a CA certificate to the system trust store:
ca_info = ca_manager.get_ca("myca")
if not ca_info:
print("CA not found!")
exit(1)
# Get sudo password (you might want to use getpass or environment variable)
import getpass
password = getpass.getpass("Enter sudo password: ")
if system_cert_manager.install_ca_cert(
ca_cert_path=ca_info["cert"],
ca_name=ca_info["name"],
password=password
):
print("CA installed to system successfully!")
else:
print("Failed to install CA")
Note
The SystemCertManager automatically detects your Linux distribution and uses
the appropriate installation method. It supports:
Debian/Ubuntu
Fedora/RHEL/CentOS
Arch/Manjaro
openSUSE/SLES
Removing CAs from System¶
Remove a CA certificate from the system trust store:
import getpass
password = getpass.getpass("Enter sudo password: ")
if system_cert_manager.remove_ca_cert("myca", password):
print("CA removed from system successfully!")
else:
print("Failed to remove CA")
Complete Examples¶
Example 1: Automated Certificate Generation¶
Create a script that generates certificates for multiple services:
from certica.ca_manager import CAManager
from certica.cert_manager import CertManager
base_dir = "output"
ca_manager = CAManager(base_dir)
cert_manager = CertManager(base_dir)
# Create or get CA
ca_name = "production-ca"
ca_info = ca_manager.get_ca(ca_name)
if not ca_info:
print(f"Creating CA: {ca_name}")
result = ca_manager.create_root_ca(
ca_name=ca_name,
organization="My Company Inc.",
country="US",
validity_days=3650
)
ca_info = ca_manager.get_ca(ca_name)
# Services to create certificates for
services = [
{"name": "api", "dns": ["api.example.com"]},
{"name": "www", "dns": ["www.example.com", "example.com"]},
{"name": "admin", "dns": ["admin.example.com"]},
]
# Generate certificates
for service in services:
print(f"Creating certificate for {service['name']}...")
try:
result = cert_manager.sign_certificate(
ca_key=ca_info["key"],
ca_cert=ca_info["cert"],
ca_name=ca_info["name"],
cert_name=service["name"],
cert_type="server",
dns_names=service["dns"],
organization="My Company Inc.",
validity_days=365
)
print(f" ✓ Created: {result['cert']}")
except Exception as e:
print(f" ✗ Error: {e}")
Example 2: Certificate Rotation Script¶
Create a script that checks certificate expiration and rotates them:
from certica.cert_manager import CertManager
from certica.ca_manager import CAManager
from datetime import datetime
import subprocess
base_dir = "output"
cert_manager = CertManager(base_dir)
ca_manager = CAManager(base_dir)
def get_cert_expiry(cert_path):
"""Get certificate expiration date"""
result = subprocess.run(
["openssl", "x509", "-in", cert_path, "-noout", "-enddate"],
capture_output=True,
text=True
)
# Parse the date from output like "notAfter=Dec 31 23:59:59 2024 GMT"
if result.returncode == 0:
date_str = result.stdout.split("=")[1].strip()
return datetime.strptime(date_str, "%b %d %H:%M:%S %Y %Z")
return None
# Check all certificates
certs = cert_manager.list_certificates()
today = datetime.now()
for cert in certs:
expiry = get_cert_expiry(cert["cert"])
if expiry:
days_until_expiry = (expiry - today).days
if days_until_expiry < 30: # Less than 30 days
print(f"⚠ Certificate {cert['name']} expires in {days_until_expiry} days")
# Add rotation logic here
Example 3: Integration with Configuration Management¶
Create certificates and update configuration files:
from certica.ca_manager import CAManager
from certica.cert_manager import CertManager
import json
base_dir = "output"
ca_manager = CAManager(base_dir)
cert_manager = CertManager(base_dir)
# Create certificate
ca_info = ca_manager.get_ca("myca")
result = cert_manager.sign_certificate(
ca_key=ca_info["key"],
ca_cert=ca_info["cert"],
ca_name=ca_info["name"],
cert_name="nginx-server",
cert_type="server",
dns_names=["example.com"]
)
# Update nginx configuration
nginx_config = {
"ssl_certificate": result["cert"],
"ssl_certificate_key": result["key"]
}
# Save to configuration file
with open("nginx_ssl_config.json", "w") as f:
json.dump(nginx_config, f, indent=2)
print("Certificate created and configuration updated!")
Best Practices¶
Error Handling¶
Always handle exceptions properly:
try:
result = ca_manager.create_root_ca(ca_name="myca")
except FileExistsError:
print("CA already exists - using existing one")
ca_info = ca_manager.get_ca("myca")
except Exception as e:
print(f"Unexpected error: {e}")
raise
Resource Cleanup¶
Certica automatically cleans up partial files if operations fail, but you should still handle errors gracefully:
try:
result = cert_manager.sign_certificate(...)
except KeyboardInterrupt:
print("Operation cancelled by user")
# Certica will clean up partial files automatically
except Exception as e:
print(f"Error: {e}")
# Check if partial files need manual cleanup
Security Considerations¶
Never commit private keys to version control
Use proper file permissions (Certica sets these automatically)
Protect CA keys - they can sign any certificate
Use separate CAs for different environments (dev, staging, production)
Rotate certificates regularly
Monitor expiration dates and set up alerts
Warning
The CA private key is the most sensitive file. If compromised, an attacker can create trusted certificates for any domain. Always:
Store CA keys securely
Use strong file permissions (Certica sets 600 automatically)
Consider encrypting CA keys at rest
Limit access to CA keys
Common Pitfalls¶
Forgetting to Check if CA Exists¶
Always check if a CA exists before using it:
# ❌ Bad: May fail if CA doesn't exist
ca_info = ca_manager.get_ca("myca")
result = cert_manager.sign_certificate(
ca_key=ca_info["key"], # This will fail if ca_info is None
...
)
# ✅ Good: Check first
ca_info = ca_manager.get_ca("myca")
if not ca_info:
print("CA not found! Create it first.")
exit(1)
result = cert_manager.sign_certificate(
ca_key=ca_info["key"],
...
)
Not Including All DNS Names¶
Always include all DNS names and IPs that will be used:
# ❌ Bad: Missing www subdomain
cert_manager.sign_certificate(
...,
dns_names=["example.com"] # Missing www.example.com
)
# ✅ Good: Include all variations
cert_manager.sign_certificate(
...,
dns_names=["example.com", "www.example.com", "api.example.com"]
)
Ignoring Return Values¶
Always check return values:
# ❌ Bad: Not checking if operation succeeded
system_cert_manager.install_ca_cert(...)
# ✅ Good: Check return value
if system_cert_manager.install_ca_cert(...):
print("Installation successful")
else:
print("Installation failed - check logs")