telebit/cmd/dnsclient/dnsclient.go

111 lines
2.8 KiB
Go

//go:generate go run -mod=vendor git.rootprojects.org/root/go-gitver
package main
import (
"errors"
"flag"
"fmt"
"net/url"
"os"
"strings"
dns01 "git.rootprojects.org/root/telebit/dns01"
jwt "github.com/dgrijalva/jwt-go"
"github.com/go-acme/lego/v3/challenge"
_ "github.com/joho/godotenv/autoload"
)
var (
// GitRev refers to the abbreviated commit hash
GitRev = "0000000"
// GitVersion refers to the most recent tag, plus any commits made since then
GitVersion = "v0.0.0-pre0+0000000"
// GitTimestamp refers to the timestamp of the most recent commit
GitTimestamp = "0000-00-00T00:00:00+0000"
)
func main() {
var err error
var provider challenge.Provider = nil
var domains []string
// TODO replace the websocket connection with a mock server
acmeRelay := flag.String("acme-relay-url", "", "the base url of the ACME DNS-01 relay, if not the same as the tunnel relay")
secret := flag.String("secret", "", "the same secret used by telebit-relay (used for JWT authentication)")
token := flag.String("token", "", "a pre-generated token to give the server (instead of generating one with --secret)")
flag.Parse()
if len(os.Args) >= 2 {
if "version" == os.Args[1] {
fmt.Printf("telebit %s %s %s", GitVersion, GitRev, GitTimestamp)
os.Exit(0)
}
}
if "" == *token {
if "" == *secret {
*secret = os.Getenv("SECRET")
}
*token, err = getToken(*secret, domains)
}
if nil != err {
fmt.Fprintf(os.Stderr, "neither secret nor token provided")
os.Exit(1)
return
}
if "" == *acmeRelay {
panic(errors.New("ACME relay should be specified"))
}
endpoint := *acmeRelay
if !strings.HasSuffix(endpoint, "/") {
endpoint += "/"
}
/*
if strings.HasSuffix(endpoint, "/") {
endpoint = endpoint[:len(endpoint)-1]
}
endpoint += "/api/dns/"
*/
if provider, err = newAPIDNSProvider(endpoint, *token); nil != err {
panic(err)
}
err = provider.Present(os.Getenv("HOSTNAME"), "xxx", "yyy")
if nil != err {
fmt.Fprintf(os.Stderr, err.Error())
}
err = provider.Present(os.Getenv("HOSTNAME"), "xxx", "yyy")
if nil != err {
fmt.Fprintf(os.Stderr, err.Error())
os.Exit(1)
}
fmt.Println("quite possibly successful")
}
// newAPIDNSProvider is for the sake of demoing the tunnel
func newAPIDNSProvider(baseURL string, token string) (*dns01.DNSProvider, error) {
config := dns01.NewDefaultConfig()
config.Token = token
endpoint, err := url.Parse(baseURL)
if nil != err {
return nil, err
}
config.Endpoint = endpoint
return dns01.NewDNSProviderConfig(config)
}
func getToken(secret string, domains []string) (token string, err error) {
tokenData := jwt.MapClaims{"domains": domains}
jwtToken := jwt.NewWithClaims(jwt.SigningMethodHS256, tokenData)
if token, err = jwtToken.SignedString([]byte(secret)); err != nil {
return "", err
}
return token, nil
}