From d751d7fb6518c5919422938b280fe2c3c5413e30 Mon Sep 17 00:00:00 2001 From: Marius Kimmina Date: Sun, 3 Apr 2022 10:45:13 +0200 Subject: [PATCH 1/4] initial proposal Signed-off-by: Marius Kimmina --- 20220403-ACME-TLS.md | 211 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 211 insertions(+) create mode 100644 20220403-ACME-TLS.md diff --git a/20220403-ACME-TLS.md b/20220403-ACME-TLS.md new file mode 100644 index 0000000..25dd1d1 --- /dev/null +++ b/20220403-ACME-TLS.md @@ -0,0 +1,211 @@ +# Add ACME protocol support for certificate management into TLS plugin + +| Status | Proposed | +:-------------- |:---------------------------------------------------- | +| **RFC #** | [13](https://github.com/coredns/rfc/pull/13) | +| **Author(s)** | Marius Kimmina(@[mariuskimmina](https://github.com/mariuskimmina)) | +| **Sponsor** | Yong Tang (@[yongtang](https://github.com/yongtang)), Paul Greenberg (@[greenpau](https://github.com/greenpau)) | +| **Updated** | 2022-04-01 | +| **Obsoletes** | | + +## Objective + +This project aims to add ACME support to the existing TLS plugin, which is used to configure the CoreDNS server's TLS certificates, so that the management of these certificate can be automated. + +## Motivation and Scope + +There are two ways in which ACME can be intereting for the CoreDNS project: + +* CoreDNS needs a certificate management tool to solve its own DNS over TLS certificate issue. +* CoreDNS potentially can be used to provide generic certificate management method for scenarios beyond serving DNS over TLS issue. This is not mentioned in the original project page as you can also use HTTP challenge (which many people will use due to the familiarity of http than DNS.). + +This proposal will focus on the first case - meaning that we CoreDNS is serving DNS over TLS (DoT) or DNS over HTTPs (DoH) and for that it needs to have a valid TLS certificate. Obtaining such a valid certificate for the CoreDNS server itself is what should be automated by this project. +To use the ACME challenge ownership of a domain, such as `coredns.io` or `example.com` is required, thus when using CoreDNS with an IP address and without any domain, obtaining a valid certificate can not be automated by ACME. + +### Manual Certificate Management + +To obtain a valid (signed by a CA) certificate historically the following steps were required + +1. Generate private key +2. Generate CSR +3. Order SSL certificate +4. Paste CSR into online form +5. Choose an email address +6. Wait for email +7. Click link in email +8. Wait for another email +9. Download certificate +10. Concat into bundle +11. Upload bundle to server +12. Configure server to use cert and key +13. Remember to renew the certificate before it expires + +Some parts here can already be automated easily, like Generating a private key and a CSR - it's really the middle part that's involves emails and clicking links that's a problem. + +### Automatic Certificate Management + +1. Generate private key +2. Generate CSR +3. Solve ACME Challenge +4. Download certificate bundle +5. Configure server to use cert and key +6. Repeat Steps 2 to 5 before the certificate expries + +And all of these steps can be automated + +## How ACME works + +ACME is a client-server protocl where the Server side is implemented by a Certificate Authority (CA) such as [Let's Encrypt][lets-encrypt] the client side is implemented by a service that wants to obtain a valid certificate, such as CoreDNS in this case. The client has to prove ownership of a domain before the CA can give out a certificate, to achieve that, one of the following challenges has to be completed: + +### HTTP01 Challenge +This requires port 80. + +CA gives the ACME client a token which puts a file on the server at http:///.well-known/acme-challenge/. The file contains the token, plus a thumbprint of your account key. Once the client tells the CA that the file is ready, Let’s Encrypt tries retrieving it. If the validation checks get the right responses from the web server, the validation is considered successful and the certificate can be issued. + +To implement this in CoreDNS I propose that the underlying Caddy server could be used to serve the file at `/.well-known/acme-challenge/`. I am not familar enough with the codebase of CoreDNS to know how feasible it would be to do this from a plugin - see questions and discussions section. + +### DNS01 Challenge +After the CA gives the ACME client a token, the client will then create a TXT record derived from that token and your account key, and put that record at _acme-challenge.. The CA queries the DNS system for that record and the certificate can be issued if it matches. +However, to do this automatically, the DNS provider needs to offer an API by which changes can be made to domain names. Wildcard certificates can be issued with this challenge. + +## Deliverables +* The existing TLS plugin will be extended to support the ACME protocol +* It will be possible to setup CoreDNS with a verified certificate, signed by a CA such as Let's Encrypt, without manually generating and renewing it +* Documentation on how to use the TLS plugin with ACME + +## Design Proposal + +The major task of this project is to integrate the above defined specs of ACME protocol into CoreDNS so that it could automate certificate management. + +In current scenarios, in order to enable DNS over TLS users have to manually provide certificates via the following Corefile configurations: + +``` +tls://example.com { + tls cert.pem key.pem +} +``` + +This `cert.pem` and `key.pem` file currently have to be manually created and renewed. + +I propose to extend the existing `tls` plugin to support the ACME protocol so that we can instead create a Corefile like this: + +``` +tls://example.com { + tls acme { + domain exmaple.com + } +} +``` + +To implement ACME there are a couple packages that we could use to help us such as: + +* [acmez](https://pkg.go.dev/github.com/mholt/acmez) +* [CertMagic](https://github.com/caddyserver/certmagic) +* [lego](https://github.com/go-acme/lego) +* [autocert](https://github.com/golang/crypto/tree/master/acme/autocert) + +Deciding for one of these implementation, or potentially even creating a new one, is an outstanding task. + + +## Storage + +During the whole process there are a couple things that need to be stored: + +* Private Key +* Certificate Signing Request (CSR) +* Certificate + +Where the generation of the private key and the CSR as well as storing them might be handled by an ACME library which might limit our decisions for these two. for the Cert that's being returned from the ACME server there should be no restraints. +The following storing options are available: + +* [Cert Resource Records](https://datatracker.ietf.org/doc/html/rfc4398) +* TXT Records +* Local file storage + +I propose to use the Cert RR for the Certificate, as for the private key and the CSR we definitely don't want to share these with anyone so local file storage should be the right choice here. + +## Clustered Environments + +In clustered environment, where there are multiple CoreDNS instances running, certificate sharing is a major concern. Certificate sharing is important as it is neither feasible nor desireable for each CoreDNS instance to fetch certificate individually. + +Since high availability is not a major concern, as queries are cached at every level, a solution is to configure CoreDNS instances as "leader" and "worker". + +1. Leader: In a cluster, a single DNS Server can be configured as "leader", which would be responsible for actually performing ACME challenges and obtaining certificate from the Let's Encrypt CA. The leader would then store the certificate in the zone file as CERT RR. + +2. Worker: The worker is responsible for fetching the certificates from the master. The worker is not responsible for performing ACME challenges. Whenever a DNS query is received at the worker node, the worker first queries the master for the certificate. Workers should cache the certificate and use it for further DoH queries. + +Configurations: + +Leader +``` +https://example.com { + tls acme { + leader + domain + challenge + } +} +``` + +Worker +``` +https://example.com { + tls acme { + worker + domain + } +} +``` + +The worker caches the CERT RR (for X seconds) to reduce querying the master for the certificate every time a DNS query is received. + + +## Timeline + +**April 4 - Mai 20: Pre GSoC** +* Familiarize myself more with the project +* Improve the project proposal +* Study concepts related to the project + +**Mai 20 - June 13:** +* (Final) Design decisions: + * ACME library + * Corefile layout + * Storage + * Clustered Implementation +* Start implementing + + +**June 13 - September 19:** +1. Integrate ACME library (or own implementation if necessary) into TLS plugin +2. Implement Challenges +3. Develop Tests for ACME challenges +3. Start writing documentation +4. Start working on cluster implementation +5. Develop Tests for cluster implementation +6. Finish the documentation + +I hope to be done by September 01 the latest and have until September 19 as a buffer. +I will also be in contact with the mentors and hope to gather a lot of feedback along the way. + + +**September 19 - onwards: After GSoC** +* Keep Contributing to CoreDNS and possibly other CNCF projects + + +## Questions and Discussion Topics + +1. Can a CoreDNS plugin utilize the underlying Caddy server to solve the HTTP-01 Challenge - which means serving a file on port 80? +2. For the DNS-01 Challenge, I would assume that CoreDNS will generally not be the authoritative DNS Server for the domain in question, thus, we would also use the API of a DNS Provider to solve this challenge, right? +3. How should I configure the workers to look for the leader? When the certificate is renewed, how does the master know where the workers are and how to send the certificate to them? + +## References + +A lot of this proposal has been reused from a previous attempts [here](https://github.com/coredns/rfc/pull/12) and [here](https://github.com/coredns/rfc/pull/11), so a lot of credit belongs to the authors of these previous proposals. + +1. [ACME RFC](https://tools.ietf.org/html/rfc8555) +2. [DNS Challenge Types](https://letsencrypt.org/docs/challenge-types/) +3. [Explanation of ACME Protocol](https://www.thesslstore.com/blog/acme-protocol-what-it-is-and-how-it-works/) + + +[lets-encrypt]: https://letsencrypt.org/ \ No newline at end of file From 5c2861452613055144b7e11d71a4f60cd482b755 Mon Sep 17 00:00:00 2001 From: Marius Kimmina Date: Thu, 7 Apr 2022 10:46:20 +0200 Subject: [PATCH 2/4] Improve the proposal after a few things have been clarified Signed-off-by: Marius Kimmina --- 20220403-ACME-TLS.md | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/20220403-ACME-TLS.md b/20220403-ACME-TLS.md index 25dd1d1..9084f43 100644 --- a/20220403-ACME-TLS.md +++ b/20220403-ACME-TLS.md @@ -1,4 +1,4 @@ -# Add ACME protocol support for certificate management into TLS plugin +# Add ACME protocol support for certificate management into TLS plugin | Status | Proposed | :-------------- |:---------------------------------------------------- | @@ -19,8 +19,9 @@ There are two ways in which ACME can be intereting for the CoreDNS project: * CoreDNS needs a certificate management tool to solve its own DNS over TLS certificate issue. * CoreDNS potentially can be used to provide generic certificate management method for scenarios beyond serving DNS over TLS issue. This is not mentioned in the original project page as you can also use HTTP challenge (which many people will use due to the familiarity of http than DNS.). -This proposal will focus on the first case - meaning that we CoreDNS is serving DNS over TLS (DoT) or DNS over HTTPs (DoH) and for that it needs to have a valid TLS certificate. Obtaining such a valid certificate for the CoreDNS server itself is what should be automated by this project. +This proposal will focus on the first case - meaning that when CoreDNS is serving DNS over TLS (DoT) or DNS over HTTPs (DoH) it needs to have a valid TLS certificate. Obtaining such a valid certificate for the CoreDNS server itself is what should be automated by this project. To use the ACME challenge ownership of a domain, such as `coredns.io` or `example.com` is required, thus when using CoreDNS with an IP address and without any domain, obtaining a valid certificate can not be automated by ACME. +CoreDNS also needs to be the authoritative DNS Server for the domain in question - CoreDNS needs to be able to set a TXT Record on the domain that ownership needs to be proven of. ### Manual Certificate Management @@ -59,14 +60,14 @@ ACME is a client-server protocl where the Server side is implemented by a Certif ### HTTP01 Challenge This requires port 80. - CA gives the ACME client a token which puts a file on the server at http:///.well-known/acme-challenge/. The file contains the token, plus a thumbprint of your account key. Once the client tells the CA that the file is ready, Let’s Encrypt tries retrieving it. If the validation checks get the right responses from the web server, the validation is considered successful and the certificate can be issued. +To implement this in CoreDNS I propose that the underlying Caddy server could be used to serve the file at `/.well-known/acme-challenge/`. -To implement this in CoreDNS I propose that the underlying Caddy server could be used to serve the file at `/.well-known/acme-challenge/`. I am not familar enough with the codebase of CoreDNS to know how feasible it would be to do this from a plugin - see questions and discussions section. +This Challenge is out of scope for this proposal, the ACME implementation in CoreDNS will only support the DNS Challenge, CoreDNS should not act as a web-server. ### DNS01 Challenge After the CA gives the ACME client a token, the client will then create a TXT record derived from that token and your account key, and put that record at _acme-challenge.. The CA queries the DNS system for that record and the certificate can be issued if it matches. -However, to do this automatically, the DNS provider needs to offer an API by which changes can be made to domain names. Wildcard certificates can be issued with this challenge. +For this to work, CoreDNS needs to be the authoritative DNS server for the domain and thus be able to set the TXT Record. ## Deliverables * The existing TLS plugin will be extended to support the ACME protocol @@ -75,12 +76,11 @@ However, to do this automatically, the DNS provider needs to offer an API by whi ## Design Proposal -The major task of this project is to integrate the above defined specs of ACME protocol into CoreDNS so that it could automate certificate management. - +The major task of this project is to integrate the above defined specs of ACME protocol into CoreDNS so that it could automate certificate management. In current scenarios, in order to enable DNS over TLS users have to manually provide certificates via the following Corefile configurations: ``` -tls://example.com { +tls://dns.example.com { tls cert.pem key.pem } ``` @@ -90,7 +90,7 @@ This `cert.pem` and `key.pem` file currently have to be manually created and ren I propose to extend the existing `tls` plugin to support the ACME protocol so that we can instead create a Corefile like this: ``` -tls://example.com { +tls://dns.example.com { tls acme { domain exmaple.com } @@ -109,13 +109,13 @@ Deciding for one of these implementation, or potentially even creating a new one ## Storage -During the whole process there are a couple things that need to be stored: +During the whole process there are a couple things that need to be stored: * Private Key * Certificate Signing Request (CSR) * Certificate -Where the generation of the private key and the CSR as well as storing them might be handled by an ACME library which might limit our decisions for these two. for the Cert that's being returned from the ACME server there should be no restraints. +Where the generation of the private key and the CSR as well as storing them might be handled by an ACME library which might limit our decisions for these two. for the Cert that's being returned from the ACME server there should be no restraints. The following storing options are available: * [Cert Resource Records](https://datatracker.ietf.org/doc/html/rfc4398) @@ -128,9 +128,9 @@ I propose to use the Cert RR for the Certificate, as for the private key and the In clustered environment, where there are multiple CoreDNS instances running, certificate sharing is a major concern. Certificate sharing is important as it is neither feasible nor desireable for each CoreDNS instance to fetch certificate individually. -Since high availability is not a major concern, as queries are cached at every level, a solution is to configure CoreDNS instances as "leader" and "worker". +Since high availability is not a major concern, as queries are cached at every level, a solution is to configure CoreDNS instances as "leader" and "worker". -1. Leader: In a cluster, a single DNS Server can be configured as "leader", which would be responsible for actually performing ACME challenges and obtaining certificate from the Let's Encrypt CA. The leader would then store the certificate in the zone file as CERT RR. +1. Leader: In a cluster, a single DNS Server can be configured as "leader", which would be responsible for actually performing ACME challenges and obtaining certificates from the Let's Encrypt CA. The leader would then store the certificate in the zone file as CERT RR. 2. Worker: The worker is responsible for fetching the certificates from the master. The worker is not responsible for performing ACME challenges. Whenever a DNS query is received at the worker node, the worker first queries the master for the certificate. Workers should cache the certificate and use it for further DoH queries. @@ -142,7 +142,6 @@ https://example.com { tls acme { leader domain - challenge } } ``` @@ -190,13 +189,15 @@ I will also be in contact with the mentors and hope to gather a lot of feedback **September 19 - onwards: After GSoC** -* Keep Contributing to CoreDNS and possibly other CNCF projects +* Keep Contributing to CoreDNS and possibly other CNCF projects ## Questions and Discussion Topics 1. Can a CoreDNS plugin utilize the underlying Caddy server to solve the HTTP-01 Challenge - which means serving a file on port 80? + * This question has been answered: the HTTP Challenge is out-of-scope for this project, only the DNS challenge is supported 2. For the DNS-01 Challenge, I would assume that CoreDNS will generally not be the authoritative DNS Server for the domain in question, thus, we would also use the API of a DNS Provider to solve this challenge, right? + * This question has been answered: We do assume that CoreDNS will be the authoritative DNS server for the domain and sets the TXT Record itself. 3. How should I configure the workers to look for the leader? When the certificate is renewed, how does the master know where the workers are and how to send the certificate to them? ## References @@ -208,4 +209,4 @@ A lot of this proposal has been reused from a previous attempts [here](https://g 3. [Explanation of ACME Protocol](https://www.thesslstore.com/blog/acme-protocol-what-it-is-and-how-it-works/) -[lets-encrypt]: https://letsencrypt.org/ \ No newline at end of file +[lets-encrypt]: https://letsencrypt.org/ From 71441cd2e6df20b1600da9325b89b4218ee7ab43 Mon Sep 17 00:00:00 2001 From: Marius Kimmina Date: Wed, 13 Apr 2022 17:10:50 +0200 Subject: [PATCH 3/4] Improve proposal, adding section for configuration options Signed-off-by: Marius Kimmina --- 20220403-ACME-TLS.md | 56 ++++++++++++++++++++++++++++++-------------- 1 file changed, 39 insertions(+), 17 deletions(-) diff --git a/20220403-ACME-TLS.md b/20220403-ACME-TLS.md index 9084f43..5b4afad 100644 --- a/20220403-ACME-TLS.md +++ b/20220403-ACME-TLS.md @@ -17,7 +17,7 @@ This project aims to add ACME support to the existing TLS plugin, which is used There are two ways in which ACME can be intereting for the CoreDNS project: * CoreDNS needs a certificate management tool to solve its own DNS over TLS certificate issue. -* CoreDNS potentially can be used to provide generic certificate management method for scenarios beyond serving DNS over TLS issue. This is not mentioned in the original project page as you can also use HTTP challenge (which many people will use due to the familiarity of http than DNS.). +* CoreDNS could be used to fullfill the DNS-01 Challenge for other applications, such as a webservers. This proposal will focus on the first case - meaning that when CoreDNS is serving DNS over TLS (DoT) or DNS over HTTPs (DoH) it needs to have a valid TLS certificate. Obtaining such a valid certificate for the CoreDNS server itself is what should be automated by this project. To use the ACME challenge ownership of a domain, such as `coredns.io` or `example.com` is required, thus when using CoreDNS with an IP address and without any domain, obtaining a valid certificate can not be automated by ACME. @@ -99,13 +99,13 @@ tls://dns.example.com { To implement ACME there are a couple packages that we could use to help us such as: -* [acmez](https://pkg.go.dev/github.com/mholt/acmez) -* [CertMagic](https://github.com/caddyserver/certmagic) -* [lego](https://github.com/go-acme/lego) -* [autocert](https://github.com/golang/crypto/tree/master/acme/autocert) - -Deciding for one of these implementation, or potentially even creating a new one, is an outstanding task. +* [acmez][acemz] +* [CertMagic][CertMagic] +* [lego][lego] +* [autocert][autocert] +As it was discussed before on the original Issue, CertMagic might have too many features that we don't need for our use case - the same could be said for lego and autocert. +So just using acmez as the most barebones implemenation of the acme-protocol seems to be the right call for this project. ## Storage @@ -118,7 +118,7 @@ During the whole process there are a couple things that need to be stored: Where the generation of the private key and the CSR as well as storing them might be handled by an ACME library which might limit our decisions for these two. for the Cert that's being returned from the ACME server there should be no restraints. The following storing options are available: -* [Cert Resource Records](https://datatracker.ietf.org/doc/html/rfc4398) +* [Cert Resource Records][CRR] * TXT Records * Local file storage @@ -138,26 +138,41 @@ Configurations: Leader ``` -https://example.com { +tls://dns.example.com { tls acme { leader - domain + domain example.com } } ``` Worker ``` -https://example.com { - tls acme { +tls://dns.example.com { + tls acme { worker - domain + domain example.com } } ``` The worker caches the CERT RR (for X seconds) to reduce querying the master for the certificate every time a DNS query is received. +## Further configuration options + +### Wildcard certificates + +The DNS-01 Challenge can be used to create Wildcard certificates, the plugin could either get a cert for e.g. `dns.example.com` or for `*.example.com`. +By default it seems more reasonable to not use Wildcard certificates but we could have them as an opt-in feature with a Corefile like This + + +tls://dns.example.com { + tls acme { + domain example.com + wildcard + } +} + ## Timeline @@ -204,9 +219,16 @@ I will also be in contact with the mentors and hope to gather a lot of feedback A lot of this proposal has been reused from a previous attempts [here](https://github.com/coredns/rfc/pull/12) and [here](https://github.com/coredns/rfc/pull/11), so a lot of credit belongs to the authors of these previous proposals. -1. [ACME RFC](https://tools.ietf.org/html/rfc8555) -2. [DNS Challenge Types](https://letsencrypt.org/docs/challenge-types/) -3. [Explanation of ACME Protocol](https://www.thesslstore.com/blog/acme-protocol-what-it-is-and-how-it-works/) - +1. [ACME RFC][acme-rfc] +2. [DNS Challenge Types][dns-challenge-types] +3. [Explanation of ACME Protocol][acme-explanation] [lets-encrypt]: https://letsencrypt.org/ +[acmez]: https://pkg.go.dev/github.com/mholt/acmez +[CertMagic]: https://github.com/caddyserver/certmagic +[lego]: https://github.com/go-acme/lego +[autocert]: https://github.com/golang/crypto/tree/master/acme/autocert +[CRR]: https://datatracker.ietf.org/doc/html/rfc4398 +[acme-rfc]: https://tools.ietf.org/html/rfc8555 +[dns-challenge-types]: https://letsencrypt.org/docs/challenge-types/ +[acme-explanation]: https://www.thesslstore.com/blog/acme-protocol-what-it-is-and-how-it-works/ From 9186a9c60445f14ed8c06d2eaa0a5620fdec9548 Mon Sep 17 00:00:00 2001 From: Marius Kimmina Date: Wed, 13 Apr 2022 17:12:42 +0200 Subject: [PATCH 4/4] fix broken link Signed-off-by: Marius Kimmina --- 20220403-ACME-TLS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/20220403-ACME-TLS.md b/20220403-ACME-TLS.md index 5b4afad..ca31b8a 100644 --- a/20220403-ACME-TLS.md +++ b/20220403-ACME-TLS.md @@ -99,7 +99,7 @@ tls://dns.example.com { To implement ACME there are a couple packages that we could use to help us such as: -* [acmez][acemz] +* [acmez][acmez] * [CertMagic][CertMagic] * [lego][lego] * [autocert][autocert]