caddyserver / certmagic

Automatic HTTPS for any Go program: fully-managed TLS certificate issuance and renewal
https://pkg.go.dev/github.com/caddyserver/certmagic?tab=doc
Apache License 2.0
4.89k stars 278 forks source link

Using Certmagic with pebble #257

Closed RonniSkansing closed 8 months ago

RonniSkansing commented 8 months ago

What version of the package are you using?

v.0.19.2

What are you trying to do?

Trying to run Certmagic with Pebble as a development setup.

What steps did you take?

I retrieved the root certificate from the pebble server and added in to the default trustedRoots. Then created a default instance and tried to retrieve a certificate for example.com.

package main

import (
    "context"
    "crypto/tls"
    "crypto/x509"
    "encoding/pem"
    "io"
    "log"
    "net/http"

    "github.com/caddyserver/certmagic"
)

const DEV_ACME_URL = "https://localhost:14000/dir"
const DEV_ACME_URL_ROOT_CERT = "https://localhost:15000/roots/0"

func main() {
    // get the root cert from pebble
    client := &http.Client{
        Transport: &http.Transport{
            TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
        },
    }
    res, err := client.Get(DEV_ACME_URL_ROOT_CERT)
    if err != nil {
        log.Fatal(err)
    }
    acmeRootCertPemBlock, err := io.ReadAll(res.Body)
    if err != nil {
        log.Fatal(err)
    }
    certDERBlock, _ := pem.Decode(acmeRootCertPemBlock)
    if certDERBlock == nil {
        log.Fatal("Failed to parse the certificate PEM.")
    }
    acmeRootCert, err := x509.ParseCertificate(certDERBlock.Bytes)
    if err != nil {
        log.Fatal(err)
    }
        // add cert to trusted roots
    pool := x509.NewCertPool()
    pool.AddCert(acmeRootCert)
    certmagic.DefaultACME = certmagic.ACMEIssuer{
        CA:           DEV_ACME_URL,
        TestCA:       DEV_ACME_URL,
        Email:        "dev@localhost.tld",
        Agreed:       true,
        TrustedRoots: pool,
    }

        // test setup
    magic := certmagic.NewDefault()
    magic.ManageSync(context.TODO(), []string{"example.com"}
}

docker-compose for pebble part

 pebble:
  image: letsencrypt/pebble
  command: pebble -config /test/my-pebble-config.json
  ports:
    - 14000:14000  # ACME port
    - 15000:15000  # Management port
  environment:
    - PEBBLE_VA_NOSLEEP=1
  volumes:
    - ./acme/pebble-config.json:/test/my-pebble-config.json

What did you expect to happen, and what actually happened instead?

I expected the client to be able to communicate with Pebble server. However it fails due to the certificate being signed by a unknown authority.

Error:

1.6995322571964943e+09  info    obtain  acquiring lock  {"identifier": "example.com"}
1.6995322572084048e+09  info    obtain  lock acquired   {"identifier": "example.com"}
1.6995322572085469e+09  info    obtain  obtaining certificate   {"identifier": "example.com"}
1.6995322572112968e+09  warn    acme_client HTTP request failed; retrying   {"url": "https://localhost:14000/dir", "error": "performing request: Get \"https://localhost:14000/dir\": tls: failed to verify certificate: x509: certificate signed by unknown authority"}
1.6995322574669735e+09  warn    acme_client HTTP request failed; retrying   {"url": "https://localhost:14000/dir", "error": "performing request: Get \"https://localhost:14000/dir\": tls: failed to verify certificate: x509: certificate signed by unknown authority"}
1.6995322577227457e+09  warn    acme_client HTTP request failed; retrying   {"url": "https://localhost:14000/dir", "error": "performing request: Get \"https://localhost:14000/dir\": tls: failed to verify certificate: x509: certificate signed by unknown authority"}
1.6995322577228525e+09  error   obtain  could not get certificate from issuer   {"identifier": "example.com", "issuer": "localhost:14000-dir", "error": "registering account [mailto:dev@localhost.tld] with server: provisioning client: performing request: Get \"https://localhost:14000/dir\": tls: failed to verify certificate: x509: certificate signed by unknown authority"}
1.6995322577228823e+09  info    obtain  releasing lock  {"identifier": "example.com"}

Please link to any related issues, pull requests, and/or discussion

This issues describes exactly the same issue. It suggests to add the certificate to the trusted stores, however it did not work for me.

https://github.com/caddyserver/certmagic/issues/191

RonniSkansing commented 8 months ago

I was using the wrong certificate.

The certificate in pebble is the pebble.minica.pem and they keys are available at https://github.com/letsencrypt/pebble/blob/main/test/certs/