certbot-dns-aa 0.1.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,34 @@
1
+ Metadata-Version: 2.4
2
+ Name: certbot-dns-aa
3
+ Version: 0.1.1
4
+ Summary: Certbot DNS-01 plugin for Andrews & Arnold using Selenium
5
+ Requires-Python: >=3.8
6
+ Description-Content-Type: text/markdown
7
+ Requires-Dist: certbot
8
+ Requires-Dist: selenium
9
+ Requires-Dist: webdriver-manager
10
+ Requires-Dist: zope.interface
11
+
12
+ # certbot_dns_aa
13
+
14
+ This is a plugin for certbot to implement a DNS-01 challenge for Andrews and Arnold. As Andrews and Arnold don't have an API, it makes use of Selenium to simulate a browser session and modify DNS records from there.
15
+
16
+ # Usage
17
+
18
+ ```bash
19
+ git clone ...
20
+ python3 -m venv .venv
21
+ source .venv/bin/activate
22
+ python3 -m pip install certbot selenium webdriver zope
23
+ pip install -e .
24
+
25
+ export AA_USERNAME="your-aa-username"
26
+ export AA_PASSWORD="your-aa-password"
27
+
28
+ sudo -E .venv/bin/certbot certonly --authenticator dns-aa -d "<your_domain>" -v
29
+ ```
30
+
31
+
32
+ ## To-do
33
+
34
+ - Add cleanup to acme challenge records
@@ -0,0 +1,23 @@
1
+ # certbot_dns_aa
2
+
3
+ This is a plugin for certbot to implement a DNS-01 challenge for Andrews and Arnold. As Andrews and Arnold don't have an API, it makes use of Selenium to simulate a browser session and modify DNS records from there.
4
+
5
+ # Usage
6
+
7
+ ```bash
8
+ git clone ...
9
+ python3 -m venv .venv
10
+ source .venv/bin/activate
11
+ python3 -m pip install certbot selenium webdriver zope
12
+ pip install -e .
13
+
14
+ export AA_USERNAME="your-aa-username"
15
+ export AA_PASSWORD="your-aa-password"
16
+
17
+ sudo -E .venv/bin/certbot certonly --authenticator dns-aa -d "<your_domain>" -v
18
+ ```
19
+
20
+
21
+ ## To-do
22
+
23
+ - Add cleanup to acme challenge records
@@ -0,0 +1,158 @@
1
+ import logging
2
+ import os
3
+ import time
4
+ from certbot import errors
5
+ from certbot.plugins import dns_common
6
+ from zope.interface import implementer
7
+
8
+ from selenium import webdriver
9
+ from selenium.webdriver.chrome.service import Service as ChromeService
10
+ from selenium.webdriver.common.by import By
11
+ from selenium.webdriver.support import expected_conditions as EC
12
+ from selenium.webdriver.support.ui import WebDriverWait
13
+ from selenium.webdriver.support.ui import Select
14
+ from webdriver_manager.chrome import ChromeDriverManager
15
+ from selenium.webdriver.common.keys import Keys
16
+
17
+ logger = logging.getLogger(__name__)
18
+
19
+ class Authenticator(dns_common.DNSAuthenticator):
20
+ """
21
+ Certbot Authenticator for Andrews & Arnold Control Pages using Selenium.
22
+ """
23
+
24
+ description = "Obtain certificates using a DNS-01 challenge via Andrews & Arnold Control Pages automation."
25
+
26
+ def __init__(self, *args, **kwargs):
27
+ super().__init__(*args, **kwargs)
28
+ self.credentials = None
29
+
30
+ @classmethod
31
+ def add_parser_arguments(cls, add):
32
+ super().add_parser_arguments(add, default_propagation_seconds=60)
33
+ add("credentials", help="Path to A&A credentials INI file (or use environment variables).")
34
+
35
+ def more_info(self):
36
+ return "Configure your Andrews & Arnold credentials to allow Certbot to automatically manage DNS-01 TXT records."
37
+
38
+ def _setup_credentials(self):
39
+ # self.username = os.environ.get("AA_USERNAME")
40
+ # self.password = os.environ.get("AA_PASSWORD")
41
+
42
+ self.credentials = self._configure_credentials(
43
+ 'credentials',
44
+ 'Andrews & Arnold credentials INI file',
45
+ {
46
+ 'username': 'A&A control pages username.',
47
+ 'password': 'A&A control pages password.',
48
+ }
49
+ )
50
+ self.username = self.credentials.conf('username')
51
+ self.password = self.credentials.conf('password')
52
+
53
+ # def _validate_credentials(self, credentials):
54
+ # if not credentials.conf('username') or not credentials.conf('password'):
55
+ # raise errors.PluginError("Username and password must be set in the credentials file.")
56
+
57
+ # if not self.username or not self.password:
58
+ # raise errors.PluginError("A&A Username and Password must be provided via environment variables.")
59
+
60
+ def _perform(self, domain, validation_name, validation_value):
61
+ self._setup_credentials()
62
+
63
+ options = webdriver.ChromeOptions()
64
+ options.add_argument("--headless")
65
+ options.add_argument("--no-sandbox")
66
+ options.add_argument("--disable-dev-shm-usage")
67
+
68
+ driver = webdriver.Chrome(
69
+ service=ChromeService(ChromeDriverManager().install()), options=options
70
+ )
71
+ wait = WebDriverWait(driver, 15)
72
+
73
+ try:
74
+ logger.info("Navigating to Andrews & Arnold Control Pages login...")
75
+ driver.get("https://control.aa.net.uk/")
76
+
77
+
78
+ username_field = wait.until(
79
+ EC.presence_of_element_located((By.NAME, "USERNAME"))
80
+ )
81
+ password_field = driver.find_element(By.NAME, "PASSWORD")
82
+
83
+ username_field.send_keys(self.username)
84
+ password_field.send_keys(self.password)
85
+
86
+ login_button = driver.find_element(
87
+ By.XPATH, "//button[@type='submit'] | //input[@type='submit']"
88
+ )
89
+ login_button.click()
90
+
91
+
92
+ wait.until(
93
+ EC.presence_of_element_located(
94
+ (By.XPATH, "//*[contains(text(), 'Logout')]")
95
+ )
96
+ )
97
+ logger.info("Successfully logged into A&A Control Pages.")
98
+
99
+ logger.info(f"Navigating to DNS settings for {domain}...")
100
+ domain_link = wait.until(
101
+ EC.presence_of_element_located(
102
+ (By.XPATH, f"//a[contains(text(), '{domain}')]")
103
+ )
104
+ )
105
+ domain_link.click()
106
+
107
+ record_type = wait.until(
108
+ EC.presence_of_element_located((By.NAME, "rectype"))
109
+ )
110
+ Select(record_type).select_by_visible_text("TXT")
111
+
112
+ ttl_elem = wait.until(
113
+ EC.presence_of_element_located((By.NAME, "TTL"))
114
+ )
115
+ Select(ttl_elem).select_by_visible_text("1 minute")
116
+
117
+ record_name = wait.until(
118
+ EC.presence_of_element_located((By.NAME, "node"))
119
+ )
120
+
121
+ record_name.send_keys(validation_name)
122
+
123
+ record_value = wait.until(
124
+ EC.presence_of_element_located((By.NAME, "recvalue"))
125
+ )
126
+ record_value.send_keys(validation_value)
127
+ record_value.send_keys(Keys.ENTER)
128
+
129
+ logger.info("Successfully added DNS challenge record.")
130
+ time.sleep(5)
131
+
132
+ except Exception as e:
133
+ logger.error(f"Failed to add DNS record via Selenium: {e}")
134
+ raise errors.PluginError(f"Selenium automation failed: {e}")
135
+ finally:
136
+ driver.quit()
137
+
138
+ def _cleanup(self, domain, validation_name, validation_value):
139
+ pass
140
+
141
+ # Certbot hooks
142
+ def perform(self, achalls):
143
+ responses = []
144
+ for achall in achalls:
145
+ domain = achall.domain
146
+ validation_name = "_acme-challenge"
147
+ validation_value = achall.validation(achall.account_key)
148
+ logger.info(f"Validation value: {validation_value}")
149
+ self._perform(domain, validation_name, validation_value)
150
+ responses.append(achall.response(achall.account_key))
151
+ return responses
152
+
153
+ def cleanup(self, achalls):
154
+ for achall in achalls:
155
+ domain = achall.domain
156
+ validation_name = "_acme-challenge"
157
+ validation_value = achall.validation(achall.account_key)
158
+ self._cleanup(domain, validation_name, validation_value)
@@ -0,0 +1,34 @@
1
+ Metadata-Version: 2.4
2
+ Name: certbot-dns-aa
3
+ Version: 0.1.1
4
+ Summary: Certbot DNS-01 plugin for Andrews & Arnold using Selenium
5
+ Requires-Python: >=3.8
6
+ Description-Content-Type: text/markdown
7
+ Requires-Dist: certbot
8
+ Requires-Dist: selenium
9
+ Requires-Dist: webdriver-manager
10
+ Requires-Dist: zope.interface
11
+
12
+ # certbot_dns_aa
13
+
14
+ This is a plugin for certbot to implement a DNS-01 challenge for Andrews and Arnold. As Andrews and Arnold don't have an API, it makes use of Selenium to simulate a browser session and modify DNS records from there.
15
+
16
+ # Usage
17
+
18
+ ```bash
19
+ git clone ...
20
+ python3 -m venv .venv
21
+ source .venv/bin/activate
22
+ python3 -m pip install certbot selenium webdriver zope
23
+ pip install -e .
24
+
25
+ export AA_USERNAME="your-aa-username"
26
+ export AA_PASSWORD="your-aa-password"
27
+
28
+ sudo -E .venv/bin/certbot certonly --authenticator dns-aa -d "<your_domain>" -v
29
+ ```
30
+
31
+
32
+ ## To-do
33
+
34
+ - Add cleanup to acme challenge records
@@ -0,0 +1,9 @@
1
+ README.md
2
+ pyproject.toml
3
+ certbot_dns_aa/dns_aa.py
4
+ certbot_dns_aa.egg-info/PKG-INFO
5
+ certbot_dns_aa.egg-info/SOURCES.txt
6
+ certbot_dns_aa.egg-info/dependency_links.txt
7
+ certbot_dns_aa.egg-info/entry_points.txt
8
+ certbot_dns_aa.egg-info/requires.txt
9
+ certbot_dns_aa.egg-info/top_level.txt
@@ -0,0 +1,2 @@
1
+ [certbot.plugins]
2
+ dns-aa = certbot_dns_aa.dns_aa:Authenticator
@@ -0,0 +1,4 @@
1
+ certbot
2
+ selenium
3
+ webdriver-manager
4
+ zope.interface
@@ -0,0 +1 @@
1
+ certbot_dns_aa
@@ -0,0 +1,19 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61.0.0"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "certbot-dns-aa"
7
+ version = "0.1.1"
8
+ description = "Certbot DNS-01 plugin for Andrews & Arnold using Selenium"
9
+ readme = "README.md"
10
+ requires-python = ">=3.8"
11
+ dependencies = [
12
+ "certbot",
13
+ "selenium",
14
+ "webdriver-manager",
15
+ "zope.interface",
16
+ ]
17
+
18
+ [project.entry-points."certbot.plugins"]
19
+ dns-aa = "certbot_dns_aa.dns_aa:Authenticator"
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+