Skip to content
This repository has been archived by the owner on Jan 24, 2019. It is now read-only.

Commit

Permalink
Add config file support
Browse files Browse the repository at this point in the history
  • Loading branch information
jehiah committed Nov 10, 2014
1 parent 899749a commit f18d1a2
Show file tree
Hide file tree
Showing 8 changed files with 241 additions and 116 deletions.
2 changes: 2 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ language: go
install:
- go get github.com/bmizerany/assert
- go get github.com/bitly/go-simplejson
- go get github.com/mreiferson/go-options
- go get github.com/BurntSushi/toml
notifications:
email: false

31 changes: 20 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,28 +42,40 @@ intend to run `google_auth_proxy` on.
5. Take note of the **Client ID** and **Client Secret**


## Command Line Options
## Configuration

`google_auth_proxy` can be configured via command line arguments, config file or environment variables.

### Config File

An example [google_auth_proxy.cfg](contrib/google_auth_proxy.cfg.example) config file is in the contrib directory. It can be used by specifying `-config=/etc/google_auth_proxy.cfg`

### Command Line Options

```
Usage of ./google_auth_proxy:
Usage of google_auth_proxy:
-authenticated-emails-file="": authenticate against emails via file (one per line)
-client-id="": the Google OAuth Client ID: ie: "123456.apps.googleusercontent.com"
-client-secret="": the OAuth Client Secret
-cookie-domain="": an optional cookie domain to force cookies to
-cookie-expire=168h: expire timeframe for cookie
-config="": path to config file
-cookie-domain="": an optional cookie domain to force cookies to (ie: .yourcompany.com)
-cookie-expire=168h0m0s: expire timeframe for cookie
-cookie-https-only=false: set HTTPS only cookie
-cookie-secret="": the seed string for secure cookies
-google-apps-domain=[]: authenticate against the given google apps domain (may be given multiple times)
-google-apps-domain=: authenticate against the given Google apps domain (may be given multiple times)
-htpasswd-file="": additionally authenticate against a htpasswd file. Entries must be created with "htpasswd -s" for SHA encryption
-http-address="127.0.0.1:4180": <addr>:<port> to listen on for HTTP clients
-pass-basic-auth=true: pass HTTP Basic Auth information to upstream
-pass-basic-auth=true: pass HTTP Basic Auth, X-Forwarded-User and X-Forwarded-Email information to upstream
-redirect-url="": the OAuth Redirect URL. ie: "https://internalapp.yourcompany.com/oauth2/callback"
-upstream=[]: the http url(s) of the upstream endpoint. If multiple, routing is based on path
-upstream=: the http url(s) of the upstream endpoint. If multiple, routing is based on path
-version=false: print version string
```

### Environment variables

## Example Configuration
The environment variables `google_auth_client_id`, `google_auth_secret` and `google_auth_cookie_secret` can be used in place of the corresponding command-line arguments.

### Example Configuration

This example has a [Nginx](http://nginx.org/) SSL endpoint proxying to `google_auth_proxy` on port `4180`.
`google_auth_proxy` then authenticates requests for an upstream application running on port `8080`. The external
Expand Down Expand Up @@ -105,9 +117,6 @@ The command line to run `google_auth_proxy` would look like this:
--client-secret=...
```

## Environment variables

The environment variables `google_auth_client_id`, `google_auth_secret` and `google_auth_cookie_secret` can be used in place of the corresponding command-line arguments.

## Endpoint Documentation

Expand Down
44 changes: 44 additions & 0 deletions contrib/google_auth_proxy.cfg.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
## Google Auth Proxy Config File
## https://github.com/bitly/google_auth_proxy

## <addr>:<port> to listen on for HTTP clients
# http_address = "127.0.0.1:4180"

## the OAuth Redirect URL.
# redirect_url = "https://internalapp.yourcompany.com/oauth2/callback"

## the http url(s) of the upstream endpoint. If multiple, routing is based on path
# upstreams = [
# "http://127.0.0.1:8080/"
# ]

## pass HTTP Basic Auth, X-Forwarded-User and X-Forwarded-Email information to upstream
# pass_basic_auth = true

## Google Apps Domains to allow authentication for
# google_apps_domains = [
# "yourcompany.com"
# ]


## The Google OAuth Client ID, Secret
# client_id = "123456.apps.googleusercontent.com"
# client_secret = ""

## Authenticated Email Addresses File (one email per line)
# authenticated_emails_file = ""

## Htpasswd File (optional)
## Additionally authenticate against a htpasswd file. Entries must be created with "htpasswd -s" for SHA encryption
## enabling exposes a username/login signin form
# htpasswd_file = ""


## Cookie Settings
## Secret - the seed string for secure cookies
## Domain - optional cookie domain to force cookies to (ie: .yourcompany.com)
## Expire - expire timeframe for cookie
# cookie_secret = ""
# cookie_domain = ""
# cookie_expire = "168h"
# cookie_https_only = false
134 changes: 65 additions & 69 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,109 +6,105 @@ import (
"log"
"net"
"net/http"
"net/url"
"os"
"strings"
"time"
)

const VERSION = "0.1.0"

var (
showVersion = flag.Bool("version", false, "print version string")
httpAddr = flag.String("http-address", "127.0.0.1:4180", "<addr>:<port> to listen on for HTTP clients")
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")
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")
authenticatedEmailsFile = flag.String("authenticated-emails-file", "", "authenticate against emails via file (one per line)")
googleAppsDomains = StringArray{}
upstreams = StringArray{}
"github.com/BurntSushi/toml"
"github.com/mreiferson/go-options"
)

func init() {
flag.Var(&googleAppsDomains, "google-apps-domain", "authenticate against the given google apps domain (may be given multiple times)")
flag.Var(&upstreams, "upstream", "the http url(s) of the upstream endpoint. If multiple, routing is based on path")
}

func main() {
flagSet := flag.NewFlagSet("google_auth_proxy", flag.ExitOnError)

googleAppsDomains := StringArray{}
upstreams := StringArray{}

config := flagSet.String("config", "", "path to config file")
showVersion := flagSet.Bool("version", false, "print version string")

flagSet.String("http-address", "127.0.0.1:4180", "<addr>:<port> to listen on for HTTP clients")
flagSet.String("redirect-url", "", "the OAuth Redirect URL. ie: \"https://internalapp.yourcompany.com/oauth2/callback\"")
flagSet.Var(&upstreams, "upstream", "the http url(s) of the upstream endpoint. If multiple, routing is based on path")
flagSet.Bool("pass-basic-auth", true, "pass HTTP Basic Auth, X-Forwarded-User and X-Forwarded-Email information to upstream")

flagSet.Var(&googleAppsDomains, "google-apps-domain", "authenticate against the given Google apps domain (may be given multiple times)")
flagSet.String("client-id", "", "the Google OAuth Client ID: ie: \"123456.apps.googleusercontent.com\"")
flagSet.String("client-secret", "", "the OAuth Client Secret")
flagSet.String("authenticated-emails-file", "", "authenticate against emails via file (one per line)")
flagSet.String("htpasswd-file", "", "additionally authenticate against a htpasswd file. Entries must be created with \"htpasswd -s\" for SHA encryption")

flag.Parse()
flagSet.String("cookie-secret", "", "the seed string for secure cookies")
flagSet.String("cookie-domain", "", "an optional cookie domain to force cookies to (ie: .yourcompany.com)")
flagSet.Duration("cookie-expire", time.Duration(168)*time.Hour, "expire timeframe for cookie")
flagSet.Bool("cookie-https-only", false, "set HTTPS only cookie")

flagSet.Parse(os.Args[1:])

opts := NewOptions()

var cfg map[string]interface{}
if *config != "" {
_, err := toml.DecodeFile(*config, &cfg)
if err != nil {
log.Fatalf("ERROR: failed to load config file %s - %s", *config, err)
}
}

options.Resolve(opts, flagSet, cfg)

// Try to use env for secrets if no flag is set
if *clientID == "" {
*clientID = os.Getenv("google_auth_client_id")
// TODO: better parsing of these values
if opts.ClientID == "" {
opts.ClientID = os.Getenv("google_auth_client_id")
}
if *clientSecret == "" {
*clientSecret = os.Getenv("google_auth_secret")
if opts.ClientSecret == "" {
opts.ClientSecret = os.Getenv("google_auth_secret")
}
if *cookieSecret == "" {
*cookieSecret = os.Getenv("google_auth_cookie_secret")
if opts.CookieSecret == "" {
opts.CookieSecret = os.Getenv("google_auth_cookie_secret")
}

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)
err := opts.Validate()
if err != nil {
log.Fatalf("error parsing --redirect-url %s", err.Error())
log.Printf("%s", err)
os.Exit(1)
}

validator := NewValidator(googleAppsDomains, *authenticatedEmailsFile)
oauthproxy := NewOauthProxy(upstreamUrls, *clientID, *clientSecret, validator)
oauthproxy.SetRedirectUrl(redirectUrl)
if len(googleAppsDomains) != 0 && *authenticatedEmailsFile == "" {
if len(googleAppsDomains) > 1 {
oauthproxy.SignInMessage = fmt.Sprintf("Authenticate using one of the following domains: %v", strings.Join(googleAppsDomains, ", "))
validator := NewValidator(opts.GoogleAppsDomains, opts.AuthenticatedEmailsFile)
oauthproxy := NewOauthProxy(opts, validator)

if len(opts.GoogleAppsDomains) != 0 && opts.AuthenticatedEmailsFile == "" {
if len(opts.GoogleAppsDomains) > 1 {
oauthproxy.SignInMessage = fmt.Sprintf("Authenticate using one of the following domains: %v", strings.Join(opts.GoogleAppsDomains, ", "))
} else {
oauthproxy.SignInMessage = fmt.Sprintf("Authenticate using %v", googleAppsDomains[0])
oauthproxy.SignInMessage = fmt.Sprintf("Authenticate using %v", opts.GoogleAppsDomains[0])
}
}
if *htpasswdFile != "" {
oauthproxy.HtpasswdFile, err = NewHtpasswdFromFile(*htpasswdFile)

if opts.HtpasswdFile != "" {
oauthproxy.HtpasswdFile, err = NewHtpasswdFromFile(opts.HtpasswdFile)
if err != nil {
log.Fatalf("FATAL: unable to open %s %s", *htpasswdFile, err.Error())
log.Fatalf("FATAL: unable to open %s %s", opts.HtpasswdFile, err)
}
}
listener, err := net.Listen("tcp", *httpAddr)

listener, err := net.Listen("tcp", opts.HttpAddress)
if err != nil {
log.Fatalf("FATAL: listen (%s) failed - %s", *httpAddr, err.Error())
log.Fatalf("FATAL: listen (%s) failed - %s", opts.HttpAddress, err)
}
log.Printf("listening on %s", *httpAddr)
log.Printf("listening on %s", opts.HttpAddress)

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("ERROR: http.Serve() - %s", err)
}

log.Printf("HTTP: closing %s", listener.Addr().String())
log.Printf("HTTP: closing %s", listener.Addr())
}
Loading

0 comments on commit f18d1a2

Please sign in to comment.