Skip to content
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

feat: add option to handle the overall request limit #2209

Merged
merged 3 commits into from
Jun 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 1 addition & 10 deletions certificate/authorization.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,10 @@ import (
"github.com/go-acme/lego/v4/log"
)

const (
// overallRequestLimit is the overall number of request per second
// limited on the "new-reg", "new-authz" and "new-cert" endpoints.
// From the documentation the limitation is 20 requests per second,
// but using 20 as value doesn't work but 18 do.
// https://letsencrypt.org/docs/rate-limits/
overallRequestLimit = 18
)

func (c *Certifier) getAuthorizations(order acme.ExtendedOrder) ([]acme.Authorization, error) {
resc, errc := make(chan acme.Authorization), make(chan domainError)

delay := time.Second / overallRequestLimit
delay := time.Second / time.Duration(c.overallRequestLimit)

for _, authzURL := range order.Authorizations {
time.Sleep(delay)
Expand Down
32 changes: 26 additions & 6 deletions certificate/certificates.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,17 @@ import (
"golang.org/x/net/idna"
)

const (
// DefaultOverallRequestLimit is the overall number of request per second
// limited on the "new-reg", "new-authz" and "new-cert" endpoints.
// From the documentation the limitation is 20 requests per second,
// but using 20 as value doesn't work but 18 do.
// https://letsencrypt.org/docs/rate-limits/
// ZeroSSL has a limit of 7.
// https://help.zerossl.com/hc/en-us/articles/17864245480093-Advantages-over-Using-Let-s-Encrypt#h_01HT4Z1JCJFJQFJ1M3P7S085Q9
DefaultOverallRequestLimit = 18
)

// maxBodySize is the maximum size of body that we will read.
const maxBodySize = 1024 * 1024

Expand Down Expand Up @@ -94,24 +105,33 @@ type resolver interface {
}

type CertifierOptions struct {
KeyType certcrypto.KeyType
Timeout time.Duration
KeyType certcrypto.KeyType
Timeout time.Duration
OverallRequestLimit int
}

// Certifier A service to obtain/renew/revoke certificates.
type Certifier struct {
core *api.Core
resolver resolver
options CertifierOptions
core *api.Core
resolver resolver
options CertifierOptions
overallRequestLimit int
}

// NewCertifier creates a Certifier.
func NewCertifier(core *api.Core, resolver resolver, options CertifierOptions) *Certifier {
return &Certifier{
c := &Certifier{
core: core,
resolver: resolver,
options: options,
}

c.overallRequestLimit = options.OverallRequestLimit
if c.overallRequestLimit <= 0 {
c.overallRequestLimit = DefaultOverallRequestLimit
}

return c
}

// Obtain tries to obtain a single certificate using all domains passed into it.
Expand Down
6 changes: 6 additions & 0 deletions cmd/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package cmd
import (
"time"

"github.com/go-acme/lego/v4/certificate"
"github.com/go-acme/lego/v4/lego"
"github.com/urfave/cli/v2"
"software.sslmate.com/src/go-pkcs12"
Expand Down Expand Up @@ -154,6 +155,11 @@ func CreateFlags(defaultPath string) []cli.Flag {
Usage: "Set the certificate timeout value to a specific value in seconds. Only used when obtaining certificates.",
Value: 30,
},
&cli.IntFlag{
Name: "overall-request-limit",
Usage: "ACME overall requests limit.",
Value: certificate.DefaultOverallRequestLimit,
},
&cli.StringFlag{
Name: "user-agent",
Usage: "Add to the user-agent sent to the CA to identify an application embedding lego-cli",
Expand Down
5 changes: 3 additions & 2 deletions cmd/setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,9 @@ func newClient(ctx *cli.Context, acc registration.User, keyType certcrypto.KeyTy
config.CADirURL = ctx.String("server")

config.Certificate = lego.CertificateConfig{
KeyType: keyType,
Timeout: time.Duration(ctx.Int("cert.timeout")) * time.Second,
KeyType: keyType,
Timeout: time.Duration(ctx.Int("cert.timeout")) * time.Second,
OverallRequestLimit: ctx.Int("overall-request-limit"),
}
config.UserAgent = getUserAgent(ctx)

Expand Down
1 change: 1 addition & 0 deletions docs/data/zz_cli_help.toml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ GLOBAL OPTIONS:
--pfx.pass value The password used to encrypt the .pfx (PCKS#12) file. (default: "changeit") [$LEGO_PFX_PASSWORD]
--pfx.format value The encoding format to use when encrypting the .pfx (PCKS#12) file. Supported: RC2, DES, SHA256. (default: "RC2") [$LEGO_PFX_FORMAT]
--cert.timeout value Set the certificate timeout value to a specific value in seconds. Only used when obtaining certificates. (default: 30)
--overall-request-limit value ACME overall requests limit. (default: 18)
--user-agent value Add to the user-agent sent to the CA to identify an application embedding lego-cli
--help, -h show help
"""
Expand Down
2 changes: 1 addition & 1 deletion lego/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ func NewClient(config *Config) (*Client, error) {
solversManager := resolver.NewSolversManager(core)

prober := resolver.NewProber(solversManager)
certifier := certificate.NewCertifier(core, prober, certificate.CertifierOptions{KeyType: config.Certificate.KeyType, Timeout: config.Certificate.Timeout})
certifier := certificate.NewCertifier(core, prober, certificate.CertifierOptions{KeyType: config.Certificate.KeyType, Timeout: config.Certificate.Timeout, OverallRequestLimit: config.Certificate.OverallRequestLimit})

return &Client{
Certificate: certifier,
Expand Down
5 changes: 3 additions & 2 deletions lego/client_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,9 @@ func NewConfig(user registration.User) *Config {
}

type CertificateConfig struct {
KeyType certcrypto.KeyType
Timeout time.Duration
KeyType certcrypto.KeyType
Timeout time.Duration
OverallRequestLimit int
}

// createDefaultHTTPClient Creates an HTTP client with a reasonable timeout value
Expand Down