Skip to content

Add revoke API implementation to ACME API #468

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

Closed
rfranks-securenet opened this issue Feb 9, 2021 · 13 comments
Closed

Add revoke API implementation to ACME API #468

rfranks-securenet opened this issue Feb 9, 2021 · 13 comments

Comments

@rfranks-securenet
Copy link

rfranks-securenet commented Feb 9, 2021

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

  1. Set up step-ca with ACME provisioner.
  2. Use vancluever/acme terraform provider to create a certificate (example config below)
  3. 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.

@rfranks-securenet rfranks-securenet added bug needs triage Waiting for discussion / prioritization by team labels Feb 9, 2021
@dopey dopey added enhancement area/acme ACME and removed bug needs triage Waiting for discussion / prioritization by team labels Feb 10, 2021
@dopey
Copy link
Contributor

dopey commented Feb 10, 2021

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:

  1. step-ca doesn't support active revocation. Currently the CA only supports passive revocation.
  2. step-ca has 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)?

@rfranks-securenet
Copy link
Author

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.

@dopey
Copy link
Contributor

dopey commented Apr 26, 2021

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.

@rfranks-securenet
Copy link
Author

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.

@dopey dopey added the needs triage Waiting for discussion / prioritization by team label May 10, 2021
@dopey
Copy link
Contributor

dopey commented May 10, 2021

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.

@rfranks-securenet
Copy link
Author

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.

@dopey
Copy link
Contributor

dopey commented May 11, 2021

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.

@dopey dopey removed the needs triage Waiting for discussion / prioritization by team label May 18, 2021
@dopey dopey changed the title lego based client unable to revoke certificate Add revoke API implementation to ACME API May 18, 2021
@laingsc
Copy link

laingsc commented Oct 3, 2021

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.

@hslatman
Copy link
Member

hslatman commented Jun 1, 2022

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.

@LeeWong
Copy link

LeeWong commented Oct 14, 2022

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.

@hslatman
Copy link
Member

hslatman commented Oct 17, 2022

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 #625. We haven't implemented revocation using a different, but authorized, account private key yet. We're tracking this in a separate issue: #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: #1109.

@LeeWong
Copy link

LeeWong commented Oct 17, 2022

@hslatman Thank you so much for the clarification and the merge request.

@hslatman
Copy link
Member

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 #767.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants