Configure Mux to use Heroku OAuth2 provider

If a --token-secret, --heroku-client-id, and --heroku-secret are
provided to Chronograf, it will add Heroku as an OAuth2 provider. These
tokens can be obtained (as of this writing) by visiting your "manage
account" page, navigating to "Applications," and then clicking "Register
New API Client" under the "API Clients" section.
pull/10616/head
Tim Raymond 2017-02-16 12:56:59 -05:00
parent d426193597
commit 9a0b4d6251
3 changed files with 45 additions and 5 deletions

View File

@ -31,6 +31,8 @@ type MuxOpts struct {
GoogleClientID string // GoogleClientID is the Google OAuth id
GoogleClientSecret string // GoogleClientSecret is the Google OAuth secret
GoogleDomains []string // GoogleDomains is the list of domains a user may be a member of
HerokuClientID string // HerokuClientID is the Heroku OAuth id
HerokuSecret string // HerokuSecret is the Heroku OAuth secret
PublicURL string // PublicURL is the public facing URL for the server
}
@ -42,6 +44,10 @@ func (m *MuxOpts) UseGoogle() bool {
return m.TokenSecret != "" && m.GoogleClientID != "" && m.GoogleClientSecret != "" && m.PublicURL != ""
}
func (m *MuxOpts) UseHeroku() bool {
return m.TokenSecret != "" && m.HerokuClientID != "" && m.HerokuSecret != ""
}
func (m *MuxOpts) Routes() AuthRoutes {
routes := AuthRoutes{}
if m.UseGithub() {
@ -50,6 +56,9 @@ func (m *MuxOpts) Routes() AuthRoutes {
if m.UseGoogle() {
routes = append(routes, NewGoogleRoute())
}
if m.UseHeroku() {
routes = append(routes, NewHerokuRoute())
}
return routes
}
@ -195,6 +204,19 @@ func AuthAPI(opts MuxOpts, router *httprouter.Router) http.Handler {
router.Handler("GET", "/oauth/google/callback", goMux.Callback())
}
if opts.UseHeroku() {
heroku := oauth2.Heroku{
ClientID: opts.HerokuClientID,
ClientSecret: opts.HerokuSecret,
Logger: opts.Logger,
}
hMux := oauth2.NewJWTMux(&heroku, &auth, opts.Logger)
router.Handler("GET", "/oauth/heroku/login", hMux.Login())
router.Handler("GET", "/oauth/heroku/logout", hMux.Logout())
router.Handler("GET", "/oauth/heroku/callback", hMux.Callback())
}
tokenMiddleware := oauth2.AuthorizedToken(&auth, &oauth2.CookieExtractor{Name: "session"}, opts.Logger, router)
// Wrap the API with token validation middleware.
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {

View File

@ -79,3 +79,13 @@ func NewGoogleRoute() AuthRoute {
Callback: "/oauth/google/callback",
}
}
func NewHerokuRoute() AuthRoute {
return AuthRoute{
Name: "heroku",
Label: "Heroku",
Login: "/oauth/heroku/login",
Logout: "/oauth/heroku/logout",
Callback: "/oauth/heroku/callback",
}
}

View File

@ -40,18 +40,23 @@ type Server struct {
TLSCertificateKey flags.Filename `long:"tls-key" description:"the private key to use for secure conections" env:"TLS_PRIVATE_KEY"`
*/
Develop bool `short:"d" long:"develop" description:"Run server in develop mode."`
BoltPath string `short:"b" long:"bolt-path" description:"Full path to boltDB file (/var/lib/chronograf/chronograf-v1.db)" env:"BOLT_PATH" default:"chronograf-v1.db"`
CannedPath string `short:"c" long:"canned-path" description:"Path to directory of pre-canned application layouts (/usr/share/chronograf/canned)" env:"CANNED_PATH" default:"canned"`
TokenSecret string `short:"t" long:"token-secret" description:"Secret to sign tokens" env:"TOKEN_SECRET"`
Develop bool `short:"d" long:"develop" description:"Run server in develop mode."`
BoltPath string `short:"b" long:"bolt-path" description:"Full path to boltDB file (/var/lib/chronograf/chronograf-v1.db)" env:"BOLT_PATH" default:"chronograf-v1.db"`
CannedPath string `short:"c" long:"canned-path" description:"Path to directory of pre-canned application layouts (/usr/share/chronograf/canned)" env:"CANNED_PATH" default:"canned"`
TokenSecret string `short:"t" long:"token-secret" description:"Secret to sign tokens" env:"TOKEN_SECRET"`
GithubClientID string `short:"i" long:"github-client-id" description:"Github Client ID for OAuth 2 support" env:"GH_CLIENT_ID"`
GithubClientSecret string `short:"s" long:"github-client-secret" description:"Github Client Secret for OAuth 2 support" env:"GH_CLIENT_SECRET"`
GithubOrgs []string `short:"o" long:"github-organization" description:"Github organization user is required to have active membership" env:"GH_ORGS" env-delim:","`
GoogleClientID string `long:"google-client-id" description:"Google Client ID for OAuth 2 support" env:"GOOGLE_CLIENT_ID"`
GoogleClientSecret string `long:"google-client-secret" description:"Google Client Secret for OAuth 2 support" env:"GOGGLE_CLIENT_SECRET"`
GoogleDomains []string `long:"google-domains" description:"Google email domain user is required to have active membership" env:"GOOGLE_DOMAINS" env-delim:","`
PublicURL string `long:"public-url" description:"Full public URL used to access Chronograf from a web browser. Used for Google OAuth2 authentication. (http://localhost:8888)" env:"PUBLIC_URL"`
HerokuClientID string `long:"heroku-client-id" description:"Heroku Client ID for OAuth 2 support" env:"HEROKU_CLIENT_ID"`
HerokuSecret string `long:"heroku-secret" description:"Heroku Secret for OAuth 2 support" env:"HEROKU_SECRET"`
ReportingDisabled bool `short:"r" long:"reporting-disabled" description:"Disable reporting of usage stats (os,arch,version,cluster_id,uptime) once every 24hr" env:"REPORTING_DISABLED"`
LogLevel string `short:"l" long:"log-level" value-name:"choice" choice:"debug" choice:"info" choice:"warn" choice:"error" choice:"fatal" choice:"panic" default:"info" description:"Set the logging level" env:"LOG_LEVEL"`
Basepath string `short:"p" long:"basepath" description:"A URL path prefix under which all chronograf routes will be mounted" env:"BASE_PATH"`
@ -70,7 +75,8 @@ type BuildInfo struct {
func (s *Server) useAuth() bool {
gh := s.TokenSecret != "" && s.GithubClientID != "" && s.GithubClientSecret != ""
google := s.TokenSecret != "" && s.GoogleClientID != "" && s.GoogleClientSecret != "" && s.PublicURL != ""
return gh || google
heroku := s.TokenSecret != "" && s.HerokuClientID != "" && s.HerokuSecret != ""
return gh || google || heroku
}
// Serve starts and runs the chronograf server
@ -87,6 +93,8 @@ func (s *Server) Serve() error {
GoogleClientID: s.GoogleClientID,
GoogleClientSecret: s.GoogleClientSecret,
GoogleDomains: s.GoogleDomains,
HerokuClientID: s.HerokuClientID,
HerokuSecret: s.HerokuSecret,
PublicURL: s.PublicURL,
Logger: logger,
UseAuth: s.useAuth(),