add token auth
This commit is contained in:
parent
10a9ed8e3a
commit
1f22f5f34f
|
@ -5,6 +5,7 @@ acme.d
|
||||||
xversion.go
|
xversion.go
|
||||||
|
|
||||||
/mplexer/cmd/mgmt/mgmt
|
/mplexer/cmd/mgmt/mgmt
|
||||||
|
/mplexer/cmd/signjwt/signjwt
|
||||||
/mplexer/cmd/telebit/telebit
|
/mplexer/cmd/telebit/telebit
|
||||||
/telebit
|
/telebit
|
||||||
/cmd/telebit/telebit
|
/cmd/telebit/telebit
|
||||||
|
|
|
@ -3,13 +3,16 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
jwt "github.com/dgrijalva/jwt-go"
|
||||||
"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"
|
||||||
|
@ -27,6 +30,8 @@ var (
|
||||||
GitTimestamp = "0000-00-00T00:00:00+0000"
|
GitTimestamp = "0000-00-00T00:00:00+0000"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type MWKey string
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
var err error
|
var err error
|
||||||
var provider challenge.Provider = nil // TODO is this concurrency-safe?
|
var provider challenge.Provider = nil // TODO is this concurrency-safe?
|
||||||
|
@ -35,12 +40,13 @@ func main() {
|
||||||
|
|
||||||
addr := flag.String("address", "", "IPv4 or IPv6 bind address")
|
addr := flag.String("address", "", "IPv4 or IPv6 bind address")
|
||||||
port := flag.String("port", "3000", "port to listen to")
|
port := flag.String("port", "3000", "port to listen to")
|
||||||
|
secret := flag.String("secret", "", "a >= 16-character random string for JWT key signing") // SECRET
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
if "" != os.Getenv("GODADDY_API_KEY") {
|
if "" != os.Getenv("GODADDY_API_KEY") {
|
||||||
id := os.Getenv("GODADDY_API_KEY")
|
id := os.Getenv("GODADDY_API_KEY")
|
||||||
secret := os.Getenv("GODADDY_API_SECRET")
|
apiSecret := os.Getenv("GODADDY_API_SECRET")
|
||||||
if provider, err = newGoDaddyDNSProvider(id, secret); nil != err {
|
if provider, err = newGoDaddyDNSProvider(id, apiSecret); nil != err {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
} else if "" != os.Getenv("DUCKDNS_TOKEN") {
|
} else if "" != os.Getenv("DUCKDNS_TOKEN") {
|
||||||
|
@ -51,15 +57,49 @@ func main() {
|
||||||
panic("Must provide either DUCKDNS or GODADDY credentials")
|
panic("Must provide either DUCKDNS or GODADDY credentials")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if "" == *secret {
|
||||||
|
*secret = os.Getenv("SECRET")
|
||||||
|
}
|
||||||
|
if "" == *secret {
|
||||||
|
fmt.Fprintf(os.Stderr, "Usage: signjwt <secret>")
|
||||||
|
os.Exit(1)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
r := chi.NewRouter()
|
r := chi.NewRouter()
|
||||||
r.Use(middleware.Logger)
|
r.Use(middleware.Logger)
|
||||||
r.Use(middleware.Timeout(15 * time.Second))
|
r.Use(middleware.Timeout(15 * time.Second))
|
||||||
r.Use(middleware.Recoverer)
|
r.Use(middleware.Recoverer)
|
||||||
|
|
||||||
// TODO add authorization header and validation
|
r.Route("/api/dns", func(r chi.Router) {
|
||||||
//r.Post("/api/dns/{domain:[a-z0-9\\.-]+}", func(w http.ResponseWriter, r *http.Request) {
|
r.Use(func(next http.Handler) http.Handler {
|
||||||
//r.Post("/api/dns/*", func(w http.ResponseWriter, r *http.Request) {
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
r.Post("/api/dns/{domain}", func(w http.ResponseWriter, r *http.Request) {
|
var tokenString string
|
||||||
|
if auth := strings.Split(r.Header.Get("Authorization"), " "); len(auth) > 1 {
|
||||||
|
// TODO handle Basic auth tokens as well
|
||||||
|
tokenString = auth[1]
|
||||||
|
}
|
||||||
|
if "" == tokenString {
|
||||||
|
tokenString = r.URL.Query().Get("access_token")
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO check expiration and such
|
||||||
|
tok, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
|
||||||
|
return []byte(*secret), nil
|
||||||
|
})
|
||||||
|
if nil != err {
|
||||||
|
fmt.Println("validation error:", tokenString, err)
|
||||||
|
http.Error(w, "{\"error\":\"could not verify token\"}", http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx := context.WithValue(r.Context(), MWKey("token"), tok)
|
||||||
|
|
||||||
|
next.ServeHTTP(w, r.WithContext(ctx))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
r.Post("/{domain}", func(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
|
||||||
ch := Challenge{}
|
ch := Challenge{}
|
||||||
|
@ -91,8 +131,8 @@ func main() {
|
||||||
w.Write([]byte("{\"success\":true}\n"))
|
w.Write([]byte("{\"success\":true}\n"))
|
||||||
})
|
})
|
||||||
|
|
||||||
// TODO ugly Delete, but wahtever
|
// TODO ugly Delete, but whatever
|
||||||
r.Delete("/api/dns/{domain}/{token}/{keyAuth}", func(w http.ResponseWriter, r *http.Request) {
|
r.Delete("/{domain}/{token}/{keyAuth}", func(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
|
||||||
ch := Challenge{
|
ch := Challenge{
|
||||||
|
@ -113,6 +153,7 @@ func main() {
|
||||||
|
|
||||||
w.Write([]byte("{\"success\":true}\n"))
|
w.Write([]byte("{\"success\":true}\n"))
|
||||||
})
|
})
|
||||||
|
})
|
||||||
|
|
||||||
r.Get("/", func(w http.ResponseWriter, r *http.Request) {
|
r.Get("/", func(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Write([]byte("welcome\n"))
|
w.Write([]byte("welcome\n"))
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
jwt "github.com/dgrijalva/jwt-go"
|
||||||
|
_ "github.com/joho/godotenv/autoload"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
var secret string
|
||||||
|
|
||||||
|
if len(os.Args) == 2 {
|
||||||
|
secret = os.Args[1]
|
||||||
|
}
|
||||||
|
if "" == secret {
|
||||||
|
secret = os.Getenv("SECRET")
|
||||||
|
}
|
||||||
|
if "" == secret {
|
||||||
|
fmt.Fprintf(os.Stderr, "Usage: signjwt <secret>")
|
||||||
|
os.Exit(1)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
tok, err := getToken(secret, []string{})
|
||||||
|
if nil != err {
|
||||||
|
fmt.Fprintf(os.Stderr, "signing error: %s", err)
|
||||||
|
os.Exit(1)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println(tok)
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
Loading…
Reference in New Issue