Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

proxy #57

Merged
merged 1 commit into from
Jan 17, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 37 additions & 37 deletions services/proxy/README.md

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions services/proxy/pkg/command/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@ func GetCommands(cfg *config.Config) cli.Commands {
}
}

// Execute is the entry point for the ocis-proxy command.
// Execute is the entry point for the opencloud-proxy command.
func Execute(cfg *config.Config) error {
app := clihelper.DefaultApp(&cli.App{
Name: "proxy",
Usage: "proxy for oCIS",
Usage: "proxy for OpenCloud",
Commands: GetCommands(cfg),
})

Expand Down
10 changes: 5 additions & 5 deletions services/proxy/pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ type OIDC struct {
type JWKS struct {
RefreshInterval uint64 `yaml:"refresh_interval" env:"PROXY_OIDC_JWKS_REFRESH_INTERVAL" desc:"The interval for refreshing the JWKS (JSON Web Key Set) in minutes in the background via a new HTTP request to the IDP." introductionVersion:"pre5.0"`
RefreshTimeout uint64 `yaml:"refresh_timeout" env:"PROXY_OIDC_JWKS_REFRESH_TIMEOUT" desc:"The timeout in seconds for an outgoing JWKS request." introductionVersion:"pre5.0"`
RefreshRateLimit uint64 `yaml:"refresh_limit" env:"PROXY_OIDC_JWKS_REFRESH_RATE_LIMIT" desc:"Limits the rate in seconds at which refresh requests are performed for unknown keys. This is used to prevent malicious clients from imposing high network load on the IDP via ocis." introductionVersion:"pre5.0"`
RefreshRateLimit uint64 `yaml:"refresh_limit" env:"PROXY_OIDC_JWKS_REFRESH_RATE_LIMIT" desc:"Limits the rate in seconds at which refresh requests are performed for unknown keys. This is used to prevent malicious clients from imposing high network load on the IDP via OpenCloud." introductionVersion:"pre5.0"`
RefreshUnknownKID bool `yaml:"refresh_unknown_kid" env:"PROXY_OIDC_JWKS_REFRESH_UNKNOWN_KID" desc:"If set to 'true', the JWKS refresh request will occur every time an unknown KEY ID (KID) is seen. Always set a 'refresh_limit' when enabling this." introductionVersion:"pre5.0"`
}

Expand All @@ -146,12 +146,12 @@ type RoleAssignment struct {
// OIDCRoleMapper contains the configuration for the "oidc" role assignment driver
type OIDCRoleMapper struct {
RoleClaim string `yaml:"role_claim" env:"PROXY_ROLE_ASSIGNMENT_OIDC_CLAIM" desc:"The OIDC claim used to create the users role assignment." introductionVersion:"pre5.0"`
RolesMap []RoleMapping `yaml:"role_mapping" desc:"A list of mappings of ocis role names to PROXY_ROLE_ASSIGNMENT_OIDC_CLAIM claim values. This setting can only be configured in the configuration file and not via environment variables."`
RolesMap []RoleMapping `yaml:"role_mapping" desc:"A list of mappings of OpenCloud role names to PROXY_ROLE_ASSIGNMENT_OIDC_CLAIM claim values. This setting can only be configured in the configuration file and not via environment variables."`
}

// RoleMapping defines which ocis role matches a specific claim value
// RoleMapping defines which OpenCloud role matches a specific claim value
type RoleMapping struct {
RoleName string `yaml:"role_name" desc:"The name of an ocis role that this mapping should apply for."`
RoleName string `yaml:"role_name" desc:"The name of an OpenCloud role that this mapping should apply for."`
ClaimValue string `yaml:"claim_value" desc:"The value of the 'PROXY_ROLE_ASSIGNMENT_OIDC_CLAIM' that matches the role defined in 'role_name'."`
}

Expand Down Expand Up @@ -184,7 +184,7 @@ type PreSignedURL struct {

// SigningKeys is a store configuration.
type SigningKeys struct {
Store string `yaml:"store" env:"OC_CACHE_STORE;PROXY_PRESIGNEDURL_SIGNING_KEYS_STORE" desc:"The type of the signing key store. Supported values are: 'redis-sentinel', 'nats-js-kv' and 'ocisstoreservice' (deprecated). See the text description for details." introductionVersion:"5.0"`
Store string `yaml:"store" env:"OC_CACHE_STORE;PROXY_PRESIGNEDURL_SIGNING_KEYS_STORE" desc:"The type of the signing key store. Supported values are: 'redis-sentinel', 'nats-js-kv' and 'opencloudstoreservice' (deprecated). See the text description for details." introductionVersion:"5.0"`
Nodes []string `yaml:"addresses" env:"OC_CACHE_STORE_NODES;PROXY_PRESIGNEDURL_SIGNING_KEYS_STORE_NODES" desc:"A list of nodes to access the configured store. Note that the behaviour how nodes are used is dependent on the library of the configured store. See the Environment Variable Types description for more details." introductionVersion:"5.0"`
TTL time.Duration `yaml:"ttl" env:"OC_CACHE_TTL;PROXY_PRESIGNEDURL_SIGNING_KEYS_STORE_TTL" desc:"Default time to live for signing keys. See the Environment Variable Types description for more details." introductionVersion:"5.0"`
DisablePersistence bool `yaml:"disable_persistence" env:"OC_CACHE_DISABLE_PERSISTENCE;PROXY_PRESIGNEDURL_SIGNING_KEYS_STORE_DISABLE_PERSISTENCE" desc:"Disables persistence of the store. Only applies when store type 'nats-js-kv' is configured. Defaults to true." introductionVersion:"5.0"`
Expand Down
4 changes: 2 additions & 2 deletions services/proxy/pkg/config/csp.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ directives:
connect-src:
- '''self'''
- 'blob:'
- 'https://raw.githubusercontent.com/owncloud/awesome-ocis/'
- 'https://raw.githubusercontent.com/opencloud-eu/awesome/'
default-src:
- '''none'''
font-src:
Expand All @@ -19,7 +19,7 @@ directives:
- '''self'''
- 'data:'
- 'blob:'
- 'https://raw.githubusercontent.com/owncloud/awesome-ocis/'
- 'https://raw.githubusercontent.com/opencloud-eu/awesome/'
manifest-src:
- '''self'''
media-src:
Expand Down
14 changes: 7 additions & 7 deletions services/proxy/pkg/config/defaults/defaultconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,10 @@ func DefaultConfig() *config.Config {
OIDCRoleMapper: config.OIDCRoleMapper{
RoleClaim: "roles",
RolesMap: []config.RoleMapping{
{RoleName: "admin", ClaimValue: "ocisAdmin"},
{RoleName: "spaceadmin", ClaimValue: "ocisSpaceAdmin"},
{RoleName: "user", ClaimValue: "ocisUser"},
{RoleName: "user-light", ClaimValue: "ocisGuest"},
{RoleName: "admin", ClaimValue: "opencloudAdmin"},
{RoleName: "spaceadmin", ClaimValue: "opencloudSpaceAdmin"},
{RoleName: "user", ClaimValue: "opencloudUser"},
{RoleName: "user-light", ClaimValue: "opencloudGuest"},
},
},
},
Expand Down Expand Up @@ -107,7 +107,7 @@ func DefaultConfig() *config.Config {
func DefaultPolicies() []config.Policy {
return []config.Policy{
{
Name: "ocis",
Name: "opencloud",
Routes: []config.Route{
{
Endpoint: "/",
Expand Down Expand Up @@ -159,7 +159,7 @@ func DefaultPolicies() []config.Policy {
},
{
Type: config.RegexRoute,
Endpoint: "/ocs/v[12].php/cloud/user/signing-key", // only `user/signing-key` is left in ocis-ocs
Endpoint: "/ocs/v[12].php/cloud/user/signing-key", // only `user/signing-key` is left in opencloud-ocs
Service: "eu.opencloud.web.ocs",
},
{
Expand Down Expand Up @@ -330,7 +330,7 @@ func Sanitize(cfg *config.Config) {
if cfg.PolicySelector == nil {
cfg.PolicySelector = &config.PolicySelector{
Static: &config.StaticSelectorConf{
Policy: "ocis",
Policy: "opencloud",
},
}
}
Expand Down
2 changes: 1 addition & 1 deletion services/proxy/pkg/middleware/authentication.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ var (
SupportedAuthStrategies []string

// ProxyWwwAuthenticate is a list of endpoints that do not rely on reva underlying authentication, such as ocs.
// services that fallback to reva authentication are declared in the "frontend" command on oCIS. It is a list of
// services that fallback to reva authentication are declared in the "frontend" command on OpenCloud. It is a list of
// regexp.Regexp which are safe to use concurrently.
ProxyWwwAuthenticate = []regexp.Regexp{*regexp.MustCompile("/ocs/v[12].php/cloud/")}

Expand Down
11 changes: 6 additions & 5 deletions services/proxy/pkg/middleware/security_test.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
package middleware

import (
"gotest.tools/v3/assert"
"testing"

"gotest.tools/v3/assert"
)

func TestLoadCSPConfig(t *testing.T) {
Expand All @@ -12,8 +13,8 @@ directives:
frame-src:
- '''self'''
- 'https://embed.diagrams.net/'
- 'https://${ONLYOFFICE_DOMAIN|onlyoffice.owncloud.test}/'
- 'https://${COLLABORA_DOMAIN|collabora.owncloud.test}/'
- 'https://${ONLYOFFICE_DOMAIN|onlyoffice.opencloud.test}/'
- 'https://${COLLABORA_DOMAIN|collabora.opencloud.test}/'
`

config, err := loadCSPConfig([]byte(yaml))
Expand All @@ -22,6 +23,6 @@ directives:
}
assert.Equal(t, config.Directives["frame-src"][0], "'self'")
assert.Equal(t, config.Directives["frame-src"][1], "https://embed.diagrams.net/")
assert.Equal(t, config.Directives["frame-src"][2], "https://onlyoffice.owncloud.test/")
assert.Equal(t, config.Directives["frame-src"][3], "https://collabora.owncloud.test/")
assert.Equal(t, config.Directives["frame-src"][2], "https://onlyoffice.opencloud.test/")
assert.Equal(t, config.Directives["frame-src"][3], "https://collabora.opencloud.test/")
}
2 changes: 1 addition & 1 deletion services/proxy/pkg/middleware/signed_url_auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ func (m SignedURLAuthenticator) validate(req *http.Request) (err error) {
func (m SignedURLAuthenticator) allRequiredParametersArePresent(query url.Values) (err error) {
// check if required query parameters exist in given request query parameters
// OC-Signature - the computed signature - server will verify the request upon this REQUIRED
// OC-Credential - defines the user scope (shall we use the owncloud user id here - this might leak internal data ....) REQUIRED
// OC-Credential - defines the user scope (shall we use the opencloud user id here - this might leak internal data ....) REQUIRED
// OC-Date - defined the date the url was signed (ISO 8601 UTC) REQUIRED
// OC-Expires - defines the expiry interval in seconds (between 1 and 604800 = 7 days) REQUIRED
// TODO OC-Verb - defines for which http verb the request is valid - defaults to GET OPTIONAL
Expand Down
4 changes: 2 additions & 2 deletions services/proxy/pkg/proxy/policy/selector.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ var (
)

const (
SelectorCookieName = "owncloud-selector"
SelectorCookieName = "opencloud-selector"
)

// Selector is a function which selects a proxy-policy based on the request.
Expand Down Expand Up @@ -107,7 +107,7 @@ func NewStaticSelector(cfg *config.StaticSelectorConf) Selector {
}
}

// NewClaimsSelector selects the policy based on the "ocis.routing.policy" claim
// NewClaimsSelector selects the policy based on the "opencloud.routing.policy" claim
// The policy for corner cases is configurable:
//
// "policy_selector": {
Expand Down
6 changes: 3 additions & 3 deletions services/proxy/pkg/proxy/policy/selector_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,9 @@ func TestClaimsSelector(t *testing.T) {
var tests = []testCase{
{"unauthenticated", context.Background(), nil, "unauthenticated"},
{"default", oidc.NewContext(context.Background(), map[string]interface{}{oidc.OcisRoutingPolicy: ""}), nil, "default"},
{"claim-value", oidc.NewContext(context.Background(), map[string]interface{}{oidc.OcisRoutingPolicy: "ocis.routing.policy-value"}), nil, "ocis.routing.policy-value"},
{"claim-value", oidc.NewContext(context.Background(), map[string]interface{}{oidc.OcisRoutingPolicy: "opencloud.routing.policy-value"}), nil, "opencloud.routing.policy-value"},
{"cookie-only", context.Background(), &http.Cookie{Name: SelectorCookieName, Value: "cookie"}, "cookie"},
{"claim-can-override-cookie", oidc.NewContext(context.Background(), map[string]interface{}{oidc.OcisRoutingPolicy: "ocis.routing.policy-value"}), &http.Cookie{Name: SelectorCookieName, Value: "cookie"}, "ocis.routing.policy-value"},
{"claim-can-override-cookie", oidc.NewContext(context.Background(), map[string]interface{}{oidc.OcisRoutingPolicy: "opencloud.routing.policy-value"}), &http.Cookie{Name: SelectorCookieName, Value: "cookie"}, "opencloud.routing.policy-value"},
}
for _, tc := range tests {
r := httptest.NewRequest("GET", "https://example.com", nil)
Expand Down Expand Up @@ -118,7 +118,7 @@ func TestRegexSelector(t *testing.T) {
var tests = []testCase{
{"unauthenticated", context.Background(), nil, "unauthenticated"},
{"default", revactx.ContextSetUser(context.Background(), &userv1beta1.User{}), nil, "default"},
{"mail-ocis", revactx.ContextSetUser(context.Background(), &userv1beta1.User{Mail: "[email protected]"}), nil, "opencloud"},
{"mail-opencloud", revactx.ContextSetUser(context.Background(), &userv1beta1.User{Mail: "[email protected]"}), nil, "opencloud"},
{"mail-oc10", revactx.ContextSetUser(context.Background(), &userv1beta1.User{Mail: "[email protected]"}), nil, "oc10"},
{"username-einstein", revactx.ContextSetUser(context.Background(), &userv1beta1.User{Username: "einstein"}), nil, "opencloud"},
{"username-feynman", revactx.ContextSetUser(context.Background(), &userv1beta1.User{Username: "feynman"}), nil, "opencloud"},
Expand Down
4 changes: 2 additions & 2 deletions services/proxy/pkg/router/router_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ func TestRouter(t *testing.T) {
Routes: []config.Route{
{Type: config.PrefixRoute, Endpoint: "/web/unprotected/demo/", Backend: "http://web", Unprotected: true},
{Type: config.PrefixRoute, Endpoint: "/dav", Backend: "http://ocdav"},
{Type: config.PrefixRoute, Method: "REPORT", Endpoint: "/dav", Backend: "http://ocis-webdav"},
{Type: config.PrefixRoute, Method: "REPORT", Endpoint: "/dav", Backend: "http://opencloud-webdav"},
},
},
}
Expand All @@ -139,7 +139,7 @@ func TestRouter(t *testing.T) {

table := []matchertest{
{method: "PROPFIND", endpoint: "/dav/files/demo/", target: "ocdav"},
{method: "REPORT", endpoint: "/dav/files/demo/", target: "ocis-webdav"},
{method: "REPORT", endpoint: "/dav/files/demo/", target: "opencloud-webdav"},
{method: "GET", endpoint: "/web/unprotected/demo/", target: "web", unprotected: true},
}

Expand Down
6 changes: 3 additions & 3 deletions services/proxy/pkg/userroles/oidcroles.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,19 +92,19 @@ func (ra oidcRoleAssigner) UpdateUserRoleAssignment(ctx context.Context, user *c
}

// the roleMapping config is supposed to have the role mappings ordered from the highest privileged role
// down to the lowest privileged role. Since ocis currently only can handle a single role assignment we
// down to the lowest privileged role. Since OpenCloud currently only can handle a single role assignment we
// pick the highest privileged role that matches a value from the claims
roleIDFromClaim := ""
for _, mapping := range ra.Options.roleMapping {
if _, ok := claimRoles[mapping.ClaimValue]; ok {
logger.Debug().Str("ocisRole", mapping.RoleName).Str("role id", roleNamesToRoleIDs[mapping.RoleName]).Msg("first matching role")
logger.Debug().Str("opencloudRole", mapping.RoleName).Str("role id", roleNamesToRoleIDs[mapping.RoleName]).Msg("first matching role")
roleIDFromClaim = roleNamesToRoleIDs[mapping.RoleName]
break
}
}

if roleIDFromClaim == "" {
err := errors.New("no role in claim maps to an ocis role")
err := errors.New("no role in claim maps to an OpenCloud role")
logger.Error().Err(err).Msg("")
return nil, err
}
Expand Down
2 changes: 1 addition & 1 deletion services/proxy/pkg/userroles/userroles.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ func WithRolesClaim(claim string) Option {
}
}

// WithRoleMapping configures the map of ocis role names to claims values
// WithRoleMapping configures the map of OpenCloud role names to claims values
func WithRoleMapping(roleMap []config.RoleMapping) Option {
return func(o *Options) {
o.roleMapping = roleMap
Expand Down
Loading