2012-12-11 01:59:23 +00:00
package main
import (
"flag"
2012-12-17 18:38:33 +00:00
"fmt"
2012-12-11 01:59:23 +00:00
"log"
"net"
"net/http"
"net/url"
2014-08-07 20:16:39 +00:00
"os"
2012-12-11 01:59:23 +00:00
"strings"
2014-11-08 18:26:55 +00:00
"time"
2012-12-11 01:59:23 +00:00
)
2014-08-07 20:50:16 +00:00
const VERSION = "0.1.0"
2012-12-11 01:59:23 +00:00
var (
showVersion = flag . Bool ( "version" , false , "print version string" )
2012-12-26 21:53:02 +00:00
httpAddr = flag . String ( "http-address" , "127.0.0.1:4180" , "<addr>:<port> to listen on for HTTP clients" )
2012-12-11 01:59:23 +00:00
redirectUrl = flag . String ( "redirect-url" , "" , "the OAuth Redirect URL. ie: \"https://internalapp.yourcompany.com/oauth2/callback\"" )
clientID = flag . String ( "client-id" , "" , "the Google OAuth Client ID: ie: \"123456.apps.googleusercontent.com\"" )
clientSecret = flag . String ( "client-secret" , "" , "the OAuth Client Secret" )
passBasicAuth = flag . Bool ( "pass-basic-auth" , true , "pass HTTP Basic Auth information to upstream" )
htpasswdFile = flag . String ( "htpasswd-file" , "" , "additionally authenticate against a htpasswd file. Entries must be created with \"htpasswd -s\" for SHA encryption" )
cookieSecret = flag . String ( "cookie-secret" , "" , "the seed string for secure cookies" )
cookieDomain = flag . String ( "cookie-domain" , "" , "an optional cookie domain to force cookies to" )
2014-11-08 18:26:55 +00:00
cookieExpire = flag . Duration ( "cookie-expire" , time . Duration ( 168 ) * time . Hour , "expire timeframe for cookie" )
cookieHttpsOnly = flag . Bool ( "cookie-https-only" , false , "set HTTPS only cookie" )
2012-12-11 01:59:23 +00:00
authenticatedEmailsFile = flag . String ( "authenticated-emails-file" , "" , "authenticate against emails via file (one per line)" )
2014-05-22 01:47:42 +00:00
googleAppsDomains = StringArray { }
2012-12-11 01:59:23 +00:00
upstreams = StringArray { }
)
func init ( ) {
2014-05-22 01:47:42 +00:00
flag . Var ( & googleAppsDomains , "google-apps-domain" , "authenticate against the given google apps domain (may be given multiple times)" )
2012-12-11 01:59:23 +00:00
flag . Var ( & upstreams , "upstream" , "the http url(s) of the upstream endpoint. If multiple, routing is based on path" )
}
func main ( ) {
2013-07-30 21:31:59 +00:00
2012-12-11 01:59:23 +00:00
flag . Parse ( )
2013-07-30 21:31:59 +00:00
// Try to use env for secrets if no flag is set
if * clientID == "" {
* clientID = os . Getenv ( "google_auth_client_id" )
}
if * clientSecret == "" {
* clientSecret = os . Getenv ( "google_auth_secret" )
}
if * cookieSecret == "" {
* cookieSecret = os . Getenv ( "google_auth_cookie_secret" )
}
2012-12-11 01:59:23 +00:00
if * showVersion {
fmt . Printf ( "google_auth_proxy v%s\n" , VERSION )
return
}
if len ( upstreams ) < 1 {
log . Fatal ( "missing --upstream" )
}
if * cookieSecret == "" {
log . Fatal ( "missing --cookie-secret" )
}
if * clientID == "" {
log . Fatal ( "missing --client-id" )
}
if * clientSecret == "" {
log . Fatal ( "missing --client-secret" )
}
var upstreamUrls [ ] * url . URL
for _ , u := range upstreams {
upstreamUrl , err := url . Parse ( u )
if err != nil {
log . Fatalf ( "error parsing --upstream %s" , err . Error ( ) )
}
upstreamUrls = append ( upstreamUrls , upstreamUrl )
}
redirectUrl , err := url . Parse ( * redirectUrl )
if err != nil {
log . Fatalf ( "error parsing --redirect-url %s" , err . Error ( ) )
}
2014-05-22 01:47:42 +00:00
validator := NewValidator ( googleAppsDomains , * authenticatedEmailsFile )
2012-12-11 01:59:23 +00:00
oauthproxy := NewOauthProxy ( upstreamUrls , * clientID , * clientSecret , validator )
oauthproxy . SetRedirectUrl ( redirectUrl )
2014-05-22 01:47:42 +00:00
if len ( googleAppsDomains ) != 0 && * authenticatedEmailsFile == "" {
2014-11-09 05:26:52 +00:00
if len ( googleAppsDomains ) > 1 {
oauthproxy . SignInMessage = fmt . Sprintf ( "Authenticate using one of the following domains: %v" , strings . Join ( googleAppsDomains , ", " ) )
} else {
oauthproxy . SignInMessage = fmt . Sprintf ( "Authenticate using %v" , googleAppsDomains [ 0 ] )
}
2012-12-11 01:59:23 +00:00
}
if * htpasswdFile != "" {
2012-12-17 18:38:33 +00:00
oauthproxy . HtpasswdFile , err = NewHtpasswdFromFile ( * htpasswdFile )
if err != nil {
log . Fatalf ( "FATAL: unable to open %s %s" , * htpasswdFile , err . Error ( ) )
}
2012-12-11 01:59:23 +00:00
}
listener , err := net . Listen ( "tcp" , * httpAddr )
if err != nil {
log . Fatalf ( "FATAL: listen (%s) failed - %s" , * httpAddr , err . Error ( ) )
}
log . Printf ( "listening on %s" , * httpAddr )
server := & http . Server { Handler : oauthproxy }
err = server . Serve ( listener )
if err != nil && ! strings . Contains ( err . Error ( ) , "use of closed network connection" ) {
log . Printf ( "ERROR: http.Serve() - %s" , err . Error ( ) )
}
log . Printf ( "HTTP: closing %s" , listener . Addr ( ) . String ( ) )
}