From b3035b16b57477e94ade923e8a5aa25c7538843e Mon Sep 17 00:00:00 2001 From: xenolf Date: Sun, 27 Sep 2015 14:51:44 +0200 Subject: [PATCH] Support for cert revocation --- acme/client.go | 21 +++++++++++++++++++++ acme/messages.go | 5 +++++ cli_handlers.go | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 60 insertions(+) diff --git a/acme/client.go b/acme/client.go index d2ae18db..b5f34f8c 100644 --- a/acme/client.go +++ b/acme/client.go @@ -158,6 +158,27 @@ func (c *Client) ObtainCertificates(domains []string) ([]CertificateResource, er return c.requestCertificates(challenges) } +func (c *Client) RevokeCertificate(certificate []byte) error { + encodedCert := base64.URLEncoding.EncodeToString(certificate) + + jsonBytes, err := json.Marshal(revokeCertMessage{Resource: "revoke-cert", Certificate: encodedCert}) + if err != nil { + return err + } + + resp, err := c.jws.post(c.directory.RevokeCertURL, jsonBytes) + if err != nil { + return err + } + + if resp.StatusCode != 200 { + body, _ := ioutil.ReadAll(resp.Body) + return fmt.Errorf("The server returned an error while trying to revoke the certificate.\n%s", body) + } + + return nil +} + // Looks through the challenge combinations to find a solvable match. // Then solves the challenges in series and returns. func (c *Client) solveChallenges(challenges []*authorizationResource) error { diff --git a/acme/messages.go b/acme/messages.go index fdfadc4b..c5c345c7 100644 --- a/acme/messages.go +++ b/acme/messages.go @@ -75,6 +75,11 @@ type csrMessage struct { Authorizations []string `json:"authorizations"` } +type revokeCertMessage struct { + Resource string `json:"resource"` + Certificate string `json:"certificate"` +} + // CertificateResource represents a CA issued certificate. // PrivateKey and Certificate are both already PEM encoded // and can be directly written to disk. diff --git a/cli_handlers.go b/cli_handlers.go index 438c14f0..cb8d5004 100644 --- a/cli_handlers.go +++ b/cli_handlers.go @@ -113,3 +113,37 @@ func run(c *cli.Context) { } } + +func revoke(c *cli.Context) { + err := checkFolder(c.GlobalString("path")) + if err != nil { + logger().Fatalf("Cound not check/create path: %v", err) + } + + conf := NewConfiguration(c) + if !c.GlobalIsSet("email") { + logger().Fatal("You have to pass an account (email address) to the program using --email or -m") + } + + acc := NewAccount(c.GlobalString("email"), conf) + client := acme.NewClient(c.GlobalString("server"), acc, conf.RsaBits(), conf.OptPort()) + + err = checkFolder(conf.CertPath()) + if err != nil { + logger().Fatalf("Cound not check/create path: %v", err) + } + + for _, domain := range c.GlobalStringSlice("domains") { + logger().Printf("Trying to revoke certificate for domain %s", domain) + + certPath := path.Join(conf.CertPath(), domain+".crt") + certBytes, err := ioutil.ReadFile(certPath) + + err = client.RevokeCertificate(certBytes) + if err != nil { + logger().Printf("Error while revoking the certificate for domain %s\n\t%v", domain, err) + } else { + logger().Print("Certificate was revoked.") + } + } +}