Skip to content

Commit

Permalink
fix/refactor(server/client): go-libp2p v0.38.1, clean-up dns01 reques…
Browse files Browse the repository at this point in the history
…t code (#23)

* refactor(client): cleanup dns01 request code

removed duplicated/unused code, added logs

* chore: go-libp2p v0.38.1

httpauth fix;
https://github.com/libp2p/go-libp2p/releases/tag/v0.38.1

* fix(test): switch test to use client.SendChallenge

---------

Co-authored-by: Adin Schmahmann <adin.schmahmann@gmail.com>
  • Loading branch information
lidel and aschmahmann authored Dec 19, 2024
1 parent 26f81c4 commit bebe2f4
Show file tree
Hide file tree
Showing 5 changed files with 122 additions and 127 deletions.
53 changes: 20 additions & 33 deletions client/acme.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,13 @@ import (
"crypto/x509"
"errors"
"fmt"
"io"
"net/http"
"strings"
"sync"
"time"

"github.com/libp2p/go-libp2p/core/network"

httppeeridauth "github.com/libp2p/go-libp2p/p2p/http/auth"
"go.uber.org/zap"

"github.com/caddyserver/certmagic"
Expand Down Expand Up @@ -280,12 +278,13 @@ func NewP2PForgeCertMgr(opts ...P2PForgeCertMgrOptions) (*P2PForgeCertMgr, error
Email: mgrCfg.userEmail,
Agreed: true,
DNS01Solver: &dns01P2PForgeSolver{
forge: mgrCfg.forgeRegistrationEndpoint,
forgeRegistrationEndpoint: mgrCfg.forgeRegistrationEndpoint,
forgeAuth: mgrCfg.forgeAuth,
hostFn: hostFn,
modifyForgeRequest: mgrCfg.modifyForgeRequest,
userAgent: mgrCfg.userAgent,
allowPrivateForgeAddresses: mgrCfg.allowPrivateForgeAddresses,
log: mgrCfg.log.Named("dns01solver"),
},
TrustedRoots: mgrCfg.trustedRoots,
Logger: certCfg.Logger,
Expand Down Expand Up @@ -468,21 +467,25 @@ func (m *P2PForgeCertMgr) createAddrsFactory(allowPrivateForgeAddrs bool) config
}

type dns01P2PForgeSolver struct {
forge string
forgeRegistrationEndpoint string
forgeAuth string
hostFn func() host.Host
modifyForgeRequest func(r *http.Request) error
userAgent string
allowPrivateForgeAddresses bool
log *zap.SugaredLogger
}

func (d *dns01P2PForgeSolver) Wait(ctx context.Context, challenge acme.Challenge) error {
d.log.Debugw("waiting for DNS-01 TXT record to be set")
// TODO: query the authoritative DNS
time.Sleep(time.Second * 5)
return nil
}

func (d *dns01P2PForgeSolver) Present(ctx context.Context, challenge acme.Challenge) error {
d.log.Debugw("getting DNS-01 challenge value from CA", "acme_challenge", challenge)
dns01value := challenge.DNS01KeyAuthorization()
h := d.hostFn()
addrs := h.Addrs()

Expand All @@ -503,38 +506,22 @@ func (d *dns01P2PForgeSolver) Present(ctx context.Context, challenge acme.Challe
} else {
advertisedAddrs = addrs
}

req, err := ChallengeRequest(ctx, d.forge, challenge.DNS01KeyAuthorization(), advertisedAddrs)
d.log.Debugw("advertised libp2p addrs for p2p-forge broker to try", "addrs", advertisedAddrs)

d.log.Debugw("asking p2p-forge broker to set DNS-01 TXT record", "url", d.forgeRegistrationEndpoint, "dns01_value", dns01value)
err := SendChallenge(ctx,
d.forgeRegistrationEndpoint,
h.Peerstore().PrivKey(h.ID()),
dns01value,
advertisedAddrs,
d.forgeAuth,
d.userAgent,
d.modifyForgeRequest,
)
if err != nil {
return err
}

// Add forge auth header if set
if d.forgeAuth != "" {
req.Header.Set(ForgeAuthHeader, d.forgeAuth)
}

// Always include User-Agent header
if d.userAgent == "" {
d.userAgent = defaultUserAgent
return fmt.Errorf("p2p-forge broker registration error: %w", err)
}
req.Header.Set("User-Agent", d.userAgent)

if d.modifyForgeRequest != nil {
if err := d.modifyForgeRequest(req); err != nil {
return err
}
}

client := &httppeeridauth.ClientPeerIDAuth{PrivKey: h.Peerstore().PrivKey(h.ID())}
_, resp, err := client.AuthenticatedDo(http.DefaultClient, req)
if err != nil {
return err
}
if resp.StatusCode != http.StatusOK {
respBody, _ := io.ReadAll(resp.Body)
return fmt.Errorf("%s : %s", resp.Status, respBody)
}
return nil
}

Expand Down
35 changes: 26 additions & 9 deletions client/challenge.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,33 +14,50 @@ import (
"github.com/multiformats/go-multiaddr"
)

// SendChallenge submits a challenge to the DNS server for the given peerID.
// SendChallenge submits value for DNS-01 challenge to the p2p-forge HTTP server for the given peerID.
// It requires the corresponding private key and a list of multiaddresses that the peerID is listening on using
// publicly reachable IP addresses.
func SendChallenge(ctx context.Context, baseURL string, privKey crypto.PrivKey, challenge string, addrs []multiaddr.Multiaddr) error {
req, err := ChallengeRequest(ctx, baseURL, challenge, addrs)
func SendChallenge(ctx context.Context, baseURL string, privKey crypto.PrivKey, challenge string, addrs []multiaddr.Multiaddr, forgeAuth string, userAgent string, modifyForgeRequest func(r *http.Request) error) error {
// Create request
registrationURL := fmt.Sprintf("%s/v1/_acme-challenge", baseURL)
req, err := ChallengeRequest(ctx, registrationURL, challenge, addrs)
if err != nil {
return err
}

// Adjust headers if needed
if forgeAuth != "" {
req.Header.Set(ForgeAuthHeader, forgeAuth)
}
if userAgent == "" {
userAgent = defaultUserAgent
}
req.Header.Set("User-Agent", userAgent)
if modifyForgeRequest != nil {
if err := modifyForgeRequest(req); err != nil {
return err
}
}

// Execute request wrapped in ClientPeerIDAuth
client := &httppeeridauth.ClientPeerIDAuth{PrivKey: privKey}
_, resp, err := client.AuthenticatedDo(http.DefaultClient, req)
if err != nil {
return err
return fmt.Errorf("libp2p HTTP ClientPeerIDAuth error at %s: %w", registrationURL, err)
}
if resp.StatusCode != http.StatusOK {
respBody, _ := io.ReadAll(resp.Body)
return fmt.Errorf("%s : %s", resp.Status, respBody)
return fmt.Errorf("%s error from %s: %q", resp.Status, registrationURL, respBody)
}
return nil
}

// ChallengeRequest creates an HTTP Request object for submitting an ACME challenge to the DNS server for a given peerID.
// ChallengeRequest creates an HTTP Request object for submitting an ACME challenge to the p2p-forge HTTP server for a given peerID.
// Construction of the request requires a list of multiaddresses that the peerID is listening on using
// publicly reachable IP addresses.
//
// Sending the request to the DNS server requires performing HTTP PeerID Authentication for the corresponding peerID
func ChallengeRequest(ctx context.Context, baseURL string, challenge string, addrs []multiaddr.Multiaddr) (*http.Request, error) {
func ChallengeRequest(ctx context.Context, registrationURL string, challenge string, addrs []multiaddr.Multiaddr) (*http.Request, error) {
maStrs := make([]string, len(addrs))
for i, addr := range addrs {
maStrs[i] = addr.String()
Expand All @@ -57,9 +74,9 @@ func ChallengeRequest(ctx context.Context, baseURL string, challenge string, add
return nil, err
}

req, err := http.NewRequestWithContext(ctx, "POST", fmt.Sprintf("%s/v1/_acme-challenge", baseURL), bytes.NewReader(body))
req, err := http.NewRequestWithContext(ctx, "POST", registrationURL, bytes.NewReader(body))
if err != nil {
return nil, err
return nil, fmt.Errorf("failed while creating a request to %s: %w", registrationURL, err)
}

return req, nil
Expand Down
19 changes: 4 additions & 15 deletions e2e_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import (
"encoding/pem"
"errors"
"fmt"
"io"
"log"
"math/big"
"net"
Expand All @@ -29,7 +28,6 @@ import (
"github.com/libp2p/go-libp2p"
"github.com/libp2p/go-libp2p/core/crypto"
"github.com/libp2p/go-libp2p/core/peer"
httppeeridauth "github.com/libp2p/go-libp2p/p2p/http/auth"
"github.com/libp2p/go-libp2p/p2p/net/swarm"
libp2pquic "github.com/libp2p/go-libp2p/p2p/transport/quic"
"github.com/libp2p/go-libp2p/p2p/transport/tcp"
Expand Down Expand Up @@ -237,22 +235,13 @@ func TestSetACMEChallenge(t *testing.T) {
testDigest := sha256.Sum256([]byte("test"))
testChallenge := base64.RawURLEncoding.EncodeToString(testDigest[:])

req, err := client.ChallengeRequest(ctx, fmt.Sprintf("http://127.0.0.1:%d", httpPort), testChallenge, h.Addrs())
err = client.SendChallenge(ctx, fmt.Sprintf("http://127.0.0.1:%d", httpPort), sk, testChallenge, h.Addrs(), authToken, "", func(req *http.Request) error {
req.Host = forgeRegistration
return nil
})
if err != nil {
t.Fatal(err)
}
req.Host = forgeRegistration
req.Header.Set(authForgeHeader, authToken)

peerHTTPClient := &httppeeridauth.ClientPeerIDAuth{PrivKey: sk}
_, resp, err := peerHTTPClient.AuthenticatedDo(http.DefaultClient, req)
if err != nil {
t.Fatal(err)
}
if resp.StatusCode != http.StatusOK {
respBody, _ := io.ReadAll(resp.Body)
t.Fatal(fmt.Errorf("%s : %s", resp.Status, respBody))
}

peerIDb36, err := peer.ToCid(h.ID()).StringOfBase(multibase.Base36)
if err != nil {
Expand Down
47 changes: 24 additions & 23 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ require (
github.com/ipfs/go-log/v2 v2.5.1
github.com/joho/godotenv v1.5.1
github.com/letsencrypt/pebble/v2 v2.6.0
github.com/libp2p/go-libp2p v0.37.2
github.com/libp2p/go-libp2p v0.38.1
github.com/mholt/acmez/v2 v2.0.3
github.com/miekg/dns v1.1.62
github.com/multiformats/go-multiaddr v0.13.0
github.com/multiformats/go-multiaddr v0.14.0
github.com/multiformats/go-multiaddr-dns v0.4.1
github.com/multiformats/go-multibase v0.2.0
github.com/prometheus/client_golang v1.20.5
Expand Down Expand Up @@ -54,7 +54,7 @@ require (
github.com/golang/snappy v0.0.4 // indirect
github.com/google/flatbuffers v1.12.1 // indirect
github.com/google/gopacket v1.1.19 // indirect
github.com/google/pprof v0.0.0-20241017200806-017d972448fc // indirect
github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/gorilla/websocket v1.5.3 // indirect
github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645 // indirect
Expand All @@ -65,7 +65,7 @@ require (
github.com/jbenet/goprocess v0.1.4 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/klauspost/compress v1.17.11 // indirect
github.com/klauspost/cpuid/v2 v2.2.8 // indirect
github.com/klauspost/cpuid/v2 v2.2.9 // indirect
github.com/koron/go-ssdp v0.0.4 // indirect
github.com/letsencrypt/challtestsrv v1.3.2 // indirect
github.com/libdns/libdns v0.2.2 // indirect
Expand All @@ -74,7 +74,7 @@ require (
github.com/libp2p/go-libp2p-asn-util v0.4.1 // indirect
github.com/libp2p/go-msgio v0.3.0 // indirect
github.com/libp2p/go-nat v0.2.0 // indirect
github.com/libp2p/go-netroute v0.2.1 // indirect
github.com/libp2p/go-netroute v0.2.2 // indirect
github.com/libp2p/go-reuseport v0.4.0 // indirect
github.com/libp2p/go-yamux/v4 v4.0.1 // indirect
github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd // indirect
Expand All @@ -92,55 +92,56 @@ require (
github.com/multiformats/go-multistream v0.6.0 // indirect
github.com/multiformats/go-varint v0.0.7 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/onsi/ginkgo/v2 v2.20.2 // indirect
github.com/onsi/ginkgo/v2 v2.22.0 // indirect
github.com/opencontainers/runtime-spec v1.2.0 // indirect
github.com/opentracing/opentracing-go v1.2.0 // indirect
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 // indirect
github.com/pion/datachannel v1.5.9 // indirect
github.com/pion/datachannel v1.5.10 // indirect
github.com/pion/dtls/v2 v2.2.12 // indirect
github.com/pion/ice/v2 v2.3.36 // indirect
github.com/pion/ice/v2 v2.3.37 // indirect
github.com/pion/interceptor v0.1.37 // indirect
github.com/pion/logging v0.2.2 // indirect
github.com/pion/mdns v0.0.12 // indirect
github.com/pion/randutil v0.1.0 // indirect
github.com/pion/rtcp v1.2.14 // indirect
github.com/pion/rtp v1.8.9 // indirect
github.com/pion/sctp v1.8.33 // indirect
github.com/pion/rtcp v1.2.15 // indirect
github.com/pion/rtp v1.8.10 // indirect
github.com/pion/sctp v1.8.35 // indirect
github.com/pion/sdp/v3 v3.0.9 // indirect
github.com/pion/srtp/v2 v2.0.20 // indirect
github.com/pion/stun v0.6.1 // indirect
github.com/pion/transport/v2 v2.2.10 // indirect
github.com/pion/transport/v3 v3.0.7 // indirect
github.com/pion/turn/v2 v2.1.6 // indirect
github.com/pion/webrtc/v3 v3.3.4 // indirect
github.com/pion/webrtc/v3 v3.3.5 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/prometheus/client_model v0.6.1 // indirect
github.com/prometheus/common v0.60.0 // indirect
github.com/prometheus/common v0.61.0 // indirect
github.com/prometheus/procfs v0.15.1 // indirect
github.com/quic-go/qpack v0.5.1 // indirect
github.com/quic-go/quic-go v0.48.2 // indirect
github.com/quic-go/webtransport-go v0.8.1-0.20241018022711-4ac2c9250e66 // indirect
github.com/raulk/go-watchdog v1.3.0 // indirect
github.com/spaolacci/murmur3 v1.1.0 // indirect
github.com/stretchr/testify v1.9.0 // indirect
github.com/stretchr/testify v1.10.0 // indirect
github.com/wlynxg/anet v0.0.5 // indirect
github.com/zeebo/blake3 v0.2.4 // indirect
go.opencensus.io v0.24.0 // indirect
go.uber.org/dig v1.18.0 // indirect
go.uber.org/fx v1.23.0 // indirect
go.uber.org/mock v0.5.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/crypto v0.28.0 // indirect
golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c // indirect
golang.org/x/mod v0.21.0 // indirect
golang.org/x/net v0.30.0 // indirect
golang.org/x/sync v0.8.0 // indirect
golang.org/x/sys v0.26.0 // indirect
golang.org/x/text v0.19.0 // indirect
golang.org/x/tools v0.26.0 // indirect
golang.org/x/crypto v0.31.0 // indirect
golang.org/x/exp v0.0.0-20241217172543-b2144cdd0a67 // indirect
golang.org/x/mod v0.22.0 // indirect
golang.org/x/net v0.32.0 // indirect
golang.org/x/sync v0.10.0 // indirect
golang.org/x/sys v0.28.0 // indirect
golang.org/x/text v0.21.0 // indirect
golang.org/x/tools v0.28.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect
google.golang.org/grpc v1.63.2 // indirect
google.golang.org/protobuf v1.35.1 // indirect
google.golang.org/protobuf v1.36.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/utils v0.0.0-20230726121419-3b25d923346b // indirect
lukechampine.com/blake3 v1.3.0 // indirect
Expand Down
Loading

0 comments on commit bebe2f4

Please sign in to comment.