// The Let's Encrypt state directory format keeps certificates but not their // URLs. Since boulder uses the serial number to form the URL, we can // reconstruct the URL. But since not even the provider association is stored, // we have to guess. func determineLECertificateURL(certFilename string) (string, error) { b, err := ioutil.ReadFile(certFilename) if err != nil { return "", err } certs, err := acmeutils.LoadCertificates(b) if err != nil { return "", err } if len(certs) == 0 { return "", fmt.Errorf("no certs") } c, err := x509.ParseCertificate(certs[0]) if err != nil { return "", err } // Don't need directory URL, direct certificate URL load only. cl := acmeapi.Client{} _, certURL, err := acmeendpoints.CertificateToEndpointURL(&cl, c, context.TODO()) if err != nil { return "", err } return certURL, nil }
func TestOCSP(t *testing.T) { b, err := acmeutils.LoadCertificates([]byte(testOCSPCerts)) if err != nil { t.Fatalf("cannot load certificates") } c0, err := x509.ParseCertificate(b[0]) if err != nil { t.Fatalf("cannot parse certificate") } c1, err := x509.ParseCertificate(b[1]) if err != nil { t.Fatalf("cannot parse certificate") } cl := Client{} res, err := cl.CheckOCSP(c0, c1, context.TODO()) if err != nil { t.Fatalf("ocsp error: %v", err) } if res.Status != ocsp.Revoked { t.Fatalf("ocsp status should be revoked (1) but is %v", res.Status) } }
func (s *fdbStore) validateCert(certID string, c *fdb.Collection) error { ss, err := fdb.String(c.Open("url")) if err != nil { return err } ss = strings.TrimSpace(ss) if !acmeapi.ValidURL(ss) { return fmt.Errorf("certificate has invalid URI") } actualCertID := determineCertificateID(ss) if certID != actualCertID { return fmt.Errorf("cert ID mismatch: %#v != %#v", certID, actualCertID) } crt := &Certificate{ URL: ss, Certificates: nil, Cached: false, RevocationDesired: fdb.Exists(c, "revoke"), Revoked: fdb.Exists(c, "revoked"), } fullchain, err := fdb.Bytes(c.Open("fullchain")) if err == nil { certs, err := acmeutils.LoadCertificates(fullchain) if err != nil { return err } xcrt, err := x509.ParseCertificate(certs[0]) if err != nil { return err } keyID := determineKeyIDFromCert(xcrt) crt.Key = s.keys[keyID] if crt.Key != nil { err := c.WriteLink("privkey", fdb.Link{Target: "keys/" + keyID + "/privkey"}) if err != nil { return err } } crt.Certificates = certs crt.Cached = true } s.certs[certID] = crt return nil }
func TestURL(t *testing.T) { _, err := ByDirectoryURL("https://unknown/directory") if err != ErrNotFound { t.Fail() } for _, tc := range urlTestCases { e, err := ByDirectoryURL(tc.Endpoint.DirectoryURL) if err != nil { t.Fatalf("cannot get by directory URL") } if e != tc.Endpoint { t.Fatalf("got wrong endpoint: %v != %v", e, tc.Endpoint) } certs, err := acmeutils.LoadCertificates([]byte(tc.Cert)) if err != nil { t.Fatalf("cannot load test certificate") } c0, err := x509.ParseCertificate(certs[0]) if err != nil { t.Fatalf("cannot parse certificate") } cl := acmeapi.Client{} e, certURL, err := CertificateToEndpointURL(&cl, c0, context.TODO()) if err != nil { t.Fatalf("cannot map certificate to endpoint") } e2, err := CertificateToEndpoint(&cl, c0, context.TODO()) if e2 != e { t.Fatalf("mismatch") } if e != tc.Endpoint { t.Fatalf("certificate mapped to wrong endpoint: %v != %v", e, tc.Endpoint) } dURL, err := CertificateURLToDirectoryURL(certURL) if err != nil { t.Fatalf("cannot map certificate URL to directory URL: %v", err) } if dURL != e.DirectoryURL { t.Fatalf("directory URL mismatch: %v != %v", dURL, e.DirectoryURL) } } }