mirror of
https://github.com/opencloud-eu/opencloud.git
synced 2026-05-18 13:35:37 -04:00
proxy(router): Allow to set some outgoing headers
This introduces the "additional_headers", "remote_user_header" and "skip_x_access_token" config keys to allow configuring routes to external services that require addtional headers to be set. "remote_user_header": defines the name of a Header that will carry the userid of the authenticated user on the outgoing request. "additional_headers": defines a list of header names and values that will be added to outgoing requests on matching routes. "skip_x_access_token": when set to true the reva access token will not be added to the outgoing request. Needed for #206
This commit is contained in:
@@ -64,9 +64,12 @@ type Route struct {
|
||||
// Backend is a static URL to forward the request to
|
||||
Backend string `yaml:"backend,omitempty"`
|
||||
// Service name to look up in the registry
|
||||
Service string `yaml:"service,omitempty"`
|
||||
ApacheVHost bool `yaml:"apache_vhost,omitempty"`
|
||||
Unprotected bool `yaml:"unprotected,omitempty"`
|
||||
Service string `yaml:"service,omitempty"`
|
||||
ApacheVHost bool `yaml:"apache_vhost,omitempty"`
|
||||
Unprotected bool `yaml:"unprotected,omitempty"`
|
||||
AdditionalHeaders map[string]string `yaml:"additional_headers,omitempty"`
|
||||
RemoteUserHeader string `yaml:"remote_user_header,omitempty"`
|
||||
SkipXAccessToken bool `yaml:"skip_x_access_token"`
|
||||
}
|
||||
|
||||
// RouteType defines the type of route
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/jellydator/ttlcache/v3"
|
||||
"github.com/opencloud-eu/opencloud/services/proxy/pkg/router"
|
||||
"github.com/opencloud-eu/opencloud/services/proxy/pkg/user/backend"
|
||||
"github.com/opencloud-eu/opencloud/services/proxy/pkg/userroles"
|
||||
|
||||
@@ -209,7 +210,13 @@ func (m accountResolver) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
}
|
||||
}
|
||||
|
||||
req.Header.Set(revactx.TokenHeader, token)
|
||||
ri := router.ContextRoutingInfo(ctx)
|
||||
if ri.RemoteUserHeader() != "" {
|
||||
req.Header.Set(ri.RemoteUserHeader(), user.GetId().GetOpaqueId())
|
||||
}
|
||||
if !ri.SkipXAccessToken() {
|
||||
req.Header.Set(revactx.TokenHeader, token)
|
||||
}
|
||||
|
||||
m.next.ServeHTTP(w, req)
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
userv1beta1 "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
|
||||
"github.com/opencloud-eu/opencloud/pkg/log"
|
||||
"github.com/opencloud-eu/opencloud/pkg/oidc"
|
||||
"github.com/opencloud-eu/opencloud/services/proxy/pkg/router"
|
||||
"github.com/opencloud-eu/opencloud/services/proxy/pkg/user/backend"
|
||||
"github.com/opencloud-eu/opencloud/services/proxy/pkg/user/backend/mocks"
|
||||
userRoleMocks "github.com/opencloud-eu/opencloud/services/proxy/pkg/userroles/mocks"
|
||||
@@ -206,6 +207,7 @@ func mockRequest(claims map[string]interface{}) (*http.Request, *httptest.Respon
|
||||
}
|
||||
|
||||
ctx := oidc.NewContext(context.Background(), claims)
|
||||
ctx = router.SetRoutingInfo(ctx, router.RoutingInfo{})
|
||||
req := httptest.NewRequest("GET", "http://example.com/foo", nil).WithContext(ctx)
|
||||
rw := httptest.NewRecorder()
|
||||
|
||||
|
||||
@@ -86,9 +86,11 @@ func New(serviceSelector selector.Selector, policySelectorCfg *config.PolicySele
|
||||
|
||||
// RoutingInfo contains the proxy rewrite hook and some information about the route.
|
||||
type RoutingInfo struct {
|
||||
rewrite func(*httputil.ProxyRequest)
|
||||
endpoint string
|
||||
unprotected bool
|
||||
rewrite func(*httputil.ProxyRequest)
|
||||
endpoint string
|
||||
unprotected bool
|
||||
remoteUserHeader string
|
||||
skipXAccessToken bool
|
||||
}
|
||||
|
||||
// Rewrite returns the proxy rewrite hook.
|
||||
@@ -101,6 +103,17 @@ func (r RoutingInfo) IsRouteUnprotected() bool {
|
||||
return r.unprotected
|
||||
}
|
||||
|
||||
// RemoteUserHeader returns the name of Header for setting the remote user value
|
||||
func (r RoutingInfo) RemoteUserHeader() string {
|
||||
return r.remoteUserHeader
|
||||
}
|
||||
|
||||
// SkipXAccessToken return true if the reva access token should not be added to the
|
||||
// outgoing request
|
||||
func (r RoutingInfo) SkipXAccessToken() bool {
|
||||
return r.skipXAccessToken
|
||||
}
|
||||
|
||||
// Router handles the routing of HTTP requests according to the given policies.
|
||||
type Router struct {
|
||||
logger log.Logger
|
||||
@@ -126,8 +139,10 @@ func (rt Router) addHost(policy string, target *url.URL, route config.Route) {
|
||||
}
|
||||
|
||||
rt.rewriters[policy][routeType][route.Method] = append(rt.rewriters[policy][routeType][route.Method], RoutingInfo{
|
||||
endpoint: route.Endpoint,
|
||||
unprotected: route.Unprotected,
|
||||
endpoint: route.Endpoint,
|
||||
unprotected: route.Unprotected,
|
||||
remoteUserHeader: route.RemoteUserHeader,
|
||||
skipXAccessToken: route.SkipXAccessToken,
|
||||
rewrite: func(req *httputil.ProxyRequest) {
|
||||
if route.Service != "" {
|
||||
// select next node
|
||||
@@ -161,6 +176,10 @@ func (rt Router) addHost(policy string, target *url.URL, route config.Route) {
|
||||
req.Out.Host = target.Host
|
||||
}
|
||||
|
||||
for k, v := range route.AdditionalHeaders {
|
||||
req.Out.Header.Set(k, v)
|
||||
}
|
||||
|
||||
req.Out.URL.Path = singleJoiningSlash(target.Path, req.Out.URL.Path)
|
||||
if targetQuery == "" || req.Out.URL.RawQuery == "" {
|
||||
req.Out.URL.RawQuery = targetQuery + req.Out.URL.RawQuery
|
||||
|
||||
Reference in New Issue
Block a user