-
-
Notifications
You must be signed in to change notification settings - Fork 279
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[enh] Certificate management integration (e.g. Let's Encrypt ...) #180
Conversation
… certificate install)
sudo yunohost domain -h
cert-install Install Let's Encrypt certificates for given domains
(all by default).
cert-status List status of current certificates (all by default).
list List domains
remove Delete domains
add Create a custom domain
dns-conf Generate DNS configuration for a domain
cert-renew Renew the Let's Encrypt certificates for given domains
(all by default). Could |
As said on the chat room, there is three solutions: Debian packagesThat solution would be the best choice. SubtreesFor now, we could add them as subtrees from respective repositories: tabulate and acme-tiny. PipIt's kind of ugly solution: sudo pip install tabulate acme-tiny I suggest to use subtrees solution for now, and Debian packages on Debian Stretch. |
|
||
def _install_cron() : | ||
|
||
cron_job_file = "/etc/cron.weekly/certificateRenewer" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe rename cron file to something more consistent with other yunohost cron. Currently we have /etc/cron.d/yunohost-applist-yunohost
, /etc/cron.d/yunohost-firewall
and /etc/cron.d/yunohost-dyndns
.
I don't know if it worth to move this cron to /etc/cron.d
as well.
I vote for /etc/cron.d/yunohost-certificate-renew
;)
def _dns_ip_match_public_ip(public_ip, domain) : | ||
|
||
try : | ||
r = requests.get("http://dns-api.org/A/"+domain) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please use https url ;)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know if using 'dnspython' lib is easy, but I'd like to avoid using a third party API. Note that 'dnspython' is package in Debian's python-dns
.
else : | ||
return True | ||
|
||
def _domain_is_accessible_through_HTTP(ip, domain) : |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This test looks really weak, I don't think that this is the good way to do that but I don't have any other in mind right now.
@@ -731,13 +731,7 @@ def _dns_ip_match_public_ip(public_ip, domain): | |||
|
|||
def _domain_is_accessible_through_HTTP(ip, domain): | |||
try: | |||
# Check HTTP reachability | |||
requests.head("http://" + ip, headers={"Host": domain}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no matter what domain
value is, this requests will not return any exception ;)
Maybe we should request /yunohost/admin or /yunohost/api to be sure that domain & ip will match. See https://dev.yunohost.org/issues/638 for example
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As discussed on the chat, even requesting /yunohost/admin
or /yunohost/api
doesn't give a clear indication. Properly diagnosing the status/configuration of a domain seems to be a complicated problem 😛. Let's agree that these are some minimal checks for now, and can be refined later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
agreed
if ("urn:acme:error:rateLimited" in str(e)) : | ||
raise MoulinetteError(errno.EINVAL, m18n.n('certmanager_hit_rate_limit', domain=domain)) | ||
else : | ||
raise |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
shouldn't we raise a MoulinetteError
, with something like "Unknown error: ..." ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed. Fixed in e66a708.
…lready existing in nginx
Warning: we need to merge this into unstable, not into testing (we can still have the discussion and review here) |
I have done a test with the presence of letsencrypt_ynh it was ok, the webadmin ask me to uninstall it before. For the cli I have add the answer:
I have done a test with nginx disable:
|
Why displaying yunohost domain cert-status
certificates:
le.moul.re:
CA_type: Self-signed
summary: WARNING
validity: 3649 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It works fine on my side.
I tested main commands and usage (not every stranges cases and details).
It could be merge.
The |
This is with the assumption that domains in Yunohost are supposed to be suitable for "public" use, not for a private use (i.e. just you, + maybe a few friends ?). If your domain is for private use, good for you : add the cert exception popping in your browser, or download the CA certificate - done, ignore the warning. But if your domain is meant to be visited by some other, nontechnical people, (95% of the use case IMHO ?) you don't want them to run into the spooky warning of all modern browser about self-signed cert, and there's no reason to have a self-cert if you can install a LE cert with one command or two clicks. Hence the choice to report a warning. The meaning of the warning is not really explicit in the CLI, but it is a bit more in the web interface. |
To me that sounds related to the propagation to the FFDN resolvers. We might actually have a lot of impatient user who run into this if they want their cert ASAP after setting up their domain 😛. On the CLI you should have seen this message : "The DNS 'A' record for domain {domain:s} is different from this server IP. If you recently modified your A record, please wait for it to propagate (some DNS propagation checkers are available online). (If you know what you are doing, use --no-checks to disable those checks.)". On the web interface, we could change the message to tell the user to try again later ? But that's in another PR anyway. (Pro Tip ™️ : https://dnschecker.org/ allows to see the worldwide propagation of a DNS change) |
well done @alexAubin and all! I am super excited to this PR merged ! :) |
Hi guys,
here's a first proposition of integration of Let's Encrypt (and more generally certificate management).
It adds the following features :
Check certificate status
Install Let's Encrypt certificates
Renew Let's Encrypt certificate
Some more details / explanations
pip install acme-tiny
;ssowatconf
function to automatically authorize the ACME challenge uri/.well-known/blah
if it is present in the nginx conf ;cert-install
automatically adds a small cron-job (2 lines of code), callingyunohost domain cert-renew --email
every week, which will renew Let's Encrypt certificates which are about to expire, and send an email toroot
if some renewing fails ;cert-install
andcert-renew
include some checks that the domain seems to have a reasonable setup to attempt Let's Encrypt certificate installation (DNS poiting to global IP, + being able to GET a page) ;cert-install
can be used to regenerate a self-signed certificate (in case you don't want Let's Encrypt anymore for some reason). The short/mid-term goal is also to refactorize this part of code to get rid ofos.system()
calls and use the OpenSSL.crypto module instead.There are more features we can think about including in the future, such as supporting other ACME authorities, supporting DNS-based challenge, set level of security (e.g. deactivate TLS v1.0 and 1.1), import certificates from non-ACME authorities, provide a diagnosis for domain (e.g. inform user a Let's Encrypt cert can be installed, display current SSL Labs rating) etc... But for now, let's focus on the basic stuff :)
Remaining work
pip install acme-tiny
andpip install tabulate
for example.Cheers !