Skip to content
This repository has been archived by the owner on Sep 7, 2022. It is now read-only.

"acme cert -webroot" option #59

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
43 changes: 41 additions & 2 deletions cert.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
"net/http"
"path/filepath"
"time"
"os"

"golang.org/x/crypto/acme"
)
Expand Down Expand Up @@ -64,6 +65,8 @@ Default location of the config dir is
certManual = false
certDNS = false
certKeypath string
certWebroot string
certWebrootMode = 0600
)

func init() {
Expand All @@ -74,6 +77,8 @@ func init() {
cmdCert.flag.BoolVar(&certManual, "manual", certManual, "")
cmdCert.flag.BoolVar(&certDNS, "dns", certDNS, "")
cmdCert.flag.StringVar(&certKeypath, "k", "", "")
cmdCert.flag.StringVar(&certWebroot, "webroot", "", "write http-01 mode challenge to that webroot directory")
cmdCert.flag.IntVar(&certWebrootMode, "webroot-mode", certWebrootMode, "file mode for challenge file created in -webroot")
}

func runCert(args []string) {
Expand All @@ -83,6 +88,12 @@ func runCert(args []string) {
if certManual && certDNS {
fatalf("-dns and -manual are mutually exclusive, only one should be specified")
}
if certWebroot != "" && certDNS {
fatalf("-webroot and -dns are mutually exclusive, only one should be specified")
}
if certWebroot != "" && certManual {
fatalf("-webroot and -manual are mutually exclusive, only one should be specified")
}
cn := args[0]
if certKeypath == "" {
certKeypath = filepath.Join(configDir, cn+".key")
Expand Down Expand Up @@ -175,13 +186,25 @@ func authz(ctx context.Context, client *acme.Client, domain string) error {
defer ln.Close()

switch {
case certWebroot != "":
// directly copy to given webroot
tok, err := client.HTTP01ChallengeResponse(chal.Token)
if err != nil {
return err
}
path, err := challengeCreateWebrootFile(
client.HTTP01ChallengePath(chal.Token), tok)
if err != nil {
return err
}
defer os.Remove(path)
case certManual:
// manual challenge response
tok, err := client.HTTP01ChallengeResponse(chal.Token)
if err != nil {
return err
}
file, err := challengeFile(domain, tok)
file, err := challengeCreateTmpFile(domain, tok)
if err != nil {
return err
}
Expand Down Expand Up @@ -216,7 +239,7 @@ func authz(ctx context.Context, client *acme.Client, domain string) error {
return err
}

func challengeFile(domain, content string) (string, error) {
func challengeCreateTmpFile(domain, content string) (string, error) {
f, err := ioutil.TempFile("", domain)
if err != nil {
return "", err
Expand All @@ -228,6 +251,22 @@ func challengeFile(domain, content string) (string, error) {
return f.Name(), err
}

func challengeCreateWebrootFile(filename, content string) (string, error) {
path := filepath.Join(certWebroot, filename)
f, err := os.OpenFile(
path,
os.O_WRONLY|os.O_CREATE|os.O_TRUNC|os.O_EXCL,
os.FileMode(certWebrootMode))
if err != nil {
return "", err
}
_, err = fmt.Fprint(f, content)
if err1 := f.Close(); err1 != nil && err == nil {
err = err1
}
return path, err
}

func http01Handler(path, value string) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.URL.Path != path {
Expand Down