Server-less Python Web Services for AWS Lambda and API Gateway
Automated SSL certificate provisioning using Let's Encrypt ACME protocol for securing deployed applications with HTTPS. This capability enables automatic SSL certificate generation, renewal, and domain configuration for serverless applications.
Main certificate generation and domain update functionality.
def get_cert_and_update_domain(**kwargs):
"""
Main function to obtain SSL certificate and update domain.
Orchestrates the complete SSL certificate provisioning process
including domain validation, certificate generation, and AWS configuration.
Parameters:
- domain: str, domain name for certificate
- email: str, contact email for Let's Encrypt
- certificate_arn: str, existing certificate ARN to update
- route53_hosted_zone_id: str, Route53 hosted zone ID
- aws_region: str, AWS region for certificate
- **kwargs: Additional configuration options
Returns:
dict: Certificate information and ARN
"""Core certificate creation using Let's Encrypt ACME protocol.
def get_cert(
domain,
email,
account_key_path=None,
domain_key_path=None,
ca=None,
**kwargs
):
"""
Obtain SSL certificate from Let's Encrypt ACME CA.
Performs domain ownership validation and requests certificate
from Let's Encrypt Certificate Authority.
Parameters:
- domain: str, domain name for certificate
- email: str, contact email address
- account_key_path: str, path to ACME account key file
- domain_key_path: str, path to domain private key file
- ca: str, Certificate Authority URL
- **kwargs: Additional ACME configuration
Returns:
dict: Certificate data and metadata
"""Generate cryptographic keys and certificate signing requests.
def create_domain_key(key_path=None, key_size=2048):
"""
Create RSA private key for domain certificate.
Generates RSA private key for SSL certificate with
specified key size and saves to file.
Parameters:
- key_path: str, path to save private key file
- key_size: int, RSA key size in bits (default 2048)
Returns:
str: Path to generated private key file
"""def create_domain_csr(domain, key_path, csr_path=None, **kwargs):
"""
Create certificate signing request for domain.
Generates CSR using domain private key with proper
subject and extensions for SSL certificate.
Parameters:
- domain: str, domain name for certificate
- key_path: str, path to domain private key
- csr_path: str, path to save CSR file
- **kwargs: Additional CSR configuration
Returns:
str: Path to generated CSR file
"""Process and format certificates for deployment.
def create_chained_certificate(cert_path, chain_path=None):
"""
Create full certificate chain for deployment.
Combines domain certificate with intermediate certificates
to create complete certificate chain for SSL.
Parameters:
- cert_path: str, path to domain certificate file
- chain_path: str, path to certificate chain file
Returns:
str: Full certificate chain content
"""def encode_certificate(cert_content):
"""
Encode certificate for AWS usage.
Formats certificate content for AWS Certificate Manager
or other AWS services requiring specific encoding.
Parameters:
- cert_content: str, certificate content to encode
Returns:
str: Encoded certificate content
"""Handle ACME protocol interactions with Certificate Authority.
def verify_challenge(challenge_url, challenge_content):
"""
Verify ACME domain ownership challenge.
Validates that domain challenge file is properly accessible
at the expected URL for domain ownership verification.
Parameters:
- challenge_url: str, URL to challenge file
- challenge_content: str, expected challenge content
Returns:
bool: True if challenge verification successful
"""def sign_certificate(csr_path, ca_url, account_key, **kwargs):
"""
Sign certificate with Certificate Authority.
Submits CSR to CA for signing and retrieves signed
certificate after domain validation.
Parameters:
- csr_path: str, path to certificate signing request
- ca_url: str, Certificate Authority URL
- account_key: str, ACME account private key
- **kwargs: Additional signing configuration
Returns:
str: Signed certificate content
"""Manage ACME account registration and key parsing.
def register_account(email, account_key, ca_url):
"""
Register new account with ACME Certificate Authority.
Creates new account with Let's Encrypt using email
and account private key for future certificate requests.
Parameters:
- email: str, contact email address
- account_key: str, ACME account private key
- ca_url: str, Certificate Authority URL
Returns:
dict: Account registration information
"""def parse_account_key(key_content):
"""
Parse ACME account private key.
Parses and validates ACME account key format
for use in certificate requests.
Parameters:
- key_content: str, account private key content
Returns:
dict: Parsed key information
"""def parse_csr(csr_content):
"""
Parse certificate signing request data.
Extracts and validates information from CSR
including domain names and key information.
Parameters:
- csr_content: str, CSR content to parse
Returns:
dict: Parsed CSR information
"""Temporary directory management for certificate operations.
def gettempdir():
"""
Get temporary directory for certificate operations.
Returns appropriate temporary directory path for
storing certificate files during generation process.
Returns:
str: Temporary directory path
"""# Default Certificate Authority URL (Let's Encrypt production)
DEFAULT_CA = "https://acme-v02.api.letsencrypt.org/directory"from zappa.letsencrypt import get_cert_and_update_domain
# Generate certificate for domain
cert_info = get_cert_and_update_domain(
domain='api.myapp.com',
email='admin@myapp.com',
route53_hosted_zone_id='Z123456789',
aws_region='us-east-1'
)
print(f"Certificate ARN: {cert_info['certificate_arn']}")from zappa.letsencrypt import (
create_domain_key,
create_domain_csr,
get_cert,
create_chained_certificate
)
# Generate domain private key
key_path = create_domain_key('domain.key', key_size=2048)
# Create certificate signing request
csr_path = create_domain_csr(
domain='myapp.com',
key_path=key_path,
csr_path='domain.csr'
)
# Get certificate from Let's Encrypt
cert_data = get_cert(
domain='myapp.com',
email='admin@myapp.com',
domain_key_path=key_path
)
# Create full certificate chain
full_chain = create_chained_certificate(cert_data['cert_path'])from zappa.letsencrypt import register_account, parse_account_key
# Register account with Let's Encrypt
account_key_content = """-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEA...
-----END RSA PRIVATE KEY-----"""
account_info = register_account(
email='certificates@myapp.com',
account_key=account_key_content,
ca_url='https://acme-v02.api.letsencrypt.org/directory'
)
print(f"Account registered: {account_info['status']}")from zappa.letsencrypt import verify_challenge
# Verify domain ownership challenge
challenge_verified = verify_challenge(
challenge_url='http://myapp.com/.well-known/acme-challenge/token123',
challenge_content='token123.signature456'
)
if challenge_verified:
print("Domain ownership verified successfully")
else:
print("Challenge verification failed")from zappa.letsencrypt import get_cert
# Use Let's Encrypt staging environment for testing
staging_ca = "https://acme-staging-v02.api.letsencrypt.org/directory"
cert_data = get_cert(
domain='test.myapp.com',
email='test@myapp.com',
ca=staging_ca
)
print(f"Test certificate obtained: {cert_data['cert_path']}")from zappa.letsencrypt import create_chained_certificate, encode_certificate
# Create certificate chain
cert_chain = create_chained_certificate(
cert_path='domain.crt',
chain_path='chain.crt'
)
# Encode for AWS
encoded_cert = encode_certificate(cert_chain)
# Use with AWS Certificate Manager
import boto3
acm = boto3.client('acm', region_name='us-east-1')
response = acm.import_certificate(
Certificate=encoded_cert,
PrivateKey=open('domain.key').read(),
CertificateChain=cert_chain
)
print(f"Certificate imported: {response['CertificateArn']}")from zappa.letsencrypt import get_cert_and_update_domain
from zappa.asynchronous import task
@task
def renew_certificate(domain, email, cert_arn):
"""Async certificate renewal task."""
try:
new_cert = get_cert_and_update_domain(
domain=domain,
email=email,
certificate_arn=cert_arn,
renew=True
)
return f"Certificate renewed: {new_cert['certificate_arn']}"
except Exception as e:
return f"Renewal failed: {str(e)}"
# Schedule certificate renewal
renewal_response = renew_certificate(
domain='api.myapp.com',
email='admin@myapp.com',
cert_arn='arn:aws:acm:us-east-1:123456789012:certificate/abc123'
)Install with Tessl CLI
npx tessl i tessl/pypi-zappa