add alice and maintain a set order on the middlewares. Write uuid as a temporary response header
This commit is contained in:
@@ -2,6 +2,12 @@
|
||||
"HTTP": {
|
||||
"Namespace": "com.owncloud"
|
||||
},
|
||||
"oidc": {
|
||||
"endpoint": "https://localhost:9200",
|
||||
"realm": "",
|
||||
"signing_algs": ["RS256", "PS256"],
|
||||
"insecure": true
|
||||
},
|
||||
"policy_selector": {
|
||||
"static": {"policy" : "reva"}
|
||||
},
|
||||
|
||||
@@ -243,6 +243,7 @@ github.com/go-acme/lego/v3 v3.1.0/go.mod h1:074uqt+JS6plx+c9Xaiz6+L+GBb+7itGtzfc
|
||||
github.com/go-acme/lego/v3 v3.3.0/go.mod h1:iGSY2vQrvQs3WezicSB/oVbO2eCrD88dpWPwb1qLqu0=
|
||||
github.com/go-chi/chi v4.0.2+incompatible h1:maB6vn6FqCxrpz4FqWdh4+lwpyZIQS7YEAUcHlgXVRs=
|
||||
github.com/go-chi/chi v4.0.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ=
|
||||
github.com/go-chi/chi v4.1.0+incompatible h1:ETj3cggsVIY2Xao5ExCu6YhEh5MD6JTfcBzS37R260w=
|
||||
github.com/go-chi/chi v4.1.0+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ=
|
||||
github.com/go-chi/render v1.0.1/go.mod h1:pq4Rr7HbnsdaeHagklXub+p6Wd16Af5l9koip1OvJns=
|
||||
github.com/go-cmd/cmd v1.0.5/go.mod h1:y8q8qlK5wQibcw63djSl/ntiHUHXHGdCkPk0j4QeW4s=
|
||||
@@ -308,6 +309,7 @@ github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi
|
||||
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
||||
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
||||
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
||||
github.com/golang/protobuf v1.4.0 h1:oOuy+ugB+P/kBdUnG5QaMXSIyJ1q38wWSojYCb3z5VQ=
|
||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
@@ -1073,6 +1075,7 @@ google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLY
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
||||
google.golang.org/protobuf v1.21.0 h1:qdOKuR/EIArgaWNjetjgTzgVTAZ+S/WXVrq9HW9zimw=
|
||||
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
||||
gopkg.in/DataDog/dd-trace-go.v1 v1.19.0/go.mod h1:DVp8HmDh8PuTu2Z0fVVlBsyWaC++fzwVCaGWylTe3tg=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/justinas/alice"
|
||||
"github.com/owncloud/ocis-pkg/v2/log"
|
||||
"github.com/owncloud/ocis-pkg/v2/oidc"
|
||||
"github.com/owncloud/ocis-proxy/pkg/middleware"
|
||||
@@ -154,7 +155,7 @@ func Server(cfg *config.Config) *cli.Command {
|
||||
proxyHTTP.Metrics(metrics),
|
||||
proxyHTTP.Flags(flagset.RootWithConfig(config.New())),
|
||||
proxyHTTP.Flags(flagset.ServerWithConfig(config.New())),
|
||||
proxyHTTP.Middlewares(loadMiddlewares(cfg, logger)...),
|
||||
proxyHTTP.Middlewares(loadMiddlewares(cfg, logger)),
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
@@ -234,11 +235,7 @@ func Server(cfg *config.Config) *cli.Command {
|
||||
}
|
||||
}
|
||||
|
||||
func loadMiddlewares(cfg *config.Config, l log.Logger) []middleware.M {
|
||||
var configuredMiddlewares = make([]middleware.M, 0)
|
||||
|
||||
configuredMiddlewares = append(configuredMiddlewares, middleware.RedirectToHTTPS)
|
||||
|
||||
func loadMiddlewares(cfg *config.Config, l log.Logger) alice.Chain {
|
||||
if cfg.OIDC != nil {
|
||||
l.Info().Msg("Loading OIDC-Middleware")
|
||||
l.Debug().Interface("oidc_config", cfg.OIDC).Msg("OIDC-Config")
|
||||
@@ -250,8 +247,9 @@ func loadMiddlewares(cfg *config.Config, l log.Logger) []middleware.M {
|
||||
oidc.Logger(l),
|
||||
)
|
||||
|
||||
configuredMiddlewares = append(configuredMiddlewares, oidcMW)
|
||||
// configuredMiddlewares = append(configuredMiddlewares, oidcMW, middleware.AccountUUID)
|
||||
return alice.New(middleware.RedirectToHTTPS, oidcMW, middleware.AccountUUID)
|
||||
}
|
||||
|
||||
return configuredMiddlewares
|
||||
return alice.New(middleware.RedirectToHTTPS)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
|
||||
mclient "github.com/micro/go-micro/v2/client"
|
||||
acc "github.com/owncloud/ocis-accounts/pkg/proto/v0"
|
||||
ocisoidc "github.com/owncloud/ocis-pkg/v2/oidc"
|
||||
)
|
||||
|
||||
// AccountUUID fetches the ocis account uuid from the oidc standard claims
|
||||
func AccountUUID(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
claims := r.Context().Value(ClaimsKey)
|
||||
if claims == nil {
|
||||
next.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
entry, err := svcCache.Get(AccountsKey, claims.(ocisoidc.StandardClaims).Email)
|
||||
if err != nil {
|
||||
c := acc.NewSettingsService("com.owncloud.accounts", mclient.DefaultClient) // TODO this won't work with a registry other than mdns. Look into Micro's client initialization.
|
||||
resp, err := c.Get(context.Background(), &acc.Query{
|
||||
Key: "200~a54bf154-e6a5-4e96-851b-a56c9f6c1fce",
|
||||
// Email: claims.Email // depends on https://github.com/owncloud/ocis-accounts/pull/28
|
||||
})
|
||||
if err != nil {
|
||||
// placeholder. Add more meaningful response
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
err = svcCache.Set(AccountsKey, claims.(ocisoidc.StandardClaims).Email, resp.Payload.Account.Uuid)
|
||||
if err != nil {
|
||||
// placeholder. Add more meaningful response
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
// TODO: build JWT and set it, instead of the uuid on that header.
|
||||
w.Header().Set("x-ocis-accounts-uuid", resp.Payload.Account.Uuid)
|
||||
}
|
||||
|
||||
uuid, ok := entry.V.(string)
|
||||
if !ok {
|
||||
// placeholder. Add more meaningful response
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
// TODO: build JWT and set it, instead of the uuid on that header.
|
||||
w.Header().Set("x-ocis-accounts-uuid", uuid)
|
||||
|
||||
next.ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
@@ -28,6 +28,9 @@ var (
|
||||
|
||||
// UUIDKey works as a context key
|
||||
UUIDKey interface{} = "uuid"
|
||||
|
||||
// ClaimsKey works as a context key for user claims
|
||||
ClaimsKey interface{} = "claims"
|
||||
)
|
||||
|
||||
// newOIDCOptions initializes the available default options.
|
||||
@@ -42,7 +45,7 @@ func newOIDCOptions(opts ...ocisoidc.Option) ocisoidc.Options {
|
||||
}
|
||||
|
||||
// OpenIDConnect provides a middleware to check access secured by a static token.
|
||||
func OpenIDConnect(opts ...ocisoidc.Option) M {
|
||||
func OpenIDConnect(opts ...ocisoidc.Option) func(next http.Handler) http.Handler {
|
||||
opt := newOIDCOptions(opts...)
|
||||
|
||||
// set defaults
|
||||
@@ -60,14 +63,6 @@ func OpenIDConnect(opts ...ocisoidc.Option) M {
|
||||
header := r.Header.Get("Authorization")
|
||||
path := r.URL.Path
|
||||
|
||||
uuid, err := uuidFromClaims(ocisoidc.StandardClaims{})
|
||||
if err != nil {
|
||||
// stop the auth flow altogether?
|
||||
}
|
||||
|
||||
withUUID := context.WithValue(r.Context(), UUIDKey, uuid)
|
||||
r = r.WithContext(withUUID)
|
||||
|
||||
// Ignore request to "/konnect/v1/userinfo" as this will cause endless loop when getting userinfo
|
||||
// needs a better idea on how to not hardcode this
|
||||
if header == "" || !strings.HasPrefix(header, "Bearer ") || path == "/konnect/v1/userinfo" {
|
||||
@@ -122,10 +117,13 @@ func OpenIDConnect(opts ...ocisoidc.Option) M {
|
||||
return
|
||||
}
|
||||
|
||||
// inject claims to the request context for the account_uuid middleware.
|
||||
ctxWithClaims := context.WithValue(r.Context(), ClaimsKey, claims)
|
||||
r = r.WithContext(ctxWithClaims)
|
||||
|
||||
// add UUID to the request context for the handler to deal with
|
||||
// void call for correct staticchecks.
|
||||
_, err = uuidFromClaims(claims)
|
||||
|
||||
if err != nil {
|
||||
opt.Logger.Error().Err(err).Interface("account uuid", userInfo).Msg("failed to unmarshal userinfo claims")
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
@@ -164,7 +162,7 @@ func uuidFromClaims(claims ocisoidc.StandardClaims) (string, error) {
|
||||
if err != nil {
|
||||
c := acc.NewSettingsService("com.owncloud.accounts", mclient.DefaultClient) // TODO this won't work with a registry other than mdns. Look into Micro's client initialization.
|
||||
resp, err := c.Get(context.Background(), &acc.Query{
|
||||
Key: "200~a54bf154-e6a5-4e96-851b-a56c9f6c1fce", // use hardcoded key...
|
||||
Key: "200~a54bf154-e6a5-4e96-851b-a56c9f6c1fce",
|
||||
// Email: claims.Email // depends on https://github.com/owncloud/ocis-accounts/pull/28
|
||||
})
|
||||
if err != nil {
|
||||
|
||||
@@ -4,11 +4,11 @@ import (
|
||||
"context"
|
||||
"net/http"
|
||||
|
||||
"github.com/justinas/alice"
|
||||
"github.com/micro/cli/v2"
|
||||
"github.com/owncloud/ocis-pkg/v2/log"
|
||||
"github.com/owncloud/ocis-proxy/pkg/config"
|
||||
"github.com/owncloud/ocis-proxy/pkg/metrics"
|
||||
"github.com/owncloud/ocis-proxy/pkg/middleware"
|
||||
)
|
||||
|
||||
// Option defines a single option function.
|
||||
@@ -23,7 +23,7 @@ type Options struct {
|
||||
Metrics *metrics.Metrics
|
||||
Flags []cli.Flag
|
||||
Namespace string
|
||||
Middlewares []middleware.M
|
||||
Middlewares alice.Chain
|
||||
}
|
||||
|
||||
// newOptions initializes the available default options.
|
||||
@@ -87,7 +87,7 @@ func Handler(h http.Handler) Option {
|
||||
}
|
||||
|
||||
// Middlewares provides a function to register middlewares
|
||||
func Middlewares(val ...middleware.M) Option {
|
||||
func Middlewares(val alice.Chain) Option {
|
||||
return func(o *Options) {
|
||||
o.Middlewares = val
|
||||
}
|
||||
|
||||
@@ -2,12 +2,10 @@ package http
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"net/http"
|
||||
"os"
|
||||
|
||||
svc "github.com/owncloud/ocis-pkg/v2/service/http"
|
||||
"github.com/owncloud/ocis-proxy/pkg/crypto"
|
||||
"github.com/owncloud/ocis-proxy/pkg/middleware"
|
||||
"github.com/owncloud/ocis-proxy/pkg/version"
|
||||
)
|
||||
|
||||
@@ -40,6 +38,7 @@ func Server(opts ...Option) (svc.Service, error) {
|
||||
}
|
||||
|
||||
tlsConfig := &tls.Config{Certificates: []tls.Certificate{cer}}
|
||||
chain := options.Middlewares.Then(options.Handler)
|
||||
|
||||
service := svc.NewService(
|
||||
svc.Name("web.proxy"),
|
||||
@@ -50,9 +49,7 @@ func Server(opts ...Option) (svc.Service, error) {
|
||||
svc.Address(options.Config.HTTP.Addr),
|
||||
svc.Context(options.Context),
|
||||
svc.Flags(options.Flags...),
|
||||
svc.Handler(
|
||||
applyMiddlewares(options.Handler, options.Middlewares...),
|
||||
),
|
||||
svc.Handler(chain),
|
||||
)
|
||||
|
||||
if err := service.Init(); err != nil {
|
||||
@@ -61,12 +58,3 @@ func Server(opts ...Option) (svc.Service, error) {
|
||||
|
||||
return service, nil
|
||||
}
|
||||
|
||||
func applyMiddlewares(next http.Handler, mws ...middleware.M) http.Handler {
|
||||
var h = next
|
||||
for _, mw := range mws {
|
||||
h = mw(h)
|
||||
}
|
||||
|
||||
return h
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user