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.
- certbot_dns_aa-0.1.1/PKG-INFO +34 -0
- certbot_dns_aa-0.1.1/README.md +23 -0
- certbot_dns_aa-0.1.1/certbot_dns_aa/dns_aa.py +158 -0
- certbot_dns_aa-0.1.1/certbot_dns_aa.egg-info/PKG-INFO +34 -0
- certbot_dns_aa-0.1.1/certbot_dns_aa.egg-info/SOURCES.txt +9 -0
- certbot_dns_aa-0.1.1/certbot_dns_aa.egg-info/dependency_links.txt +1 -0
- certbot_dns_aa-0.1.1/certbot_dns_aa.egg-info/entry_points.txt +2 -0
- certbot_dns_aa-0.1.1/certbot_dns_aa.egg-info/requires.txt +4 -0
- certbot_dns_aa-0.1.1/certbot_dns_aa.egg-info/top_level.txt +1 -0
- certbot_dns_aa-0.1.1/pyproject.toml +19 -0
- certbot_dns_aa-0.1.1/setup.cfg +4 -0
|
@@ -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 @@
|
|
|
1
|
+
|
|
@@ -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"
|