Skip to content

Commit

Permalink
feat(cli): add an option to set the private key (#2431)
Browse files Browse the repository at this point in the history
  • Loading branch information
ldez authored Feb 10, 2025
1 parent a25218d commit c96a165
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 10 deletions.
10 changes: 9 additions & 1 deletion certificate/certificates.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,8 @@ type ObtainRequest struct {
type ObtainForCSRRequest struct {
CSR *x509.CertificateRequest

PrivateKey crypto.PrivateKey

NotBefore time.Time
NotAfter time.Time
Bundle bool
Expand Down Expand Up @@ -262,7 +264,13 @@ func (c *Certifier) ObtainForCSR(request ObtainForCSRRequest) (*Resource, error)
log.Infof("[%s] acme: Validations succeeded; requesting certificates", strings.Join(domains, ", "))

failures := newObtainError()
cert, err := c.getForCSR(domains, order, request.Bundle, request.CSR.Raw, nil, request.PreferredChain)

var privateKey []byte
if request.PrivateKey != nil {
privateKey = certcrypto.PEMEncode(request.PrivateKey)
}

cert, err := c.getForCSR(domains, order, request.Bundle, request.CSR.Raw, privateKey, request.PreferredChain)
if err != nil {
for _, auth := range authz {
failures.Add(challenge.GetTargetedDomain(auth), err)
Expand Down
31 changes: 22 additions & 9 deletions cmd/cmd_run.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ const (
flgMustStaple = "must-staple"
flgNotBefore = "not-before"
flgNotAfter = "not-after"
flgPrivateKey = "private-key"
flgPreferredChain = "preferred-chain"
flgProfile = "profile"
flgAlwaysDeactivateAuthorizations = "always-deactivate-authorizations"
Expand Down Expand Up @@ -64,6 +65,10 @@ func createRun() *cli.Command {
Usage: "Set the notAfter field in the certificate (RFC3339 format)",
Layout: time.RFC3339,
},
&cli.StringFlag{
Name: flgPrivateKey,
Usage: "Path to private key (in PEM encoding) for the certificate. By default, the private key is generated.",
},
&cli.StringFlag{
Name: flgPreferredChain,
Usage: "If the CA offers multiple certificate chains, prefer the chain with an issuer matching this Subject Common Name." +
Expand Down Expand Up @@ -203,21 +208,21 @@ func obtainCertificate(ctx *cli.Context, client *lego.Client) (*certificate.Reso
// obtain a certificate, generating a new private key
request := certificate.ObtainRequest{
Domains: domains,
Bundle: bundle,
MustStaple: ctx.Bool(flgMustStaple),
NotBefore: getTime(ctx, flgNotBefore),
NotAfter: getTime(ctx, flgNotAfter),
Bundle: bundle,
PreferredChain: ctx.String(flgPreferredChain),
Profile: ctx.String(flgProfile),
AlwaysDeactivateAuthorizations: ctx.Bool(flgAlwaysDeactivateAuthorizations),
}

notBefore := ctx.Timestamp(flgNotBefore)
if notBefore != nil {
request.NotBefore = *notBefore
}

notAfter := ctx.Timestamp(flgNotAfter)
if notAfter != nil {
request.NotAfter = *notAfter
if ctx.IsSet(flgPrivateKey) {
var err error
request.PrivateKey, err = loadPrivateKey(ctx.String(flgPrivateKey))
if err != nil {
return nil, fmt.Errorf("load private key: %w", err)
}
}

return client.Certificate.Obtain(request)
Expand All @@ -240,5 +245,13 @@ func obtainCertificate(ctx *cli.Context, client *lego.Client) (*certificate.Reso
AlwaysDeactivateAuthorizations: ctx.Bool(flgAlwaysDeactivateAuthorizations),
}

if ctx.IsSet(flgPrivateKey) {
var err error
request.PrivateKey, err = loadPrivateKey(ctx.String(flgPrivateKey))
if err != nil {
return nil, fmt.Errorf("load private key: %w", err)
}
}

return client.Certificate.ObtainForCSR(request)
}
1 change: 1 addition & 0 deletions docs/data/zz_cli_help.toml
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ OPTIONS:
--must-staple Include the OCSP must staple TLS extension in the CSR and generated certificate. Only works if the CSR is generated by lego. (default: false)
--not-before value Set the notBefore field in the certificate (RFC3339 format)
--not-after value Set the notAfter field in the certificate (RFC3339 format)
--private-key value Path to private key (in PEM encoding) for the certificate. By default, the private key is generated.
--preferred-chain value If the CA offers multiple certificate chains, prefer the chain with an issuer matching this Subject Common Name. If no match, the default offered chain will be used.
--profile value If the CA offers multiple certificate profiles (draft-aaron-acme-profiles), choose this one.
--always-deactivate-authorizations value Force the authorizations to be relinquished even if the certificate request was successful.
Expand Down

0 comments on commit c96a165

Please sign in to comment.