From 5bb198c1a5da3132945915947b88ad4a59dc7fcb Mon Sep 17 00:00:00 2001 From: "kali kaneko (leap communications)" Date: Sat, 25 Jan 2020 15:54:54 -0600 Subject: pass sip authentication variables as env vars --- cmd/vpnweb/vpnweb.go | 4 ++-- config/CONFIG | 11 ++++++++++ pkg/auth/middleware.go | 31 ++++++++++++++++----------- pkg/auth/sip2/auth.go | 43 +++++++++++++++++++++++-------------- pkg/config/main.go | 58 +++++++++++++++++++++++--------------------------- 5 files changed, 86 insertions(+), 61 deletions(-) diff --git a/cmd/vpnweb/vpnweb.go b/cmd/vpnweb/vpnweb.go index f59cc7d..ddd919c 100644 --- a/cmd/vpnweb/vpnweb.go +++ b/cmd/vpnweb/vpnweb.go @@ -24,8 +24,8 @@ func main() { http.HandleFunc("/3/refresh-token", auth.RefreshAuthMiddleware(opts.Auth)) */ - http.Handle("/3/cert", auth.RestrictedMiddleware(opts.Auth, ch)) - http.HandleFunc("/3/auth", auth.Authenticator(opts)) + http.Handle("/3/cert", auth.RestrictedMiddleware(opts, ch)) + http.HandleFunc("/3/auth", auth.AuthenticatorMiddleware(opts)) /* static files */ diff --git a/config/CONFIG b/config/CONFIG index 04b4496..cdd34ca 100755 --- a/config/CONFIG +++ b/config/CONFIG @@ -1,4 +1,15 @@ +# general variables + export VPNWEB_AUTH=sip export VPNWEB_CAKEY=test/files/ca.key export VPNWEB_CACRT=test/files/ca.crt export VPNWEB_PORT=8000 +export VPNWEB_AUTH_SECRET=othaoPhejei8aidaeghaiVohie4du + +# sip authentication + +export VPNWEB_SIP_USER=leap +export VPNWEB_SIP_PASS="Kohapassword1!" +export VPNWEB_SIP_HOST="localhost" +export VPNWEB_SIP_PORT="6001" +export VPNWEB_SIP_LIBR_LOCATION=testlibrary diff --git a/pkg/auth/middleware.go b/pkg/auth/middleware.go index 9b42fa9..37c204e 100644 --- a/pkg/auth/middleware.go +++ b/pkg/auth/middleware.go @@ -11,23 +11,29 @@ import ( ) const anonAuth string = "anon" -const sipAuth string = "sip" - -/* FIXME -- get this from configuration variables */ - -var jwtSigningSecret = []byte("thesingingkey") +const sip2Auth string = "sip" func bailOnBadAuthModule(module string) { log.Fatal("Unknown auth module: '", module, "'. Should be one of: ", anonAuth, ", ", sipAuth, ".") } -func Authenticator(opts *config.Opts) http.HandlerFunc { +func checkForAuthSecret(opts *config.Opts) { + if opts.AuthSecret == "" { + log.Fatal("Need to provide a AuthSecret value for SIP Authentication") + } + if len(opts.AuthSecret) < 20 { + log.Fatal("Please provider an AuthSecret longer than 20 chars") + } +} + +func AuthenticatorMiddleware(opts *config.Opts) http.HandlerFunc { switch opts.Auth { case anonAuth: return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { http.Error(w, "no authentication in anon mode", http.StatusBadRequest) }) - case sipAuth: + case sip2Auth: + checkForAuthSecret(opts) return sip2.SipAuthenticator(opts) default: bailOnBadAuthModule(opts.Auth) @@ -35,22 +41,23 @@ func Authenticator(opts *config.Opts) http.HandlerFunc { return nil } -func RestrictedMiddleware(auth string, ch web.CertHandler) http.Handler { +func RestrictedMiddleware(opts *config.Opts, ch web.CertHandler) http.Handler { jwtMiddleware := jwtmiddleware.New(jwtmiddleware.Options{ ValidationKeyGetter: func(token *jwt.Token) (interface{}, error) { - return jwtSigningSecret, nil + return []byte(opts.AuthSecret), nil }, SigningMethod: jwt.SigningMethodHS256, }) - switch auth { + switch opts.Auth { case anonAuth: return http.HandlerFunc(ch.CertResponder) - case sipAuth: + case sip2Auth: + checkForAuthSecret(opts) return jwtMiddleware.Handler(http.HandlerFunc(ch.CertResponder)) default: - bailOnBadAuthModule(auth) + bailOnBadAuthModule(opts.Auth) } return nil } diff --git a/pkg/auth/sip2/auth.go b/pkg/auth/sip2/auth.go index 1d3f309..f5ad0a4 100644 --- a/pkg/auth/sip2/auth.go +++ b/pkg/auth/sip2/auth.go @@ -5,38 +5,51 @@ import ( jwt "github.com/dgrijalva/jwt-go" "log" "net/http" + "os" "time" "0xacab.org/leap/vpnweb/pkg/config" ) -const LibraryLocation string = "testlibrary" -const SipUser string = "leap" -const SipPasswd string = "Kohapassword1!" - -// XXX duplicated, pass in opts -var jwtSigningSecret = []byte("thesingingkey") +const SipUserVar string = "VPNWEB_SIP_USER" +const SipPassVar string = "VPNWEB_SIP_PASS" +const SipPortVar string = "VPNWEB_SIP_PORT" +const SipHostVar string = "VPNWEB_SIP_HOST" +const SipLibrLocVar string = "VPNWEB_SIP_LIBR_LOCATION" type Credentials struct { User string Password string } -func SipAuthenticator(opts *config.Opts) http.HandlerFunc { - log.Println("Initializing sip2 authenticator...") +func getConfigFromEnv(envVar string) string { + val, exists := os.LookupEnv(envVar) + if !exists { + log.Fatal("Need to set required env var:", envVar) + } + return val +} - /* TODO -- should pass specific SIP options as a secondary struct */ +func SipAuthenticator(opts *config.Opts) http.HandlerFunc { /* TODO -- catch connection errors */ - sip := NewClient("localhost", "6001", LibraryLocation) + log.Println("Initializing sip2 authenticator") + + SipUser := getConfigFromEnv(SipUserVar) + SipPass := getConfigFromEnv(SipPassVar) + SipHost := getConfigFromEnv(SipHostVar) + SipPort := getConfigFromEnv(SipPortVar) + SipLibrLoc := getConfigFromEnv(SipLibrLocVar) + + sip := NewClient(SipHost, SipPort, SipLibrLoc) ok, err := sip.Connect() if err != nil { - log.Fatal("cannot connect sip client") + log.Fatal("Cannot connect sip client") } - ok = sip.Login(SipUser, SipPasswd) + ok = sip.Login(SipUser, SipPass) if !ok { - log.Println("Error on SIP login") + log.Fatal("Error on SIP login") } else { log.Println("SIP login ok") } @@ -67,10 +80,8 @@ func SipAuthenticator(opts *config.Opts) http.HandlerFunc { log.Println("Valid auth for user", c.User) token := jwt.New(jwt.SigningMethodHS256) claims := token.Claims.(jwt.MapClaims) - /* maybe no uid at all */ - claims["uid"] = "user" claims["exp"] = time.Now().Add(time.Hour * 24).Unix() - tokenString, _ := token.SignedString(jwtSigningSecret) + tokenString, _ := token.SignedString([]byte(opts.AuthSecret)) w.Write([]byte(tokenString)) }) return authTokenHandler diff --git a/pkg/config/main.go b/pkg/config/main.go index cfa97ed..fa23257 100644 --- a/pkg/config/main.go +++ b/pkg/config/main.go @@ -4,33 +4,29 @@ import ( "flag" "log" "os" - "reflect" ) const DefaultAuthenticationModule = "anonymous" type Opts struct { - Notls bool - CaCrt string - CaKey string - TlsCrt string - TlsKey string - Port string - Auth string + Notls bool + CaCrt string + CaKey string + TlsCrt string + TlsKey string + Port string + Auth string + AuthSecret string } -// TODO -- remove use of reflect +func fallbackToEnv(variable *string, envVar, defaultVar string) { -func (o *Opts) fallbackToEnv(field string, envVar string, defaultVal string) { - r := reflect.ValueOf(o) - f := reflect.Indirect(r).FieldByName(field) - - if f.String() == "" { + if *variable == "" { val, exists := os.LookupEnv(envVar) if exists && val != "" { - f.SetString(val) + *variable = val } else { - f.SetString(defaultVal) + *variable = defaultVar } } } @@ -54,21 +50,23 @@ func doTlsFilesSanityCheck(tlsCrt string, tlsKey string) { } func InitializeFlags(opts *Opts) { - flag.BoolVar(&opts.Notls, "notls", false, "disable TLS on the service") - flag.StringVar(&opts.CaCrt, "caCrt", "", "path to the CA public key") - flag.StringVar(&opts.CaKey, "caKey", "", "path to the CA private key") - flag.StringVar(&opts.TlsCrt, "tls_crt", "", "path to the cert file for TLS") - flag.StringVar(&opts.TlsKey, "tls_key", "", "path to the key file for TLS") - flag.StringVar(&opts.Port, "port", "", "port where the server will listen (default: 8000)") - flag.StringVar(&opts.Auth, "auth", "", "authentication module (anonymous, sip)") + flag.BoolVar(&opts.Notls, "notls", false, "Disable TLS on the service") + flag.StringVar(&opts.CaCrt, "caCrt", "", "Path to the CA public key") + flag.StringVar(&opts.CaKey, "caKey", "", "Path to the CA private key") + flag.StringVar(&opts.TlsCrt, "tlsCrt", "", "Path to the cert file for TLS") + flag.StringVar(&opts.TlsKey, "tlsKey", "", "Path to the key file for TLS") + flag.StringVar(&opts.Port, "port", "", "Port where the server will listen (default: 8000)") + flag.StringVar(&opts.Auth, "auth", "", "Authentication module (anonymous, sip)") + flag.StringVar(&opts.AuthSecret, "authSecret", "", "Authentication secret (optional)") flag.Parse() - opts.fallbackToEnv("CaCrt", "VPNWEB_CACRT", "") - opts.fallbackToEnv("CaKey", "VPNWEB_CAKEY", "") - opts.fallbackToEnv("TlsCrt", "VPNWEB_TLSCRT", "") - opts.fallbackToEnv("TlsKey", "VPNWEB_TLSKEY", "") - opts.fallbackToEnv("Port", "VPNWEB_PORT", "8000") - opts.fallbackToEnv("Auth", "VPNWEB_AUTH", DefaultAuthenticationModule) + fallbackToEnv(&opts.CaCrt, "VPNWEB_CACRT", "") + fallbackToEnv(&opts.CaKey, "VPNWEB_CAKEY", "") + fallbackToEnv(&opts.TlsCrt, "VPNWEB_TLSCRT", "") + fallbackToEnv(&opts.TlsKey, "VPNWEB_TLSKEY", "") + fallbackToEnv(&opts.Port, "VPNWEB_PORT", "8000") + fallbackToEnv(&opts.Auth, "VPNWEB_AUTH", DefaultAuthenticationModule) + fallbackToEnv(&opts.AuthSecret, "VPNWEB_AUTHSECRET", "") } func CheckConfigurationOptions(opts *Opts) { @@ -94,6 +92,4 @@ func CheckConfigurationOptions(opts *Opts) { } log.Println("Authentication module:", opts.Auth) - - // TODO -- check authentication module is valud, bail out otherwise } -- cgit v1.2.3