certificates
certificates copied to clipboard
Add revoke API implementation to ACME API
Subject of the issue
When using the vancluever/acme Terraform provider, cert creation works fine, but revoking results in 404 error
Your environment
- OS - CentOS 7
- Version - Smallstep CA/0.15.4 (linux/amd64)
Steps to reproduce
- Set up step-ca with ACME provisioner.
- Use vancluever/acme terraform provider to create a certificate (example config below)
- Use Terraform destroy.
provider "acme" {
server_url = "https://acme.example.com/acme/acme/directory"
}
resource "acme_certificate" "certificate" {
account_key_pem = "--PEM-DATA--"
common_name = "test.example.com"
subject_alternative_names = ["test.example.com"]
}
Expected behaviour
Certificate should be revoked.
Actual behaviour
404 error on certificate revocation.
Error from Terraform:
Error: 404 ::POST :: https://acme.example.com/acme/acme/revoke-cert :: invalid character 'p' after top-level value :: 404 page not found
Error from StepCA:
Feb 09 14:36:09 centos.example.com step-ca[17512]: time="2021-02-09T14:36:09Z" level=warning duration="22.498µs" duration-ns=22498 fields.time="2021-02-09T14:36:09Z" method=POST name=ca path=/acme/acme/revoke-cert protocol=HTTP/1.1 referer= remote-address=10.20.30.40 request-id=c0h9rme5jd28fp3kbtp0 size=19 status=404 user-agent="xenolf-acme/4.1.3 (release; linux; amd64)" user-id=
Additional context
The ACME provider in Terraform uses the lego library, which is included in the compatible libraries.
Any help to turn on more debugging, or work out what is going on would be much appreciated.
Hey @rfranks-securenet thanks for opening the issue!
step-ca doesn't currently support the ACME cert revocation API. There are two reasons why we chose not to support this API in our initial implementation:
step-cadoesn't support active revocation. Currently the CA only supports passive revocation.step-cahas it's own, non ACME, API for passive revocation.
CRL and OCSP (active revocation) are on our roadmap. When we add those it will make sense to come back and implement support for ACME cert revocation as well.
So, this isn't so much a bug as a "Not Implemented" (hence the 404).
Why are you revoking a certificate (is it necessary) and would the step cli command: step ca revoke be sufficient (again, this only accomplishes passive revocation)?
It's part of the terraform workflow; as part of the destroy (which tears down all the infrastructure it has created). I'll have a look and see if there is a way of excluding the cert from the destroy.
Alternatively, would there be a way of changing it so, whilst it doesn't actually implement the revocation, it returns a 200? Even if in the body it gave a warning that the cert wasn't actually revoked? I think that would be enough to trick the provider into thinking that it has been revoked.
If we were to update that response I think it would make more sense to return HTTP Not Implemented (501), but I don't know how helpful that would be for your scenario.
If you wanted to update the code in a branch I'd be happy to point you to where a change would need to be made.
Would you consider using a HTTP 204 No Content. On the basis that the revocation is passive anyway, the server doesn't need to do anything. That would satisfy the revocation from a lego-client point of view.
Yes please, if you could point me in the right direction.
Will discuss with the team tomorrow morning and get back to you. The problem in my mind is that responding 204 would indicate success for the revocation. I wouldn't want users then building assumptions based on that "successful" response.
How are you installing step-ca? Maybe we can build a bespoke release that addresses your usecase.
I'm happy to compile manually. I can write a patch that I apply to the source code before compiling, and use that binary, if you can point me in the direction of the right place in source.
The other code you could return is a 202 - accepted. That code specifically says that it's been accepted, but will not necessarily be processed.
Hey @rfranks-securenet after discussing with the team, we're wary to return any value that could be misconstrued for success.
That said, we'd love to get the ACME revoke api hooked up to our existing revocation interface. It probably wouldn't be hard. Few hours of work (with unit tests). If anyone is interested let me know and we can do a code walkthrough.
@rfranks-securenet also happy to help you compile a local version. Here's where the API is "set" in the Handler: https://github.com/smallstep/certificates/blob/master/acme/api/handler.go#L104-L114. You'll want to add a MethodFunc for the revoke endpoint. It should be fairly similar to the existing ones. There's already a RevokeCertLinkType here: https://github.com/smallstep/certificates/blob/master/acme/api/linker.go. Then you'd add a function like:
func (h *Handler) RevokeCert(w http.ResponseWrite, r *http.Request) {
...
}
Set the proper headers that (you can see an example success response at the bottom of this section - https://datatracker.ietf.org/doc/html/rfc8555#section-7.6). And just w.Write(nil) -- see the GetCertificate method at the bottom of the handler file for example.
Just encountered the same thing, just did a terraform state rm....in this case the domain changed on 6 certs so wanted to destroy which is a revoke action.
When looking through the open issues I discovered this one wasn't closed yet, while support for ACME revocation was added in #625. @rfranks-securenet, @laingsc: pinging you to see if this is still an issue for you and to check if you tried the newest version of step-ca already.
step-ca currently supports revocation by authenticating using the private key belonging to the cert to be revoked as well as using the private key belonging to the account that requested the certificate. There's an open issue to also support using a different account private key that is also authorized for the identifier(s) (#767), but there are no concrete plans to support that now.
Hi I am very new to step-ca.
@hslatman, @rfranks-securenet , @laingsc Does ACME revocation implementation support cert revocation by authenticating using the private key belonging to the cert to be revoked as well as using the private key belonging to the account that requested the certificate?
Based on line 262 to line 269 on acme.go, it does not seem to support:
// AuthorizeRevoke is called just before the certificate is to be revoked by
// the CA. It can be used to authorize revocation of a certificate. It
// currently is a no-op.
// TODO(hs): add configuration option that toggles revocation? Or change function signature to make it more useful?
// Or move certain logic out of the Revoke API to here? Would likely involve some more stuff in the ctx.
func (p *ACME) AuthorizeRevoke(ctx context.Context, token string) error {
return nil
}
Thank you.
Hey @LeeWong,
Yes, step-ca does support revocation via ACME. You can revoke a certificate both using the certificate private key as well as the account private key that was used to request the certificate. This functionality was merged in https://github.com/smallstep/certificates/pull/625. We haven't implemented revocation using a different, but authorized, account private key yet. We're tracking this in a separate issue: https://github.com/smallstep/certificates/issues/767.
I admit the TODO is misleading. It's a leftover from developing revocation support. The method exists because AuthorizeRevoke is an interface method. For ACME the authorization is performed in the HTTP handlers instead, because it relies on more than just a "token"; it needs the full HTTP request. I've created a PR to remove the comment and slightly clarify the function doc: https://github.com/smallstep/certificates/pull/1109.
@hslatman Thank you so much for the clarification and the merge request.
I'm going to close this issue, because ACME revocation support has been in step-ca for a while. It can be reopened if issues arise. Support for ACME revocation authorization using a different, but authorized, account key is tracked in https://github.com/smallstep/certificates/issues/767.