v3.0.0: authenticate with a yk_ App key, not email/app_password
The email+app_password -> /api/v1/auth/login bearer mint was retired with personal app passwords (dns commit 834c90e). Switch to sending a yeil App key (yk_<keyId>_<secret>) directly as the Bearer token, which the DNS API's principal auth accepts. Single credential 'dns_yeil_api_key'; removed the login round-trip. BREAKING: existing credential files must replace email/app_password with an api_key (an App with DNS record-write permission, minted in team Apps). README + version bumped. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,9 +1,9 @@
|
||||
"""DNS-01 authenticator plugin for Certbot using the yeil public API.
|
||||
|
||||
Authenticates against dns.yeil.app/api/v1/auth/login with an
|
||||
email + app password, caches the Bearer token for the run, then
|
||||
adds/removes TXT records via the public records API. Any yeil user
|
||||
with an app password and an owned DNS zone can use it.
|
||||
Authenticates to dns.yeil.app with a yeil App key (yk_...) sent as a
|
||||
Bearer token, then adds/removes TXT records via the public records API.
|
||||
Create an App with DNS record-write permission on your zone(s) in your
|
||||
yeil team settings (the Apps tab) and put its key in the credentials file.
|
||||
|
||||
The certbot host only needs HTTPS reachability to dns.yeil.app; no
|
||||
NetBird or shared admin key.
|
||||
@@ -34,10 +34,6 @@ class Authenticator(dns_common.DNSAuthenticator):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.credentials = None
|
||||
# Bearer token cached for the lifetime of this plugin instance.
|
||||
# The login route mints a 30-day session; we only need it for
|
||||
# the duration of one certbot run.
|
||||
self._token = None
|
||||
# (domain, validation_name, validation) -> (zone_id, record_id)
|
||||
self._records = {}
|
||||
|
||||
@@ -59,8 +55,10 @@ class Authenticator(dns_common.DNSAuthenticator):
|
||||
"credentials",
|
||||
"yeil API credentials INI file",
|
||||
{
|
||||
"email": "yeil account email (e.g. you@yourdomain.com)",
|
||||
"app_password": "yeil app password (create one in account.yeil.app/security)",
|
||||
"api_key": (
|
||||
"yeil App key (yk_...) with DNS record-write permission on "
|
||||
"your zone(s); create an App under Apps in your team settings"
|
||||
),
|
||||
},
|
||||
)
|
||||
|
||||
@@ -85,9 +83,7 @@ class Authenticator(dns_common.DNSAuthenticator):
|
||||
req.add_header("Content-Type", "application/json")
|
||||
req.add_header("Content-Length", str(len(data)))
|
||||
if auth:
|
||||
if not self._token:
|
||||
self._login()
|
||||
req.add_header("Authorization", f"Bearer {self._token}")
|
||||
req.add_header("Authorization", f"Bearer {self._api_key()}")
|
||||
|
||||
try:
|
||||
with urlopen(req, timeout=HTTP_TIMEOUT) as resp:
|
||||
@@ -114,20 +110,14 @@ class Authenticator(dns_common.DNSAuthenticator):
|
||||
f"yeil dns API error ({method} {path}, {e.code}): {msg}"
|
||||
)
|
||||
|
||||
def _login(self):
|
||||
email = self.credentials.conf("email")
|
||||
password = self.credentials.conf("app_password")
|
||||
result = self._request(
|
||||
"POST",
|
||||
"/api/v1/auth/login",
|
||||
body={"email": email, "password": password},
|
||||
auth=False,
|
||||
)
|
||||
if not isinstance(result, dict) or "token" not in result:
|
||||
def _api_key(self):
|
||||
key = self.credentials.conf("api_key")
|
||||
if not key:
|
||||
raise errors.PluginError(
|
||||
"yeil dns API login returned no token"
|
||||
"yeil credentials file is missing 'api_key' "
|
||||
"(a yk_... App key with DNS record-write permission)"
|
||||
)
|
||||
self._token = result["token"]
|
||||
return key
|
||||
|
||||
# ── Zone resolution ────────────────────────────────────────────────
|
||||
|
||||
|
||||
Reference in New Issue
Block a user