-
Notifications
You must be signed in to change notification settings - Fork 9.6k
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
ACME (LetsEncrypt) Provider Support #3599
Comments
I'm a big +1 for this. I think having "acme" as a separate provider is cleaner and gives us flexibility to change interfaces for each. |
Looks like this is a standalone plugin now: https://github.com/paybyphone/terraform-provider-acme We should consider moving this into core given the popularity of LE. |
@sethvargo there was discussion about that in #7058. See there for more context, but the two key points were:
Possibly the growing popularity of Let's Encrypt warrants a change in strategy here, but at that time I'd figured that having it as an external provider was a good compromise to make the functionality available while giving us an opportunity to find a more Terraform-idiomatic implementation of the workflow. |
Wow, speak of the devil, I was thinking about this today! Also on and off for the last little bit. I've been trying to brainstorm how we could make ACME in its current form a true TF-centric workflow. As there's been much said already here and in #7058, I'll get right to it: The challenge with making ACME play nicely with Terraform in its current state is how to deal with authorizations. They are multi-state resources that need to be called back to from whatever is used to handle one of the challenges (essentially a sub-resource of authorizations) issued by the CA to validate the authorization. As such it makes TF workflow kind of tricky, without certain current concept-only stage features such as conditionals and partial applies. The ACME spec as LE currently implements it follows this workflow for certificate generation.
Now, possibly, we could do this right now by breaking up the authorization resource into two resources, one for each stage. Example with say, Route 53 for DNS challenges (plausibly the majority of TF scenarios):
As a breakdown:
If everyone thinks that this is still something worth pursuing, let me know. I can get started on:
|
I just wanted to document some of the brainstorming that I've been doing on this one for the last few days. It's a bit messy, but I think it gets the job done in as sane of a way as possible.
The authorization process will be pretty de-centralized, having to rely on waiters in some parts to make sure things are okay to proceed:
This reduces reliance on Finally, we would converge on using resources in the TLS provider to do the crypto. No private key generation or request creation would be done by the ACME provider. A sample pseudo-config can be found in this gist. The only real outstanding issue I can really see is cleanup of any DNS records. These tokens are not necessary to keep around after authorization so it kind of feels a bit sketchy to leave them around after the fact. Judging from what I've been reading, it's not a big deal if they are, but you kind of expect automation to handle these kinds of things. Any ideas on this one are welcome! |
Thanks for the continued thinking on this, @vancluever! I like this new model a lot. The idea of a resource that "hangs" until some other action is completed is rather unconventional, so I think we'd need some careful documentation for that and some good examples, but it does seem like the approach that makes the best use of Terraform's existing resources. I also like the How is IETF standardization going? Do you think things have settled enough now that we could commit to this interface and not get broken by future refactoring of the workflow? (I notice the Go library itself explicitly disclaims any API compatibility promises, which doesn't bode well. 😀) |
Thanks @apparentlymart! Yeah, the waiter thing is really the only way I can think of getting around a lack of partial applies, and also the fact that tooling should asset that DNS propagation has taken place to reduce the risk of the authorization failing due to a race condition. Definitely we should be ensuring that documentation is really clear on what's happening under the hood, and we can also use debug logs to help with verbosity to assist with any necessary troubleshooting. I've updated the gist so that As for how the standardization is going - I think we are pretty much in the same boat as we were last year, funny enough. I haven not had to make any real major changes to the standalone provider in any fashion that seriously changes how the provider workflow works, and most of the research I've been doing for the above draft has not indicated any serious change. In fact, Boulder has kind of diverged from the ACME standard. My assessment is, being that Boulder is probably the closest thing to a reference implementation for an ACME CA, and I don't think that Let's Encrypt will be introducing any sort of changes that would ultimately break the ecosystem that now exists around the product, is following LE's implementation of ACME (and probably what Google is tracking too in |
Would |
Hey @mattes, right now a certificate renewal is actually just requesting a new certificate, which is basically how it's handled in lego (what the external plugin uses). So there's not necessarily a renewal, if you will. How this translates to Terraform is pretty simple - my plan is to preserve the Either way the plan is to make sure that the provider can handle renewals automatically - as this is crucial to a useful ACME client implementation. The more minimal API over lego just means that Terraform will have to handle a bit more of the logic, and will be a lot more granular - but that has been the plan for a while. |
Would this become part part of https://github.com/terraform-providers/terraform-provider-tls or be a provider on its own? |
Hey @Nowaker, unless something changes, this would be its own provider (the |
Seems this issue can be closed, because its related PR (#7058) has been resolved (close and agree to be standalone plugin). |
A good point, @ozbillwang. This issue represented an early proposal/discussion and there's now a concrete implementation and so this issue's usefulness is limited anyway. Furthermore, even if this provider were adopted into the set that HashiCorp distributes that would now be done in its own repository rather than in this one. Thanks for the nudge! I'm going to close this. For the moment, anyone who wants to use ACME (Let's Encrypt) with Terraform should take a look at the third-party plugin. |
I'm going to lock this issue because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active issues. If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further. |
Let's Encrypt and the ACME protocol are nearing release, so I wanted to think a little about how Terraform might interact with these.
The ACME protocol is interesting in that several of its operations require either manual operator intervention or dynamic management of other resources depending on responses from the server. For example, if the server requires DNS-based or HTTP-based domain verification, then completing that verification requires either creating a DNS record in a zone or adding a new resource to an HTTP server respectively. The verification process is also very dynamic, with the server dictating to the client which verifications are supported in which combinations.
Terraform's design isn't well-suited to that sort of thing, but I think Terraform can work with ACME in some other ways that would still be useful, as described in the following sections,
CA Account Registration
Terraform could manage registration, which is effectively creating an account with a CA.
Registration requires a private key. The
tls_private_key
resource that'll be added by #2778 can potentially be used for this, with the drawback of the key being saved in the Terraform state, or the user can generate a key in a separate file and include it viafile(...)
, thereby allowing it to be somehow securely provided to Terraform by surrounding orchestration.There is a manual step here in that the server can require the user to agree to a terms-of-service before the account is activated. This could be accommodated in Terraform by having Terraform inspect the response for a
terms-of-service
link, and if so fail with an error (printing out the TOS URL) unless a separate attributeagree_to_tos
is set. We can't force the user to actually read the TOS, but I think this complies with the spirit of the thing.Creating a certificate for an identifier that was already authorized outside of Terraform
Identifier authorization is really the tricky part of ACME since it's pretty dynamic and the server can request a variety of different combinations of different verifications that we can't know until runtime.
However, if the authorization process has already completed via some other process then Terraform can be used to actually issue certificates, since that's a much more predictable process:
This resource requires a PEM-formatted certificate request. One way to create that would be to use the
tls_cert_request
resource that will be added by #2778.The ACME protocol allows the server to process such a request asynchronously, so Terraform would need to poll the certificate URL returned from the initial request until a certificate becomes available there.
It can then produce the following attributes, to match with the
tls_self_signed_cert
resource added by #2778:cert_pem
- The certificate data in PEM format.validity_end_time
- The time until which the certificate is invalid, as an RFC3339 timestamp.Ideally this resource would support the same
early_renewal_hours
parameter I implemented fortls_self_signed_cert
so that Terraform can pre-emptively request a new certificate some time before the existing cert expires, for a graceful transition between certificates.Automating Identifier Authorization with a Provisioner
Although verification can't (easily) be completely handled by Terraform, we can have Terraform orchestrate the process by creating the verification request and then running a provisioner to complete it:
In the above example,
${self.json}
is assumed to return a compact JSON serialization of the authorization response so it can be easily passed into a tool that understands how to decode it and act on some or all of the challenges described.Separate provider or integrate into TLS?
The TLS provider proposed in #2778 is a logical-only provider. The above examples assume a new provider called "acme" that contains these new ACME-specific resources.
However, the above resources are defined such that each resource is self-contained and the provider itself takes no configuration. Thus these resources could potentially just be folded into the TLS provider, making it be a suite of resources for working with TLS resources of various kinds.
If the above resources were in the TLS provider they could instead be called
tls_registration_account
andtls_certificate
, with theserver_url
attribute changing toacme_server_url
:Since ACME is largely an implementation detail of the Let's Encrypt offering but will hopefully be implemented by many different CAs in future, I'm leaning towards folding these resources into the
tls
provider so that they are more discoverable for users who might not know the details of the underlying protocol. The docs for these resources can then talk a little about how the ACME protocol is used, and give the correctacme_server_url
value for the Let's Encrypt ACME server, which is likely to be the most common server people will use.The text was updated successfully, but these errors were encountered: