I’ve just pushed an initial attempt of a certbot snap to the store. It appears to work locally but is blocked from publication as it’s a classic snap.
This needs to be a classic snap because of the nature of certbot: part of its job is to know how to detect and automatically reconfigure your web server to prove control over it. Newer versions of certbot enhance this capability. For snapd to provide an interface to this, it’d have to reimplement this part of certbot within itself, and keep up with further certbot development. New certbot releases with feature changes in this area would be blocked from being snapped until a newer snapd provided updates to its reimplementation. I think it’s clear that this would make no sense, so certbot needs to be a classic snap.
Please approve certbot as a classic snap into the store.
For now I’m keeping the build snapcraft.yaml here and am using the same repository for issues.
This could be said of any technology that is snapped and is not a reason in and of itself to grant classic confinement. Put another way, snapd is in the business of updating its interfaces as needed.
That said, it looks like certbot could be used with ‘certonly’ which should work today in stict mode. Without ‘certonly’, certbot will run various tools that may or may not be installed on the system and write into /etc for various services (apache, nginx, haproxy, plesk, etc) across all distributions. docs/using.rst talks about setting up pre and post hooks to restart services, which on systemd systems ends up translating to requiring use of systemctl, which as I’ve pointed out elsewhere, gives device ownership to the snap (meaning the snap has as much trust as a classic snap).
However, at its core, this is a form of ‘administration’ snap which we have typically not allowed in the store. While I could imagine an interface that allowed writes to the various /etc directories, when in strict mode the snap wouldn’t have access to the various utilities it requires (eg, apachectl, postfix, nginxctl, etc) unless it shipped them, and if it did ship them, there would be no guarantee that they would match the running system. It is possible for the snap to ship matching utilities for every server version for every distribution that supports snaps, but this seems unmaintainable.
Considering the above, IMO either the snap should be granted classic or should not be a snap at all. Really, this seems most-suited as a snapcraft part so a snap that shipped apache could include this part and have certbot as a part of the snap. The snap is allowed to restart its own services and write to its $SNAP_DATA/etc/apache2 (or wherever).
@niemeyer - I’ve done the snapd requirements analysis above. Please comment on whether this should be granted classic.
Most technologies that are snapped have stable interfaces that can have a stable interface implementation. With certbot, this is not the case. What’s special here is that certbot is the cutting edge of what would have to be the snapd interface implementation. Either you need to allow certbot to take ownership of this as a classic snap, or somebody needs to put as much ongoing work into implementation and maintenance of the snapd interface as upstream does to this part of certbot while also working with certbot upstream to separate out its internals to allow calling to either its implementation or snapd’s interface, or not allow a certbot snap at all. The first option would work. The second option is possible but would require more work than I think any team is prepared to volunteer. The third option means that certbot will have to rely on third party PPAs indefinitely and can never be a first class citizen on Ubuntu for as long as certbot upstream velocity remains high.
“certonly” would certainly work only in strict mode, but I’m not sure that there’s any point in providing a snap that only does half the work. I’d like Ubuntu to be able to provide a simple and current UX for certificate acquisition via ACME. If it won’t be possible to recommend a snap that provides this, having a snap would be pointless.
Note that if you allowed an interface to write to configure webservers under /etc, I think it’d be difficult to maintain confidence that this doesn’t provide root. Configure apache to run as root without dropping privs and expose something inside /etc as cgi-bin, for example, and you have root. We’d need to ensure that packaging of all web servers, however delivered, make this impossible, and that seems like an unreasonable large surface to protect to me. In other words, if you can configure the webserver, we have to treat you as having root.
Agree with @jdstrand analysis. This sounds like a snap that would exist to modify the system configuration and would depend heavily on the tooling and particular behavior that exists outside the snap, which tends to be hard to do when that needs to work across several distributions across a long time span. It is inherently not self contained, not isolated, and the service it provides to the external world is as a tightly coupled component that depends heavily on the other parts of the system. Sounds like a snap that would tend not to work for too many people.
Also agree with @jdstrand’s analysis that this would be best as a part that can be integrated into other snaps. That would indeed help users by not having to worry about certbot at all, as long as it works inside the contained environment.
Just as a precedent, the nextcloud snap integrates transparently with certbot as an implementation detail of the product (just in case, nextcloud is not classic).
After multiple rounds of face to face meetings on this topic, we have a tentative approval on granting classic to the certbot snap, on the following basis:
The software demonstrably shows great care in working in a vast number of Linux systems, not only in breath but also in depth, including ancient versions of well known distributions.
The byproduct of the software working properly is a mostly unchanged system, with certificates installed and HTTPS working.
The software does not act on the system unless the administrator explicitly request so.
The software is very popular and backed by an accredited organization (EFF)
The upstream will be involved in the process, and will communicate with the server team so that it’s clear how important it is that the snap works well across multiple Linux systems, and multiple versions of those, even when facing automatic updates.
In the interest of time, I’ll grant use of classic based on @rbasak not changing ‘grade: devel’ and not handing over the snap until the above points are acknowledged. This is now live and will pass automated review in the future. For the existing revision, please either request a manual review or upload a new revision.
I’m an upstream developer of Certbot and @niemeyer’s points sound good to me. We have a question for you all though.
Certbot has a plugin system which allows people to extend the project adding new ways to obtain or deploy certificates. We have plugins to perform domain validation with different DNS providers and plugins configure certificates with software like Apache and Nginx. We also have third party plugins written by people outside of the Certbot team.
To allow people to continue to use this system with a Certbot snap, @rbasak proposed https://github.com/basak/certbot-snap-build/tree/snap-plugins/doc. The way this works is plugins snapped separately can expose their code to the Certbot snap over the content interface which it will load and run.
The potential concern here we wanted to ask you about is that the plugin will be run with Certbot’s classic confinement even if the plugin is a regular confined snap. Classic confinement is often what is needed by the plugin to be able to do things like configure certificates with a web server, however, plugins would be able to do this without review if they implement the correct interfaces and are connected to the Certbot snap.
Are you all OK with Certbot plugins potentially written by a third party using this setup after users manually connect them to the Certbot snap? What about us configuring our own plugins we snap separately to automatically connect since they will be coming from the same publisher?
We wanted to get your approval here before continuing with this approach.
You can’t use the content interface. making it a classic snap will completely turn off interface usage (but with classic you can indeed just access the content of the plugin snaps anyway. classic behaves no different to I.e. a self contained app tarball you extract to /opt, just with some package management (install/remove/rollback) added)
Just note that using classic means your app will not be usable in ubuntu core (iot/cloud/embedded) systems where use of classic is completely denied.
I’m aware of the limitation. We are still using the interface to identify the plugins for the classic snap to load. We aren’t using the interface to actually load them. See my proof of concept for details.
That’s fine - the point of the classic snap is to permit certbot administration of SSL-based services installed on the host system itself outside of a snap. This doesn’t make sense in the iot/cloud/embedded space since AIUI there is no concept of that.
For iot/cloud/embedded I’d expect a certbot part to be used instead. This is orthogonal to, and out of the scope of, the current certbot snap effort.
heh, so you think an IoT gateway that manages a few 100 PLCs in a factory shouldn’t use certbot to manage its certificates when talking to its clients ? i think certbot would be a great bit of added security here and having a strict confined snap (with potentially having additional interfaces) would be a great thing …
nontheless, my point was not to be the party pooper, but just to point out the limitations, after all @jdstrand already granted classic, i didnt mean to stir up a discussion, just to bring up some points about limits this decision brings along
No, I’m saying that the right way to integrate certbot into such a device would be to embed a certbot part into the snap that provides your SSL-based service itself. As I say this is orthogonal to this current effort as it would exist to support a different use case.
I can conceive of an architecture where there is a snap that provides an interface to coordinate so that a single certificate can be obtained to be shared between multiple services, each that is in its own snap. If this were to be done, it’d be a confined snap, yes, but it would again be orthogonal to and an entirely different effort to the current one. You’d need to invent and implement your own IPC protocols to operate certbot over such an interface since it would require a separation between CSR generation, certificate storage, service configuration and challenge implementation in a fashion that I don’t believe exists today. I’m not sure certbot would even be the right tool for the job; a different ACME implementation might work better. If someone wants to work on that anyway, please feel free, and if you end up using certbot then we can coordinate what to do about the namespace then.
Edit: and to be clear, nothing that we’re doing limits a future implementation to support the use cases that you mention.
and i’m saying having a single snap with a content interface that all other SSL service using snaps can utilize would be nicer … i understand what you mean but even on IoT gateways we like to avoid duplication
anyway, as i said, it wasnt the purpose of my post to stir up a discussion, but to mention the limitations for the OP, which i did…
This has the potential to invalidate at least the spirit of some of @niemeyer’s points above, but reading the proposal in GitHub - basak/certbot-snap-build at snap-plugins/doc requires an admin to run sudo snap connect certbot:plugin ..., which must be done by an admin (ie, honors point ‘3’) and the proposal mentions ‘Only perform this step if you trust the plugin author to have “root” on your system.’, which is great, but it would be good if this was somehow surfaced to the admin who might be cutting and pasting commands and not knowing the ramifications of the snap connect command. I’m not sure what a good UX would be for that, but can say that a connection hook may be helpful and/or a wrapper that notices the registered plugin and says something like “INFO: 3rd party plugin detected. Please only use if you trust the author of this plugin with root on your system” (or similar, I don’t want to dictate how this is done).
IMO, this is ok so long as the risk of the snap connect is bubbled up to the user in some manner. @pedronis please comment if you feel my assessment and recommendation need refinement.
A way to do this I think would be to have a prepare-plug-plugin hook in the certbot snap that did something like this:
#!/bin/bash -e
if [ "$(snapctl get plugin-accepted)" = "ok" ]; then
# allow the connection, but reset config to allow for other slots to go through this auth flow
snapctl unset plugin-accepted
exit 0
else
echo "Only connect this interface if you trust the plugin author to have root on the system"
echo "Run \`snap set $SNAP_NAME plugin-accepted=ok\` to acknowledge this and then run this command again to perform the connection"
exit 1
fi
For example with an example snap with network-setup-observe, this looks like:
$ snap install my-snap-name_0.1_amd64.snap --dangerous
my-snap-name 0.1 installed
$ snap connect my-snap-name:network-setup-observe
error: cannot perform the following tasks:
- Run hook prepare-plug-network-setup-observe of snap "my-snap-name" (run hook "prepare-plug-network-setup-observe":
-----
Only connect this interface if you trust the plugin author to have root on the system
Run `snap set my-snap-name plugin-accepted=ok` to acknowledge this and then run this command again to perform the connection
-----)
$ snap set my-snap-name plugin-accepted=ok
$ snap get my-snap-name
Key Value
plugin-accepted ok
$ snap connect my-snap-name:network-setup-observe
$ snap get my-snap-name
error: snap "my-snap-name" has no configuration
$ snap connections my-snap-name
Interface Plug Slot Notes
network my-snap-name:network :network -
network-bind my-snap-name:network-bind :network-bind -
network-setup-observe my-snap-name:network-setup-observe :network-setup-observe manual
This isn’t ideal because it only works with a single connection at a time and the interface hook here doesn’t have a way to uniquely identify an admin’s acceptance of a particular connection, just that they acknowledge a single plugin. I.e. you could have issues like this:
$ snap connect certbot:plugin some-plugin-author1:plugin
<error run snap set ... >
$ snap set certbot plugin-accepted=ok
$ snap connect certbot:plugin some-other-plugin-author2:plugin
<incorrect success, should only have worked for some-plugin-author1:plugin>
Unfortunately I think it is by design that interface hooks do not have knowledge of the other side of the connection, except for attributes. Attributes could be used by the other side, where the other snap is required to set something, but this seems not ideal because then all the plugin authors need to agree on a format for setting attributes that the certbot snap can verify in these hooks.