add alice and maintain a set order on the middlewares. Write uuid as a temporary response header

This commit is contained in:
A.Unger
2020-05-06 14:30:41 +02:00
parent 65b1926d70
commit b74496bbf4
7 changed files with 86 additions and 36 deletions
+6
View File
@@ -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"}
},
+3
View File
@@ -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=
+6 -8
View File
@@ -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)
}
+57
View File
@@ -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)
})
}
+9 -11
View File
@@ -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 {
+3 -3
View File
@@ -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 -14
View File
@@ -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
}