././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1578004028.8276916 certbot-plugin-gandi-1.2.5/0000755000175000000120000000000000000000000016300 5ustar00shepardwheel00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1578004028.8276916 certbot-plugin-gandi-1.2.5/PKG-INFO0000644000175000000120000000736200000000000017405 0ustar00shepardwheel00000000000000Metadata-Version: 2.1 Name: certbot-plugin-gandi Version: 1.2.5 Summary: Certbot plugin for authentication using Gandi LiveDNS Home-page: https://github.com/obynio/certbot-plugin-gandi Author: Yohann Leon Author-email: yohann@leon.re License: UNKNOWN Description: # Certbot plugin for authentication using Gandi LiveDNS This is a plugin for [Certbot](https://certbot.eff.org/) that uses the Gandi LiveDNS API to allow [Gandi](https://www.gandi.net/) customers to prove control of a domain name. ## Usage 1. Obtain a Gandi API token (see [Gandi LiveDNS API](https://doc.livedns.gandi.net/)) 2. Install the plugin using `pip install certbot-plugin-gandi` 3. Create a `gandi.ini` config file with the following contents and apply `chmod 600 gandi.ini` on it: ``` # live dns v5 api key certbot_plugin_gandi:dns_api_key=APIKEY # optional organization id, remove it if not used certbot_plugin_gandi:dns_sharing_id=SHARINGID ``` Replace `APIKEY` with your Gandi API key and ensure permissions are set to disallow access to other users. 4. Run `certbot` and direct it to use the plugin for authentication and to use the config file previously created: ``` certbot certonly -a certbot-plugin-gandi:dns --certbot-plugin-gandi:dns-credentials gandi.ini -d domain.com ``` Add additional options as required to specify an installation plugin etc. Please note that this solution is usually not relevant if you're using Gandi's web hosting services as Gandi offers free automated certificates for all simplehosting plans having SSL in the admin interface. Huge thanks to Michael Porter for its original work ! ## Distribution * PyPI: https://pypi.org/project/certbot-plugin-gandi/ * Archlinux: https://aur.archlinux.org/packages/certbot-dns-gandi-git/ ## Wildcard certificates This plugin is particularly useful when you need to obtain a wildcard certificate using dns challenges: ``` certbot certonly -a certbot-plugin-gandi:dns --certbot-plugin-gandi:dns-credentials gandi.ini -d domain.com -d \*.domain.com --server https://acme-v02.api.letsencrypt.org/directory ``` ## Automatic renewal You can setup automatic renewal using `crontab` with the following job for weekly renewal attempts: ``` 0 0 * * 0 certbot renew -q -a certbot-plugin-gandi:dns --certbot-plugin-gandi:dns-credentials /etc/letsencrypt/gandi/gandi.ini --server https://acme-v02.api.letsencrypt.org/directory ``` Platform: UNKNOWN Classifier: Development Status :: 4 - Beta Classifier: Environment :: Plugins Classifier: Intended Audience :: System Administrators Classifier: License :: OSI Approved :: MIT License Classifier: Operating System :: POSIX :: Linux Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 2 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.4 Classifier: Programming Language :: Python :: 3.5 Classifier: Programming Language :: Python :: 3.6 Classifier: Programming Language :: Python :: 3.7 Classifier: Topic :: Internet :: WWW/HTTP Classifier: Topic :: Security Classifier: Topic :: System :: Installation/Setup Classifier: Topic :: System :: Networking Classifier: Topic :: System :: Systems Administration Classifier: Topic :: Utilities Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.* Description-Content-Type: text/markdown ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1577920192.0 certbot-plugin-gandi-1.2.5/README.md0000644000175000000120000000415600000000000017565 0ustar00shepardwheel00000000000000# Certbot plugin for authentication using Gandi LiveDNS This is a plugin for [Certbot](https://certbot.eff.org/) that uses the Gandi LiveDNS API to allow [Gandi](https://www.gandi.net/) customers to prove control of a domain name. ## Usage 1. Obtain a Gandi API token (see [Gandi LiveDNS API](https://doc.livedns.gandi.net/)) 2. Install the plugin using `pip install certbot-plugin-gandi` 3. Create a `gandi.ini` config file with the following contents and apply `chmod 600 gandi.ini` on it: ``` # live dns v5 api key certbot_plugin_gandi:dns_api_key=APIKEY # optional organization id, remove it if not used certbot_plugin_gandi:dns_sharing_id=SHARINGID ``` Replace `APIKEY` with your Gandi API key and ensure permissions are set to disallow access to other users. 4. Run `certbot` and direct it to use the plugin for authentication and to use the config file previously created: ``` certbot certonly -a certbot-plugin-gandi:dns --certbot-plugin-gandi:dns-credentials gandi.ini -d domain.com ``` Add additional options as required to specify an installation plugin etc. Please note that this solution is usually not relevant if you're using Gandi's web hosting services as Gandi offers free automated certificates for all simplehosting plans having SSL in the admin interface. Huge thanks to Michael Porter for its original work ! ## Distribution * PyPI: https://pypi.org/project/certbot-plugin-gandi/ * Archlinux: https://aur.archlinux.org/packages/certbot-dns-gandi-git/ ## Wildcard certificates This plugin is particularly useful when you need to obtain a wildcard certificate using dns challenges: ``` certbot certonly -a certbot-plugin-gandi:dns --certbot-plugin-gandi:dns-credentials gandi.ini -d domain.com -d \*.domain.com --server https://acme-v02.api.letsencrypt.org/directory ``` ## Automatic renewal You can setup automatic renewal using `crontab` with the following job for weekly renewal attempts: ``` 0 0 * * 0 certbot renew -q -a certbot-plugin-gandi:dns --certbot-plugin-gandi:dns-credentials /etc/letsencrypt/gandi/gandi.ini --server https://acme-v02.api.letsencrypt.org/directory ``` ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1578004028.8276916 certbot-plugin-gandi-1.2.5/certbot_plugin_gandi/0000755000175000000120000000000000000000000022462 5ustar00shepardwheel00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1551136318.0 certbot-plugin-gandi-1.2.5/certbot_plugin_gandi/__init__.py0000644000175000000120000000000000000000000024561 0ustar00shepardwheel00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1578003343.0 certbot-plugin-gandi-1.2.5/certbot_plugin_gandi/gandi_api.py0000644000175000000120000000621700000000000024755 0ustar00shepardwheel00000000000000import requests import six from collections import namedtuple from certbot.plugins import dns_common _GandiConfig = namedtuple('_GandiConfig', ('api_key', 'sharing_id',)) _BaseDomain = namedtuple('_BaseDomain', ('fqdn')) def get_config(api_key, sharing_id): return _GandiConfig(api_key=api_key, sharing_id=sharing_id) def _get_json(response): try: data = response.json() except ValueError: return dict() return data def _get_response_message(response, default=''): return _get_json(response).get('message', default) def _headers(cfg): return { 'Content-Type': 'application/json', 'X-Api-Key': cfg.api_key } def _get_url(*segs): return 'https://dns.api.gandi.net/api/v5/{}'.format('/'.join(segs)) def _request(cfg, method, segs, **kw): headers = _headers(cfg) url = _get_url(*segs) return requests.request(method, url, headers=headers, params={'sharing_id': cfg.sharing_id}, **kw) def _get_base_domain(cfg, domain): for candidate_base_domain in dns_common.base_domain_name_guesses(domain): response = _request(cfg, 'GET', ('domains', candidate_base_domain)) if response.ok: data = _get_json(response) fqdn = data.get('fqdn') if fqdn: return _BaseDomain(fqdn=fqdn) return None def _get_relative_name(base_domain, name): suffix = '.' + base_domain.fqdn return name[:-len(suffix)] if name.endswith(suffix) else None def _get_txt_record(cfg, base_domain, relative_name): response = _request(cfg, 'GET', ['domains', base_domain.fqdn, 'records', relative_name, 'TXT']) if not response.ok: return [] data = _get_json(response) vals = data.get('rrset_values') if vals: return vals else: return [] def _update_txt_record(cfg, base_domain, relative_name, rrset): return _request(cfg, 'PUT', ['domains', base_domain.fqdn, 'records', relative_name, 'TXT'], json={'rrset_values': rrset}) def _update_record(cfg, domain, name, request_runner): base_domain = _get_base_domain(cfg, domain) if base_domain is None: return 'Unable to get base domain for "{}"'.format(domain) relative_name = _get_relative_name(base_domain, name) if relative_name is None: return 'Unable to derive relative name for "{}"'.format(name) response = request_runner(base_domain, relative_name) return None if response.ok else _get_response_message(response) def add_txt_record(cfg, domain, name, value): def requester(base_domain, relative_name): rrset = [value] + _get_txt_record(cfg, base_domain, relative_name) return _update_txt_record(cfg, base_domain, relative_name, rrset) return _update_record(cfg, domain, name, requester) def del_txt_record(cfg, domain, name, value): def requester(base_domain, relative_name): existing = _get_txt_record(cfg, base_domain, relative_name) rrset = list(filter(lambda rr: rr.strip('"') != value, existing)) return _update_txt_record(cfg, base_domain, relative_name, rrset) return _update_record(cfg, domain, name, requester) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1578003459.0 certbot-plugin-gandi-1.2.5/certbot_plugin_gandi/main.py0000644000175000000120000000456600000000000023773 0ustar00shepardwheel00000000000000import zope.interface import logging import uuid from certbot import interfaces, errors from certbot.plugins import dns_common from . import gandi_api logger = logging.getLogger(__name__) @zope.interface.implementer(interfaces.IAuthenticator) @zope.interface.provider(interfaces.IPluginFactory) class Authenticator(dns_common.DNSAuthenticator): """DNS Authenticator for Gandi (using LiveDNS).""" description = 'Obtain certificates using a DNS TXT record (if you are using Gandi for DNS).' 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) add('credentials', help='Gandi credentials INI file.') 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 Gandi LiveDNS API.' def _validate_sharing_id(self, credentials): sharing_id = credentials.conf('sharing-id') if sharing_id: try: uuid.UUID(sharing_id, version=4) except ValueError: raise errors.PluginError("Invalid sharing_id: {0}.".format(sharing_id)) def _setup_credentials(self): self.credentials = self._configure_credentials( 'credentials', 'Gandi credentials INI file', { 'api-key': 'API key for Gandi account', }, self._validate_sharing_id ) def _perform(self, domain, validation_name, validation): error = gandi_api.add_txt_record(self._get_gandi_config(), domain, validation_name, validation) if error is not None: raise errors.PluginError('An error occurred adding the DNS TXT record: {0}'.format(error)) def _cleanup(self, domain, validation_name, validation): error = gandi_api.del_txt_record(self._get_gandi_config(), domain, validation_name, validation) if error is not None: logger.warn('Unable to find or delete the DNS TXT record: %s', error) def _get_gandi_config(self): return gandi_api.get_config(api_key = self.credentials.conf('api-key'), sharing_id = self.credentials.conf('sharing-id')) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1578004028.8276916 certbot-plugin-gandi-1.2.5/certbot_plugin_gandi.egg-info/0000755000175000000120000000000000000000000024154 5ustar00shepardwheel00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1578004028.0 certbot-plugin-gandi-1.2.5/certbot_plugin_gandi.egg-info/PKG-INFO0000644000175000000120000000736200000000000025261 0ustar00shepardwheel00000000000000Metadata-Version: 2.1 Name: certbot-plugin-gandi Version: 1.2.5 Summary: Certbot plugin for authentication using Gandi LiveDNS Home-page: https://github.com/obynio/certbot-plugin-gandi Author: Yohann Leon Author-email: yohann@leon.re License: UNKNOWN Description: # Certbot plugin for authentication using Gandi LiveDNS This is a plugin for [Certbot](https://certbot.eff.org/) that uses the Gandi LiveDNS API to allow [Gandi](https://www.gandi.net/) customers to prove control of a domain name. ## Usage 1. Obtain a Gandi API token (see [Gandi LiveDNS API](https://doc.livedns.gandi.net/)) 2. Install the plugin using `pip install certbot-plugin-gandi` 3. Create a `gandi.ini` config file with the following contents and apply `chmod 600 gandi.ini` on it: ``` # live dns v5 api key certbot_plugin_gandi:dns_api_key=APIKEY # optional organization id, remove it if not used certbot_plugin_gandi:dns_sharing_id=SHARINGID ``` Replace `APIKEY` with your Gandi API key and ensure permissions are set to disallow access to other users. 4. Run `certbot` and direct it to use the plugin for authentication and to use the config file previously created: ``` certbot certonly -a certbot-plugin-gandi:dns --certbot-plugin-gandi:dns-credentials gandi.ini -d domain.com ``` Add additional options as required to specify an installation plugin etc. Please note that this solution is usually not relevant if you're using Gandi's web hosting services as Gandi offers free automated certificates for all simplehosting plans having SSL in the admin interface. Huge thanks to Michael Porter for its original work ! ## Distribution * PyPI: https://pypi.org/project/certbot-plugin-gandi/ * Archlinux: https://aur.archlinux.org/packages/certbot-dns-gandi-git/ ## Wildcard certificates This plugin is particularly useful when you need to obtain a wildcard certificate using dns challenges: ``` certbot certonly -a certbot-plugin-gandi:dns --certbot-plugin-gandi:dns-credentials gandi.ini -d domain.com -d \*.domain.com --server https://acme-v02.api.letsencrypt.org/directory ``` ## Automatic renewal You can setup automatic renewal using `crontab` with the following job for weekly renewal attempts: ``` 0 0 * * 0 certbot renew -q -a certbot-plugin-gandi:dns --certbot-plugin-gandi:dns-credentials /etc/letsencrypt/gandi/gandi.ini --server https://acme-v02.api.letsencrypt.org/directory ``` Platform: UNKNOWN Classifier: Development Status :: 4 - Beta Classifier: Environment :: Plugins Classifier: Intended Audience :: System Administrators Classifier: License :: OSI Approved :: MIT License Classifier: Operating System :: POSIX :: Linux Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 2 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.4 Classifier: Programming Language :: Python :: 3.5 Classifier: Programming Language :: Python :: 3.6 Classifier: Programming Language :: Python :: 3.7 Classifier: Topic :: Internet :: WWW/HTTP Classifier: Topic :: Security Classifier: Topic :: System :: Installation/Setup Classifier: Topic :: System :: Networking Classifier: Topic :: System :: Systems Administration Classifier: Topic :: Utilities Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.* Description-Content-Type: text/markdown ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1578004028.0 certbot-plugin-gandi-1.2.5/certbot_plugin_gandi.egg-info/SOURCES.txt0000644000175000000120000000057400000000000026046 0ustar00shepardwheel00000000000000README.md setup.py certbot_plugin_gandi/__init__.py certbot_plugin_gandi/gandi_api.py certbot_plugin_gandi/main.py certbot_plugin_gandi.egg-info/PKG-INFO certbot_plugin_gandi.egg-info/SOURCES.txt certbot_plugin_gandi.egg-info/dependency_links.txt certbot_plugin_gandi.egg-info/entry_points.txt certbot_plugin_gandi.egg-info/requires.txt certbot_plugin_gandi.egg-info/top_level.txt././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1578004028.0 certbot-plugin-gandi-1.2.5/certbot_plugin_gandi.egg-info/dependency_links.txt0000644000175000000120000000000100000000000030222 0ustar00shepardwheel00000000000000 ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1578004028.0 certbot-plugin-gandi-1.2.5/certbot_plugin_gandi.egg-info/entry_points.txt0000644000175000000120000000010100000000000027442 0ustar00shepardwheel00000000000000[certbot.plugins] dns = certbot_plugin_gandi.main:Authenticator ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1578004028.0 certbot-plugin-gandi-1.2.5/certbot_plugin_gandi.egg-info/requires.txt0000644000175000000120000000004700000000000026555 0ustar00shepardwheel00000000000000certbot zope.interface requests>=2.4.2 ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1578004028.0 certbot-plugin-gandi-1.2.5/certbot_plugin_gandi.egg-info/top_level.txt0000644000175000000120000000002500000000000026703 0ustar00shepardwheel00000000000000certbot_plugin_gandi ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1578004028.8276916 certbot-plugin-gandi-1.2.5/setup.cfg0000644000175000000120000000004600000000000020121 0ustar00shepardwheel00000000000000[egg_info] tag_build = tag_date = 0 ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1578003941.0 certbot-plugin-gandi-1.2.5/setup.py0000644000175000000120000000320000000000000020005 0ustar00shepardwheel00000000000000from setuptools import setup, find_packages with open("README.md", "r") as fh: long_description = fh.read() setup( name='certbot-plugin-gandi', version='1.2.5', author="Yohann Leon", author_email="yohann@leon.re", description="Certbot plugin for authentication using Gandi LiveDNS", long_description=long_description, long_description_content_type="text/markdown", url="https://github.com/obynio/certbot-plugin-gandi", packages=find_packages(), python_requires=' >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*', install_requires=[ 'certbot', 'zope.interface', 'requests>=2.4.2', ], entry_points={ 'certbot.plugins': [ 'dns = certbot_plugin_gandi.main:Authenticator', ], }, classifiers=[ 'Development Status :: 4 - Beta', 'Environment :: Plugins', 'Intended Audience :: System Administrators', 'License :: OSI Approved :: MIT License', 'Operating System :: POSIX :: Linux', 'Programming Language :: Python', 'Programming Language :: Python :: 2', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.7', 'Topic :: Internet :: WWW/HTTP', 'Topic :: Security', 'Topic :: System :: Installation/Setup', 'Topic :: System :: Networking', 'Topic :: System :: Systems Administration', 'Topic :: Utilities', ], )