Skip to content

Commit

Permalink
Added serve all command
Browse files Browse the repository at this point in the history
  • Loading branch information
arekkas authored and arekkas committed Nov 3, 2017
1 parent 8362e1c commit dfc071c
Show file tree
Hide file tree
Showing 9 changed files with 247 additions and 130 deletions.
2 changes: 1 addition & 1 deletion Dockerfile-management
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,6 @@ RUN dep ensure -vendor-only
ADD . .
RUN go install .

ENTRYPOINT /go/bin/oathkeeper management
ENTRYPOINT /go/bin/oathkeeper serve management

EXPOSE 4456
2 changes: 1 addition & 1 deletion Dockerfile-proxy
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,6 @@ RUN dep ensure -vendor-only
ADD . .
RUN go install .

ENTRYPOINT /go/bin/oathkeeper proxy
ENTRYPOINT /go/bin/oathkeeper serve proxy

EXPOSE 4455
46 changes: 46 additions & 0 deletions cmd/all.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package cmd

import (
"fmt"

"github.com/ory/hydra/sdk/go/hydra"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)

// allCmd represents the all command
var allCmd = &cobra.Command{
Use: "all",
Short: "A brief description of your command",
Run: func(cmd *cobra.Command, args []string) {
rules, err := newRuleManager(viper.GetString("DATABASE_URL"))
if err != nil {
logger.WithError(err).Fatalln("Unable to connect to rule backend.")
}

pc := &proxyConfig{
hydra: &hydra.Configuration{
ClientID: viper.GetString("HYDRA_CLIENT_ID"),
ClientSecret: viper.GetString("HYDRA_CLIENT_SECRET"),
EndpointURL: viper.GetString("HYDRA_URL"),
Scopes: []string{"hydra.warden"},
},
rules: rules, backendURL: viper.GetString("BACKEND_URL"),
bearerTokenSecret: viper.GetString("JWT_SHARED_SECRET"),
cors: parseCorsOptions(""),
address: fmt.Sprintf("%s:%s", viper.GetString("PROXY_HOST"), viper.GetString("PROXY_PORT")),
}

mc := &managementConfig{
rules: rules,
address: fmt.Sprintf("%s:%s", viper.GetString("MANAGEMENT_HOST"), viper.GetString("MANAGEMENT_PORT")),
}

go runManagement(mc)
runProxy(pc)
},
}

func init() {
serveCmd.AddCommand(allCmd)
}
51 changes: 51 additions & 0 deletions cmd/helper_server.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package cmd

import (
"strconv"
"strings"
"time"

"github.com/ory/oathkeeper/rule"
"github.com/rs/cors"
"github.com/spf13/viper"
)

func refresh(c *proxyConfig, m *rule.CachedMatcher, fails int) {
duration, _ := time.ParseDuration(c.refreshDelay)
if duration == 0 {
duration = time.Second * 30
}

time.Sleep(duration)

if err := m.Refresh(); err != nil {
logger.WithError(err).WithField("retry", fails).Errorln("Unable to refresh rules.")
if fails > 15 {
logger.WithError(err).WithField("retry", fails).Fatalf("Terminating after retry %d.\n", fails)
}

refresh(c, m, fails+1)
return
}

refresh(c, m, 0)
}

func parseCorsOptions(prefix string) cors.Options {
if prefix != "" {
prefix = prefix + "_"
}

allowCredentials, _ := strconv.ParseBool(viper.GetString(prefix + "CORS_ALLOWED_CREDENTIALS"))
debug, _ := strconv.ParseBool(viper.GetString(prefix + "CORS_DEBUG"))
maxAge, _ := strconv.Atoi(viper.GetString(prefix + "CORS_MAX_AGE"))
return cors.Options{
AllowedOrigins: strings.Split(viper.GetString(prefix+"CORS_ALLOWED_ORIGINS"), ","),
AllowedMethods: strings.Split(viper.GetString(prefix+"CORS_ALLOWED_METHODS"), ","),
AllowedHeaders: strings.Split(viper.GetString(prefix+"CORS_ALLOWED_HEADERS"), ","),
ExposedHeaders: strings.Split(viper.GetString(prefix+"CORS_EXPOSED_HEADERS"), ","),
AllowCredentials: allowCredentials,
MaxAge: maxAge,
Debug: debug,
}
}
File renamed without changes.
56 changes: 35 additions & 21 deletions cmd/management.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,38 +29,52 @@ import (
"github.com/urfave/negroni"
)

type managementConfig struct {
rules rule.Manager
address string
}

func runManagement(c *managementConfig) {
handler := rule.Handler{H: herodot.NewJSONWriter(logger), M: c.rules}
router := httprouter.New()
handler.SetRoutes(router)

n := negroni.New()
n.Use(negronilogrus.NewMiddlewareFromLogger(logger, "oahtkeeper-management"))
n.UseHandler(router)

addr := c.address
server := graceful.WithDefaults(&http.Server{
Addr: addr,
Handler: router,
})

logger.Printf("Listening on %s.\n", addr)
if err := graceful.Graceful(server.ListenAndServe, server.Shutdown); err != nil {
logger.Fatalf("Unable to gracefully shutdown HTTP server because %s.\n", err)
return
}
logger.Println("HTTP server was shutdown gracefully")
}

// managementCmd represents the management command
var managementCmd = &cobra.Command{
Use: "management",
Run: func(cmd *cobra.Command, args []string) {
rm, err := newRuleManager(viper.GetString("DATABASE_URL"))
rules, err := newRuleManager(viper.GetString("DATABASE_URL"))
if err != nil {
logger.WithError(err).Fatalln("Unable to connect to rule backend.")
}

handler := rule.Handler{H: herodot.NewJSONWriter(logger), M: rm}
router := httprouter.New()
handler.SetRoutes(router)

n := negroni.New()
n.Use(negronilogrus.NewMiddlewareFromLogger(logger, "oahtkeeper-management"))
n.UseHandler(router)

addr := fmt.Sprintf("%s:%s", viper.GetString("MANAGEMENT_HOST"), viper.GetString("MANAGEMENT_PORT"))
server := graceful.WithDefaults(&http.Server{
Addr: addr,
Handler: router,
})

logger.Printf("Listening on %s.\n", addr)
if err := graceful.Graceful(server.ListenAndServe, server.Shutdown); err != nil {
logger.Fatalf("Unable to gracefully shutdown HTTP server because %s.\n", err)
return
config := &managementConfig{
rules: rules,
address: fmt.Sprintf("%s:%s", viper.GetString("MANAGEMENT_HOST"), viper.GetString("MANAGEMENT_PORT")),
}
logger.Println("HTTP server was shutdown gracefully")

runManagement(config)
},
}

func init() {
RootCmd.AddCommand(managementCmd)
serveCmd.AddCommand(managementCmd)
}
136 changes: 61 additions & 75 deletions cmd/proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,6 @@ import (
"net/http"
"net/http/httputil"
"net/url"
"os"
"strconv"
"strings"
"time"

"github.com/meatballhat/negroni-logrus"
"github.com/ory/graceful"
Expand All @@ -22,99 +18,89 @@ import (
"github.com/urfave/negroni"
)

type proxyConfig struct {
hydra *hydra.Configuration
backendURL string
databaseURL string
cors cors.Options
address string
refreshDelay string
rules rule.Manager
bearerTokenSecret string
}

// proxyCmd represents the proxy command
var proxyCmd = &cobra.Command{
Use: "proxy",
Short: "Runs the reverse proxy",
Run: func(cmd *cobra.Command, args []string) {
sdk, err := hydra.NewSDK(&hydra.Configuration{
ClientID: viper.GetString("HYDRA_CLIENT_ID"),
ClientSecret: viper.GetString("HYDRA_CLIENT_SECRET"),
EndpointURL: viper.GetString("HYDRA_URL"),
Scopes: []string{"hydra.warden"},
})
if err != nil {
logger.WithError(err).Fatalln("Unable to connect to Hydra SDK.")
return
}
backend, err := url.Parse(viper.GetString("BACKEND_URL"))
rules, err := newRuleManager(viper.GetString("DATABASE_URL"))
if err != nil {
logger.WithError(err).Fatalln("Unable to parse backend URL.")
logger.WithError(err).Fatalln("Unable to connect to rule backend.")
}

rm, err := newRuleManager(viper.GetString("DATABASE_URL"))
if err != nil {
logger.WithError(err).Fatalln("Unable to connect to rule backend.")
config := &proxyConfig{
hydra: &hydra.Configuration{
ClientID: viper.GetString("HYDRA_CLIENT_ID"),
ClientSecret: viper.GetString("HYDRA_CLIENT_SECRET"),
EndpointURL: viper.GetString("HYDRA_URL"),
Scopes: []string{"hydra.warden"},
},
rules: rules, backendURL: viper.GetString("BACKEND_URL"),
bearerTokenSecret: viper.GetString("JWT_SHARED_SECRET"),
cors: parseCorsOptions(""),
address: fmt.Sprintf("%s:%s", viper.GetString("PROXY_HOST"), viper.GetString("PROXY_PORT")),
}

matcher := &rule.CachedMatcher{Manager: rm, Rules: []rule.Rule{}}
runProxy(config)
},
}

if err := matcher.Refresh(); err != nil {
logger.WithError(err).Fatalln("Unable to refresh rules.")
}
func runProxy(c *proxyConfig) {
sdk, err := hydra.NewSDK(c.hydra)
if err != nil {
logger.WithError(err).Fatalln("Unable to connect to Hydra SDK.")
return
}
backend, err := url.Parse(c.backendURL)
if err != nil {
logger.WithError(err).Fatalln("Unable to parse backend URL.")
}

go refresh(matcher, 0)
matcher := &rule.CachedMatcher{Manager: c.rules, Rules: []rule.Rule{}}

eval := evaluator.NewWardenEvaluator(logger, matcher, sdk)
d := director.NewDirector(backend, eval, logger, viper.GetString("JWT_SHARED_SECRET"))
proxy := &httputil.ReverseProxy{
Director: d.Director,
Transport: d,
}
if err := matcher.Refresh(); err != nil {
logger.WithError(err).Fatalln("Unable to refresh rules.")
}

n := negroni.New()
n.Use(negronilogrus.NewMiddlewareFromLogger(logger, "oahtkeeper-proxy"))
n.UseHandler(proxy)

allowCredentials, _ := strconv.ParseBool(os.Getenv("CORS_ALLOWED_CREDENTIALS"))
debug, _ := strconv.ParseBool(os.Getenv("CORS_DEBUG"))
maxAge, _ := strconv.Atoi(os.Getenv("CORS_MAX_AGE"))
ch := cors.New(cors.Options{
AllowedOrigins: strings.Split(os.Getenv("CORS_ALLOWED_ORIGINS"), ","),
AllowedMethods: strings.Split(os.Getenv("CORS_ALLOWED_METHODS"), ","),
AllowedHeaders: strings.Split(os.Getenv("CORS_ALLOWED_HEADERS"), ","),
ExposedHeaders: strings.Split(os.Getenv("CORS_EXPOSED_HEADERS"), ","),
AllowCredentials: allowCredentials,
MaxAge: maxAge,
Debug: debug,
}).Handler(n)

addr := fmt.Sprintf("%s:%s", viper.GetString("PROXY_HOST"), viper.GetString("PROXY_PORT"))
server := graceful.WithDefaults(&http.Server{
Addr: addr,
Handler: ch,
})

logger.Printf("Listening on %s.\n", addr)
if err := graceful.Graceful(server.ListenAndServe, server.Shutdown); err != nil {
logger.Fatalf("Unable to gracefully shutdown HTTP server becase %s.\n", err)
return
}
logger.Println("HTTP server was shutdown gracefully")
},
}
go refresh(c, matcher, 0)

func refresh(m *rule.CachedMatcher, fails int) {
duration, _ := time.ParseDuration(viper.GetString("REFRESH_DELAY"))
if duration == 0 {
duration = time.Second * 30
eval := evaluator.NewWardenEvaluator(logger, matcher, sdk)
d := director.NewDirector(backend, eval, logger, c.bearerTokenSecret)
proxy := &httputil.ReverseProxy{
Director: d.Director,
Transport: d,
}

time.Sleep(duration)
n := negroni.New()
n.Use(negronilogrus.NewMiddlewareFromLogger(logger, "oahtkeeper-proxy"))
n.UseHandler(proxy)

if err := m.Refresh(); err != nil {
logger.WithError(err).WithField("retry", fails).Errorln("Unable to refresh rules.")
if fails > 15 {
logger.WithError(err).WithField("retry", fails).Fatalf("Terminating after retry %d.\n", fails)
}
ch := cors.New(c.cors).Handler(n)

refresh(m, fails+1)
server := graceful.WithDefaults(&http.Server{
Addr: c.address,
Handler: ch,
})

logger.Printf("Listening on %s.\n", c.address)
if err := graceful.Graceful(server.ListenAndServe, server.Shutdown); err != nil {
logger.Fatalf("Unable to gracefully shutdown HTTP server because %s.\n", err)
return
}

refresh(m, 0)
logger.Println("HTTP server was shutdown gracefully")
}

func init() {
RootCmd.AddCommand(proxyCmd)
serveCmd.AddCommand(proxyCmd)
}
Loading

0 comments on commit dfc071c

Please sign in to comment.