Coverage for frappe_manager / ssl_manager / ssl_utils.py: 0%
48 statements
« prev ^ index » next coverage.py v7.13.5, created at 2026-07-02 18:35 +0530
« prev ^ index » next coverage.py v7.13.5, created at 2026-07-02 18:35 +0530
1"""
2SSL Manager utility functions for credentials and configuration management.
3"""
5from typing import TYPE_CHECKING, Optional
7if TYPE_CHECKING:
8 from frappe_manager.site_manager.bench_config import BenchConfig
10from frappe_manager.metadata_manager import FMConfigManager
11from frappe_manager.ssl_manager import LETSENCRYPT_PREFERRED_CHALLENGE
12from frappe_manager.ssl_manager.certificate import SSLCertificate
13from frappe_manager.ssl_manager.certificate_exceptions import SSLDNSChallengeCredentailsNotFound
16def get_dns_credentials_for_certificate(
17 certificate: SSLCertificate,
18 bench_config: Optional["BenchConfig"] = None,
19) -> dict[str, str] | None:
20 """
21 Load DNS credentials and format for acme.sh.
23 Checks credentials in this order:
24 1. Bench-level DNS provider config (if bench_config provided)
25 2. Global FM config
26 3. Certificate-specific credentials (api_token/api_key on cert object)
28 This function retrieves Cloudflare API credentials and formats them as
29 environment variables for acme.sh dns_cf plugin.
31 Args:
32 certificate: Certificate configuration
33 bench_config: Optional bench configuration for bench-level credentials
35 Returns:
36 Dictionary of environment variables for acme.sh:
37 - {'CF_Token': 'xxx'} for API token auth, or
38 - {'CF_Key': 'xxx', 'CF_Email': 'xxx'} for global API key auth
39 - None if not a DNS challenge
41 Raises:
42 SSLDNSChallengeCredentailsNotFound: If DNS challenge requires credentials but none found
44 Example:
45 >>> cert = SSLCertificate(domain="example.com", challenge_type=LETSENCRYPT_PREFERRED_CHALLENGE.dns01)
46 >>> creds = get_dns_credentials_for_certificate(cert, bench_config)
47 >>> # Use creds with acme.sh service
48 >>> service.generate_certificate(cert, dns_credentials=creds)
49 """
50 if certificate.challenge_type != LETSENCRYPT_PREFERRED_CHALLENGE.dns01:
51 return None
53 credentials = {}
55 if bench_config and bench_config.dns_providers:
56 cloudflare_config = bench_config.dns_providers.get("cloudflare")
57 if cloudflare_config and cloudflare_config.exists:
58 if cloudflare_config.api_token:
59 credentials["CF_Token"] = cloudflare_config.api_token
60 elif cloudflare_config.api_key:
61 credentials["CF_Key"] = cloudflare_config.api_key
62 if cloudflare_config.email:
63 credentials["CF_Email"] = str(cloudflare_config.email)
64 if credentials:
65 return credentials
67 fm_config = FMConfigManager.import_from_toml()
69 if fm_config.cloudflare.api_token:
70 credentials["CF_Token"] = fm_config.cloudflare.api_token
71 elif fm_config.cloudflare.api_key:
72 credentials["CF_Key"] = fm_config.cloudflare.api_key
73 if fm_config.cloudflare.email:
74 credentials["CF_Email"] = str(fm_config.cloudflare.email)
76 if not credentials:
77 if hasattr(certificate, "api_token") and certificate.api_token:
78 credentials["CF_Token"] = certificate.api_token
79 elif hasattr(certificate, "api_key") and certificate.api_key:
80 credentials["CF_Key"] = certificate.api_key
81 if hasattr(certificate, "email") and certificate.email:
82 credentials["CF_Email"] = str(certificate.email)
84 if not credentials:
85 raise SSLDNSChallengeCredentailsNotFound()
87 return credentials
90def get_dns_credentials_dict(
91 api_token: str | None = None,
92 api_key: str | None = None,
93 email: str | None = None,
94) -> dict[str, str]:
95 """
96 Create DNS credentials dictionary from individual parameters.
98 Useful for explicitly passing credentials instead of loading from config.
100 Args:
101 api_token: Cloudflare API token (preferred)
102 api_key: Cloudflare Global API key (legacy)
103 email: Email for Global API key auth
105 Returns:
106 Dictionary formatted for acme.sh
108 Raises:
109 SSLDNSChallengeCredentailsNotFound: If no valid credentials provided
111 Example:
112 >>> creds = get_dns_credentials_dict(api_token="my_token_here")
113 >>> service.generate_certificate(cert, dns_credentials=creds)
114 """
115 credentials = {}
117 if api_token:
118 credentials["CF_Token"] = api_token
119 elif api_key:
120 credentials["CF_Key"] = api_key
121 if email:
122 credentials["CF_Email"] = email
124 if not credentials:
125 raise SSLDNSChallengeCredentailsNotFound(
126 "No Cloudflare credentials provided. Need either api_token or (api_key + email)",
127 )
129 return credentials