From 4a2618d41552d1297a204dbd2e1bf69952e3bd24 Mon Sep 17 00:00:00 2001 From: Robie Basak Date: Tue, 3 Sep 2019 11:45:20 +0100 Subject: [PATCH 1/5] Add CERTBOT_PLUGIN_PATH support Initial revision Fix interface export path Switch to strict confinement Normalise slot parameters --- certbot-dns-dnsimple/snap/snapcraft.yaml | 22 ++++++++++++++++++++++ certbot/certbot/_internal/plugins/disco.py | 2 ++ 2 files changed, 24 insertions(+) create mode 100644 certbot-dns-dnsimple/snap/snapcraft.yaml diff --git a/certbot-dns-dnsimple/snap/snapcraft.yaml b/certbot-dns-dnsimple/snap/snapcraft.yaml new file mode 100644 index 000000000..ade7d7e86 --- /dev/null +++ b/certbot-dns-dnsimple/snap/snapcraft.yaml @@ -0,0 +1,22 @@ +name: certbot-dns-dnsimple +version: script +version-script: cd parts/certbot-dns-dnsimple/src && git describe|sed s/^v// +summary: DNSimple DNS Authenticator plugin for Certbot +description: TBC +confinement: strict +grade: devel + +parts: + certbot-dns-dnsimple: + plugin: python + source: git://github.com/certbot/certbot + source-branch: master + source-subdir: certbot-dns-dnsimple + python-version: python3 + +slots: + certbot: + interface: content + content: certbot-1 + read: + - $SNAP/lib/python3.5/site-packages diff --git a/certbot/certbot/_internal/plugins/disco.py b/certbot/certbot/_internal/plugins/disco.py index f1d89f06a..4fd20c16e 100644 --- a/certbot/certbot/_internal/plugins/disco.py +++ b/certbot/certbot/_internal/plugins/disco.py @@ -2,6 +2,8 @@ import collections import itertools import logging +import os +import sys import pkg_resources import six From 8ccc96bbddf1c0d3077f2f1e9c15d5e79a11d614 Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Mon, 27 Apr 2020 14:13:59 -0700 Subject: [PATCH 2/5] update certbot-dns-dnsimple snapcraft.yml. update dnsimple snapcraft.yml --- certbot-dns-dnsimple/snap/snapcraft.yaml | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/certbot-dns-dnsimple/snap/snapcraft.yaml b/certbot-dns-dnsimple/snap/snapcraft.yaml index ade7d7e86..8a685b25e 100644 --- a/certbot-dns-dnsimple/snap/snapcraft.yaml +++ b/certbot-dns-dnsimple/snap/snapcraft.yaml @@ -1,22 +1,24 @@ name: certbot-dns-dnsimple -version: script -version-script: cd parts/certbot-dns-dnsimple/src && git describe|sed s/^v// summary: DNSimple DNS Authenticator plugin for Certbot description: TBC confinement: strict grade: devel +base: core18 +adopt-info: certbot-dns-dnsimple parts: certbot-dns-dnsimple: plugin: python - source: git://github.com/certbot/certbot - source-branch: master - source-subdir: certbot-dns-dnsimple + source: . + constraints: [$SNAPCRAFT_PART_SRC/constraints.txt] python-version: python3 + override-pull: | + snapcraftctl pull + snapcraftctl set-version `grep ^version $SNAPCRAFT_PART_SRC/setup.py | cut -f2 -d= | tr -d "'[:space:]"` slots: certbot: interface: content content: certbot-1 read: - - $SNAP/lib/python3.5/site-packages + - $SNAP/lib/python3.6/site-packages From 0bebdedcbc4f9c71bc42edf1c68f84da336ca8b7 Mon Sep 17 00:00:00 2001 From: Robie Basak Date: Tue, 3 Sep 2019 15:13:27 +0100 Subject: [PATCH 3/5] Initial revision Fix headings Fix error in build instructions --- README.md | 110 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 000000000..bf79c35f6 --- /dev/null +++ b/README.md @@ -0,0 +1,110 @@ +# Certbot Plugin Snaps + +This is a proof of concept of how a Certbot snap might support plugin snaps +that add functionality to Certbot using its existing plugin API. + +## Architecture + +This is a description of how Certbot plugin functionality is exposed via snaps. +For information on Certbot's plugin architecture itself, see the [Certbot +documentation on +plugins](https://certbot.eff.org/docs/contributing.html#plugin-architecture). + +The Certbot snap itself is a classic snap. Plugin snaps are regular confined +snaps, but normally do not provide any "apps" themselves. Plugin snaps export +loadable Python modules to the Certbot snap via a snap content interface. + +Certbot itself accepts a `CERTBOT_PLUGIN_PATH` environment variable. This +support is currently patched but this is intended to be upstreamed. The +variable, if set, should contain a `:`-separated list of paths to add to +Certbot's plugin search path. + +The Certbot snap runs Certbot via a wrapper which examines its list of +connected interfaces, sets `CERTBOT_PLUGIN_PATH` accordingly, and then `exec`s +Certbot itself. + +## Use (Production) + +_Note: this production use example assumes that these snaps are available in +stable channels in the Snap Store, which they aren't yet. See below for +development instructions._ + +To use a Certbot plugin snap, install both the plugin snap and the Certbot snap +as usual. Plugin snaps are confined as normal; the Certbot snap is a classic +snap and thus needs `--classic` during installation. For example: + + snap install --classic certbot + snap install certbot-dns-dnsimple + +Then connect the plugin snap to the main certbot snap as follows. Note that +this connection allows the plugin snap code to run inside the certbot process, +which has access to your host system. Only perform this step if you trust the +plugin author to have "root" on your system. + + sudo snap connect certbot:plugin certbot-dns-dnsimple + +Now certbot will automatically load and use the plugin when it is run. To check +that this has worked, `certbot plugins` should list the plugin. + +You can now operate the plugin as normal. + +## Use (Testing and Development) + +To try this out, you'll need to build the snaps (a patched Certbot snap and a +plugin snap) manually. + + 1. Start with a Xenial VM. + 2. Install snapcraft with `snap install --classic snapcraft`. + 3. Run `git clone git://github.com/basak/certbot-snap-build -b snap-plugins/snap/certbot`. + 4. `cd certbot-snap-build` + 5. Run `git clone https://github.com/basak/certbot-snap-build -b snap-plugins/certbot certbot` (this is a workaround for #13). + 6. Run `certbot/tools/strip_hashes.py certbot/letsencrypt-auto-source/pieces/dependency-requirements.txt > certbot/constraints.txt` (this is a workaround for #13). + 7. Run `snapcraft`. + 8. Install the generated snap with `sudo snap install --dangerous --classic certbot_*_amd64.snap`. You can transfer the snap to a different machine to run it there instead if you prefer. + 9. `cd ..` + 10. `git clone git://github.com/basak/certbot-snap-build.git -b snap-plugins/snap/certbot-dns-dnsimple certbot-dns-dnsimple` + 11. `cd certbot-dns-dnsimple` + 12. `snapcraft` + 13. Install the generated snap with `sudo snap install --dangerous certbot-dns-dnsimple_*_amd64.snap`. Again, you can transfer the snap to a different machine to run it there instead if you prefer. + 14. Connect the plugin with `sudo snap connect certbot:plugin certbot-dns-dnsimple`. + 15. Now you can run Certbot as normal. For example, `certbot plugins` should display the DNSimple plugin as installed. + +## Code + +This proof of concept ships four git branches: + +1. [This documentation](https://github.com/basak/certbot-snap-build/tree/snap-plugins/doc). +2. [A fork of Certbot upstream that adds support for + `CERTBOT_PLUGIN_PATH`](https://github.com/basak/certbot-snap-build/tree/snap-plugins/certbot). +3. [A fork of the proof of concept Certbot snap packaging that adds plugin + support](https://github.com/basak/certbot-snap-build/tree/snap-plugins/snap/certbot). +4. [An example of snap packaging for the Certbot DNSimple + plugin](https://github.com/basak/certbot-snap-build/tree/snap-plugins/snap/certbot-dns-dnsimple). + +If adopted, these would all be upstreamed, and no branches would be necessary. +Snap packaging is intended to be maintained within upstream code trees +themselves with the addition of `snapcraft.yaml`, much like Travis CI +integration. + +## Publishing Permissions + +There are security implications to permitting anyone to publish, without +review, a plugin into the Snap Store which will then run in Certbot's classic +snap context, with full access to the host system. + +At a minimum, it is clear that this should happen only with the user's explicit +opt-in action. + +As implemented, Certbot will only load plugins connected via the snap interface +mechanism, so permission is effectively delegated to what interface connections +the snap infrastucture will permit. + +I am not clear as to exactly what is and isn't currently permitted, and what +interfaces can or cannot be set to be automatically connected. + +It seems fairly clear that, at a minimum, a manual connection between snaps +coming from the same publisher will be permitted. + +## Outstanding issues + +[Outstanding items relating to plugin support in Certbot snaps are tracked on GitHub](https://github.com/basak/certbot-snap-build/issues?q=is%3Aissue+is%3Aopen+label%3Aplugin). From 44b1bd8e0ea809766c03fbe320a577fae3114b46 Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Mon, 27 Apr 2020 15:22:57 -0700 Subject: [PATCH 4/5] Update README fix branch name grammar remove readme link Remove links to Robie's repo. say you cant use docker Commands not command Update publishing permissions section. Have Certbot trust plugins. Do not run snapcraft with sudo. --- README.md | 75 +++++++++++++++++++++++++++++------------------------- README.rst | 1 - 2 files changed, 41 insertions(+), 35 deletions(-) delete mode 120000 README.rst diff --git a/README.md b/README.md index bf79c35f6..b6a52077a 100644 --- a/README.md +++ b/README.md @@ -53,38 +53,46 @@ You can now operate the plugin as normal. To try this out, you'll need to build the snaps (a patched Certbot snap and a plugin snap) manually. - 1. Start with a Xenial VM. - 2. Install snapcraft with `snap install --classic snapcraft`. - 3. Run `git clone git://github.com/basak/certbot-snap-build -b snap-plugins/snap/certbot`. - 4. `cd certbot-snap-build` - 5. Run `git clone https://github.com/basak/certbot-snap-build -b snap-plugins/certbot certbot` (this is a workaround for #13). - 6. Run `certbot/tools/strip_hashes.py certbot/letsencrypt-auto-source/pieces/dependency-requirements.txt > certbot/constraints.txt` (this is a workaround for #13). - 7. Run `snapcraft`. - 8. Install the generated snap with `sudo snap install --dangerous --classic certbot_*_amd64.snap`. You can transfer the snap to a different machine to run it there instead if you prefer. - 9. `cd ..` - 10. `git clone git://github.com/basak/certbot-snap-build.git -b snap-plugins/snap/certbot-dns-dnsimple certbot-dns-dnsimple` - 11. `cd certbot-dns-dnsimple` - 12. `snapcraft` - 13. Install the generated snap with `sudo snap install --dangerous certbot-dns-dnsimple_*_amd64.snap`. Again, you can transfer the snap to a different machine to run it there instead if you prefer. - 14. Connect the plugin with `sudo snap connect certbot:plugin certbot-dns-dnsimple`. - 15. Now you can run Certbot as normal. For example, `certbot plugins` should display the DNSimple plugin as installed. +### Initial VM Set Up -## Code +These steps need to be done once to set up your VM and do not need to be run again to rebuild the snap. -This proof of concept ships four git branches: + 1. Start with a Xenial VM. You need a full virtual machine using something like DigitalOcean, EC2, or VirtualBox. Docker won't work. Another version of Ubuntu can probably be used, but Xenial was used when writing these instructions. + 2. Set up a user other than root with sudo privileges for use with snapcraft and run all of the following commands with it. A command to do this for a user named certbot looks like `adduser certbot && usermod -aG sudo certbot && su - certbot`. + 3. Install git and python with `sudo apt update && sudo apt install git python`. + 4. Set up lxd for use with snapcraft by running `sudo snap install lxd && sudo /snap/bin/lxd.migrate -yes && sudo /snap/bin/lxd waitready && sudo /snap/bin/lxd init --auto` + 5. Add your current user to the lxd group and update your shell to have the new assignment by running `sudo usermod -a -G lxd ${USER} && newgrp lxd`. + 6. Install snapcraft with `sudo snap install --classic snapcraft`. + 7. `cd ~` (or any other directory where you want our source files to be) + 8. Run `git clone git://github.com/certbot/certbot -b snap-plugin` + 9. `cd certbot` -1. [This documentation](https://github.com/basak/certbot-snap-build/tree/snap-plugins/doc). -2. [A fork of Certbot upstream that adds support for - `CERTBOT_PLUGIN_PATH`](https://github.com/basak/certbot-snap-build/tree/snap-plugins/certbot). -3. [A fork of the proof of concept Certbot snap packaging that adds plugin - support](https://github.com/basak/certbot-snap-build/tree/snap-plugins/snap/certbot). -4. [An example of snap packaging for the Certbot DNSimple - plugin](https://github.com/basak/certbot-snap-build/tree/snap-plugins/snap/certbot-dns-dnsimple). +### Build the Snaps -If adopted, these would all be upstreamed, and no branches would be necessary. -Snap packaging is intended to be maintained within upstream code trees -themselves with the addition of `snapcraft.yaml`, much like Travis CI -integration. +These are the steps to build and install the snaps. If you have run these steps before, you may want to run the commands in the section below to clean things up before building the snap again. + + 1. Run `tools/strip_hashes.py letsencrypt-auto-source/pieces/dependency-requirements.txt > constraints.txt` (this is a workaround for https://github.com/certbot/certbot/issues/7957). + 2. Run `snapcraft --use-lxd`. + 3. Install the generated snap with `sudo snap install --dangerous --classic certbot_*_amd64.snap`. You can transfer the snap to a different machine to run it there instead if you prefer. + 4. Run `tools/strip_hashes.py letsencrypt-auto-source/pieces/dependency-requirements.txt > certbot-dns-dnsimple/constraints.txt`. + 5. `cd certbot-dns-dnsimple` + 6. `snapcraft --use-lxd` + 7. Run `sudo snap set certbot trust-plugin-with-root=ok`. + 8. Install the generated snap with `sudo snap install --dangerous certbot-dns-dnsimple_*_amd64.snap`. Again, you can transfer the snap to a different machine to run it there instead if you prefer. + 9. Connect the plugin with `sudo snap connect certbot:plugin certbot-dns-dnsimple`. + 10. Now you can run Certbot as normal. For example, `certbot plugins` should display the DNSimple plugin as installed. + +### Reset the Environment + +The instructions below clean up the build environment so it can reliably be used again. + +1. `cd ~/certbot` (or to an alternate path where you put our source files) +2. `snapcraft clean --use-lxd` +3. `rm certbot_*_amd64.snap` +4. `cd certbot-dns-dnsimple` +5. `rm certbot-dns-dnsimple_*_amd64.snap` +6. `snapcraft clean --use-lxd` +7. `cd ..` ## Publishing Permissions @@ -99,12 +107,11 @@ As implemented, Certbot will only load plugins connected via the snap interface mechanism, so permission is effectively delegated to what interface connections the snap infrastucture will permit. -I am not clear as to exactly what is and isn't currently permitted, and what -interfaces can or cannot be set to be automatically connected. - -It seems fairly clear that, at a minimum, a manual connection between snaps -coming from the same publisher will be permitted. +We have approval from the snap team to use this design as long as we make it +more explicit what a user is agreeing to when they connect a plugin to the +Certbot snap. That work is tracked by +https://github.com/certbot/certbot/issues/7667. ## Outstanding issues -[Outstanding items relating to plugin support in Certbot snaps are tracked on GitHub](https://github.com/basak/certbot-snap-build/issues?q=is%3Aissue+is%3Aopen+label%3Aplugin). +[Outstanding items relating to plugin support in Certbot snaps are tracked on GitHub](https://github.com/certbot/certbot/issues?q=is%3Aopen+is%3Aissue+label%3A%22area%3A+snaps%22). diff --git a/README.rst b/README.rst deleted file mode 120000 index 645fd4c78..000000000 --- a/README.rst +++ /dev/null @@ -1 +0,0 @@ -certbot/README.rst \ No newline at end of file From 29a23d31489cc999419ab4dfa2a44f9cc60178c7 Mon Sep 17 00:00:00 2001 From: Erica Portnoy Date: Wed, 17 Jun 2020 17:27:27 -0700 Subject: [PATCH 5/5] Update README instructions for merged master Use Focal when following README instructions Discard changes to disco.py bring README up to date with current knowledge Move README to snap/local/ --- README.rst | 1 + certbot/certbot/_internal/plugins/disco.py | 2 -- README.md => snap/local/README.md | 16 +++++++++------- 3 files changed, 10 insertions(+), 9 deletions(-) create mode 120000 README.rst rename README.md => snap/local/README.md (88%) diff --git a/README.rst b/README.rst new file mode 120000 index 000000000..645fd4c78 --- /dev/null +++ b/README.rst @@ -0,0 +1 @@ +certbot/README.rst \ No newline at end of file diff --git a/certbot/certbot/_internal/plugins/disco.py b/certbot/certbot/_internal/plugins/disco.py index 4fd20c16e..f1d89f06a 100644 --- a/certbot/certbot/_internal/plugins/disco.py +++ b/certbot/certbot/_internal/plugins/disco.py @@ -2,8 +2,6 @@ import collections import itertools import logging -import os -import sys import pkg_resources import six diff --git a/README.md b/snap/local/README.md similarity index 88% rename from README.md rename to snap/local/README.md index b6a52077a..d3ce1dcd4 100644 --- a/README.md +++ b/snap/local/README.md @@ -34,6 +34,7 @@ as usual. Plugin snaps are confined as normal; the Certbot snap is a classic snap and thus needs `--classic` during installation. For example: snap install --classic certbot + snap set certbot trust-plugin-with-root=ok snap install certbot-dns-dnsimple Then connect the plugin snap to the main certbot snap as follows. Note that @@ -57,10 +58,11 @@ plugin snap) manually. These steps need to be done once to set up your VM and do not need to be run again to rebuild the snap. - 1. Start with a Xenial VM. You need a full virtual machine using something like DigitalOcean, EC2, or VirtualBox. Docker won't work. Another version of Ubuntu can probably be used, but Xenial was used when writing these instructions. + 1. Start with a Focal VM. You need a full virtual machine using something like DigitalOcean, EC2, or VirtualBox. Docker won't work. Another version of Ubuntu can probably be used, but Focal was used when writing these instructions. 2. Set up a user other than root with sudo privileges for use with snapcraft and run all of the following commands with it. A command to do this for a user named certbot looks like `adduser certbot && usermod -aG sudo certbot && su - certbot`. - 3. Install git and python with `sudo apt update && sudo apt install git python`. - 4. Set up lxd for use with snapcraft by running `sudo snap install lxd && sudo /snap/bin/lxd.migrate -yes && sudo /snap/bin/lxd waitready && sudo /snap/bin/lxd init --auto` + 3. Install git and python with `sudo apt update && sudo apt install -y git python`. + 4. Set up lxd for use with snapcraft by running `sudo snap install lxd && sudo /snap/bin/lxd.migrate -yes && sudo /snap/bin/lxd waitready && sudo /snap/bin/lxd init --auto` (errors here are ok; it may already + have been installed on your system). 5. Add your current user to the lxd group and update your shell to have the new assignment by running `sudo usermod -a -G lxd ${USER} && newgrp lxd`. 6. Install snapcraft with `sudo snap install --classic snapcraft`. 7. `cd ~` (or any other directory where you want our source files to be) @@ -71,7 +73,7 @@ These steps need to be done once to set up your VM and do not need to be run aga These are the steps to build and install the snaps. If you have run these steps before, you may want to run the commands in the section below to clean things up before building the snap again. - 1. Run `tools/strip_hashes.py letsencrypt-auto-source/pieces/dependency-requirements.txt > constraints.txt` (this is a workaround for https://github.com/certbot/certbot/issues/7957). + 1. Run `tools/strip_hashes.py letsencrypt-auto-source/pieces/dependency-requirements.txt | grep -v python-augeas > snap-constraints.txt` (this is a workaround for https://github.com/certbot/certbot/issues/7957). 2. Run `snapcraft --use-lxd`. 3. Install the generated snap with `sudo snap install --dangerous --classic certbot_*_amd64.snap`. You can transfer the snap to a different machine to run it there instead if you prefer. 4. Run `tools/strip_hashes.py letsencrypt-auto-source/pieces/dependency-requirements.txt > certbot-dns-dnsimple/constraints.txt`. @@ -108,9 +110,9 @@ mechanism, so permission is effectively delegated to what interface connections the snap infrastucture will permit. We have approval from the snap team to use this design as long as we make it -more explicit what a user is agreeing to when they connect a plugin to the -Certbot snap. That work is tracked by -https://github.com/certbot/certbot/issues/7667. +explicit what a user is agreeing to when they connect a plugin to the +Certbot snap. That work was completed in +https://github.com/certbot/certbot/issues/8013. ## Outstanding issues