Skip to content

Commit

Permalink
Merge pull request #48 from Comcast/bascule-auth
Browse files Browse the repository at this point in the history
Added bascule to scytale
  • Loading branch information
kristinapathak committed May 10, 2019
2 parents 98e43b2 + 20b701a commit ea42537
Show file tree
Hide file tree
Showing 5 changed files with 123 additions and 76 deletions.
59 changes: 34 additions & 25 deletions src/glide.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion src/glide.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
package: .
import:
- package: github.com/Comcast/webpa-common
version: 723a128f40c78e45ca079dd113ebb2cf798b7aef
version: v1.0.1
- package: github.com/Comcast/comcast-bascule
version: v0.2.5
130 changes: 83 additions & 47 deletions src/scytale/primaryHandler.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,16 @@ package main
import (
"bytes"
"context"
"encoding/base64"
"errors"
"fmt"
"net/http"

"github.com/Comcast/comcast-bascule/bascule"
"github.com/Comcast/comcast-bascule/bascule/basculehttp"
"github.com/Comcast/webpa-common/basculechecks"
"github.com/Comcast/webpa-common/logging"
"github.com/Comcast/webpa-common/logging/logginghttp"
"github.com/Comcast/webpa-common/secure"
"github.com/Comcast/webpa-common/secure/handler"
"github.com/Comcast/webpa-common/secure/key"
"github.com/Comcast/webpa-common/service"
"github.com/Comcast/webpa-common/service/monitor"
"github.com/Comcast/webpa-common/wrp"
Expand All @@ -39,6 +40,7 @@ import (
"github.com/go-kit/kit/log"
"github.com/go-kit/kit/log/level"
gokithttp "github.com/go-kit/kit/transport/http"
"github.com/goph/emperror"
"github.com/gorilla/mux"
"github.com/justinas/alice"
"github.com/spf13/viper"
Expand All @@ -49,73 +51,106 @@ const (
version = "v2"
)

func SetLogger(logger log.Logger) func(delegate http.Handler) http.Handler {
return func(delegate http.Handler) http.Handler {
return http.HandlerFunc(
func(w http.ResponseWriter, r *http.Request) {
ctx := r.WithContext(logging.WithLogger(r.Context(),
log.With(logger, "requestHeaders", r.Header, "requestURL", r.URL.EscapedPath(), "method", r.Method)))
delegate.ServeHTTP(w, ctx)
})
}
}

func GetLogger(ctx context.Context) bascule.Logger {
logger := log.With(logging.GetLogger(ctx), "ts", log.DefaultTimestampUTC, "caller", log.DefaultCaller)
return logger
}

func populateMessage(ctx context.Context, message *wrp.Message) {
if values, ok := handler.FromContext(ctx); ok {
message.PartnerIDs = values.PartnerIDs
if auth, ok := bascule.FromContext(ctx); ok {
if token := auth.Token; token != nil {
if ids, ok := token.Attributes().Get("partnerIDs"); ok {
if idStr, ok := ids.([]string); ok {
message.PartnerIDs = idStr
}
}
}
}
}

func authChain(v *viper.Viper, logger log.Logger, registry xmetrics.Registry) (alice.Chain, error) {
var (
m = secure.NewJWTValidationMeasures(registry)
validator, err = validators(v, m)
m *basculechecks.JWTValidationMeasures
)

if err != nil {
return alice.Chain{}, err
}

authHandler := handler.AuthorizationHandler{
HeaderName: "Authorization",
ForbiddenStatusCode: 403,
Validator: validator,
Logger: logger,
if registry != nil {
m = basculechecks.NewJWTValidationMeasures(registry)
}
listener := basculechecks.NewMetricListener(m)

authHandler.DefineMeasures(m)
return alice.New(authHandler.Decorate), nil
}

func validators(v *viper.Viper, m *secure.JWTValidationMeasures) (validator secure.Validator, err error) {
var jwtVals []JWTValidator

v.UnmarshalKey("jwtValidators", &jwtVals)
basicAllowed := make(map[string]string)
basicAuth := v.GetStringSlice("authHeader")
for _, a := range basicAuth {
decoded, err := base64.StdEncoding.DecodeString(a)
if err != nil {
logging.Info(logger).Log(logging.MessageKey(), "failed to decode auth header", "authHeader", a, logging.ErrorKey(), err.Error())
}

// if a JWTKeys section was supplied, configure a JWS validator
// and append it to the chain of validators
validators := make(secure.Validators, 0, len(jwtVals))
i := bytes.IndexByte(decoded, ':')
logging.Debug(logger).Log(logging.MessageKey(), "decoded string", "string", decoded, "i", i)
if i > 0 {
basicAllowed[string(decoded[:i])] = string(decoded[i+1:])
}
}
logging.Debug(logger).Log(logging.MessageKey(), "Created list of allowed basic auths", "allowed", basicAllowed, "config", basicAuth)

for _, validatorDescriptor := range jwtVals {
validatorDescriptor.Custom.DefineMeasures(m)
options := []basculehttp.COption{basculehttp.WithCLogger(GetLogger), basculehttp.WithCErrorResponseFunc(listener.OnErrorResponse)}
if len(basicAllowed) > 0 {
options = append(options, basculehttp.WithTokenFactory("Basic", basculehttp.BasicTokenFactory(basicAllowed)))
}
var jwtVal JWTValidator

var keyResolver key.Resolver
keyResolver, err = validatorDescriptor.Keys.NewResolver()
v.UnmarshalKey("jwtValidator", &jwtVal)
if jwtVal.Keys.URI != "" {
resolver, err := jwtVal.Keys.NewResolver()
if err != nil {
validator = validators
return
return alice.Chain{}, emperror.With(err, "failed to create resolver")
}

validator := secure.JWSValidator{
options = append(options, basculehttp.WithTokenFactory("Bearer", basculehttp.BearerTokenFactory{
DefaultKeyId: DefaultKeyID,
Resolver: keyResolver,
JWTValidators: []*jwt.Validator{validatorDescriptor.Custom.New()},
}
Resolver: resolver,
Parser: bascule.DefaultJWSParser,
JWTValidators: []*jwt.Validator{jwtVal.Custom.New()},
}))
}

authConstructor := basculehttp.NewConstructor(options...)

validator.DefineMeasures(m)
validators = append(validators, validator)
bearerRules := []bascule.Validator{
bascule.CreateNonEmptyPrincipalCheck(),
bascule.CreateNonEmptyTypeCheck(),
bascule.CreateValidTypeCheck([]string{"jwt"}),
}

basicAuth := v.GetStringSlice("authHeader")
for _, authValue := range basicAuth {
validators = append(
validators,
secure.ExactMatchValidator(authValue),
)
// only add capability check if the configuration is set
var capabilityConfig basculechecks.CapabilityConfig
v.UnmarshalKey("capabilityConfig", &capabilityConfig)
if capabilityConfig.FirstPiece != "" && capabilityConfig.SecondPiece != "" && capabilityConfig.ThirdPiece != "" {
bearerRules = append(bearerRules, bascule.CreateListAttributeCheck("capabilities", basculechecks.CreateValidCapabilityCheck(capabilityConfig)))
}

validator = validators
authEnforcer := basculehttp.NewEnforcer(
basculehttp.WithELogger(GetLogger),
basculehttp.WithRules("Basic", []bascule.Validator{
bascule.CreateAllowAllCheck(),
}),
basculehttp.WithRules("Bearer", bearerRules),
basculehttp.WithEErrorResponseFunc(listener.OnErrorResponse),
)

return
return alice.New(SetLogger(logger), authConstructor, authEnforcer, basculehttp.NewListenerDecorator(listener)), nil
}

// createEndpoints examines the configuration and produces an appropriate fanout.Endpoints, either using the configured
Expand Down Expand Up @@ -150,6 +185,7 @@ func NewPrimaryHandler(logger log.Logger, v *viper.Viper, registry xmetrics.Regi
if err := v.UnmarshalKey("fanout", &cfg); err != nil {
return nil, err
}
logging.Error(logger).Log(logging.MessageKey(), "creating primary handler")

endpoints, err := createEndpoints(logger, cfg, registry, e)
if err != nil {
Expand Down
4 changes: 2 additions & 2 deletions src/scytale/scytale.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ import (
"os"
"os/signal"

"github.com/Comcast/webpa-common/basculechecks"
"github.com/Comcast/webpa-common/concurrent"
"github.com/Comcast/webpa-common/logging"
"github.com/Comcast/webpa-common/secure"
"github.com/Comcast/webpa-common/server"
"github.com/Comcast/webpa-common/service"
"github.com/Comcast/webpa-common/service/servicecfg"
Expand Down Expand Up @@ -54,7 +54,7 @@ func scytale(arguments []string) int {
f = pflag.NewFlagSet(applicationName, pflag.ContinueOnError)
v = viper.New()

logger, metricsRegistry, webPA, err = server.Initialize(applicationName, arguments, f, v, webhook.Metrics, aws.Metrics, secure.Metrics)
logger, metricsRegistry, webPA, err = server.Initialize(applicationName, arguments, f, v, webhook.Metrics, aws.Metrics, basculechecks.Metrics)
)

if err != nil {
Expand Down
2 changes: 1 addition & 1 deletion src/scytale/scytale_type.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@
package main

import (
"github.com/Comcast/comcast-bascule/bascule/key"
"github.com/Comcast/webpa-common/secure"
"github.com/Comcast/webpa-common/secure/key"
)

//JWTValidator provides a convenient way to define jwt validator through config files
Expand Down

0 comments on commit ea42537

Please sign in to comment.