Initial commit - 611 cybersecurity skills across all subdomains

This commit is contained in:
mukul975
2026-02-25 10:47:44 +01:00
commit 22a7ab1462
1765 changed files with 280648 additions and 0 deletions
@@ -0,0 +1,79 @@
---
name: configuring-tls-1.3-for-secure-communications
description: TLS 1.3 (RFC 8446) is the latest version of the Transport Layer Security protocol, providing significant improvements over TLS 1.2 in both security and performance. It reduces handshake latency to 1-R
domain: cybersecurity
subdomain: cryptography
tags: [cryptography, tls, ssl, transport-security, network-security]
version: "1.0"
author: mahipal
license: MIT
---
# Configuring TLS 1.3 for Secure Communications
## Overview
TLS 1.3 (RFC 8446) is the latest version of the Transport Layer Security protocol, providing significant improvements over TLS 1.2 in both security and performance. It reduces handshake latency to 1-RTT (and 0-RTT for resumed sessions), removes obsolete cipher suites, and mandates perfect forward secrecy. This skill covers configuring TLS 1.3 on servers, validating configurations, and testing for common misconfigurations.
## Objectives
- Configure TLS 1.3 on nginx and Apache web servers
- Implement TLS 1.3 in Python applications using the ssl module
- Validate TLS configurations with openssl and testssl.sh
- Understand TLS 1.3 cipher suites and key exchange mechanisms
- Configure 0-RTT early data with appropriate protections
- Disable legacy TLS versions (1.0, 1.1) and weak cipher suites
## Key Concepts
### TLS 1.3 Cipher Suites
| Cipher Suite | Key Exchange | Authentication | Encryption | Hash |
|-------------|-------------|----------------|------------|------|
| TLS_AES_256_GCM_SHA384 | ECDHE/DHE | Certificate | AES-256-GCM | SHA-384 |
| TLS_AES_128_GCM_SHA256 | ECDHE/DHE | Certificate | AES-128-GCM | SHA-256 |
| TLS_CHACHA20_POLY1305_SHA256 | ECDHE/DHE | Certificate | ChaCha20-Poly1305 | SHA-256 |
### TLS 1.3 vs 1.2 Improvements
- **1-RTT Handshake**: Full handshake completes in one round trip (vs 2 in TLS 1.2)
- **0-RTT Resumption**: Resumed connections can send data immediately
- **No RSA Key Exchange**: Only ephemeral Diffie-Hellman (mandatory PFS)
- **Simplified Cipher Suites**: Removed CBC, RC4, 3DES, static RSA, SHA-1
- **Encrypted Handshake**: Server certificate is encrypted after ServerHello
### Key Exchange Groups
- **x25519**: Curve25519 ECDH (preferred, fast)
- **secp256r1**: NIST P-256 ECDH (widely supported)
- **secp384r1**: NIST P-384 ECDH (higher security margin)
- **x448**: Curve448 ECDH (highest security)
## Implementation Steps
1. Verify OpenSSL version supports TLS 1.3 (1.1.1+)
2. Generate or obtain TLS certificate and private key
3. Configure server to use TLS 1.3 cipher suites
4. Disable TLS 1.0 and 1.1 (optionally keep 1.2 for compatibility)
5. Set preferred key exchange groups
6. Enable OCSP stapling for certificate validation
7. Test configuration with openssl s_client and testssl.sh
8. Configure HSTS header for HTTP Strict Transport Security
## Security Considerations
- 0-RTT data is vulnerable to replay attacks; limit to idempotent requests
- Always include TLS 1.2 fallback if legacy client support is required
- Use ECDSA certificates for better performance (vs RSA)
- Enable OCSP stapling to improve client certificate validation
- Set HSTS header with long max-age and includeSubDomains
- Monitor for certificate transparency logs
## Validation Criteria
- [ ] TLS 1.3 handshake completes successfully
- [ ] Only approved cipher suites are offered
- [ ] Perfect forward secrecy is enforced
- [ ] TLS 1.0 and 1.1 are rejected
- [ ] OCSP stapling is functional
- [ ] Certificate chain is valid and complete
- [ ] testssl.sh reports no vulnerabilities
@@ -0,0 +1,67 @@
# TLS 1.3 Configuration Template
## Pre-Configuration Checklist
- [ ] Verify OpenSSL version >= 1.1.1 (`openssl version`)
- [ ] Obtain valid TLS certificate from trusted CA
- [ ] Identify all server endpoints requiring TLS
- [ ] Determine minimum TLS version (1.2 or 1.3 only)
- [ ] Plan certificate renewal automation (Let's Encrypt / ACME)
- [ ] Review compliance requirements (PCI-DSS, HIPAA)
## nginx Configuration Template
```nginx
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256';
ssl_prefer_server_ciphers off;
ssl_ecdh_curve X25519:secp256r1:secp384r1;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
```
## Python TLS 1.3 Client Template
```python
import ssl
import socket
context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
context.minimum_version = ssl.TLSVersion.TLSv1_3
context.load_default_certs()
with socket.create_connection(("example.com", 443)) as sock:
with context.wrap_socket(sock, server_hostname="example.com") as tls:
print(f"Protocol: {tls.version()}")
print(f"Cipher: {tls.cipher()}")
```
## Validation Commands
```bash
# Test TLS 1.3 support
openssl s_client -connect example.com:443 -tls1_3
# Show full certificate chain
openssl s_client -connect example.com:443 -showcerts
# List supported cipher suites
openssl s_client -connect example.com:443 -cipher 'ALL' -tls1_3
# Test with testssl.sh
./testssl.sh --protocols --ciphers --headers example.com
```
## Security Headers Checklist
| Header | Value | Purpose |
|--------|-------|---------|
| Strict-Transport-Security | max-age=63072000; includeSubDomains; preload | Force HTTPS |
| X-Content-Type-Options | nosniff | Prevent MIME sniffing |
| X-Frame-Options | DENY | Prevent clickjacking |
| Content-Security-Policy | default-src 'self' | Prevent XSS |
| Referrer-Policy | strict-origin-when-cross-origin | Limit referrer leakage |
@@ -0,0 +1,67 @@
# Standards and References - TLS 1.3 Configuration
## Primary Standards
### RFC 8446 - The Transport Layer Security (TLS) Protocol Version 1.3
- **URL**: https://www.rfc-editor.org/rfc/rfc8446
- **Description**: The core TLS 1.3 specification
- **Key changes**: 1-RTT handshake, mandatory PFS, removed RSA key transport, encrypted handshake messages
### RFC 8447 - IANA Registry Updates for TLS and DTLS
- **URL**: https://www.rfc-editor.org/rfc/rfc8447
- **Description**: Updates IANA registries for TLS cipher suites and extensions
### RFC 8449 - Record Size Limit Extension for TLS
- **URL**: https://www.rfc-editor.org/rfc/rfc8449
- **Description**: Allows endpoints to negotiate maximum record size
### RFC 8470 - Using Early Data in HTTP (0-RTT)
- **URL**: https://www.rfc-editor.org/rfc/rfc8470
- **Description**: Defines how 0-RTT early data works with HTTP, including replay protections
### RFC 6961 - TLS Multiple Certificate Status Extension (OCSP Stapling)
- **URL**: https://www.rfc-editor.org/rfc/rfc6961
- **Description**: Allows servers to provide OCSP responses during handshake
### RFC 6797 - HTTP Strict Transport Security (HSTS)
- **URL**: https://www.rfc-editor.org/rfc/rfc6797
- **Description**: Forces browsers to use HTTPS for all connections
## NIST Guidelines
### NIST SP 800-52 Rev. 2 - Guidelines for TLS Implementations
- **URL**: https://csrc.nist.gov/publications/detail/sp/800-52/rev-2/final
- **Description**: Federal guidelines for TLS deployment
- **TLS 1.3**: Recommended for all new deployments
- **TLS 1.2**: Acceptable with approved cipher suites
- **TLS 1.0/1.1**: Prohibited
### NIST SP 800-57 Part 3 Rev. 1 - Application-Specific Key Management
- **URL**: https://csrc.nist.gov/publications/detail/sp/800-57-part-3/rev-1/final
- **Description**: Key management guidance for TLS
## Testing Tools
### testssl.sh
- **URL**: https://testssl.sh/
- **GitHub**: https://github.com/drwetter/testssl.sh
- **Description**: Command-line tool for checking TLS/SSL configurations
### SSL Labs Server Test
- **URL**: https://www.ssllabs.com/ssltest/
- **Description**: Online TLS configuration analyzer (Qualys)
### Mozilla SSL Configuration Generator
- **URL**: https://ssl-config.mozilla.org/
- **Description**: Generate recommended TLS configurations for various servers
## Compliance
### PCI DSS v4.0
- TLS 1.0 and early TLS prohibited since June 2018
- TLS 1.2+ required; TLS 1.3 recommended
- Strong cipher suites must be configured
### HIPAA
- Encryption in transit required for ePHI
- TLS 1.2+ satisfies the requirement
@@ -0,0 +1,87 @@
# Workflows - Configuring TLS 1.3
## Workflow 1: TLS 1.3 Handshake (1-RTT)
```
Client Server
| |
|--- ClientHello ------------------>|
| (supported_versions: TLS 1.3) |
| (key_share: x25519) |
| (signature_algorithms) |
| (cipher_suites) |
| |
|<-- ServerHello -------------------|
| (selected cipher suite) |
| (key_share: x25519) |
|<-- {EncryptedExtensions} ---------|
|<-- {Certificate} -----------------|
|<-- {CertificateVerify} -----------|
|<-- {Finished} --------------------|
| |
|--- {Finished} ------------------->|
| |
|<== Application Data ==============>|
```
## Workflow 2: nginx TLS 1.3 Configuration
```
1. Check OpenSSL version (>= 1.1.1)
$ openssl version
2. Generate ECDSA certificate
$ openssl ecparam -genkey -name prime256v1 -out server.key
$ openssl req -new -x509 -key server.key -out server.crt -days 365
3. Configure nginx
Edit /etc/nginx/nginx.conf
4. Test configuration
$ nginx -t
5. Reload nginx
$ systemctl reload nginx
6. Verify TLS 1.3
$ openssl s_client -connect localhost:443 -tls1_3
```
## Workflow 3: TLS Configuration Validation
```
[Server] --> [openssl s_client test]
|
[Check protocol version]
[Check cipher suite]
[Check certificate chain]
|
[testssl.sh full scan]
|
[Check for vulnerabilities]
- BEAST, POODLE, Heartbleed
- ROBOT, DROWN, FREAK
- Weak ciphers, expired certs
|
[SSL Labs grade assessment]
Target: A+ rating
```
## Workflow 4: Certificate Lifecycle
```
[Generate Key Pair]
|
[Create CSR] --> [Submit to CA]
|
[CA Issues Certificate]
|
[Install Certificate]
|
[Configure OCSP Stapling]
|
[Set Up Auto-Renewal]
(certbot / ACME)
|
[Monitor Expiration]
```
@@ -0,0 +1,419 @@
#!/usr/bin/env python3
"""
TLS 1.3 Configuration and Validation Tool
Implements TLS 1.3 server/client testing, configuration generation,
and vulnerability scanning using Python's ssl module and OpenSSL.
Requirements:
pip install cryptography
Usage:
python process.py test-server --host example.com --port 443
python process.py generate-nginx --domain example.com --cert-path /etc/ssl
python process.py generate-cert --domain example.com --output ./certs
python process.py check-ciphers --host example.com
"""
import os
import ssl
import sys
import json
import socket
import argparse
import logging
import subprocess
import datetime
from pathlib import Path
from typing import Optional, Dict, List
from cryptography import x509
from cryptography.x509.oid import NameOID, ExtensionOID
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import ec, rsa
logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s")
logger = logging.getLogger(__name__)
TLS_13_CIPHERS = [
"TLS_AES_256_GCM_SHA384",
"TLS_AES_128_GCM_SHA256",
"TLS_CHACHA20_POLY1305_SHA256",
]
RECOMMENDED_TLS_12_CIPHERS = [
"ECDHE-ECDSA-AES256-GCM-SHA384",
"ECDHE-RSA-AES256-GCM-SHA384",
"ECDHE-ECDSA-AES128-GCM-SHA256",
"ECDHE-RSA-AES128-GCM-SHA256",
"ECDHE-ECDSA-CHACHA20-POLY1305",
"ECDHE-RSA-CHACHA20-POLY1305",
]
def test_tls_connection(host: str, port: int = 443, timeout: int = 10) -> Dict:
"""Test TLS connection to a server and report protocol details."""
results = {
"host": host,
"port": port,
"tls_13_supported": False,
"tls_12_supported": False,
"protocol_version": None,
"cipher_suite": None,
"certificate": None,
"issues": [],
}
# Test TLS 1.3
try:
ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
ctx.minimum_version = ssl.TLSVersion.TLSv1_3
ctx.maximum_version = ssl.TLSVersion.TLSv1_3
with socket.create_connection((host, port), timeout=timeout) as sock:
with ctx.wrap_socket(sock, server_hostname=host) as ssock:
results["tls_13_supported"] = True
results["protocol_version"] = ssock.version()
cipher = ssock.cipher()
results["cipher_suite"] = {
"name": cipher[0],
"protocol": cipher[1],
"bits": cipher[2],
}
cert = ssock.getpeercert()
results["certificate"] = {
"subject": dict(x[0] for x in cert.get("subject", ())),
"issuer": dict(x[0] for x in cert.get("issuer", ())),
"notBefore": cert.get("notBefore"),
"notAfter": cert.get("notAfter"),
"serialNumber": cert.get("serialNumber"),
"version": cert.get("version"),
}
logger.info(f"TLS 1.3 connection successful: {cipher[0]}")
except ssl.SSLError as e:
results["issues"].append(f"TLS 1.3 not supported: {e}")
logger.warning(f"TLS 1.3 not supported on {host}:{port}")
except Exception as e:
results["issues"].append(f"Connection error: {e}")
# Test TLS 1.2
try:
ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
ctx.minimum_version = ssl.TLSVersion.TLSv1_2
ctx.maximum_version = ssl.TLSVersion.TLSv1_2
with socket.create_connection((host, port), timeout=timeout) as sock:
with ctx.wrap_socket(sock, server_hostname=host) as ssock:
results["tls_12_supported"] = True
if not results["tls_13_supported"]:
results["protocol_version"] = ssock.version()
cipher = ssock.cipher()
results["cipher_suite"] = {
"name": cipher[0],
"protocol": cipher[1],
"bits": cipher[2],
}
except (ssl.SSLError, Exception):
pass
# Test deprecated protocols
for version_name, version_enum in [
("TLS 1.1", ssl.TLSVersion.TLSv1_1),
("TLS 1.0", ssl.TLSVersion.TLSv1),
]:
try:
ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
ctx.minimum_version = version_enum
ctx.maximum_version = version_enum
ctx.check_hostname = False
ctx.verify_mode = ssl.CERT_NONE
with socket.create_connection((host, port), timeout=timeout) as sock:
with ctx.wrap_socket(sock, server_hostname=host) as ssock:
results["issues"].append(
f"VULNERABLE: {version_name} is still enabled (should be disabled)"
)
logger.warning(f"{version_name} is enabled on {host}:{port}")
except (ssl.SSLError, OSError):
pass
return results
def check_cipher_suites(host: str, port: int = 443, timeout: int = 10) -> Dict:
"""Check which cipher suites a server supports."""
results = {"host": host, "port": port, "supported_ciphers": [], "weak_ciphers": []}
weak_patterns = ["RC4", "DES", "3DES", "MD5", "NULL", "EXPORT", "anon"]
ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
ctx.check_hostname = False
ctx.verify_mode = ssl.CERT_NONE
try:
with socket.create_connection((host, port), timeout=timeout) as sock:
with ctx.wrap_socket(sock, server_hostname=host) as ssock:
cipher = ssock.cipher()
results["negotiated_cipher"] = {
"name": cipher[0],
"protocol": cipher[1],
"bits": cipher[2],
}
shared = ssock.shared_ciphers()
if shared:
for c in shared:
cipher_info = {"name": c[0], "protocol": c[1], "bits": c[2]}
results["supported_ciphers"].append(cipher_info)
if any(weak in c[0] for weak in weak_patterns):
results["weak_ciphers"].append(cipher_info)
except Exception as e:
results["error"] = str(e)
return results
def generate_self_signed_cert(
domain: str, output_dir: str, key_type: str = "ecdsa"
) -> Dict:
"""Generate a self-signed TLS certificate for testing."""
output_path = Path(output_dir)
output_path.mkdir(parents=True, exist_ok=True)
if key_type == "ecdsa":
private_key = ec.generate_private_key(ec.SECP256R1())
key_filename = "server-ecdsa.key"
cert_filename = "server-ecdsa.crt"
else:
private_key = rsa.generate_private_key(public_exponent=65537, key_size=2048)
key_filename = "server-rsa.key"
cert_filename = "server-rsa.crt"
subject = issuer = x509.Name([
x509.NameAttribute(NameOID.COUNTRY_NAME, "US"),
x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, "California"),
x509.NameAttribute(NameOID.ORGANIZATION_NAME, "Test Organization"),
x509.NameAttribute(NameOID.COMMON_NAME, domain),
])
cert = (
x509.CertificateBuilder()
.subject_name(subject)
.issuer_name(issuer)
.public_key(private_key.public_key())
.serial_number(x509.random_serial_number())
.not_valid_before(datetime.datetime.utcnow())
.not_valid_after(datetime.datetime.utcnow() + datetime.timedelta(days=365))
.add_extension(
x509.SubjectAlternativeName([
x509.DNSName(domain),
x509.DNSName(f"*.{domain}"),
]),
critical=False,
)
.add_extension(
x509.BasicConstraints(ca=False, path_length=None),
critical=True,
)
.sign(private_key, hashes.SHA256())
)
key_path = output_path / key_filename
cert_path = output_path / cert_filename
key_path.write_bytes(
private_key.private_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PrivateFormat.TraditionalOpenSSL,
encryption_algorithm=serialization.NoEncryption(),
)
)
cert_path.write_bytes(cert.public_bytes(serialization.Encoding.PEM))
logger.info(f"Generated {key_type.upper()} certificate for {domain}")
logger.info(f" Key: {key_path}")
logger.info(f" Cert: {cert_path}")
return {
"domain": domain,
"key_type": key_type,
"key_path": str(key_path),
"cert_path": str(cert_path),
"valid_days": 365,
}
def generate_nginx_config(
domain: str, cert_path: str, key_path: str, enable_tls12: bool = True
) -> str:
"""Generate nginx TLS 1.3 configuration."""
tls_protocols = "TLSv1.3"
if enable_tls12:
tls_protocols = "TLSv1.2 TLSv1.3"
tls12_ciphers = ":".join(RECOMMENDED_TLS_12_CIPHERS)
config = f"""# TLS 1.3 Optimized nginx Configuration
# Generated for: {domain}
# Mozilla SSL Configuration Generator: Modern profile
server {{
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name {domain};
# Certificate paths
ssl_certificate {cert_path};
ssl_certificate_key {key_path};
# Protocol versions
ssl_protocols {tls_protocols};
# TLS 1.2 cipher suites (TLS 1.3 ciphers are configured automatically)
ssl_ciphers '{tls12_ciphers}';
ssl_prefer_server_ciphers off;
# ECDH curve
ssl_ecdh_curve X25519:secp256r1:secp384r1;
# OCSP Stapling
ssl_stapling on;
ssl_stapling_verify on;
resolver 1.1.1.1 8.8.8.8 valid=300s;
resolver_timeout 5s;
# Session configuration
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
# Security headers
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "DENY" always;
add_header X-XSS-Protection "0" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
# Root and index
root /var/www/{domain}/html;
index index.html;
location / {{
try_files $uri $uri/ =404;
}}
}}
# HTTP to HTTPS redirect
server {{
listen 80;
listen [::]:80;
server_name {domain};
return 301 https://$server_name$request_uri;
}}
"""
return config
def generate_apache_config(
domain: str, cert_path: str, key_path: str, enable_tls12: bool = True
) -> str:
"""Generate Apache TLS 1.3 configuration."""
tls_protocols = "TLSv1.3"
if enable_tls12:
tls_protocols = "TLSv1.2 TLSv1.3"
tls12_ciphers = ":".join(RECOMMENDED_TLS_12_CIPHERS)
config = f"""# TLS 1.3 Optimized Apache Configuration
# Generated for: {domain}
<VirtualHost *:443>
ServerName {domain}
DocumentRoot /var/www/{domain}/html
SSLEngine on
SSLCertificateFile {cert_path}
SSLCertificateKeyFile {key_path}
# Protocol versions
SSLProtocol all -{" -".join(["SSLv3", "TLSv1", "TLSv1.1"])}
{"" if enable_tls12 else "SSLProtocol TLSv1.3"}
# Cipher suites
SSLCipherSuite {tls12_ciphers}
SSLHonorCipherOrder off
# OCSP Stapling
SSLUseStapling on
SSLStaplingCache shmcb:/var/run/ocsp(128000)
# Security headers
Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
Header always set X-Content-Type-Options "nosniff"
Header always set X-Frame-Options "DENY"
</VirtualHost>
# HTTP to HTTPS redirect
<VirtualHost *:80>
ServerName {domain}
Redirect permanent / https://{domain}/
</VirtualHost>
"""
return config
def main():
parser = argparse.ArgumentParser(description="TLS 1.3 Configuration Tool")
subparsers = parser.add_subparsers(dest="command")
# Test server
test = subparsers.add_parser("test-server", help="Test TLS configuration of a server")
test.add_argument("--host", required=True, help="Server hostname")
test.add_argument("--port", type=int, default=443, help="Server port")
# Check ciphers
ciphers = subparsers.add_parser("check-ciphers", help="Check supported cipher suites")
ciphers.add_argument("--host", required=True, help="Server hostname")
ciphers.add_argument("--port", type=int, default=443, help="Server port")
# Generate certificate
cert = subparsers.add_parser("generate-cert", help="Generate self-signed certificate")
cert.add_argument("--domain", required=True, help="Domain name")
cert.add_argument("--output", default="./certs", help="Output directory")
cert.add_argument("--key-type", choices=["ecdsa", "rsa"], default="ecdsa")
# Generate nginx config
nginx = subparsers.add_parser("generate-nginx", help="Generate nginx TLS config")
nginx.add_argument("--domain", required=True, help="Domain name")
nginx.add_argument("--cert-path", required=True, help="Certificate file path")
nginx.add_argument("--key-path", required=True, help="Private key file path")
nginx.add_argument("--tls12", action="store_true", default=True, help="Enable TLS 1.2")
# Generate Apache config
apache = subparsers.add_parser("generate-apache", help="Generate Apache TLS config")
apache.add_argument("--domain", required=True, help="Domain name")
apache.add_argument("--cert-path", required=True, help="Certificate file path")
apache.add_argument("--key-path", required=True, help="Private key file path")
args = parser.parse_args()
if args.command == "test-server":
result = test_tls_connection(args.host, args.port)
print(json.dumps(result, indent=2, default=str))
elif args.command == "check-ciphers":
result = check_cipher_suites(args.host, args.port)
print(json.dumps(result, indent=2))
elif args.command == "generate-cert":
result = generate_self_signed_cert(args.domain, args.output, args.key_type)
print(json.dumps(result, indent=2))
elif args.command == "generate-nginx":
config = generate_nginx_config(args.domain, args.cert_path, args.key_path, args.tls12)
print(config)
elif args.command == "generate-apache":
config = generate_apache_config(args.domain, args.cert_path, args.key_path)
print(config)
else:
parser.print_help()
if __name__ == "__main__":
main()