chore: move provider "manual" into a dedicated package (#2739)

This commit is contained in:
Ludovic Fernandez 2025-12-01 20:51:43 +01:00 committed by GitHub
commit ea97ce2f62
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 149 additions and 43 deletions

View file

@ -0,0 +1,13 @@
package manual
import (
"github.com/go-acme/lego/v4/challenge/dns01"
)
// DNSProvider is an implementation of the ChallengeProvider interface.
type DNSProvider = dns01.DNSProviderManual
// NewDNSProvider returns a DNSProvider instance.
func NewDNSProvider() (*DNSProvider, error) {
return &DNSProvider{}, nil
}

View file

@ -0,0 +1,69 @@
Name = "Manual"
Description = '''Solving the DNS-01 challenge using CLI prompt.'''
Code = "manual"
Since = "v0.3.0"
Example = '''
lego --email you@example.com --dns manual -d '*.example.com' -d example.com run
'''
Additional = '''
## Example
To start using the CLI prompt "provider", start lego with `--dns manual`:
```console
$ lego --email "you@example.com" --domains="example.com" --dns "manual" run
```
What follows are a few log print-outs, interspersed with some prompts, asking for you to do perform some actions:
```txt
No key found for account you@example.com. Generating a P256 key.
Saved key to ./.lego/accounts/acme-v02.api.letsencrypt.org/you@example.com/keys/you@example.com.key
Please review the TOS at https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf
Do you accept the TOS? Y/n
```
If you accept the linked Terms of Service, hit `Enter`.
```txt
[INFO] acme: Registering account for you@example.com
!!!! HEADS UP !!!!
Your account credentials have been saved in your Let's Encrypt
configuration directory at "./.lego/accounts".
You should make a secure backup of this folder now. This
configuration directory will also contain certificates and
private keys obtained from Let's Encrypt so making regular
backups of this folder is ideal.
[INFO] [example.com] acme: Obtaining bundled SAN certificate
[INFO] [example.com] AuthURL: https://acme-v02.api.letsencrypt.org/acme/authz-v3/2345678901
[INFO] [example.com] acme: Could not find solver for: tls-alpn-01
[INFO] [example.com] acme: Could not find solver for: http-01
[INFO] [example.com] acme: use dns-01 solver
[INFO] [example.com] acme: Preparing to solve DNS-01
lego: Please create the following TXT record in your example.com. zone:
_acme-challenge.example.com. 120 IN TXT "hX0dPkG6Gfs9hUvBAchQclkyyoEKbShbpvJ9mY5q2JQ"
lego: Press 'Enter' when you are done
```
Do as instructed, and create the TXT records, and hit `Enter`.
```txt
[INFO] [example.com] acme: Trying to solve DNS-01
[INFO] [example.com] acme: Checking DNS record propagation using [192.168.8.1:53]
[INFO] Wait for propagation [timeout: 1m0s, interval: 2s]
[INFO] [example.com] acme: Waiting for DNS record propagation.
[INFO] [example.com] The server validated our request
[INFO] [example.com] acme: Cleaning DNS-01 challenge
lego: You can now remove this TXT record from your example.com. zone:
_acme-challenge.example.com. 120 IN TXT "hX0dPkG6Gfs9hUvBAchQclkyyoEKbShbpvJ9mY5q2JQ"
[INFO] [example.com] acme: Validations succeeded; requesting certificates
[INFO] [example.com] Server responded with a certificate.
```
As mentioned, you can now remove the TXT record again.
'''

View file

@ -0,0 +1,61 @@
package manual
import (
"io"
"os"
"testing"
"github.com/stretchr/testify/require"
)
func TestDNSProviderManual(t *testing.T) {
backupStdin := os.Stdin
defer func() { os.Stdin = backupStdin }()
testCases := []struct {
desc string
input string
expectError bool
}{
{
desc: "Press enter",
input: "ok\n",
},
{
desc: "Missing enter",
input: "ok",
expectError: true,
},
}
for _, test := range testCases {
t.Run(test.desc, func(t *testing.T) {
file, err := os.CreateTemp(t.TempDir(), "lego_test")
require.NoError(t, err)
t.Cleanup(func() { _ = file.Close() })
_, err = file.WriteString(test.input)
require.NoError(t, err)
_, err = file.Seek(0, io.SeekStart)
require.NoError(t, err)
os.Stdin = file
manualProvider, err := NewDNSProvider()
require.NoError(t, err)
err = manualProvider.Present("example.com", "", "")
if test.expectError {
require.Error(t, err)
} else {
require.NoError(t, err)
err = manualProvider.CleanUp("example.com", "", "")
require.NoError(t, err)
}
})
}
}

View file

@ -6,7 +6,6 @@ import (
"fmt"
"github.com/go-acme/lego/v4/challenge"
"github.com/go-acme/lego/v4/challenge/dns01"
"github.com/go-acme/lego/v4/providers/dns/acmedns"
"github.com/go-acme/lego/v4/providers/dns/active24"
"github.com/go-acme/lego/v4/providers/dns/alidns"
@ -104,6 +103,7 @@ import (
"github.com/go-acme/lego/v4/providers/dns/luadns"
"github.com/go-acme/lego/v4/providers/dns/mailinabox"
"github.com/go-acme/lego/v4/providers/dns/manageengine"
"github.com/go-acme/lego/v4/providers/dns/manual"
"github.com/go-acme/lego/v4/providers/dns/metaname"
"github.com/go-acme/lego/v4/providers/dns/metaregistrar"
"github.com/go-acme/lego/v4/providers/dns/mijnhost"
@ -181,8 +181,6 @@ import (
// NewDNSChallengeProviderByName Factory for DNS providers.
func NewDNSChallengeProviderByName(name string) (challenge.Provider, error) {
switch name {
case "manual":
return dns01.NewDNSProviderManual()
case "acme-dns", "acmedns":
return acmedns.NewDNSProvider()
case "active24":
@ -377,6 +375,8 @@ func NewDNSChallengeProviderByName(name string) (challenge.Provider, error) {
return mailinabox.NewDNSProvider()
case "manageengine":
return manageengine.NewDNSProvider()
case "manual":
return manual.NewDNSProvider()
case "metaname":
return metaname.NewDNSProvider()
case "metaregistrar":