Move Oauth configs to the database

This commit is contained in:
marcos
2017-12-18 12:14:21 -03:00
parent 6a1e91b1e9
commit 5332f954dd
4 changed files with 100 additions and 78 deletions

View File

@@ -7,8 +7,6 @@ import (
"github.com/gorilla/securecookie" "github.com/gorilla/securecookie"
"golang.org/x/oauth2" "golang.org/x/oauth2"
oauth2FB "golang.org/x/oauth2/facebook"
oauth2Github "golang.org/x/oauth2/github"
) )
const ( const (
@@ -29,18 +27,16 @@ var UseLetsEncrypt, ExternalDindVolume, NoWindows bool
var LetsEncryptCertsDir string var LetsEncryptCertsDir string
var MaxLoadAvg float64 var MaxLoadAvg float64
var ForceTLS bool var ForceTLS bool
var Providers map[string]*oauth2.Config
var SecureCookie *securecookie.SecureCookie var SecureCookie *securecookie.SecureCookie
var AdminToken string var AdminToken string
var GithubClientID, GithubClientSecret string
var FacebookClientID, FacebookClientSecret string
var DockerClientID, DockerClientSecret string
var PlaygroundDomain string var PlaygroundDomain string
var SegmentId string var SegmentId string
// TODO move this to a sync map so it can be updated on demand when the configuration for a playground changes
var Providers = map[string]map[string]*oauth2.Config{}
func ParseFlags() { func ParseFlags() {
flag.StringVar(&LetsEncryptCertsDir, "letsencrypt-certs-dir", "/certs", "Path where let's encrypt certs will be stored") flag.StringVar(&LetsEncryptCertsDir, "letsencrypt-certs-dir", "/certs", "Path where let's encrypt certs will be stored")
flag.BoolVar(&UseLetsEncrypt, "letsencrypt-enable", false, "Enabled let's encrypt tls certificates") flag.BoolVar(&UseLetsEncrypt, "letsencrypt-enable", false, "Enabled let's encrypt tls certificates")
@@ -64,15 +60,6 @@ func ParseFlags() {
flag.StringVar(&DefaultDinDImage, "default-dind-image", "franela/dind", "Default DinD image to use if not specified otherwise") flag.StringVar(&DefaultDinDImage, "default-dind-image", "franela/dind", "Default DinD image to use if not specified otherwise")
flag.StringVar(&DefaultSessionDuration, "default-session-duration", "4h", "Default session duration if not specified otherwise") flag.StringVar(&DefaultSessionDuration, "default-session-duration", "4h", "Default session duration if not specified otherwise")
flag.StringVar(&GithubClientID, "oauth-github-client-id", "", "Github OAuth Client ID")
flag.StringVar(&GithubClientSecret, "oauth-github-client-secret", "", "Github OAuth Client Secret")
flag.StringVar(&FacebookClientID, "oauth-facebook-client-id", "", "Facebook OAuth Client ID")
flag.StringVar(&FacebookClientSecret, "oauth-facebook-client-secret", "", "Facebook OAuth Client Secret")
flag.StringVar(&DockerClientID, "oauth-docker-client-id", "", "Docker OAuth Client ID")
flag.StringVar(&DockerClientSecret, "oauth-docker-client-secret", "", "Docker OAuth Client Secret")
flag.StringVar(&PlaygroundDomain, "playground-domain", "localhost", "Domain to use for the playground") flag.StringVar(&PlaygroundDomain, "playground-domain", "localhost", "Domain to use for the playground")
flag.StringVar(&AdminToken, "admin-token", "", "Token to validate admin user for admin endpoints") flag.StringVar(&AdminToken, "admin-token", "", "Token to validate admin user for admin endpoints")
@@ -82,43 +69,4 @@ func ParseFlags() {
SecureCookie = securecookie.New([]byte(CookieHashKey), []byte(CookieBlockKey)) SecureCookie = securecookie.New([]byte(CookieHashKey), []byte(CookieBlockKey))
registerOAuthProviders()
}
func registerOAuthProviders() {
Providers = map[string]*oauth2.Config{}
if GithubClientID != "" && GithubClientSecret != "" {
conf := &oauth2.Config{
ClientID: GithubClientID,
ClientSecret: GithubClientSecret,
Scopes: []string{"user:email"},
Endpoint: oauth2Github.Endpoint,
}
Providers["github"] = conf
}
if FacebookClientID != "" && FacebookClientSecret != "" {
conf := &oauth2.Config{
ClientID: FacebookClientID,
ClientSecret: FacebookClientSecret,
Scopes: []string{"email", "public_profile"},
Endpoint: oauth2FB.Endpoint,
}
Providers["facebook"] = conf
}
if DockerClientID != "" && DockerClientSecret != "" {
oauth2.RegisterBrokenAuthHeaderProvider(".id.docker.com")
conf := &oauth2.Config{
ClientID: DockerClientID,
ClientSecret: DockerClientSecret,
Scopes: []string{"openid"},
Endpoint: oauth2.Endpoint{
AuthURL: "https://id.docker.com/id/oauth/authorize/",
TokenURL: "https://id.docker.com/id/oauth/token",
},
}
Providers["docker"] = conf
}
} }

View File

@@ -12,6 +12,7 @@ import (
"time" "time"
"golang.org/x/crypto/acme/autocert" "golang.org/x/crypto/acme/autocert"
"golang.org/x/oauth2"
gh "github.com/gorilla/handlers" gh "github.com/gorilla/handlers"
"github.com/gorilla/mux" "github.com/gorilla/mux"
@@ -19,9 +20,12 @@ import (
"github.com/play-with-docker/play-with-docker/config" "github.com/play-with-docker/play-with-docker/config"
"github.com/play-with-docker/play-with-docker/event" "github.com/play-with-docker/play-with-docker/event"
"github.com/play-with-docker/play-with-docker/pwd" "github.com/play-with-docker/play-with-docker/pwd"
"github.com/play-with-docker/play-with-docker/pwd/types"
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp" "github.com/prometheus/client_golang/prometheus/promhttp"
"github.com/urfave/negroni" "github.com/urfave/negroni"
oauth2FB "golang.org/x/oauth2/facebook"
oauth2Github "golang.org/x/oauth2/github"
) )
var core pwd.PWDApi var core pwd.PWDApi
@@ -47,7 +51,7 @@ func Bootstrap(c pwd.PWDApi, ev event.EventApi) {
} }
func Register(extend HandlerExtender) { func Register(extend HandlerExtender) {
initLandings() initPlaygrounds()
r := mux.NewRouter() r := mux.NewRouter()
corsRouter := mux.NewRouter() corsRouter := mux.NewRouter()
@@ -168,28 +172,73 @@ func Register(extend HandlerExtender) {
} }
} }
func initLandings() { func initPlaygrounds() {
pgs, err := core.PlaygroundList() pgs, err := core.PlaygroundList()
if err != nil { if err != nil {
log.Fatal("Error getting playgrounds to initialize landings") log.Fatal("Error getting playgrounds for initialization")
} }
for _, p := range pgs {
if p.AssetsDir == "" {
p.AssetsDir = "default"
}
var b bytes.Buffer for _, p := range pgs {
t, err := template.New("landing.html").Delims("[[", "]]").ParseFiles(fmt.Sprintf("./www/%s/landing.html", p.AssetsDir)) initAssets(p)
if err != nil { initOauthProviders(p)
log.Fatalf("Error parsing template %v", err) }
} }
if err := t.Execute(&b, struct{ SegmentId string }{config.SegmentId}); err != nil {
log.Fatalf("Error executing template %v", err) func initAssets(p *types.Playground) {
} if p.AssetsDir == "" {
landingBytes, err := ioutil.ReadAll(&b) p.AssetsDir = "default"
if err != nil { }
log.Fatalf("Error reading template bytes %v", err)
} var b bytes.Buffer
landings[p.Id] = landingBytes t, err := template.New("landing.html").Delims("[[", "]]").ParseFiles(fmt.Sprintf("./www/%s/landing.html", p.AssetsDir))
if err != nil {
log.Fatalf("Error parsing template %v", err)
}
if err := t.Execute(&b, struct{ SegmentId string }{config.SegmentId}); err != nil {
log.Fatalf("Error executing template %v", err)
}
landingBytes, err := ioutil.ReadAll(&b)
if err != nil {
log.Fatalf("Error reading template bytes %v", err)
}
landings[p.Id] = landingBytes
}
func initOauthProviders(p *types.Playground) {
config.Providers[p.Id] = map[string]*oauth2.Config{}
if p.GithubClientID != "" && p.GithubClientSecret != "" {
conf := &oauth2.Config{
ClientID: p.GithubClientID,
ClientSecret: p.GithubClientSecret,
Scopes: []string{"user:email"},
Endpoint: oauth2Github.Endpoint,
}
config.Providers[p.Id]["github"] = conf
}
if p.FacebookClientID != "" && p.FacebookClientSecret != "" {
conf := &oauth2.Config{
ClientID: p.FacebookClientID,
ClientSecret: p.FacebookClientSecret,
Scopes: []string{"email", "public_profile"},
Endpoint: oauth2FB.Endpoint,
}
config.Providers[p.Id]["facebook"] = conf
}
if p.DockerClientID != "" && p.DockerClientSecret != "" {
oauth2.RegisterBrokenAuthHeaderProvider(".id.docker.com")
conf := &oauth2.Config{
ClientID: p.DockerClientID,
ClientSecret: p.DockerClientSecret,
Scopes: []string{"openid"},
Endpoint: oauth2.Endpoint{
AuthURL: "https://id.docker.com/id/oauth/authorize/",
TokenURL: "https://id.docker.com/id/oauth/token",
},
}
config.Providers[p.Id]["docker"] = conf
} }
} }

View File

@@ -34,8 +34,15 @@ func LoggedInUser(rw http.ResponseWriter, req *http.Request) {
} }
func ListProviders(rw http.ResponseWriter, req *http.Request) { func ListProviders(rw http.ResponseWriter, req *http.Request) {
playground := core.PlaygroundFindByDomain(req.Host)
if playground == nil {
log.Printf("Playground for domain %s was not found!", req.Host)
rw.WriteHeader(http.StatusBadRequest)
return
}
providers := []string{} providers := []string{}
for name, _ := range config.Providers { for name, _ := range config.Providers[playground.Id] {
providers = append(providers, name) providers = append(providers, name)
} }
json.NewEncoder(rw).Encode(providers) json.NewEncoder(rw).Encode(providers)
@@ -44,8 +51,14 @@ func ListProviders(rw http.ResponseWriter, req *http.Request) {
func Login(rw http.ResponseWriter, req *http.Request) { func Login(rw http.ResponseWriter, req *http.Request) {
vars := mux.Vars(req) vars := mux.Vars(req)
providerName := vars["provider"] providerName := vars["provider"]
playground := core.PlaygroundFindByDomain(req.Host)
if playground == nil {
log.Printf("Playground for domain %s was not found!", req.Host)
rw.WriteHeader(http.StatusBadRequest)
return
}
provider, found := config.Providers[providerName] provider, found := config.Providers[playground.Id][providerName]
if !found { if !found {
log.Printf("Could not find provider %s\n", providerName) log.Printf("Could not find provider %s\n", providerName)
rw.WriteHeader(http.StatusNotFound) rw.WriteHeader(http.StatusNotFound)
@@ -76,8 +89,14 @@ func Login(rw http.ResponseWriter, req *http.Request) {
func LoginCallback(rw http.ResponseWriter, req *http.Request) { func LoginCallback(rw http.ResponseWriter, req *http.Request) {
vars := mux.Vars(req) vars := mux.Vars(req)
providerName := vars["provider"] providerName := vars["provider"]
playground := core.PlaygroundFindByDomain(req.Host)
if playground == nil {
log.Printf("Playground for domain %s was not found!", req.Host)
rw.WriteHeader(http.StatusBadRequest)
return
}
provider, found := config.Providers[providerName] provider, found := config.Providers[playground.Id][providerName]
if !found { if !found {
log.Printf("Could not find provider %s\n", providerName) log.Printf("Could not find provider %s\n", providerName)
rw.WriteHeader(http.StatusNotFound) rw.WriteHeader(http.StatusNotFound)

View File

@@ -81,4 +81,10 @@ type Playground struct {
Extras PlaygroundExtras `json:"extras" bson:"extras"` Extras PlaygroundExtras `json:"extras" bson:"extras"`
AssetsDir string `json:"assets_dir" bson:"assets_dir"` AssetsDir string `json:"assets_dir" bson:"assets_dir"`
Tasks []string `json:"tasks" bson:"tasks"` Tasks []string `json:"tasks" bson:"tasks"`
GithubClientID string `json:"github_client_id" bson:"github_client_id"`
GithubClientSecret string `json:"github_client_secret" bson:"github_client_secret"`
FacebookClientID string `json:"facebook_client_id" bson:"facebook_client_id"`
FacebookClientSecret string `json:"facebook_client_secret" bson:"facebook_client_secret"`
DockerClientID string `json:"docker_client_id" bson:"docker_client_id"`
DockerClientSecret string `json:"docker_client_secret" bson:"docker_client_secret"`
} }