bugfix HTTP-01 relay and update docs
This commit is contained in:
parent
adb12c43b2
commit
8c8d5b150f
|
@ -24,6 +24,7 @@ telebit-client-windows.exe
|
||||||
/cmd/wsconnect/wsconnect
|
/cmd/wsconnect/wsconnect
|
||||||
/cmd/mgmt/mgmt
|
/cmd/mgmt/mgmt
|
||||||
/cmd/signjwt/signjwt
|
/cmd/signjwt/signjwt
|
||||||
|
/signjwt
|
||||||
/cmd/telebit/telebit
|
/cmd/telebit/telebit
|
||||||
|
|
||||||
/telebit
|
/telebit
|
||||||
|
|
|
@ -161,7 +161,7 @@ go build -mod=vendor -ldflags "-s -w" -o signjwt cmd/signjwt/*.go
|
||||||
To generate an `admin` token:
|
To generate an `admin` token:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
VERDOR_ID="test-id"
|
VENDOR_ID="test-id"
|
||||||
SECRET="xxxxxxxxxxx"
|
SECRET="xxxxxxxxxxx"
|
||||||
TOKEN=$(./signjwt \
|
TOKEN=$(./signjwt \
|
||||||
--expires-in 15m \
|
--expires-in 15m \
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
# MGMT Server
|
||||||
|
|
||||||
|
# Config
|
||||||
|
|
||||||
|
```bash
|
||||||
|
VERBOSE=
|
||||||
|
|
||||||
|
PORT=6468
|
||||||
|
|
||||||
|
# JWT Verification Secret
|
||||||
|
#SECRET=XxxxxxxxxxxxxxxX
|
||||||
|
|
||||||
|
DB_URL=postgres://postgres:postgres@localhost:5432/postgres
|
||||||
|
DOMAIN=mgmt.example.com
|
||||||
|
TUNNEL_DOMAIN=tunnel.example.com
|
||||||
|
|
||||||
|
NAMECOM_USERNAME=johndoe
|
||||||
|
NAMECOM_API_TOKEN=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||||
|
```
|
||||||
|
|
||||||
|
# Build
|
||||||
|
|
||||||
|
```bash
|
||||||
|
go generate -mod vendor ./...
|
||||||
|
|
||||||
|
pushd cmd/mgmt
|
||||||
|
go build -mod vendor -o telebit-mgmt
|
||||||
|
popd
|
||||||
|
```
|
|
@ -58,6 +58,9 @@ func handleDNSRoutes(r chi.Router) {
|
||||||
r.Delete("/{domain}/{token}/{keyAuth}/{challengeType}", deleteChallenge)
|
r.Delete("/{domain}/{token}/{keyAuth}/{challengeType}", deleteChallenge)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO pick one and stick with it
|
||||||
|
r.Route("/acme-relay", handleACMEChallenges)
|
||||||
|
r.Route("/acme-solver", handleACMEChallenges)
|
||||||
r.Route("/dns", handleACMEChallenges)
|
r.Route("/dns", handleACMEChallenges)
|
||||||
r.Route("/http", handleACMEChallenges)
|
r.Route("/http", handleACMEChallenges)
|
||||||
}
|
}
|
||||||
|
|
102
cmd/mgmt/mgmt.go
102
cmd/mgmt/mgmt.go
|
@ -15,6 +15,7 @@ import (
|
||||||
"github.com/go-acme/lego/v3/challenge"
|
"github.com/go-acme/lego/v3/challenge"
|
||||||
"github.com/go-acme/lego/v3/providers/dns/duckdns"
|
"github.com/go-acme/lego/v3/providers/dns/duckdns"
|
||||||
"github.com/go-acme/lego/v3/providers/dns/godaddy"
|
"github.com/go-acme/lego/v3/providers/dns/godaddy"
|
||||||
|
"github.com/go-acme/lego/v3/providers/dns/namedotcom"
|
||||||
_ "github.com/joho/godotenv/autoload"
|
_ "github.com/joho/godotenv/autoload"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -43,51 +44,89 @@ func help() {
|
||||||
func main() {
|
func main() {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
addr := flag.String("address", "", "IPv4 or IPv6 bind address")
|
var port string
|
||||||
port := flag.String("port", "3000", "port to listen to")
|
var lnAddr string
|
||||||
challengesPort := flag.String("challenges-port", "80", "port to use to respond to .well-known/acme-challenge tokens")
|
var dbURL string
|
||||||
dbURL := flag.String(
|
var challengesPort string
|
||||||
"db-url",
|
|
||||||
"postgres://postgres:postgres@localhost/postgres",
|
flag.StringVar(&port, "port", "",
|
||||||
"database (postgres) connection url",
|
"port to listen to (default localhost 3000)")
|
||||||
)
|
flag.StringVar(&lnAddr, "listen", "",
|
||||||
flag.StringVar(&secret, "secret", "", "a >= 16-character random string for JWT key signing")
|
"IPv4 or IPv6 bind address + port (instead of --port)")
|
||||||
flag.StringVar(&primaryDomain, "domain", "", "the base domain to use for all clients")
|
flag.StringVar(&challengesPort, "challenges-port", "80",
|
||||||
flag.StringVar(&relayDomain, "tunnel-domain", "", "the domain name of the tunnel relay service, if different from base domain")
|
"port to use to respond to .well-known/acme-challenge tokens")
|
||||||
|
flag.StringVar(&dbURL, "db-url", "postgres://postgres:postgres@localhost:5432/postgres",
|
||||||
|
"database (postgres) connection url")
|
||||||
|
flag.StringVar(&secret, "secret", "",
|
||||||
|
"a >= 16-character random string for JWT key signing")
|
||||||
|
flag.StringVar(&primaryDomain, "domain", "",
|
||||||
|
"the base domain to use for all clients")
|
||||||
|
flag.StringVar(&relayDomain, "tunnel-domain", "",
|
||||||
|
"the domain name of the tunnel relay service, if different from base domain")
|
||||||
|
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
if "" == primaryDomain {
|
if 0 == len(primaryDomain) {
|
||||||
help()
|
primaryDomain = os.Getenv("DOMAIN")
|
||||||
os.Exit(1)
|
|
||||||
}
|
}
|
||||||
if "" == relayDomain {
|
|
||||||
|
if 0 == len(relayDomain) {
|
||||||
|
relayDomain = os.Getenv("TUNNEL_DOMAIN")
|
||||||
|
}
|
||||||
|
if 0 == len(relayDomain) {
|
||||||
relayDomain = primaryDomain
|
relayDomain = primaryDomain
|
||||||
}
|
}
|
||||||
|
|
||||||
if "" != os.Getenv("GODADDY_API_KEY") {
|
if 0 == len(dbURL) {
|
||||||
|
dbURL = os.Getenv("DB_URL")
|
||||||
|
}
|
||||||
|
|
||||||
|
if 0 == len(secret) {
|
||||||
|
secret = os.Getenv("SECRET")
|
||||||
|
}
|
||||||
|
|
||||||
|
// prefer --listen (with address) over --port (localhost only)
|
||||||
|
if 0 == len(lnAddr) {
|
||||||
|
lnAddr = os.Getenv("LISTEN")
|
||||||
|
}
|
||||||
|
if 0 == len(lnAddr) {
|
||||||
|
if 0 == len(port) {
|
||||||
|
port = os.Getenv("PORT")
|
||||||
|
}
|
||||||
|
if 0 == len(port) {
|
||||||
|
port = "3000"
|
||||||
|
}
|
||||||
|
lnAddr = "localhost:" + port
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(os.Getenv("GODADDY_API_KEY")) > 0 {
|
||||||
id := os.Getenv("GODADDY_API_KEY")
|
id := os.Getenv("GODADDY_API_KEY")
|
||||||
apiSecret := os.Getenv("GODADDY_API_SECRET")
|
apiSecret := os.Getenv("GODADDY_API_SECRET")
|
||||||
if provider, err = newGoDaddyDNSProvider(id, apiSecret); nil != err {
|
if provider, err = newGoDaddyDNSProvider(id, apiSecret); nil != err {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
} else if "" != os.Getenv("DUCKDNS_TOKEN") {
|
} else if len(os.Getenv("DUCKDNS_TOKEN")) > 0 {
|
||||||
if provider, err = newDuckDNSProvider(os.Getenv("DUCKDNS_TOKEN")); nil != err {
|
if provider, err = newDuckDNSProvider(os.Getenv("DUCKDNS_TOKEN")); nil != err {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
} else if len(os.Getenv("NAMECOM_API_TOKEN")) > 0 {
|
||||||
|
if provider, err = newNameDotComDNSProvider(
|
||||||
|
os.Getenv("NAMECOM_USERNAME"),
|
||||||
|
os.Getenv("NAMECOM_API_TOKEN"),
|
||||||
|
); nil != err {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
panic("Must provide either DUCKDNS or GODADDY credentials")
|
fmt.Println("DNS-01 relay disabled")
|
||||||
}
|
}
|
||||||
|
|
||||||
if "" == secret {
|
if 0 == len(primaryDomain) || 0 == len(secret) || 0 == len(dbURL) {
|
||||||
secret = os.Getenv("SECRET")
|
|
||||||
}
|
|
||||||
if "" == secret {
|
|
||||||
help()
|
help()
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
connStr := *dbURL
|
connStr := dbURL
|
||||||
// TODO url.Parse
|
// TODO url.Parse
|
||||||
if strings.Contains(connStr, "@localhost/") || strings.Contains(connStr, "@localhost:") {
|
if strings.Contains(connStr, "@localhost/") || strings.Contains(connStr, "@localhost:") {
|
||||||
connStr += "?sslmode=disable"
|
connStr += "?sslmode=disable"
|
||||||
|
@ -104,16 +143,23 @@ func main() {
|
||||||
defer store.Close()
|
defer store.Close()
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
fmt.Println("Listening for ACME challenges on :" + *challengesPort)
|
fmt.Println("Listening for ACME challenges on :" + challengesPort)
|
||||||
if err := http.ListenAndServe(":"+*challengesPort, routeStatic()); nil != err {
|
if err := http.ListenAndServe(":"+challengesPort, routeStatic()); nil != err {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
bind := *addr + ":" + *port
|
fmt.Println("Listening on", lnAddr)
|
||||||
fmt.Println("Listening on", bind)
|
fmt.Fprintf(os.Stderr, "failed: %s", http.ListenAndServe(lnAddr, routeAll()))
|
||||||
fmt.Fprintf(os.Stderr, "failed: %s", http.ListenAndServe(bind, routeAll()))
|
}
|
||||||
|
|
||||||
|
// newNameDotComDNSProvider is for the sake of demoing the tunnel
|
||||||
|
func newNameDotComDNSProvider(username, apitoken string) (*namedotcom.DNSProvider, error) {
|
||||||
|
config := namedotcom.NewDefaultConfig()
|
||||||
|
config.Username = username
|
||||||
|
config.APIToken = apitoken
|
||||||
|
return namedotcom.NewDNSProviderConfig(config)
|
||||||
}
|
}
|
||||||
|
|
||||||
// newDuckDNSProvider is for the sake of demoing the tunnel
|
// newDuckDNSProvider is for the sake of demoing the tunnel
|
||||||
|
|
|
@ -18,6 +18,7 @@ import (
|
||||||
"github.com/go-chi/chi/middleware"
|
"github.com/go-chi/chi/middleware"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// MgmtClaims includes a Slug, for backwards compatibility
|
||||||
type MgmtClaims struct {
|
type MgmtClaims struct {
|
||||||
Slug string `json:"slug"`
|
Slug string `json:"slug"`
|
||||||
jwt.StandardClaims
|
jwt.StandardClaims
|
||||||
|
@ -197,7 +198,7 @@ func routeAll() chi.Router {
|
||||||
http.Error(w, msg, http.StatusNotFound)
|
http.Error(w, msg, http.StatusNotFound)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if "" != original.MachinePPID {
|
if len(original.MachinePPID) > 0 {
|
||||||
msg := `{"error":"the presented key has already been used", "code":"E_EXIST"}`
|
msg := `{"error":"the presented key has already been used", "code":"E_EXIST"}`
|
||||||
log.Printf("/api/register-device/\n")
|
log.Printf("/api/register-device/\n")
|
||||||
log.Println(err)
|
log.Println(err)
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"time"
|
||||||
|
|
||||||
telebit "git.rootprojects.org/root/telebit"
|
telebit "git.rootprojects.org/root/telebit"
|
||||||
"git.rootprojects.org/root/telebit/dbg"
|
"git.rootprojects.org/root/telebit/dbg"
|
||||||
|
@ -30,6 +31,7 @@ var durAbbrs = map[byte]bool{
|
||||||
func main() {
|
func main() {
|
||||||
var secret, clientSecret, relaySecret string
|
var secret, clientSecret, relaySecret string
|
||||||
|
|
||||||
|
debug := flag.Bool("debug", true, "show more debug output")
|
||||||
machinePPID := flag.String("machine-ppid", "", "spoof the machine ppid")
|
machinePPID := flag.String("machine-ppid", "", "spoof the machine ppid")
|
||||||
machineID := flag.String("machine-id", "", "spoof the raw machine id")
|
machineID := flag.String("machine-id", "", "spoof the raw machine id")
|
||||||
vendorID := flag.String("vendor-id", "", "a unique identifier for a deploy target environment")
|
vendorID := flag.String("vendor-id", "", "a unique identifier for a deploy target environment")
|
||||||
|
@ -39,6 +41,10 @@ func main() {
|
||||||
flag.StringVar(&secret, "secret", "", "either the remote server or the tunnel relay secret (used for JWT authentication)")
|
flag.StringVar(&secret, "secret", "", "either the remote server or the tunnel relay secret (used for JWT authentication)")
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
|
if *debug {
|
||||||
|
dbg.Debug = *debug
|
||||||
|
}
|
||||||
|
|
||||||
if 0 == len(*authURL) {
|
if 0 == len(*authURL) {
|
||||||
*authURL = os.Getenv("AUTH_URL")
|
*authURL = os.Getenv("AUTH_URL")
|
||||||
}
|
}
|
||||||
|
@ -145,7 +151,7 @@ func main() {
|
||||||
fmt.Fprintf(os.Stderr, "[debug] pub = %s\n", pub)
|
fmt.Fprintf(os.Stderr, "[debug] pub = %s\n", pub)
|
||||||
}
|
}
|
||||||
|
|
||||||
tok, err := authstore.HMACToken(ppid, expNum)
|
tok, err := authstore.HMACToken(ppid, 15*time.Minute, expNum)
|
||||||
if nil != err {
|
if nil != err {
|
||||||
fmt.Fprintf(os.Stderr, "signing error: %s\n", err)
|
fmt.Fprintf(os.Stderr, "signing error: %s\n", err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
|
|
|
@ -66,6 +66,14 @@ func InitAdmin(authURL string) {
|
||||||
|
|
||||||
// Proxy mgmt server ACME DNS 01 Challenges
|
// Proxy mgmt server ACME DNS 01 Challenges
|
||||||
r.Get("/api/dns/*", proxyHandleFunc)
|
r.Get("/api/dns/*", proxyHandleFunc)
|
||||||
|
r.Post("/api/dns/*", proxyHandleFunc)
|
||||||
|
r.Delete("/api/dns/*", proxyHandleFunc)
|
||||||
|
r.Get("/api/http/*", proxyHandleFunc)
|
||||||
|
r.Post("/api/http/*", proxyHandleFunc)
|
||||||
|
r.Delete("/api/http/*", proxyHandleFunc)
|
||||||
|
r.Get("/api/acme-relay/*", proxyHandleFunc)
|
||||||
|
r.Post("/api/acme-relay/*", proxyHandleFunc)
|
||||||
|
r.Delete("/api/acme-relay/*", proxyHandleFunc)
|
||||||
|
|
||||||
r.Route("/api", func(r chi.Router) {
|
r.Route("/api", func(r chi.Router) {
|
||||||
// TODO token needs a globally unique subject
|
// TODO token needs a globally unique subject
|
||||||
|
|
|
@ -18,9 +18,9 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
telebit "git.rootprojects.org/root/telebit"
|
"git.rootprojects.org/root/telebit"
|
||||||
"git.rootprojects.org/root/telebit/dbg"
|
"git.rootprojects.org/root/telebit/dbg"
|
||||||
tbDns01 "git.rootprojects.org/root/telebit/internal/dns01"
|
"git.rootprojects.org/root/telebit/internal/dns01"
|
||||||
"git.rootprojects.org/root/telebit/internal/http01"
|
"git.rootprojects.org/root/telebit/internal/http01"
|
||||||
"git.rootprojects.org/root/telebit/internal/service"
|
"git.rootprojects.org/root/telebit/internal/service"
|
||||||
"git.rootprojects.org/root/telebit/iplist"
|
"git.rootprojects.org/root/telebit/iplist"
|
||||||
|
@ -28,7 +28,7 @@ import (
|
||||||
"git.rootprojects.org/root/telebit/mgmt/authstore"
|
"git.rootprojects.org/root/telebit/mgmt/authstore"
|
||||||
"git.rootprojects.org/root/telebit/table"
|
"git.rootprojects.org/root/telebit/table"
|
||||||
"git.rootprojects.org/root/telebit/tunnel"
|
"git.rootprojects.org/root/telebit/tunnel"
|
||||||
legoDns01 "github.com/go-acme/lego/v3/challenge/dns01"
|
legoDNS01 "github.com/go-acme/lego/v3/challenge/dns01"
|
||||||
|
|
||||||
"github.com/coolaj86/certmagic"
|
"github.com/coolaj86/certmagic"
|
||||||
"github.com/denisbrodbeck/machineid"
|
"github.com/denisbrodbeck/machineid"
|
||||||
|
@ -36,6 +36,7 @@ import (
|
||||||
"github.com/go-acme/lego/v3/challenge"
|
"github.com/go-acme/lego/v3/challenge"
|
||||||
"github.com/go-acme/lego/v3/providers/dns/duckdns"
|
"github.com/go-acme/lego/v3/providers/dns/duckdns"
|
||||||
"github.com/go-acme/lego/v3/providers/dns/godaddy"
|
"github.com/go-acme/lego/v3/providers/dns/godaddy"
|
||||||
|
"github.com/go-acme/lego/v3/providers/dns/namedotcom"
|
||||||
"github.com/joho/godotenv"
|
"github.com/joho/godotenv"
|
||||||
_ "github.com/joho/godotenv/autoload"
|
_ "github.com/joho/godotenv/autoload"
|
||||||
)
|
)
|
||||||
|
@ -112,6 +113,7 @@ func main() {
|
||||||
var portForwards []Forward
|
var portForwards []Forward
|
||||||
var resolvers []string
|
var resolvers []string
|
||||||
|
|
||||||
|
debug := flag.Bool("debug", true, "show debug output")
|
||||||
spfDomain := flag.String("spf-domain", "", "domain with SPF-like list of IP addresses which are allowed to connect to clients")
|
spfDomain := flag.String("spf-domain", "", "domain with SPF-like list of IP addresses which are allowed to connect to clients")
|
||||||
// TODO replace the websocket connection with a mock server
|
// TODO replace the websocket connection with a mock server
|
||||||
vendorID := flag.String("vendor-id", "", "a unique identifier for a deploy target environment")
|
vendorID := flag.String("vendor-id", "", "a unique identifier for a deploy target environment")
|
||||||
|
@ -133,7 +135,7 @@ func main() {
|
||||||
apiHostname := flag.String("api-hostname", "", "the hostname used to manage clients")
|
apiHostname := flag.String("api-hostname", "", "the hostname used to manage clients")
|
||||||
secret := flag.String("secret", "", "the same secret used by telebit-relay (used for JWT authentication)")
|
secret := flag.String("secret", "", "the same secret used by telebit-relay (used for JWT authentication)")
|
||||||
token := flag.String("token", "", "an auth token for the server (instead of generating --secret); use --token=false to ignore any $TOKEN in env")
|
token := flag.String("token", "", "an auth token for the server (instead of generating --secret); use --token=false to ignore any $TOKEN in env")
|
||||||
_ = flag.String("leeway", "", "(reserved for future use) allow for time drift / skew (hard-coded to 15 minutes)")
|
leeway := flag.Duration("leeway", 15*time.Minute, "allow for time drift / skew (hard-coded to 15 minutes)")
|
||||||
bindAddrsStr := flag.String("listen", "", "list of bind addresses on which to listen, such as localhost:80, or :443")
|
bindAddrsStr := flag.String("listen", "", "list of bind addresses on which to listen, such as localhost:80, or :443")
|
||||||
tlsLocals := flag.String("tls-locals", "", "like --locals, but TLS will be used to connect to the local port")
|
tlsLocals := flag.String("tls-locals", "", "like --locals, but TLS will be used to connect to the local port")
|
||||||
locals := flag.String("locals", "", "a list of <from-domain>:<to-port>")
|
locals := flag.String("locals", "", "a list of <from-domain>:<to-port>")
|
||||||
|
@ -142,7 +144,7 @@ func main() {
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
if !dbg.Debug {
|
if !dbg.Debug {
|
||||||
dbg.Debug = *verbose
|
dbg.Debug = *verbose || *debug
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(*envpath) > 0 {
|
if len(*envpath) > 0 {
|
||||||
|
@ -253,7 +255,7 @@ func main() {
|
||||||
for _, resolver := range strings.Fields(strings.ReplaceAll(*resolverList, ",", " ")) {
|
for _, resolver := range strings.Fields(strings.ReplaceAll(*resolverList, ",", " ")) {
|
||||||
resolvers = append(resolvers, resolver)
|
resolvers = append(resolvers, resolver)
|
||||||
}
|
}
|
||||||
legoDns01.AddRecursiveNameservers(resolvers)
|
legoDNS01.AddRecursiveNameservers(resolvers)
|
||||||
}
|
}
|
||||||
|
|
||||||
if 0 == len(*portToPorts) {
|
if 0 == len(*portToPorts) {
|
||||||
|
@ -325,7 +327,7 @@ func main() {
|
||||||
*token = ""
|
*token = ""
|
||||||
}
|
}
|
||||||
if 0 == len(*token) {
|
if 0 == len(*token) {
|
||||||
*token, err = authstore.HMACToken(ppid)
|
*token, err = authstore.HMACToken(ppid, *leeway)
|
||||||
if dbg.Debug {
|
if dbg.Debug {
|
||||||
fmt.Printf("[debug] app_id: %q\n", VendorID)
|
fmt.Printf("[debug] app_id: %q\n", VendorID)
|
||||||
//fmt.Printf("[debug] client_secret: %q\n", ClientSecret)
|
//fmt.Printf("[debug] client_secret: %q\n", ClientSecret)
|
||||||
|
@ -384,19 +386,18 @@ func main() {
|
||||||
authorizer = NewAuthorizer(*authURL)
|
authorizer = NewAuthorizer(*authURL)
|
||||||
|
|
||||||
dns01Base := directory.DNS01Proxy.URL
|
dns01Base := directory.DNS01Proxy.URL
|
||||||
if "" == *acmeRelay {
|
if 0 == len(*acmeRelay) {
|
||||||
*acmeRelay = dns01Base
|
*acmeRelay = dns01Base
|
||||||
} else {
|
} else {
|
||||||
fmt.Println("Suggested ACME DNS 01 Proxy URL:", dns01Base)
|
fmt.Println("Suggested ACME DNS 01 Proxy URL:", dns01Base)
|
||||||
fmt.Println("--acme-relay-url ACME DNS 01 Proxy URL:", *acmeRelay)
|
fmt.Println("--acme-relay-url ACME DNS 01 Proxy URL:", *acmeRelay)
|
||||||
}
|
}
|
||||||
if "" == *acmeRelay {
|
if 0 == len(*acmeHTTP01Relay) {
|
||||||
fmt.Fprintf(os.Stderr, "Discovered Directory Endpoints: %+v\n", directory)
|
*acmeHTTP01Relay = directory.HTTP01Proxy.URL
|
||||||
fmt.Fprintf(os.Stderr, "No ACME DNS 01 Proxy URL detected, nor supplied\n")
|
} else {
|
||||||
os.Exit(exitBadConfig)
|
fmt.Println("Suggested ACME HTTP 01 Proxy URL:", dns01Base)
|
||||||
return
|
fmt.Println("--acme-http-01-relay-url ACME DNS 01 Proxy URL:", *acmeRelay)
|
||||||
}
|
}
|
||||||
fmt.Println("DNS 01 URL", *acmeRelay)
|
|
||||||
|
|
||||||
grants, err = telebit.Inspect(*authURL, *token)
|
grants, err = telebit.Inspect(*authURL, *token)
|
||||||
if nil != err {
|
if nil != err {
|
||||||
|
@ -429,7 +430,19 @@ func main() {
|
||||||
}
|
}
|
||||||
authorizer = NewAuthorizer(*authURL)
|
authorizer = NewAuthorizer(*authURL)
|
||||||
|
|
||||||
var dns01Solver *tbDns01.Solver
|
fmt.Printf("Email: %q\n", *email)
|
||||||
|
|
||||||
|
acme := &telebit.ACME{
|
||||||
|
Email: *email,
|
||||||
|
StoragePath: *certpath,
|
||||||
|
Agree: *acmeAgree,
|
||||||
|
Directory: *acmeDirectory,
|
||||||
|
EnableTLSALPNChallenge: *enableTLSALPN01,
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
// Blog about the stupidity of this typing
|
||||||
|
// var dns01Solver *dns01.Solver = nil
|
||||||
if len(*acmeRelay) > 0 {
|
if len(*acmeRelay) > 0 {
|
||||||
provider, err := getACMEProvider(acmeRelay, token)
|
provider, err := getACMEProvider(acmeRelay, token)
|
||||||
if nil != err {
|
if nil != err {
|
||||||
|
@ -439,33 +452,8 @@ func main() {
|
||||||
os.Exit(exitBadArguments)
|
os.Exit(exitBadArguments)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
dns01Solver = tbDns01.NewSolver(provider)
|
|
||||||
}
|
|
||||||
|
|
||||||
var http01Solver *http01.Solver
|
|
||||||
if len(*acmeHTTP01Relay) > 0 {
|
|
||||||
endpoint, err := url.Parse(*acmeHTTP01Relay)
|
|
||||||
if nil != err {
|
|
||||||
fmt.Fprintf(os.Stderr, "%s\n", err)
|
|
||||||
os.Exit(exitBadArguments)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
http01Solver, err = http01.NewSolver(&http01.Config{
|
|
||||||
Endpoint: endpoint,
|
|
||||||
Token: *token,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Printf("Email: %q\n", *email)
|
|
||||||
|
|
||||||
acme := &telebit.ACME{
|
|
||||||
Email: *email,
|
|
||||||
StoragePath: *certpath,
|
|
||||||
Agree: *acmeAgree,
|
|
||||||
Directory: *acmeDirectory,
|
|
||||||
DNS01Solver: dns01Solver,
|
|
||||||
/*
|
/*
|
||||||
options: legoDns01.WrapPreCheck(func(domain, fqdn, value string, orig legoDns01.PreCheckFunc) (bool, error) {
|
options: legoDNS01.WrapPreCheck(func(domain, fqdn, value string, orig legoDNS01.PreCheckFunc) (bool, error) {
|
||||||
ok, err := orig(fqdn, value)
|
ok, err := orig(fqdn, value)
|
||||||
if ok && dnsPropagationDelay > 0 {
|
if ok && dnsPropagationDelay > 0 {
|
||||||
fmt.Printf("[Telebit-ACME-DNS] sleeping an additional %s\n", dnsPropagationDelay)
|
fmt.Printf("[Telebit-ACME-DNS] sleeping an additional %s\n", dnsPropagationDelay)
|
||||||
|
@ -474,10 +462,35 @@ func main() {
|
||||||
return ok, err
|
return ok, err
|
||||||
}),
|
}),
|
||||||
*/
|
*/
|
||||||
HTTP01Solver: http01Solver,
|
//DNSChallengeOption: legoDNS01.DNSProviderOption,
|
||||||
//DNSChallengeOption: legoDns01.DNSProviderOption,
|
acme.DNS01Solver = dns01.NewSolver(provider)
|
||||||
EnableHTTPChallenge: *enableHTTP01,
|
fmt.Println("Using DNS-01 solver for ACME Challenges")
|
||||||
EnableTLSALPNChallenge: *enableTLSALPN01,
|
}
|
||||||
|
|
||||||
|
if *enableHTTP01 {
|
||||||
|
acme.EnableHTTPChallenge = true
|
||||||
|
}
|
||||||
|
if len(*acmeHTTP01Relay) > 0 {
|
||||||
|
acme.EnableHTTPChallenge = true
|
||||||
|
endpoint, err := url.Parse(*acmeHTTP01Relay)
|
||||||
|
if nil != err {
|
||||||
|
fmt.Fprintf(os.Stderr, "%s\n", err)
|
||||||
|
os.Exit(exitBadArguments)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
http01Solver, err := http01.NewSolver(&http01.Config{
|
||||||
|
Endpoint: endpoint,
|
||||||
|
Token: *token,
|
||||||
|
})
|
||||||
|
|
||||||
|
acme.HTTP01Solver = http01Solver
|
||||||
|
fmt.Println("Using HTTP-01 solver for ACME Challenges")
|
||||||
|
}
|
||||||
|
|
||||||
|
if nil == acme.HTTP01Solver && nil == acme.DNS01Solver {
|
||||||
|
fmt.Fprintf(os.Stderr, "Neither ACME HTTP 01 nor DNS 01 proxy URL detected, nor supplied\n")
|
||||||
|
os.Exit(1)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
mux := muxAll(portForwards, forwards, acme, apiHostname, authURL, grants)
|
mux := muxAll(portForwards, forwards, acme, apiHostname, authURL, grants)
|
||||||
|
@ -533,7 +546,7 @@ func main() {
|
||||||
time.Sleep(10 * time.Minute)
|
time.Sleep(10 * time.Minute)
|
||||||
if "" != ClientSecret {
|
if "" != ClientSecret {
|
||||||
// re-create token unless no secret was supplied
|
// re-create token unless no secret was supplied
|
||||||
*token, err = authstore.HMACToken(ppid)
|
*token, err = authstore.HMACToken(ppid, *leeway)
|
||||||
}
|
}
|
||||||
err = mgmt.Ping(*authURL, *token)
|
err = mgmt.Ping(*authURL, *token)
|
||||||
if nil != err {
|
if nil != err {
|
||||||
|
@ -831,6 +844,13 @@ func getACMEProvider(acmeRelay, token *string) (challenge.Provider, error) {
|
||||||
if provider, err = newGoDaddyDNSProvider(id, apiSecret); nil != err {
|
if provider, err = newGoDaddyDNSProvider(id, apiSecret); nil != err {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
} else if "" != os.Getenv("NAMECOM_API_TOKEN") {
|
||||||
|
if provider, err = newNameDotComDNSProvider(
|
||||||
|
os.Getenv("NAMECOM_USERNAME"),
|
||||||
|
os.Getenv("NAMECOM_API_TOKEN"),
|
||||||
|
); nil != err {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
} else if "" != os.Getenv("DUCKDNS_TOKEN") {
|
} else if "" != os.Getenv("DUCKDNS_TOKEN") {
|
||||||
if provider, err = newDuckDNSProvider(os.Getenv("DUCKDNS_TOKEN")); nil != err {
|
if provider, err = newDuckDNSProvider(os.Getenv("DUCKDNS_TOKEN")); nil != err {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -857,6 +877,14 @@ func getACMEProvider(acmeRelay, token *string) (challenge.Provider, error) {
|
||||||
return provider, nil
|
return provider, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// newNameDotComDNSProvider is for the sake of demoing the tunnel
|
||||||
|
func newNameDotComDNSProvider(username, apitoken string) (*namedotcom.DNSProvider, error) {
|
||||||
|
config := namedotcom.NewDefaultConfig()
|
||||||
|
config.Username = username
|
||||||
|
config.APIToken = apitoken
|
||||||
|
return namedotcom.NewDNSProviderConfig(config)
|
||||||
|
}
|
||||||
|
|
||||||
// newDuckDNSProvider is for the sake of demoing the tunnel
|
// newDuckDNSProvider is for the sake of demoing the tunnel
|
||||||
func newDuckDNSProvider(token string) (*duckdns.DNSProvider, error) {
|
func newDuckDNSProvider(token string) (*duckdns.DNSProvider, error) {
|
||||||
config := duckdns.NewDefaultConfig()
|
config := duckdns.NewDefaultConfig()
|
||||||
|
@ -873,15 +901,15 @@ func newGoDaddyDNSProvider(id, secret string) (*godaddy.DNSProvider, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// newAPIDNSProvider is for the sake of demoing the tunnel
|
// newAPIDNSProvider is for the sake of demoing the tunnel
|
||||||
func newAPIDNSProvider(baseURL string, token string) (*tbDns01.DNSProvider, error) {
|
func newAPIDNSProvider(baseURL string, token string) (*dns01.DNSProvider, error) {
|
||||||
config := tbDns01.NewDefaultConfig()
|
config := dns01.NewDefaultConfig()
|
||||||
config.Token = token
|
config.Token = token
|
||||||
endpoint, err := url.Parse(baseURL)
|
endpoint, err := url.Parse(baseURL)
|
||||||
if nil != err {
|
if nil != err {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
config.Endpoint = endpoint
|
config.Endpoint = endpoint
|
||||||
return tbDns01.NewDNSProviderConfig(config)
|
return dns01.NewDNSProviderConfig(config)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -1,7 +1,31 @@
|
||||||
CLIENT_SUBJECT=newbie
|
# TUNNEL_RELAY_URL
|
||||||
|
# The URL of the Telebit Relay, of course.
|
||||||
|
# Note that many client configuration details can be preassigned at
|
||||||
|
# https://devices.example.com/.well-known/telebit.app/index.json
|
||||||
TUNNEL_RELAY_URL=https://devices.example.com/
|
TUNNEL_RELAY_URL=https://devices.example.com/
|
||||||
|
|
||||||
|
# VENDOR_ID
|
||||||
|
# Used to distinguish between different white-labeled Telebit binaries.
|
||||||
|
# It's just as well to generate a random ID for your organization.
|
||||||
|
VENDOR_ID=
|
||||||
|
|
||||||
|
# Used for Let's Encrypt registration
|
||||||
|
# ACME_AGREE
|
||||||
|
ACME_AGREE=true
|
||||||
|
# ACME_EMAIL
|
||||||
|
ACME_EMAIL=johndoe@example.com
|
||||||
|
|
||||||
|
# CLIENT_SUBJECT (optional)
|
||||||
|
# NOT used by Telebit.
|
||||||
|
# This is for the Device Management & Authentication server.
|
||||||
|
CLIENT_SUBJECT=newbie
|
||||||
CLIENT_SECRET=xxxxxxxxxxxxxxxx
|
CLIENT_SECRET=xxxxxxxxxxxxxxxx
|
||||||
LOCALS=https:$CLIENT_SUBJECT.devices.example.com:3000,https:*.$CLIENT_SUBJECT.devices.example.com:3000
|
LOCALS=https:$CLIENT_SUBJECT.devices.example.com:3000,https:*.$CLIENT_SUBJECT.devices.example.com:3000
|
||||||
#ACME_HTTP_01_RELAY_URL=http://localhost:4200/api/http
|
#ACME_HTTP_01_RELAY_URL=http://localhost:4200/api/http
|
||||||
#PORT_FORWARDS=3443:3001,8443:3002
|
#PORT_FORWARDS=3443:3001,8443:3002
|
||||||
#DUCKDNS_TOKEN=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
#DUCKDNS_TOKEN=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
||||||
|
|
||||||
|
# AUTH_URL
|
||||||
|
# The client may receive this as `.authn.url`
|
||||||
|
# through `https://$API_DOMAIN/.well-known/telebit.app/index.json`
|
||||||
|
# Setting the ENV AUTH_URL or the flag --auth-url overrides the discovery endpoint
|
||||||
|
|
|
@ -1,8 +1,32 @@
|
||||||
# For bash tests
|
# DOMAIN
|
||||||
MGMT_SECRET=xxxxxxxxxxxxxxxx
|
# This is the base domain from which all devices
|
||||||
MGMT_URL=https://devices.example.com
|
# will be given a subdomain (ex: foobar.devices.example.com).
|
||||||
|
DOMAIN=devices.example.com
|
||||||
|
|
||||||
|
# TUNNEL_DOMAIN
|
||||||
|
# This is the domain that will be used for the wss:// connection URL.
|
||||||
|
TUNNEL_DOMAIN=new.telebit.cloud
|
||||||
|
|
||||||
# For mgmt server itself
|
# For mgmt server itself
|
||||||
|
#SECRET=XxxxxxxxxxxxxxxX
|
||||||
|
DB_URL=postgres://postgres:postgres@localhost:5432/postgres
|
||||||
|
|
||||||
|
# PORT
|
||||||
|
# the localhost port on which to listen
|
||||||
|
PORT=6468
|
||||||
|
|
||||||
|
# LISTEN
|
||||||
|
# alternative to PORT, including address
|
||||||
|
#LISTEN=localhost:6468
|
||||||
|
|
||||||
DUCKDNS_TOKEN=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
|
DUCKDNS_TOKEN=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
|
||||||
GODADDY_API_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
|
||||||
GODADDY_API_SECRET=XXXXXXXXXXXXXXXXXXXXXX
|
#NAMECOM_USERNAME=johndoe
|
||||||
|
#NAMECOM_API_TOKEN=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||||
|
|
||||||
|
#GODADDY_API_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||||
|
#GODADDY_API_SECRET=XXXXXXXXXXXXXXXXXXXXXX
|
||||||
|
|
||||||
|
# For bash tests
|
||||||
|
MGMT_SECRET=XxxxxxxxxxxxxxxX
|
||||||
|
MGMT_URL=https://devices.example.com
|
||||||
|
|
|
@ -1,21 +1,46 @@
|
||||||
# For Tunnel Relay Service
|
# For Tunnel Relay Service
|
||||||
|
|
||||||
|
# SECRET
|
||||||
|
# This should be the same as the MGMT server secret
|
||||||
|
# It is used for JWT token creation and verification
|
||||||
|
SECRET=xxxxxxxxxxxxxxxx
|
||||||
|
|
||||||
|
# VERBOSE=true
|
||||||
|
# This will cause more verbose logs
|
||||||
VERBOSE=true
|
VERBOSE=true
|
||||||
|
|
||||||
|
# API_HOSTNAME
|
||||||
|
# This is the domain name that should be captured for the API
|
||||||
|
# (as opposed to being routed downstream)
|
||||||
|
# If this is not set, the relay will not be active.
|
||||||
API_HOSTNAME=devices.example.com
|
API_HOSTNAME=devices.example.com
|
||||||
|
|
||||||
|
# LISTEN
|
||||||
|
# This is the addr:port combo to which telebit should bind and listen.
|
||||||
|
# Note: a tunnel client can itself still be a relay through the tunnel.
|
||||||
LISTEN=":443"
|
LISTEN=":443"
|
||||||
|
|
||||||
# To proxy incoming requests for 'https://mgmt.devices.example.com' to localhost:3010
|
# LOCALS
|
||||||
LOCALS=https:mgmt.devices.example.com:3010
|
# Act as a reverse proxy for matching incoming requests
|
||||||
|
# LOCALS=<source-proto>:<source-name>:<destination-port>
|
||||||
|
# Example: 'https://mgmt.devices.example.com' to localhost:6468
|
||||||
|
LOCALS=https:mgmt.devices.example.com:6468
|
||||||
|
|
||||||
# For Device Management & Authorization Server
|
# AUTH_URL
|
||||||
AUTH_URL=http://localhost:4200/api
|
# Telebit is narrowly scoped to handle network connections
|
||||||
|
# The concerns of Device Management & Authorization should
|
||||||
|
# be handled per each specific use case.
|
||||||
|
AUTH_URL=http://localhost:6468/api
|
||||||
|
|
||||||
# For Let's Encrypt ACME registration
|
# For Let's Encrypt ACME registration of the API_HOSTNAME
|
||||||
|
# and LOCALS (reverse-proxied traffic).
|
||||||
|
# This is NOT for the remote telebit clients!
|
||||||
ACME_AGREE=true
|
ACME_AGREE=true
|
||||||
ACME_EMAIL=jon.doe@example.com
|
ACME_EMAIL=jon.doe@example.com
|
||||||
|
ACME_RELAY_URL=http://localhost:6468/api/acme-relay
|
||||||
# For Let's Encrypt ACME Challenges (pick one)
|
# (pick ONLY ONE DNS-01 provider)
|
||||||
ACME_RELAY_URL=http://localhost:4200/api/dns
|
DUCKDNS_TOKEN=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
|
||||||
SECRET=xxxxxxxxxxxxxxxx
|
#NAMECOM_USERNAME=johndoe
|
||||||
#DUCKDNS_TOKEN=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
|
#NAMECOM_API_TOKEN=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||||
#GODADDY_API_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
#GODADDY_API_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||||
#GODADDY_API_SECRET=XXXXXXXXXXXXXXXXXXXXXX
|
#GODADDY_API_SECRET=XXXXXXXXXXXXXXXXXXXXXX
|
||||||
|
|
1
go.sum
1
go.sum
|
@ -239,6 +239,7 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJ
|
||||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||||
|
github.com/namedotcom/go v0.0.0-20180403034216-08470befbe04 h1:o6uBwrhM5C8Ll3MAAxrQxRHEu7FkapwTuI2WmL1rw4g=
|
||||||
github.com/namedotcom/go v0.0.0-20180403034216-08470befbe04/go.mod h1:5sN+Lt1CaY4wsPvgQH/jsuJi4XO2ssZbdsIizr4CVC8=
|
github.com/namedotcom/go v0.0.0-20180403034216-08470befbe04/go.mod h1:5sN+Lt1CaY4wsPvgQH/jsuJi4XO2ssZbdsIizr4CVC8=
|
||||||
github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uYLpLIr5fm8diHn0JbqRycJi6w0Ms=
|
github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uYLpLIr5fm8diHn0JbqRycJi6w0Ms=
|
||||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
|
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
|
||||||
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"path"
|
"path"
|
||||||
|
@ -202,11 +203,13 @@ type Solver struct {
|
||||||
|
|
||||||
// Present creates a DNS-01 Challenge Token
|
// Present creates a DNS-01 Challenge Token
|
||||||
func (s *Solver) Present(ctx context.Context, ch acme.Challenge) error {
|
func (s *Solver) Present(ctx context.Context, ch acme.Challenge) error {
|
||||||
|
log.Println("Present DNS-01 challenge solution for", ch.Identifier.Value)
|
||||||
return s.provider.Present(ch.Identifier.Value, ch.Token, ch.KeyAuthorization)
|
return s.provider.Present(ch.Identifier.Value, ch.Token, ch.KeyAuthorization)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CleanUp deletes a DNS-01 Challenge Token
|
// CleanUp deletes a DNS-01 Challenge Token
|
||||||
func (s *Solver) CleanUp(ctx context.Context, ch acme.Challenge) error {
|
func (s *Solver) CleanUp(ctx context.Context, ch acme.Challenge) error {
|
||||||
|
log.Println("CleanUp DNS-01 challenge solution for", ch.Identifier.Value)
|
||||||
c := make(chan error)
|
c := make(chan error)
|
||||||
go func() {
|
go func() {
|
||||||
c <- s.provider.CleanUp(ch.Identifier.Value, ch.Token, ch.KeyAuthorization)
|
c <- s.provider.CleanUp(ch.Identifier.Value, ch.Token, ch.KeyAuthorization)
|
||||||
|
@ -222,6 +225,7 @@ func (s *Solver) CleanUp(ctx context.Context, ch acme.Challenge) error {
|
||||||
// Wait blocks until the TXT record created in Present() appears in
|
// Wait blocks until the TXT record created in Present() appears in
|
||||||
// authoritative lookups, i.e. until it has propagated, or until
|
// authoritative lookups, i.e. until it has propagated, or until
|
||||||
// timeout, whichever is first.
|
// timeout, whichever is first.
|
||||||
func (s *Solver) Wait(ctx context.Context, challenge acme.Challenge) error {
|
func (s *Solver) Wait(ctx context.Context, ch acme.Challenge) error {
|
||||||
return s.dnsChecker.Wait(ctx, challenge)
|
log.Println("Wait on DNS-01 challenge self-verification for", ch.Identifier.Value)
|
||||||
|
return s.dnsChecker.Wait(ctx, ch)
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"path"
|
"path"
|
||||||
|
@ -60,8 +61,9 @@ func NewSolver(config *Config) (*Solver, error) {
|
||||||
return &Solver{config: config}, nil
|
return &Solver{config: config}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Present creates a DNS-01 Challenge Token
|
// Present creates a HTTP-01 Challenge Token
|
||||||
func (s *Solver) Present(ctx context.Context, ch acme.Challenge) error {
|
func (s *Solver) Present(ctx context.Context, ch acme.Challenge) error {
|
||||||
|
log.Println("Present HTTP-01 challenge solution for", ch.Identifier.Value)
|
||||||
msg := &Challenge{
|
msg := &Challenge{
|
||||||
Type: "http-01",
|
Type: "http-01",
|
||||||
Token: ch.Token,
|
Token: ch.Token,
|
||||||
|
@ -81,6 +83,7 @@ func (s *Solver) Present(ctx context.Context, ch acme.Challenge) error {
|
||||||
|
|
||||||
// CleanUp deletes an HTTP-01 Challenge Token
|
// CleanUp deletes an HTTP-01 Challenge Token
|
||||||
func (s *Solver) CleanUp(ctx context.Context, ch acme.Challenge) error {
|
func (s *Solver) CleanUp(ctx context.Context, ch acme.Challenge) error {
|
||||||
|
log.Println("CleanUp HTTP-01 challenge solution for", ch.Identifier.Value)
|
||||||
msg := &Challenge{
|
msg := &Challenge{
|
||||||
Type: "http-01",
|
Type: "http-01",
|
||||||
Token: ch.Token,
|
Token: ch.Token,
|
||||||
|
|
|
@ -52,7 +52,7 @@ func ToPublicKeyString(secret string) string {
|
||||||
return pub
|
return pub
|
||||||
}
|
}
|
||||||
|
|
||||||
func HMACToken(secret string, maybeExp ...int) (token string, err error) {
|
func HMACToken(secret string, leeway time.Duration, maybeExp ...int) (token string, err error) {
|
||||||
keyID := ToPublicKeyString(secret)
|
keyID := ToPublicKeyString(secret)
|
||||||
if dbg.Debug {
|
if dbg.Debug {
|
||||||
fmt.Fprintf(os.Stderr, "[debug] keyID=%s\n", keyID)
|
fmt.Fprintf(os.Stderr, "[debug] keyID=%s\n", keyID)
|
||||||
|
@ -67,7 +67,6 @@ func HMACToken(secret string, maybeExp ...int) (token string, err error) {
|
||||||
|
|
||||||
b := make([]byte, 16)
|
b := make([]byte, 16)
|
||||||
_, _ = rand.Read(b)
|
_, _ = rand.Read(b)
|
||||||
leeway := 15 * time.Minute
|
|
||||||
claims := &jwt.StandardClaims{
|
claims := &jwt.StandardClaims{
|
||||||
Id: base64.RawURLEncoding.EncodeToString(b),
|
Id: base64.RawURLEncoding.EncodeToString(b),
|
||||||
Subject: "", // TODO
|
Subject: "", // TODO
|
||||||
|
|
|
@ -443,7 +443,7 @@ func NewCertMagic(acme *ACME) (*certmagic.Config, error) {
|
||||||
})
|
})
|
||||||
// yes, a circular reference, passing `magic` to its own Issuer
|
// yes, a circular reference, passing `magic` to its own Issuer
|
||||||
fmt.Printf("ACME Email: %q\n", acme.Email)
|
fmt.Printf("ACME Email: %q\n", acme.Email)
|
||||||
magic.Issuer = certmagic.NewACMEManager(magic, certmagic.ACMEManager{
|
manager := certmagic.ACMEManager{
|
||||||
DNS01Solver: acme.DNS01Solver,
|
DNS01Solver: acme.DNS01Solver,
|
||||||
HTTP01Solver: acme.HTTP01Solver,
|
HTTP01Solver: acme.HTTP01Solver,
|
||||||
CA: acme.Directory,
|
CA: acme.Directory,
|
||||||
|
@ -452,7 +452,9 @@ func NewCertMagic(acme *ACME) (*certmagic.Config, error) {
|
||||||
DisableHTTPChallenge: !acme.EnableHTTPChallenge,
|
DisableHTTPChallenge: !acme.EnableHTTPChallenge,
|
||||||
DisableTLSALPNChallenge: !acme.EnableTLSALPNChallenge,
|
DisableTLSALPNChallenge: !acme.EnableTLSALPNChallenge,
|
||||||
// plus any other customizations you need
|
// plus any other customizations you need
|
||||||
})
|
}
|
||||||
|
|
||||||
|
magic.Issuer = certmagic.NewACMEManager(magic, manager)
|
||||||
return magic, nil
|
return magic, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -82,7 +82,9 @@ func Discover(relay string) (*Endpoints, error) {
|
||||||
if len(directives.ChallengeProxy.Pathname) > 0 {
|
if len(directives.ChallengeProxy.Pathname) > 0 {
|
||||||
directives.ChallengeProxy.URL = endpointToURLString(directives.APIHost, directives.ChallengeProxy)
|
directives.ChallengeProxy.URL = endpointToURLString(directives.APIHost, directives.ChallengeProxy)
|
||||||
}
|
}
|
||||||
directives.DNS01Proxy.URL = endpointToURLString(directives.APIHost, directives.DNS01Proxy)
|
if len(directives.DNS01Proxy.Pathname) > 0 {
|
||||||
|
directives.DNS01Proxy.URL = endpointToURLString(directives.APIHost, directives.DNS01Proxy)
|
||||||
|
}
|
||||||
if len(directives.HTTP01Proxy.Pathname) > 0 {
|
if len(directives.HTTP01Proxy.Pathname) > 0 {
|
||||||
directives.HTTP01Proxy.URL = endpointToURLString(directives.APIHost, directives.HTTP01Proxy)
|
directives.HTTP01Proxy.URL = endpointToURLString(directives.APIHost, directives.HTTP01Proxy)
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,7 @@ github.com/go-acme/lego/v3/platform/tester
|
||||||
github.com/go-acme/lego/v3/platform/wait
|
github.com/go-acme/lego/v3/platform/wait
|
||||||
github.com/go-acme/lego/v3/providers/dns/duckdns
|
github.com/go-acme/lego/v3/providers/dns/duckdns
|
||||||
github.com/go-acme/lego/v3/providers/dns/godaddy
|
github.com/go-acme/lego/v3/providers/dns/godaddy
|
||||||
|
github.com/go-acme/lego/v3/providers/dns/namedotcom
|
||||||
# github.com/go-chi/chi v4.1.1+incompatible
|
# github.com/go-chi/chi v4.1.1+incompatible
|
||||||
## explicit
|
## explicit
|
||||||
github.com/go-chi/chi
|
github.com/go-chi/chi
|
||||||
|
@ -116,8 +117,12 @@ github.com/mholt/acmez
|
||||||
github.com/mholt/acmez/acme
|
github.com/mholt/acmez/acme
|
||||||
# github.com/miekg/dns v1.1.30
|
# github.com/miekg/dns v1.1.30
|
||||||
github.com/miekg/dns
|
github.com/miekg/dns
|
||||||
|
# github.com/namedotcom/go v0.0.0-20180403034216-08470befbe04
|
||||||
|
github.com/namedotcom/go/namecom
|
||||||
# github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e
|
# github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e
|
||||||
## explicit
|
## explicit
|
||||||
|
# github.com/pkg/errors v0.9.1
|
||||||
|
github.com/pkg/errors
|
||||||
# github.com/pmezard/go-difflib v1.0.0
|
# github.com/pmezard/go-difflib v1.0.0
|
||||||
github.com/pmezard/go-difflib/difflib
|
github.com/pmezard/go-difflib/difflib
|
||||||
# github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749
|
# github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749
|
||||||
|
|
Loading…
Reference in New Issue