change to debugable

This commit is contained in:
Helge 2020-12-21 13:19:45 +01:00
parent f6bc5bc9e9
commit d6b0bf9f05
5 changed files with 58 additions and 40 deletions

2
.gitignore vendored
View file

@ -3,6 +3,8 @@
# Created by https://www.toptal.com/developers/gitignore/api/windows,visualstudiocode,python # Created by https://www.toptal.com/developers/gitignore/api/windows,visualstudiocode,python
# Edit at https://www.toptal.com/developers/gitignore?templates=windows,visualstudiocode,python # Edit at https://www.toptal.com/developers/gitignore?templates=windows,visualstudiocode,python
my_debug/
### Python ### ### Python ###
# Byte-compiled / optimized / DLL files # Byte-compiled / optimized / DLL files
__pycache__/ __pycache__/

16
.vscode/launch.json vendored Normal file
View file

@ -0,0 +1,16 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Python: Current File",
"type": "python",
"request": "launch",
"program": "/home/pi/dev/certbot/venv3/bin/certbot",
"console": "integratedTerminal",
"args": ["certonly", "-a", "dns-ionos", "-d", "example.com", "--config-dir", "my_debug/config", "--work-dir", "my_debug/work", "--logs-dir", "my_debug/logs"]
}
]
}

View file

@ -1,4 +1,4 @@
"""DNS Authenticator for ISPConfig.""" """DNS Authenticator for IONOS."""
import json import json
import logging import logging
import time import time
@ -16,12 +16,12 @@ logger = logging.getLogger(__name__)
@zope.interface.implementer(interfaces.IAuthenticator) @zope.interface.implementer(interfaces.IAuthenticator)
@zope.interface.provider(interfaces.IPluginFactory) @zope.interface.provider(interfaces.IPluginFactory)
class Authenticator(dns_common.DNSAuthenticator): class Authenticator(dns_common.DNSAuthenticator):
"""DNS Authenticator for ISPConfig """DNS Authenticator for IONOS
This Authenticator uses the ISPConfig Remote REST API to fulfill a dns-01 challenge. This Authenticator uses the IONOS Remote REST API to fulfill a dns-01 challenge.
""" """
description = "Obtain certificates using a DNS TXT record (if you are using ISPConfig for DNS)." description = "Obtain certificates using a DNS TXT record (if you are using IONOS for DNS)."
ttl = 60 ttl = 60
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
@ -33,53 +33,53 @@ class Authenticator(dns_common.DNSAuthenticator):
super(Authenticator, cls).add_parser_arguments( super(Authenticator, cls).add_parser_arguments(
add, default_propagation_seconds=120 add, default_propagation_seconds=120
) )
add("credentials", help="ISPConfig credentials INI file.") add("credentials", help="IONOS credentials INI file.")
def more_info(self): # pylint: disable=missing-docstring,no-self-use def more_info(self): # pylint: disable=missing-docstring,no-self-use
return ( return (
"This plugin configures a DNS TXT record to respond to a dns-01 challenge using " "This plugin configures a DNS TXT record to respond to a dns-01 challenge using "
+ "the ISPConfig Remote REST API." + "the IONOS Remote REST API."
) )
def _setup_credentials(self): def _setup_credentials(self):
self.credentials = self._configure_credentials( self.credentials = self._configure_credentials(
"credentials", "credentials",
"ISPConfig credentials INI file", "IONOS credentials INI file",
{ {
"endpoint": "URL of the ISPConfig Remote API.", "endpoint": "URL of the IONOS Remote API.",
"username": "Username for ISPConfig Remote API.", "prefix": "Prefix for IONOS Remote API.",
"password": "Password for ISPConfig Remote API.", "secret": "Secret for IONOS Remote API.",
}, },
) )
def _perform(self, domain, validation_name, validation): def _perform(self, domain, validation_name, validation):
self._get_ispconfig_client().add_txt_record( self._get_ionos_client().add_txt_record(
domain, validation_name, validation, self.ttl domain, validation_name, validation, self.ttl
) )
def _cleanup(self, domain, validation_name, validation): def _cleanup(self, domain, validation_name, validation):
self._get_ispconfig_client().del_txt_record( self._get_ionos_client().del_txt_record(
domain, validation_name, validation, self.ttl domain, validation_name, validation, self.ttl
) )
def _get_ispconfig_client(self): def _get_ionos_client(self):
return _ISPConfigClient( return _ionosClient(
self.credentials.conf("endpoint"), self.credentials.conf("endpoint"),
self.credentials.conf("username"), self.credentials.conf("prefix"),
self.credentials.conf("password"), self.credentials.conf("secret"),
) )
class _ISPConfigClient(object): class _ionosClient(object):
""" """
Encapsulates all communication with the ISPConfig Remote REST API. Encapsulates all communication with the IONOS Remote REST API.
""" """
def __init__(self, endpoint, username, password): def __init__(self, endpoint, prefix, secret):
logger.debug("creating ispconfigclient") logger.debug("creating ionosclient")
self.endpoint = endpoint self.endpoint = endpoint
self.username = username self.prefix = prefix
self.password = password self.secret = secret
self.session = requests.Session() self.session = requests.Session()
self.session_id = None self.session_id = None
@ -87,7 +87,7 @@ class _ISPConfigClient(object):
if self.session_id is not None: if self.session_id is not None:
return return
logger.debug("logging in") logger.debug("logging in")
logindata = {"username": self.username, "password": self.password} logindata = {"prefix": self.prefix, "secret": self.secret}
self.session_id = self._api_request("login", logindata) self.session_id = self._api_request("login", logindata)
logger.debug("session id is %s", self.session_id) logger.debug("session id is %s", self.session_id)
@ -131,7 +131,7 @@ class _ISPConfigClient(object):
:param str record_name: The record name (typically beginning with '_acme-challenge.'). :param str record_name: The record name (typically beginning with '_acme-challenge.').
:param str record_content: The record content (typically the challenge validation). :param str record_content: The record content (typically the challenge validation).
:param int record_ttl: The record TTL (number of seconds that the record may be cached). :param int record_ttl: The record TTL (number of seconds that the record may be cached).
:raises certbot.errors.PluginError: if an error occurs communicating with the ISPConfig API :raises certbot.errors.PluginError: if an error occurs communicating with the IONOS API
""" """
self._login() self._login()
zone_id, zone_name = self._find_managed_zone_id(domain, record_name) zone_id, zone_name = self._find_managed_zone_id(domain, record_name)
@ -165,7 +165,7 @@ class _ISPConfigClient(object):
:param str record_name: The record name (typically beginning with '_acme-challenge.'). :param str record_name: The record name (typically beginning with '_acme-challenge.').
:param str record_content: The record content (typically the challenge validation). :param str record_content: The record content (typically the challenge validation).
:param int record_ttl: The record TTL (number of seconds that the record may be cached). :param int record_ttl: The record TTL (number of seconds that the record may be cached).
:raises certbot.errors.PluginError: if an error occurs communicating with the ISPConfig API :raises certbot.errors.PluginError: if an error occurs communicating with the IONOS API
""" """
self._login() self._login()
zone_id, zone_name = self._find_managed_zone_id(domain, record_name) zone_id, zone_name = self._find_managed_zone_id(domain, record_name)

View file

@ -1,4 +1,4 @@
"""Tests for certbot_dns_ispconfig.dns_ispconfig.""" """Tests for certbot_dns_ionos.dns_ionos."""
import unittest import unittest
@ -24,28 +24,28 @@ class AuthenticatorTest(
def setUp(self): def setUp(self):
super(AuthenticatorTest, self).setUp() super(AuthenticatorTest, self).setUp()
from certbot_dns_ispconfig.dns_ispconfig import Authenticator from certbot_dns_ionos.dns_ionos import Authenticator
path = os.path.join(self.tempdir, "file.ini") path = os.path.join(self.tempdir, "file.ini")
dns_test_common.write( dns_test_common.write(
{ {
"ispconfig_prefix": FAKE_PREFIX, "ionos_prefix": FAKE_PREFIX,
"ispconfig_secret": FAKE_SECRET, "ionos_secret": FAKE_SECRET,
"ispconfig_endpoint": FAKE_ENDPOINT, "ionos_endpoint": FAKE_ENDPOINT,
}, },
path, path,
) )
super(AuthenticatorTest, self).setUp() super(AuthenticatorTest, self).setUp()
self.config = mock.MagicMock( self.config = mock.MagicMock(
ispconfig_credentials=path, ispconfig_propagation_seconds=0 ionos_credentials=path, ionos_propagation_seconds=0
) # don't wait during tests ) # don't wait during tests
self.auth = Authenticator(self.config, "ispconfig") self.auth = Authenticator(self.config, "ionos")
self.mock_client = mock.MagicMock() self.mock_client = mock.MagicMock()
# _get_ispconfig_client | pylint: disable=protected-access # _get_ionos_client | pylint: disable=protected-access
self.auth._get_ispconfig_client = mock.MagicMock(return_value=self.mock_client) self.auth._get_ionos_client = mock.MagicMock(return_value=self.mock_client)
def test_perform(self): def test_perform(self):
self.auth.perform([self.achall]) self.auth.perform([self.achall])
@ -70,17 +70,17 @@ class AuthenticatorTest(
self.assertEqual(expected, self.mock_client.mock_calls) self.assertEqual(expected, self.mock_client.mock_calls)
class ISPConfigClientTest(unittest.TestCase): class ionosClientTest(unittest.TestCase):
record_name = "foo" record_name = "foo"
record_content = "bar" record_content = "bar"
record_ttl = 42 record_ttl = 42
def setUp(self): def setUp(self):
from certbot_dns_ispconfig.dns_ispconfig import _ISPConfigClient from certbot_dns_ionos.dns_ionos import _ionosClient
self.adapter = requests_mock.Adapter() self.adapter = requests_mock.Adapter()
self.client = _ISPConfigClient(FAKE_ENDPOINT, FAKE_PREFIX, FAKE_SECRET) self.client = _ionosClient(FAKE_ENDPOINT, FAKE_PREFIX, FAKE_SECRET)
self.client.session.mount("mock", self.adapter) self.client.session.mount("mock", self.adapter)
def _register_response( def _register_response(

View file

@ -1,7 +1,7 @@
from setuptools import setup from setuptools import setup
from setuptools import find_packages from setuptools import find_packages
version = "0.0.1" version = "0.0.2"
install_requires = [ install_requires = [
"acme>=0.29.0", "acme>=0.29.0",
@ -56,8 +56,8 @@ setup(
install_requires=install_requires, install_requires=install_requires,
entry_points={ entry_points={
"certbot.plugins": [ "certbot.plugins": [
"dns-ispconfig = certbot_dns_ispconfig.dns_ispconfig:Authenticator" "dns-ionos = certbot_dns_ionos.dns_ionos:Authenticator"
] ]
}, },
test_suite="certbot_dns_ispconfig", test_suite="certbot_dns_ionos",
) )