-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
349 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
include LICENSE.txt | ||
include README.md | ||
global-exclude __pycache__ | ||
global-exclude *.py[cod] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
certbot-dns-infoblox | ||
==================== | ||
|
||
Infoblox DNS Authenticator plugin for Certbot | ||
|
||
This plugin automates the process of completing a ``dns-01`` challenge by | ||
creating, and subsequently removing, TXT records using the Infoblox Remote API. | ||
|
||
|
||
Installation | ||
------------ | ||
``` | ||
pip install certbot-dns-infoblox | ||
``` | ||
|
||
Named Arguments | ||
--------------- | ||
|
||
To start using DNS authentication for Infoblox, pass the following arguments on | ||
certbot's command line: | ||
|
||
============================================================ ============================================== | ||
``--authenticator certbot-dns-infoblox:dns-infoblox`` Select the authenticator plugin (Required) | ||
|
||
``--certbot-dns-infoblox:dns-infoblox-credentials`` Infoblox remote user credentials INI file. | ||
(Default: /etc/letsencrypt/infoblox.ini) | ||
|
||
``--certbot-dns-infoblox:dns-infoblox-propagation-seconds`` Waiting time for DNS to propagate before asking | ||
the ACME server to verify the DNS record. | ||
(Default: 10) | ||
============================================================ ============================================== | ||
|
||
If you are using certbot >= 1.0, you can skip the `certbot-dns-infoblox:` | ||
in the above arguments. | ||
|
||
|
||
Credentials | ||
----------- | ||
An example ``credentials.ini`` file: | ||
|
||
.. code-block:: ini | ||
# | ||
# Sample Infoblox INI file | ||
# | ||
dns_infoblox_hostname="infoblox.example.net" | ||
dns_infoblox_username="my-wapi-user" | ||
dns_infoblox_password="5f4dcc3b5aa765d61d8327deb882cf99" | ||
dns_infoblox_view="" | ||
|
||
The path to this file can be provided interactively or using the | ||
``--dns-infoblox-credentials`` command-line argument. Certbot | ||
records the path to this file for use during renewal, but does not store the | ||
file's contents. | ||
|
||
**CAUTION:** You should protect these API credentials as you would the | ||
password to your infoblox account. Users who can read this file can use these | ||
credentials to issue arbitrary API calls on your behalf. Users who can cause | ||
Certbot to run using these credentials can complete a ``dns-01`` challenge to | ||
acquire new certificates or revoke existing certificates for associated | ||
domains, even if those domains aren't being managed by this server. | ||
|
||
Certbot will emit a warning if it detects that the credentials file can be | ||
accessed by other users on your system. The warning reads "Unsafe permissions | ||
on credentials configuration file", followed by the path to the credentials | ||
file. This warning will be emitted each time Certbot uses the credentials file, | ||
including for renewal, and cannot be silenced except by addressing the issue | ||
(e.g., by using a command like ``chmod 600`` to restrict access to the file). | ||
|
||
|
||
Examples | ||
-------- | ||
To acquire a single certificate for both ``example.com`` and | ||
``*.example.com``, waiting 100 seconds for DNS propagation: | ||
|
||
.. code-block:: bash | ||
|
||
certbot certonly \ | ||
--authenticator dns-infoblox \ | ||
--dns-infoblox-credentials /etc/letsencrypt/.secrets/domain.tld.ini \ | ||
--dns-infoblox-propagation-seconds 100 \ | ||
--agree-tos \ | ||
--rsa-key-size 4096 \ | ||
-d 'example.com' \ | ||
-d '*.example.com' | ||
|
||
Notes | ||
----- | ||
|
||
This is based on the work in [certbot-dns-ipsconfig](https://github.com/m42e/certbot-dns-ispconfig) | ||
and the package [infoblox-client](https://github.com/infobloxopen/infoblox-client) python package. | ||
|
||
Note that all your issued certificates can be found in public databases, e.g., [crt.sh](https://crt.sh/). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
""" | ||
The `~certbot_dns_infoblox.dns_infoblox` plugin automates the process of | ||
completing a ``dns-01`` challenge (`~acme.challenges.DNS01`) by creating, and | ||
subsequently removing, TXT records using the Infoblox REST API. | ||
Named Arguments | ||
--------------- | ||
======================================== ===================================== | ||
``--dns-infoblox-credentials`` Infoblox Remote API credentials | ||
INI file. (Default: | ||
/etc/letsencrypt/infoblox.ini) | ||
``--dns-infoblox-propagation-seconds`` The number of seconds to wait for DNS | ||
to propagate before asking the ACME | ||
server to verify the DNS record. | ||
(Default: 10) | ||
======================================== ===================================== | ||
Credentials | ||
----------- | ||
Use of this plugin requires a configuration file containing Infoblox Remote | ||
WAPI credentials. | ||
.. code-block:: ini | ||
:name: credentials.ini | ||
:caption: Example credentials file: | ||
# INFOBLOX API credentials used by Certbot | ||
dns_infoblox_hostname = "infoblox.example.org:8080" | ||
dns_infoblox_username = "myapiuser" | ||
dns_infoblox_password = "mysecretpassword" | ||
dns_infoblox_view = "external" | ||
The path to this file can be provided interactively or using the | ||
``--dns-infoblox-credentials`` command-line argument. Certbot records the path | ||
to this file for use during renewal, but does not store the file's contents. | ||
.. caution:: | ||
You should protect these API credentials as you would a password. Users who | ||
can read this file can use these credentials to issue arbitrary API calls on | ||
your behalf. Users who can cause Certbot to run using these credentials can | ||
complete a ``dns-01`` challenge to acquire new certificates or revoke | ||
existing certificates for associated domains, even if those domains aren't | ||
being managed by this server. | ||
Certbot will emit a warning if it detects that the credentials file can be | ||
accessed by other users on your system. The warning reads "Unsafe permissions | ||
on credentials configuration file", followed by the path to the credentials | ||
file. This warning will be emitted each time Certbot uses the credentials file, | ||
including for renewal, and cannot be silenced except by addressing the issue | ||
(e.g., by using a command like ``chmod 600`` to restrict access to the file). | ||
Examples | ||
-------- | ||
.. code-block:: bash | ||
:caption: To acquire a certificate for ``example.com`` | ||
certbot certonly \\ | ||
--dns-infoblox \\ | ||
--dns-infoblox-credentials ~/.secrets/certbot/infoblox.ini \\ | ||
-d example.com | ||
.. code-block:: bash | ||
:caption: To acquire a single certificate for both ``example.com`` and | ||
``www.example.com`` | ||
certbot certonly \\ | ||
--dns-infoblox \\ | ||
--dns-infoblox-credentials ~/.secrets/certbot/infoblox.ini \\ | ||
-d example.com \\ | ||
-d www.example.com | ||
.. code-block:: bash | ||
:caption: To acquire a certificate for ``example.com``, waiting 240 seconds | ||
for DNS propagation | ||
certbot certonly \\ | ||
--dns-infoblox \\ | ||
--dns-infoblox-credentials ~/.secrets/certbot/infoblox.ini \\ | ||
--dns-infoblox-propagation-seconds 240 \\ | ||
-d example.com | ||
""" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
"""Internal implementation of `~certbot_dns_infoblox.dns_infoblox` plugin.""" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
"""DNS Authenticator for Infoblox.""" | ||
import logging | ||
import time | ||
|
||
import infoblox_client.connector | ||
import infoblox_client.objects | ||
import zope.interface | ||
from certbot import interfaces | ||
from certbot.plugins import dns_common | ||
|
||
logger = logging.getLogger(__name__) | ||
|
||
|
||
@zope.interface.implementer(interfaces.IAuthenticator) | ||
@zope.interface.provider(interfaces.IPluginFactory) | ||
class Authenticator(dns_common.DNSAuthenticator): | ||
"""DNS Authenticator for Infoblox | ||
This Authenticator uses the Infoblox REST API to fulfill a | ||
dns-01 challenge. | ||
""" | ||
|
||
description = ("Obtain certificates using a DNS TXT record " | ||
"(if you are using Infoblox for DNS).") | ||
ttl = 120 | ||
|
||
def __init__(self, *args, **kwargs): | ||
super(Authenticator, self).__init__(*args, **kwargs) | ||
self.credentials = None | ||
|
||
@classmethod | ||
def add_parser_arguments(cls, add): # pylint: disable=arguments-differ | ||
super(Authenticator, cls).add_parser_arguments( | ||
add, default_propagation_seconds=10 | ||
) | ||
add("credentials", help="Infoblox credentials INI file.", | ||
default='/etc/letsencrypt/infoblox.ini') | ||
|
||
def more_info(self): # pylint: disable=missing-docstring,no-self-use | ||
return ( | ||
"This plugin configures a DNS TXT record to respond to a " | ||
"dns-01 challenge using the Infoblox Remote REST API." | ||
) | ||
|
||
def _setup_credentials(self): | ||
self.credentials = self._configure_credentials( | ||
"credentials", | ||
"Infoblox credentials INI file", | ||
{ | ||
"hostname": "Hostname for Infoblox REST API.", | ||
"username": "Username for Infoblox REST API.", | ||
"password": "Password for Infoblox REST API.", | ||
"view": "View to use for TXT entries " | ||
"(leave blank is view is not necessary)" | ||
}, | ||
) | ||
|
||
infoclient = None | ||
infotxts = [] | ||
|
||
def _get_infoblox_client(self): | ||
if not self.infoclient: | ||
self.infoclient = { | ||
'connector': infoblox_client.connector.Connector({ | ||
'host': self.credentials.conf("hostname"), | ||
'username': self.credentials.conf("username"), | ||
'password': self.credentials.conf("password"), | ||
'ssl_verify': True | ||
}) | ||
} | ||
if self.credentials.conf("view"): | ||
self.infoclient['view'] = self.credentials.conf("view") | ||
|
||
return self.infoclient.copy() | ||
|
||
def _get_infoblox_record(self, validation_name, validation, create): | ||
record = self._get_infoblox_client() | ||
record['name'] = validation_name | ||
record['text'] = validation | ||
if create: | ||
record['ttl'] = self.ttl | ||
username = self.credentials.conf("username") | ||
record['comment'] = time.strftime( | ||
f'%Y-%m-%d %H:%M:%S: certbot-auto-{username}') | ||
|
||
return record | ||
|
||
def _perform(self, domain, validation_name, validation): | ||
txt = infoblox_client.objects.TXTRecord.create( | ||
**self._get_infoblox_record(validation_name, validation, True) | ||
) | ||
self.infotxts.append(txt) | ||
|
||
def _cleanup(self, domain, validation_name, validation): | ||
for txt in self.infotxts: | ||
if txt.name == validation_name and txt.text == validation: | ||
txt.delete() | ||
return | ||
|
||
txts = infoblox_client.objects.TXTRecord.search_all( | ||
**self._get_infoblox_record(validation_name, validation, False) | ||
) | ||
for txt in txts: | ||
# FIXME | ||
print(f'Please delete this txt record by yourself: {txt}') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
# | ||
# Sample Infoblox INI file | ||
# | ||
dns_infoblox_hostname="infoblox.example.net" | ||
dns_infoblox_username="my-wapi-user" | ||
dns_infoblox_password="5f4dcc3b5aa765d61d8327deb882cf99" | ||
dns_infoblox_view="" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
[bdist_wheel] | ||
universal = 1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
|
||
from setuptools import find_packages, setup | ||
|
||
install_requires = [ | ||
"acme>=0.29.0", | ||
"certbot>=0.34.0", | ||
'infoblox-client>=0.5.0', | ||
"setuptools", | ||
] | ||
|
||
# read the contents of the README file | ||
with open("README.md") as f: | ||
long_description = f.read() | ||
|
||
docs_extras = [ | ||
] | ||
|
||
setup( | ||
name="certbot-dns-infoblox", | ||
use_scm_version=True, | ||
setup_requires=['setuptools_scm'], | ||
|
||
description="Infoblox DNS Authenticator plugin for Certbot", | ||
long_description=long_description, | ||
long_description_content_type="text/markdown", | ||
url="https://github.com/svalgaard/certbot-dns-infoblox", | ||
author="Jens Svalgaard Kohrt", | ||
author_email="github@svalgaard.net", | ||
license="Apache License 2.0", | ||
python_requires=">=3.6", | ||
classifiers=[ | ||
"Development Status :: 4 - Beta", | ||
"Environment :: Plugins", | ||
"Intended Audience :: System Administrators", | ||
"License :: OSI Approved :: Apache Software License", | ||
"Operating System :: POSIX :: Linux", | ||
"Programming Language :: Python", | ||
"Programming Language :: Python :: 3", | ||
"Programming Language :: Python :: 3.6", | ||
"Programming Language :: Python :: 3.7", | ||
"Programming Language :: Python :: 3.8", | ||
"Programming Language :: Python :: 3.9", | ||
"Topic :: Internet :: WWW/HTTP", | ||
"Topic :: Security", | ||
"Topic :: System :: Installation/Setup", | ||
"Topic :: System :: Networking", | ||
"Topic :: System :: Systems Administration", | ||
"Topic :: Utilities", | ||
], | ||
|
||
packages=find_packages(), | ||
include_package_data=True, | ||
install_requires=install_requires, | ||
entry_points={ | ||
"certbot.plugins": [ | ||
"dns-infoblox = certbot_dns_infoblox.dns_infoblox:Authenticator", | ||
] | ||
}, | ||
) |