add RegexSelector

Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de>
This commit is contained in:
Jörn Friedrich Dreyer
2021-07-23 08:22:40 +00:00
parent 40c8031441
commit 4385d3dacb
3 changed files with 98 additions and 4 deletions
+8
View File
@@ -142,6 +142,7 @@ type PolicySelector struct {
Static *StaticSelectorConf
Migration *MigrationSelectorConf
Claims *ClaimsSelectorConf
Regex *RegexSelectorConf
}
// StaticSelectorConf is the config for the static-policy-selector
@@ -173,6 +174,13 @@ type ClaimsSelectorConf struct {
UnauthenticatedPolicy string `mapstructure:"unauthenticated_policy"`
}
// RegexSelectorConf is the config for the regex-selector
type RegexSelectorConf struct {
DefaultPolicy string `mapstructure:"default_policy"`
MatchesPolicies map[string]map[string]string `mapstructure:"matches_policies"`
UnauthenticatedPolicy string `mapstructure:"unauthenticated_policy"`
}
// New initializes a new configuration
func New() *Config {
return &Config{
+9 -4
View File
@@ -26,7 +26,7 @@ func AccountResolver(optionSetters ...Option) func(next http.Handler) http.Handl
"expires": int64(60),
})
if err != nil {
logger.Fatal().Err(err).Msgf("Could not initialize token-manager")
logger.Fatal().Err(err).Msg("Could not initialize token-manager")
}
return &accountResolver{
@@ -53,8 +53,9 @@ type accountResolver struct {
// TODO do not use the context to store values: https://medium.com/@cep21/how-to-correctly-use-context-context-in-go-1-7-8f2c0fafdf39
func (m accountResolver) ServeHTTP(w http.ResponseWriter, req *http.Request) {
claims := oidc.FromContext(req.Context())
u, ok := revauser.ContextGetUser(req.Context())
ctx := req.Context()
claims := oidc.FromContext(ctx)
u, ok := revauser.ContextGetUser(ctx)
if claims == nil && !ok {
m.next.ServeHTTP(w, req)
@@ -99,6 +100,10 @@ func (m accountResolver) ServeHTTP(w http.ResponseWriter, req *http.Request) {
return
}
// add user to context for selectors
ctx = revauser.ContextSetUser(ctx, u)
req = req.WithContext(ctx)
m.logger.Debug().Interface("claims", claims).Interface("user", u).Msg("associated claims with user")
}
@@ -107,7 +112,7 @@ func (m accountResolver) ServeHTTP(w http.ResponseWriter, req *http.Request) {
m.logger.Error().Err(err).Msg("could not get owner scope")
return
}
token, err := m.tokenManager.MintToken(req.Context(), u, s)
token, err := m.tokenManager.MintToken(ctx, u, s)
if err != nil {
m.logger.Error().Err(err).Msg("could not mint token")
w.WriteHeader(http.StatusInternalServerError)
+81
View File
@@ -4,8 +4,10 @@ import (
"context"
"fmt"
"net/http"
"regexp"
"github.com/asim/go-micro/plugins/client/grpc/v3"
revauser "github.com/cs3org/reva/pkg/user"
accounts "github.com/owncloud/ocis/accounts/pkg/proto/v0"
"github.com/owncloud/ocis/ocis-pkg/oidc"
"github.com/owncloud/ocis/proxy/pkg/config"
@@ -71,6 +73,10 @@ func LoadSelector(cfg *config.PolicySelector) (Selector, error) {
return NewClaimsSelector(cfg.Claims), nil
}
if cfg.Regex != nil {
return NewRegexSelector(cfg.Regex), nil
}
return nil, ErrUnexpectedConfigError
}
@@ -123,6 +129,15 @@ func NewMigrationSelector(cfg *config.MigrationSelectorConf, ss accounts.Account
}
// NewClaimsSelector selects the policy based on the "ocis.routing.policy" claim
// The policy for corner cases is configurable:
// "policy_selector": {
// "migration": {
// "default_policy" : "ocis",
// "unauthenticated_policy": "oc10"
// }
// },
//
// This selector can be used in migration-scenarios where some users have already migrated from ownCloud10 to OCIS and
func NewClaimsSelector(cfg *config.ClaimsSelectorConf) Selector {
return func(ctx context.Context, r *http.Request) (s string, err error) {
if claims := oidc.FromContext(r.Context()); claims != nil {
@@ -136,3 +151,69 @@ func NewClaimsSelector(cfg *config.ClaimsSelectorConf) Selector {
return cfg.UnauthenticatedPolicy, nil
}
}
// NewRegexSelector selects the policy based on a user property
// The policy for each case is configurable:
// "policy_selector": {
// "migration": {
// "matches_policies": {
// "mail": {
// "marie@example.com": "oc10"
// "[^@]+@example.com": "ocis"
// },
// "username": {
// "(einstein|feynman)": "ocis"
// "marie": "oc10"
// },
// "id": {
// "4c510ada-c86b-4815-8820-42cdf82c3d51": "ocis"
// "f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c": "oc10"
// },
// },
// "unauthenticated_policy": "oc10"
// }
// },
//
// This selector can be used in migration-scenarios where some users have already migrated from ownCloud10 to OCIS and
func NewRegexSelector(cfg *config.RegexSelectorConf) Selector {
var mailRegexPolicies map[*regexp.Regexp]string
for m, p := range cfg.MatchesPolicies["mail"] {
mailRegexPolicies[regexp.MustCompile(m)] = p
}
var usernameRegexPolicies map[*regexp.Regexp]string
for m, p := range cfg.MatchesPolicies["username"] {
usernameRegexPolicies[regexp.MustCompile(m)] = p
}
var idRegexPolicies map[*regexp.Regexp]string
for m, p := range cfg.MatchesPolicies["id"] {
usernameRegexPolicies[regexp.MustCompile(m)] = p
}
return func(ctx context.Context, r *http.Request) (s string, err error) {
if u, ok := revauser.ContextGetUser(ctx); ok {
if u.Mail != "" {
for r, p := range mailRegexPolicies {
if r.MatchString(u.Mail) {
return p, nil
}
}
}
if u.Username != "" {
for r, p := range usernameRegexPolicies {
if r.MatchString(u.Username) {
return p, nil
}
}
}
if u.Id != nil && u.Id.OpaqueId != "" {
for r, p := range idRegexPolicies {
if r.MatchString(u.Id.OpaqueId) {
return p, nil
}
}
}
return cfg.DefaultPolicy, nil
}
return cfg.UnauthenticatedPolicy, nil
}
}