Skip to content

Commit 3223516

Browse files
antiFetzenChristoph EhrenspergerantiFetzen
authored
Subdomain and cert manager compatibility (#42)
* FIX support for subdomain * ADD multiple domain format support * smaller adjustments * REWRITE device selection and replace regexp by BeautifulSoup --------- Co-authored-by: Christoph Ehrensperger <christoph.ehrensperger@patrizia.ag> Co-authored-by: antiFetzen <anti.fetzen@gmail.com>
1 parent bdcf9a9 commit 3223516

File tree

1 file changed

+29
-24
lines changed

1 file changed

+29
-24
lines changed

certbotstratoapi.py

Lines changed: 29 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -18,19 +18,31 @@ def __init__(self, api_url=None):
1818
self.api_url = "https://www.strato.de/apps/CustomerService"
1919
else:
2020
self.api_url = api_url
21-
self.txt_key = "_acme-challenge"
22-
self.txt_value = os.environ["CERTBOT_VALIDATION"]
23-
self.domain_name = os.environ["CERTBOT_DOMAIN"]
24-
self.second_level_domain_name = re.search(
25-
r"([\w-]+\.[\w-]+)$", self.domain_name
26-
).group(1)
21+
22+
self.acme_challenge_label = "_acme-challenge"
23+
24+
# Domain of the requested certificate
25+
# root-zone period and acme-challenge lable will be removed
26+
# _acme-challenge.subdomain.example.com. -> subdomain.example.com
27+
self.domain_name = re.sub(f"^{self.acme_challenge_label}\\.|\\.$", "", os.environ["CERTBOT_DOMAIN"])
28+
# Second Level Domain:
29+
# example.com
30+
self.second_level_domain_name = re.search(r"([\w-]+\.[\w-]+)$",self.domain_name).group(1)
31+
# Subdomain: All parts under the second level domain
32+
# subdomain.example.com -> subdomain
2733
self.subdomain = self.extract_subdomain()
28-
print(f"INFO: txt_key: {self.txt_key}")
29-
print(f"INFO: txt_value: {self.txt_value}")
30-
print(f"INFO: second_level_domain_name: {self.second_level_domain_name}")
34+
35+
# TXT-Record key combination of acme-challenge label and subdomain if exists
36+
self.txt_key = self.acme_challenge_label + ("" if len(self.subdomain) == 0 else "." + self.subdomain)
37+
self.txt_value = os.environ["CERTBOT_VALIDATION"]
38+
3139
print(f"INFO: domain_name: {self.domain_name}")
40+
print(f"INFO: second_level_domain_name: {self.second_level_domain_name}")
3241
print(f"INFO: subdomain: {self.subdomain}")
3342

43+
print(f"INFO: txt_key: {self.txt_key}")
44+
print(f"INFO: txt_value: {self.txt_value}")
45+
3446
# setup session for cookie sharing
3547
headers = {
3648
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:126.0) Gecko/20100101 Firefox/126.0"
@@ -84,17 +96,12 @@ def login_2fa(
8496
# Set parameter 'action_customer_login.x'
8597
param["action_customer_login.x"] = 1
8698

87-
# No idea what this regex does
88-
# TODO: rewrite with beautifulsoup
8999
# Set parameter pw_id
90-
for device in re.finditer(
91-
rf'<option value="(?P<value>(S\.{username}\.\w*))"'
92-
r'( selected(="selected")?)?\s*>(?P<name>(.+?))</option>',
93-
response.text,
94-
):
95-
if totp_devicename.strip() == device.group("name").strip():
96-
param["pw_id"] = device.group("value")
100+
for device in soup.select(f"option[value*='{username}']"):
101+
if totp_devicename.strip() == device.text.strip():
102+
param["pw_id"] = device.attrs["value"]
97103
break
104+
98105
if param.get("pw_id") is None:
99106
print("ERROR: Parsing error on 2FA site by device name.")
100107
return response
@@ -198,7 +205,7 @@ def get_txt_records(self) -> None:
198205
"cID": self.package_id,
199206
"node": "ManageDomains",
200207
"action_show_txt_records": "",
201-
"vhost": self.domain_name,
208+
"vhost": self.second_level_domain_name,
202209
},
203210
)
204211

@@ -262,13 +269,11 @@ def remove_txt_record(self, prefix: str, record_type: str) -> None:
262269

263270
def set_amce_record(self) -> None:
264271
"""Set or replace AMCE txt record on domain."""
265-
key = f"{self.txt_key}.{self.subdomain}" if self.subdomain else self.txt_key
266-
self.add_txt_record(key, "TXT", self.txt_value)
272+
self.add_txt_record(self.txt_key, "TXT", self.txt_value)
267273

268274
def reset_amce_record(self) -> None:
269275
"""Reset AMCE txt record on domain."""
270-
key = f"{self.txt_key}.{self.subdomain}" if self.subdomain else self.txt_key
271-
self.remove_txt_record(key, "TXT")
276+
self.remove_txt_record(self.txt_key, "TXT")
272277

273278
def push_txt_records(self) -> None:
274279
"""Push modified txt records to Strato."""
@@ -284,7 +289,7 @@ def push_txt_records(self) -> None:
284289
"sessionID": self.session_id,
285290
"cID": self.package_id,
286291
"node": "ManageDomains",
287-
"vhost": self.domain_name,
292+
"vhost": self.second_level_domain_name,
288293
"spf_type": "NONE",
289294
"prefix": [r["prefix"] for r in self.records],
290295
"type": [r["type"] for r in self.records],

0 commit comments

Comments
 (0)