digicert / dnstrust-constellix-certbot

Constellix certbot
Apache License 2.0
2 stars 4 forks source link

TypeError: 'type' object is not iterable (in zope/interface/declarations.py) #2

Closed jarthod closed 1 year ago

jarthod commented 1 year ago

Hi, I'm trying to use this plugin but facing the following error with any certbot command as soons as I enable it:

> sudo certbot plugins
An unexpected error occurred:
TypeError: 'type' object is not iterable
Ask for help or search for solutions at https://community.letsencrypt.org. See the logfile /tmp/certbot-log-e_s5tyou/log or re-run Certbot with -v for more details.

The stacktrace from the tmp log file is the following:

2023-04-04 08:10:34,605:DEBUG:urllib3.connectionpool:http://localhost:None "GET /v2/connections?snap=certbot&interface=content HTTP/1.1" 200 None
2023-04-04 08:10:35,279:DEBUG:certbot._internal.log:Exiting abnormally:
Traceback (most recent call last):
  File "/snap/certbot/2836/bin/certbot", line 8, in <module>
    sys.exit(main())
  File "/snap/certbot/2836/lib/python3.8/site-packages/certbot/main.py", line 19, in main
    return internal_main.main(cli_args)
  File "/snap/certbot/2836/lib/python3.8/site-packages/certbot/_internal/main.py", line 1835, in main
    plugins = plugins_disco.PluginsRegistry.find_all()
  File "/snap/certbot/2836/lib/python3.8/site-packages/certbot/_internal/plugins/disco.py", line 192, in find_all
    cls._load_entry_point(entry_point, plugins)
  File "/snap/certbot/2836/lib/python3.8/site-packages/certbot/_internal/plugins/disco.py", line 199, in _load_entry_point
    plugin_ep = PluginEntryPoint(entry_point)
  File "/snap/certbot/2836/lib/python3.8/site-packages/certbot/_internal/plugins/disco.py", line 40, in __init__
    self.plugin_cls: Type[interfaces.Plugin] = entry_point.load()
  File "/snap/certbot/2836/lib/python3.8/site-packages/pkg_resources/__init__.py", line 2468, in load
    return self.resolve()
  File "/snap/certbot/2836/lib/python3.8/site-packages/pkg_resources/__init__.py", line 2474, in resolve
    module = __import__(self.module_name, fromlist=['__name__'], level=0)
  File "/snap/certbot-dns-constellix/current/lib/python3.8/site-packages/certbot_dns_constellix/dns_constellix.py", line 21, in <module>
    class Authenticator(dns_common.DNSAuthenticator):
  File "/snap/certbot-dns-constellix/current/lib/python3.8/site-packages/zope/interface/declarations.py", line 994, in __call__
    directlyProvides(ob, *self.interfaces)
  File "/snap/certbot-dns-constellix/current/lib/python3.8/site-packages/zope/interface/declarations.py", line 816, in directlyProvides
    interfaces = _normalizeargs(interfaces)
  File "/snap/certbot-dns-constellix/current/lib/python3.8/site-packages/zope/interface/declarations.py", line 1170, in _normalizeargs
    _normalizeargs(v, output)
  File "/snap/certbot-dns-constellix/current/lib/python3.8/site-packages/zope/interface/declarations.py", line 1169, in _normalizeargs
    for v in sequence:
TypeError: 'type' object is not iterable
2023-04-04 08:10:35,279:ERROR:certbot._internal.log:An unexpected error occurred:
2023-04-04 08:10:35,280:ERROR:certbot._internal.log:TypeError: 'type' object is not iterable

I installed the plugin this way:

sudo snap set certbot trust-plugin-with-root=ok
sudo snap install certbot-dns-constellix
sudo snap connect certbot:plugin certbot-dns-constellix

I'm not sure what to do with this error but I know it comes from the constellix plugin (we can see it in the stacktrace and of my installation was working previously with the DME plugin). I'm running python 3.10.6 on Ubuntu Server 22.04.1 LTS.

Any help appreciated :)

jarthod commented 1 year ago

According to https://github.com/zopefoundation/zope.interface/issues/5 it seems to be a "reasonable error" message, so maybe it's a missuse of zope or a version incompatibility?

I have installed:

> pip list | fgrep zope
zope.interface         5.4.0

And:

> sudo snap list certbot-dns-constellix
Name                    Version        Rev  Tracking       Publisher   Notes
certbot-dns-constellix  0+git.3d7bbd6  2    latest/stable  mintopiauk  -
jarthod commented 1 year ago

Found related issues, it looks like the zope interface has been removed: https://github.com/certbot/certbot/issues/9485 And then added back to avoid breaking compatibility with outdated plugins: https://github.com/certbot/certbot/pull/9486 Wiki: https://github.com/certbot/certbot/wiki/Certbot-v2.x-Plugin-Compatibility

I'm running certbot 2.5.0 so from what I read it should work but maybe something else got broken since 2.1 with newer versions. Or maybe this exception has nothing to do with it, I'm not sure ^^

NathanSweet commented 1 year ago

I also have this problem, using certbot 2.6.0. Is there a solution?

$ snap install certbot-dns-constellix
certbot-dns-constellix 0+git.3d7bbd6 from Jessica Smith (mintopiauk) installed
$ snap set certbot trust-plugin-with-root=ok
$ snap connect certbot:plugin certbot-dns-constellix
$ certbot plugins
An unexpected error occurred:
TypeError: 'type' object is not iterable
NathanSweet commented 1 year ago

OK, this plugin isn't actually need. Use --manual to be prompted to create a TXT DNS entry manually. That gets me past my crisis, but I would like to automate it in the near future.

jarthod commented 1 year ago

That is what I was going to answer indeed ^^ about the automation I got a response from Constellix support saying this is not maintained unfortunately because it was made by a contractor. They said they'll have a look but we shouldn't expect much.

NathanSweet commented 1 year ago

Same, Constellix support said:

We do not directly support these plugins, for direct support you would need to reach out to the creator of the plugin if they support it.

When I mentioned it is important they support certbot they said:

We understand, we do not provide support for these plugins.

I don't find this reasonable, as these days automating certificate renewal is almost required. Last year I spent 4 months wrangling a certificate out of Sectigo. Maybe there are better validation companies, but I won't pay to find out again.

Constellix should support certbot officially. I would rather change DNS providers than dig around in Python code.

dhabets2 commented 1 year ago

@jarthod @NathanSweet, my apologies, but that information is incorrect. This certbot plugin was written by one of our engineers and is indeed maintained. We will schedule a bug ticket and make sure support knows as well.

jarthod commented 1 year ago

@dhabets2 Aha that is good news then :)

Side question: I used the dnsmadeeasy plugin previously which is in the official certbot DNS plugins: https://github.com/certbot/certbot/tree/master/certbot-dns-dnsmadeeasy. Is there any reason why this one is not if you are maintaining both?

mintopia commented 1 year ago

Side question: I used the dnsmadeeasy plugin previously which is in the official certbot DNS plugins: https://github.com/certbot/certbot/tree/master/certbot-dns-dnsmadeeasy. Is there any reason why this one is not if you are maintaining both?

The Certbot team haven't been accepting third-party plugins into the project for a few years now, as per the advice on their documentation, we released this as a standalone plugin for Certbot.

jarthod commented 1 year ago

@mintopia Ok thanks, so the DNS Made Easy one was simply written before and accepted?

mintopia commented 1 year ago

@jarthod Exactly, it's a shame but understandable from their side.

As @dhabets2 has mentioned, we'll get this plugin updated and a new version released.

NathanSweet commented 1 year ago

@dhabets2 Oh, that's great news, thanks! I know it's easy to have a disconnect between support and development.

It makes sense that certbot doesn't become a repository for many plugins. However, it'd be better if plugins weren't needed at all. They could come up with a standard way for certbot to validate via DNS, then Constellix and other DNS providers would implement that API.

BTW, sorry for the tangent but is there a way to use the certbot-constellix plugin without snap? I prefer to use the Debian certbot package.

astrolox commented 1 year ago

@NathanSweet

A few DNS providers would be in favour of such a solution. However there are complexities which make it non trivial, especially in the enterprise space, and that might prevent any standard from gaining widespread adoption. There have been attempts along those lines for DDNS which were quite successful but were never adopted widely enough to be considered a universal standard. Perhaps raise the suggestion with the certbot maintainers, they're in a great position to spearhead an initiative like that.

As for usage without snap. It is possible. The official documentation describes several ways to do it. We couldn't tell you what the standard Debian way is.

Finally for anyone who is interested, I stumbled accross an interesting plugin in the certbot documentation. It allows you to use the DNS providers implemented in the lego ACME client (Constellix is implemented and maintained there also). So a completely different way of solving the problem if you needed a workaround or backup solution. See https://github.com/alexzorin/certbot-dns-multi

jarthod commented 1 year ago

@astrolox thanks for this nice alternative, I'll have a look at it on my next renewal if this one isn't fixed in between.

mintopia commented 1 year ago

We have released version 2.2 of the plugin to Snapcraft and pypi. It should resolve the issues.

NathanSweet commented 1 year ago

@mintopia Thanks. Here is my attempt:

$ snap install core
2023-06-21T14:44:06Z INFO Waiting for automatic snapd restart...
core 16-2.59.4 from Canonical* installed
$ snap install certbot-dns-constellix
certbot-dns-constellix 0+git.31347d7 from Jessica Smith (mintopiauk) installed
$ snap set certbot trust-plugin-with-root=ok
error: snap "certbot" not found
$ snap install certbot --classic
certbot 2.6.0 from Certbot Project (certbot-eff**) installed
$ snap set certbot trust-plugin-with-root=ok
$ snap connect certbot:plugin certbot-dns-constellix
$ certbot plugins
Saving debug log to /var/log/letsencrypt/letsencrypt.log

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* standalone
Description: Spin up a temporary webserver
Interfaces: IAuthenticator, IPlugin
Entry point: standalone = certbot._internal.plugins.standalone:Authenticator

* webroot
Description: Place files in webroot directory
Interfaces: IAuthenticator, IPlugin
Entry point: webroot = certbot._internal.plugins.webroot:Authenticator
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
$ certbot certonly --authenticator=dns-constellix --dns-constellix-credentials=/path/constellix.ini -d example.com
usage:
  certbot [SUBCOMMAND] [options] [-d DOMAIN] [-d DOMAIN] ...

Certbot can obtain and install HTTPS/TLS/SSL certificates.  By default,
it will attempt to use a webserver both for obtaining and installing the
certificate.
certbot: error: unrecognized arguments: --dns-constellix-credentials=/root/ssl/constellix.ini

I apologize if this is a snap issue, but I followed the instructions. I don't know why the dns-constellix plugin does not appear.

mintopia commented 1 year ago

It's not showing the certbot-dns-constellix plugin for you in certbot plugins. I've just repeated the same commands as you and it's showing it for me, eg:

Saving debug log to /var/log/letsencrypt/letsencrypt.log

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* apache
Description: Apache Web Server plugin
Interfaces: Authenticator, Installer, Plugin
Entry point: apache = certbot_apache._internal.entrypoint:ENTRYPOINT

* dns-constellix
Description: Obtain certificates using a DNS TXT record (if you are using
Constellix for DNS).
Interfaces: Authenticator, Plugin
Entry point: dns-constellix =
certbot_dns_constellix.dns_constellix:Authenticator

* nginx
Description: Nginx Web Server plugin
Interfaces: Authenticator, Installer, Plugin
Entry point: nginx = certbot_nginx._internal.configurator:NginxConfigurator

* standalone
Description: Runs an HTTP server locally which serves the necessary validation
files under the /.well-known/acme-challenge/ request path. Suitable if there is
no HTTP server already running. HTTP challenge only (wildcards not supported).
Interfaces: Authenticator, Plugin
Entry point: standalone = certbot._internal.plugins.standalone:Authenticator

* webroot
Description: Saves the necessary validation files to a
.well-known/acme-challenge/ directory within the nominated webroot path. A
seperate HTTP server must be running and serving files from the webroot path.
HTTP challenge only (wildcards not supported).
Interfaces: Authenticator, Plugin
Entry point: webroot = certbot._internal.plugins.webroot:Authenticator
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

This does look to be an issue with snap that I'm not able to reproduce myself.

What does snap connections show? You should see something like:

Interface           Plug                   Slot                            Notes
content[certbot-1]  certbot:plugin         certbot-dns-constellix:certbot  manual
NathanSweet commented 1 year ago
$ snap connections
Interface           Plug            Slot                            Notes
content[certbot-1]  certbot:plugin  certbot-dns-constellix:certbot  manual

I've never used snap (and would really prefer not to, but I do need auto cert renewal), so I'm afraid I'm not much help.

I didn't have certbot initially (shown in my log above). I tried removing and readding the plugin, to no avail:

$ snap install certbot-dns-constellix
snap "certbot-dns-constellix" is already installed, see 'snap help refresh'
$ snap remove certbot-dns-constellix
certbot-dns-constellix removed
$ snap install certbot-dns-constellix
certbot-dns-constellix 0+git.31347d7 from Jessica Smith (mintopiauk) installed
$ certbot plugins
Saving debug log to /var/log/letsencrypt/letsencrypt.log

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* standalone
Description: Spin up a temporary webserver
Interfaces: IAuthenticator, IPlugin
Entry point: standalone = certbot._internal.plugins.standalone:Authenticator

* webroot
Description: Place files in webroot directory
Interfaces: IAuthenticator, IPlugin
Entry point: webroot = certbot._internal.plugins.webroot:Authenticator
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
mintopia commented 1 year ago

Did you have certbot installed from pip/manually outside of snap? I wonder if when you're running certbot, it's running the non-snap version. In which case, try sudo python3 -m pip install certbot-dns-constellix to install the python plugin instead.

NathanSweet commented 1 year ago

Ahhh, yes I installed certbot via apt. I hate that so many different managers are necessary.

I don't have pip so I guess I'll use snap, since removing it fully is probably annoying. I did apt remove certbot, ln -s /snap/bin/certbot /usr/bin/certbot, removed the Constellix plugin, added it again, and now I see the plugin.

Sorry for the noise! I guess it may be worth a mention to ensure that the certbot in use is the one coming from snap.

mintopia commented 1 year ago

I'll look into updating the documentation.

jarthod commented 1 year ago

Thanks, I just tried on my end and it looks like it's working now :+1:

I did:

> sudo snap install certbot-dns-constellix
snap "certbot-dns-constellix" is already installed, see 'snap help refresh'
> sudo snap refresh certbot-dns-constellix
snap "certbot-dns-constellix" has no updates available
> snap info certbot-dns-constellix 
name:      certbot-dns-constellix
summary:   Certbot DNS Plugin for Constellix
publisher: Jessica Smith (mintopiauk)
store-url: https://snapcraft.io/certbot-dns-constellix
license:   unset
description: |
  certbot-dns-constellix is a plugin for Certbot to perform dns-01
  challenges against the Constellix DNS API
snap-id:      xIB0dN4MQltRJo4ZBc4DFlFqFZCkdw3T
tracking:     latest/stable
refresh-date: today at 16:01 UTC
channels:
  latest/stable:    0+git.31347d7 2023-06-21 (5) 14MB -
  latest/candidate: ↑                                 
  latest/beta:      ↑                                 
  latest/edge:      0+git.31347d7 2023-06-21 (5) 14MB -
installed:          0+git.31347d7            (5) 14MB -

Not sure why refresh said "no updates" :thinking: maybe snap already automatically updated it?

Anyway:

> sudo snap connect certbot:plugin certbot-dns-constellix
> certbot plugins
[...]
* dns-constellix
Description: Obtain certificates using a DNS TXT record (if you are using
Constellix for DNS).
Interfaces: Authenticator, Plugin
Entry point: dns-constellix =
certbot_dns_constellix.dns_constellix:Authenticator
[...]

And I was able to generate my cert again with:

> sudo certbot certonly --authenticator=dns-constellix --dns-constellix-credentials /root/constellix.ini -d [...]

Thanks :raised_hands:

NathanSweet commented 1 year ago

I had trouble with certbot putting renewal files into example.com-0001, example.com-0002, etc folders, then I don't know which is the latest without manual nginx edits. I think it's supposed to keep a symlink up to date, but doesn't. Minutes ago a friend suggested using Lego: https://go-acme.github.io/lego/dns/constellix/

The Debian package is outdated and abandoned, but I downloaded and ran the latest release: it worked! No plugin or pip or snap or other manager bloat! It seems a good option for anyone else struggling with certbot, FWIW.