FastAPI-based SSL certificate automation server. - Google Public CA wildcard cert issuance via certbot - Cloudflare DNS-01 challenge with auto EAB key generation - APISIX multi-instance deployment with domain-instance mapping - Vault integration for all secrets - Bearer token auth, retry logic, Discord DM alerts - Auto-renewal scheduler (daily 03:00 UTC) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
53 lines
1.5 KiB
Python
53 lines
1.5 KiB
Python
import json
|
|
import logging
|
|
|
|
import httpx
|
|
from google.auth.transport.requests import Request
|
|
from google.oauth2 import service_account
|
|
from tenacity import retry, stop_after_attempt, wait_exponential, retry_if_exception_type
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
SCOPES = ["https://www.googleapis.com/auth/cloud-platform"]
|
|
PUBLIC_CA_API = "https://publicca.googleapis.com/v1"
|
|
|
|
|
|
def _get_credentials(sa_json: str) -> service_account.Credentials:
|
|
info = json.loads(sa_json)
|
|
return service_account.Credentials.from_service_account_info(info, scopes=SCOPES)
|
|
|
|
|
|
@retry(
|
|
stop=stop_after_attempt(3),
|
|
wait=wait_exponential(multiplier=1, min=2, max=10),
|
|
retry=retry_if_exception_type((httpx.ConnectError, httpx.TimeoutException)),
|
|
reraise=True,
|
|
)
|
|
def _request_eab_key(token: str, project: str) -> dict:
|
|
url = f"{PUBLIC_CA_API}/projects/{project}/locations/global/externalAccountKeys"
|
|
response = httpx.post(
|
|
url,
|
|
headers={
|
|
"Authorization": f"Bearer {token}",
|
|
"Content-Type": "application/json",
|
|
},
|
|
json={},
|
|
timeout=30,
|
|
)
|
|
response.raise_for_status()
|
|
return response.json()
|
|
|
|
|
|
def create_eab_key(sa_json: str, project: str) -> dict:
|
|
"""Google Public CA API로 새 EAB 키 생성."""
|
|
creds = _get_credentials(sa_json)
|
|
creds.refresh(Request())
|
|
|
|
data = _request_eab_key(creds.token, project)
|
|
|
|
logger.info("Created new EAB key: %s", data.get("keyId"))
|
|
return {
|
|
"key_id": data["keyId"],
|
|
"b64_mac_key": data["b64MacKey"],
|
|
}
|