Proxy Service Configuration

Introduction

The proxy service is an API-Gateway for the ownCloud Infinite Scale microservices. Every HTTP request goes through this service. Authentication, logging and other preprocessing of requests also happens here. Mechanisms like request rate limiting or intrusion prevention are not included in the proxy service and must be set up in front of an external reverse proxy.

See the Developer Documentation for details if you want to write your own extensions and need to change or add routes to endpoints.

Default Values

  • The proxy listens on port 9200 by default.

Authentication

The following request authentication schemes are implemented:

  • Basic Auth (Only use in development, never in production setups!)

  • OpenID Connect

  • Signed URL

  • Public Share Token

Automatic Assignments

Some assignments can be automated using yaml files, environment variables and/or OIDC claims.

Automatic User and Group Provisioning

When using an external OpenID Connect IDP, the proxy can be configured to automatically provision users upon their first login.

Prerequisites

A number of prerequisites must be met for automatic user provisioning to work:

  • Infinite Scale must be configured to use an external OpenID Connect IDP.

  • The graph service must be configured to allow updating users and groups (GRAPH_LDAP_SERVER_WRITE_ENABLED).

  • One of the claim values returned by the IDP as part of the userinfo response or the access token must be unique and stable for the user. I.e. the value must not change for the whole lifetime of the user. This claim is configured via the PROXY_USER_OIDC_CLAIM environment variable (see below). A natural choice would e.g. be the sub claim which is guaranteed to be unique and stable per IDP. If a claim like email or preferred_username is used, you have to ensure that the user’s email address or username never changes.

Configuration

To enable automatic user provisioning, the following environment variables must be set for the proxy service:

  • PROXY_AUTOPROVISION_ACCOUNTS
    Set to true to enable automatic user provisioning.

  • PROXY_AUTOPROVISION_CLAIM_USERNAME
    The name of an OIDC claim whose value should be used as the username for the auto-provisioned user in ownCloud Infinite Scale. Defaults to preferred_username. Can also be set to e.g. sub to guarantee a unique and stable username.

  • PROXY_AUTOPROVISION_CLAIM_EMAIL
    The name of an OIDC claim whose value should be used for the mail attribute of the auto-provisioned user in ownCloud Infinite Scale. Defaults to email.

  • PROXY_AUTOPROVISION_CLAIM_DISPLAYNAME
    The name of an OIDC claim whose value should be used for the displayname attribute of the auto-provisioned user in ownCloud Infinite Scale. Defaults to name.

  • PROXY_AUTOPROVISION_CLAIM_GROUPS
    The name of an OIDC claim whose value should be used to maintain a user’s group membership. The claim value should contain a list of group names the user should be a member of. Defaults to groups.

  • PROXY_USER_OIDC_CLAIM
    When resolving an authenticated OIDC user, the value of this claim is used to lookup the user in the users service. For auto provisioning setups this usually is the same claims as set via PROXY_AUTOPROVISION_CLAIM_USERNAME.

  • PROXY_USER_CS3_CLAIM
    This is the name of the user attribute in ocis that is used to lookup the user by the value of the PROXY_USER_OIDC_CLAIM. For auto provisioning setups this usually needs to be set to username.

How it Works

When a user logs into ownCloud Infinite Scale for the first time, the proxy checks if that user already exists. This is done by querying the users service for users, where the attribute set in PROXY_USER_CS3_CLAIM matches the value of the OIDC claim configured in PROXY_USER_OIDC_CLAIM.

If the user does not exist, the proxy will create a new user via the graph service using the claim values configured in PROXY_AUTOPROVISION_CLAIM_USERNAME, PROXY_AUTOPROVISION_CLAIM_EMAIL and PROXY_AUTOPROVISION_CLAIM_DISPLAYNAME.

If the user does already exist, the proxy checks if the displayname has changed and updates that accordingly via graph service.

Unless the claim configured via PROXY_AUTOPROVISION_CLAIM_EMAIL is the same as the one set via PROXY_USER_OIDC_CLAIM the proxy will also check if the email address has changed and update that as well.

Next, the proxy will check if the user is a member of the groups configured in PROXY_AUTOPROVISION_CLAIM_GROUPS. It will add the user to the groups listed via the OIDC claim that holds the groups defined in the envvar and removes it from all other groups that he is currently a member of. Groups that do not exist in the external IDP yet will be created. Note: This can be a somewhat costly operation, especially if the user is a member of a large number of groups. If the group memberships of a user are changed in the IDP after the first login, it can take up to 5 minutes until the changes are reflected in Infinite Scale.

Claims

Claim Updates

OpenID Connect (OIDC) scopes are used by an application during authentication to authorize access to a user’s detail, like name, email or picture information. A scope can also contain among other things groups, roles, and permissions data. Each scope returns a set of attributes, which are called claims. The scopes an application requests, depends on which attributes the application needs. Once the user authorizes the requested scopes, the claims are returned in a token.

These issued JWT tokens are immutable and integrity-protected. Which means, any change in the source requires issuing a new token containing updated claims. On the other hand side, there is no active synchronisation process between the identity provider (IDP) who issues the token and Infinite Scale. The earliest possible time that Infinite Scale will notice changes is, when the current access token has expired and a new access token is issued by the IDP, or the user logs out and relogs in.

  • For resource optimisation, Infinite Scale skips any checks and updates on groupmemberships, if the last update happened less than 5min ago.

  • Infinite Scale can’t differentiate between a group being renamed in the IDP and users being reassigned to a different group.

  • Infinite Scale does not get aware when a group is being deleted in the IDP, a new claim will not hold any information from the deleted group. Infinite Scale does not track a claim history to compare.

Claim Checks and Step-up Authentication

Infinite Scale provides access control via the OpenID Connect (OIDC) "Authentication Class Reference" (ACR) claim. This can be used to enforce step-up authentication on specific routes. For instance, if a user logs in with basic authentication, they may need a higher level to access a sensitive route. If the user has not authenticated at the required level, access to the route will be denied.

This is configurable via environment variables, such as:

OCIS_MFA_ENABLED: true
OCIS_MFA_AUTH_LEVEL_NAME: advanced

This feature is disabled by default and requires an external Identity Provider (IDP) that supports step-up authentication and the ACR claim. Examples of such IDPs include Keycloak.

If an authenticated user attempts to access a protected route without two-factor authentication (2FA), the server will respond with a 403 Forbidden error and an X-OCIS-MFA-Required header.

Impacts

For shares or space memberships based on groups, a renamed or deleted group will impact accessing the resource:

  • There is no user notification about the inability accessing the resource.

  • The user will only experience rejected access.

  • This also applies for connected apps like the Desktop, iOS or Android app!

To give access for rejected users on a resource, one with rights to share must update the group information.

Quota Assignments

It is possible to automatically assign a specific quota to new users depending on their role. To do this, you need to configure a mapping between roles defined by their ID and the quota in bytes. The assignment can only be done via a yaml configuration and not via environment variables. See the following proxy.yaml config snippet for a configuration example.

role_quotas:
    <role ID1>: <quota1>
    <role ID2>: <quota2>

Role Assignments

When users log in, they automatically get a role assigned. The automatic role assignment can be configured in different ways. The PROXY_ROLE_ASSIGNMENT_DRIVER environment variable (or the driver setting in the role_assignment section of the configuration file) selects which mechanism to use for the automatic role assignment.

  • When PROXY_ROLE_ASSIGNMENT_DRIVER is set to default, all users that do not have a role assigned at the time of their first login will get the role 'user' assigned. (This is also the default behavior if PROXY_ROLE_ASSIGNMENT_DRIVER is unset.

  • When PROXY_ROLE_ASSIGNMENT_DRIVER is set to oidc, the role assignment for a user will happen based on the values of an OpenID Connect Claim of that user. The name of the OpenID Connect Claim to be used for the role assignment can be configured via the PROXY_ROLE_ASSIGNMENT_OIDC_CLAIM environment variable. It is also possible to define a mapping of claim values to role names defined in ownCloud Infinite Scale via a yaml configuration. See the following proxy.yaml snippet for an example.

    role_assignment:
        driver: oidc
        oidc_role_mapper:
            role_claim: ocisRoles
            role_mapping:
                - role_name: admin
                  claim_value: myAdminRole
                - role_name: spaceadmin
                  claim_value: mySpaceAdminRole
                - role_name: user
                  claim_value: myUserRole
                - role_name: guest
                  claim_value: myGuestRole

    This would assign the role admin to users with the value myAdminRole in the claim ocisRoles. The role user to users with the values myUserRole in the claim ocisRoles and so on.

  • Wildcard or Regex Claim Matching

    The claim_value supports exact strings and regular expressions to map multiple claim values to a single role. Regexes are matched against the entire claim value (implicit start/end anchors).

    Examples:

    role_assignment:
      driver: oidc
      oidc_role_mapper:
        role_claim: ocisRoles
        role_mapping:
          # exact match
          - role_name: user
            claim_value: ocisUser
          # regex: match any value starting with "ocis-user-"
          - role_name: user-light
            claim_value: ocis-user-.*
          # regex: single alphanumeric suffix
          - role_name: guest
            claim_value: ocis-guest-[a-zA-Z0-9]

    Note: Regex patterns are treated as full matches. Typically you don’t need ^ or $. If a claim_value is an invalid regex, it only matches claim values that are exactly equal; otherwise it’s ignored. Ordering still applies, and the first matching mapping wins.

Claim values that are not mapped to a specific Infinite Scale role will be ignored.

An Infinite Scale user can only have a single role assigned. If the configured role_mapping and a user’s claim values result in multiple possible roles for a user, the order in which the role mappings are defined in the configuration is important. The first role in the role_mappings where the claim_value matches a value from the user’s roles claim will be assigned to the user. So if e.g. a user’s ocisRoles claim has the values myUserRole and mySpaceAdminRole that user will get the ocis role spaceadmin assigned (because spaceadmin appears before user in the above sample configuration).

If a user’s claim values don’t match any of the configured role mappings, an error will be logged and the user will not be able to log in.

The default role_claim (or PROXY_ROLE_ASSIGNMENT_OIDC_CLAIM) is roles. The default role_mapping is:

- role_name: admin
  claim_value: ocisAdmin
- role_name: spaceadmin
  claim_value: ocisSpaceAdmin
- role_name: user
  claim_value: ocisUser
- role_name: guest
  claim_value: ocisGuest

Space Management Through OIDC Claims

  • This is an experimental/preview feature and may change.

  • This feature only works using an external IDP. The embedded IDP does not support this.

  • If you enable this feature, you can no longer use the Web UI to manually to assign or remove users to Spaces. The Web UI no longer displays related configuration options. Assigning or removing users from a Space can only be done by claims managed through the IDP.

  • If enabled and a user is not assigned a claim with defined spaces and roles, the user can only access his personal space.

  • When this functionality has been enabled via the envvar OCIS_CLAIM_MANAGED_SPACES_ENABLED, this environment variable must also be set in the frontend service. This is necessary to block adding or removing users to or from spaces through the web UI.

If required, users can be assigned or removed to Spaces via OIDC claims. This makes central user/Space management easy. Managed via environment variables, administrators can define the claim to use, a regex ruleset to extract the Space IDs and roles from a claim for provisioning. It is also possible to manually map OIDC roles to Infinite Scale Space roles. Note that assigning works both ways. Users can be added to Spaces as well as removed. Users must log out and log in again to activate any changes. The relevant environment variables that manage Spaces through OIDC claims follow the OCIS_CLAIM_MANAGED_SPACES_xxx pattern. See Listing Space IDs for how to obtain the ID of a Space.

The following rules apply if enabled:

  • If the claim is not found, it is not considered but the incident is logged.

  • A faulty regex prevents the proxy service from starting. By this, admins can immediately identify a major configuration issue. The incident is logged.

  • Entries in a claim that do not match the regex are not considered, the incident is not logged (1).

  • Unknown Space IDs and unknown roles are not considered, the incident is not logged (1).

  • When multiple entries are created with the same Space ID but different roles, the role with the highest permission counts.

(1) …​ These incidents cannot be logged due to the fact that claims can have a variety of layouts and may also contain data unrelated to Infinite Scale.

Example Setup

The following is a simple setup of what space management through OIDC claims can look like. The way how a claim is setup depends on the IDP used. It is important to understand, that the claim setup and the corresponding regex must match.

A claim defined as ocis-spaces containing two entries:
"ocis-spaces": [
    "spaceid=b622d44a-1747-4eda-8905-89f3605d5849:role=member",
    "spaceid=129cb9b6-c579-41b5-9316-93c6543484e5:role=spectator",
]

The environment variables to extract the data from the above claim look like this:

Environment variable definition
OCIS_CLAIM_MANAGED_SPACES_ENABLED=true
OCIS_CLAIM_MANAGED_SPACES_CLAIMNAME=ocis-spaces
OCIS_CLAIM_MANAGED_SPACES_REGEXP="spaceid=([a-zA-Z0-9-]+):role=(.*)",
OCIS_CLAIM_MANAGED_SPACES_MAPPING="member:editor,spectator:viewer"


Result

This would add a user, to which this claim is assigned, to the following Spaces with defined roles:

  • b622d44a-1747-4eda-8905-89f3605d5849 with the role editor and to

  • 129cb9b6-c579-41b5-9316-93c6543484e5 with the role viewer.

Note that OCIS_CLAIM_MANAGED_SPACES_MAPPING can be omitted if roles in the claim already match roles defined by Infinite Scale.

Multi Instance Infinite Scale

Infinite Scale can be used to configure multi-instance environments. This allows multiple instances to connect to the same external IDP. Without this configuration, only one-to-one setups are possible. The environment variables to configure such a setup start with OCIS_MULTI_INSTANCE_xxx. Since this setup requires in-depth knowledge of the environment, only a configuration example can be provided, which can be found at: Multi Instance Deployment Example.

Recommendations for Production Deployments

  • The proxy service is the only service communicating to the outside and therefore needs the usual protection against DDOS, Slow Loris or other attack vectors. All other services are not exposed to the outside, but also need protective measures when it comes to distributed setups like when using container orchestration over various physical servers.

  • In a production deployment, you want to have basic authentication (PROXY_ENABLE_BASIC_AUTH) disabled which is the default state. You should also set up a firewall to only allow requests to the proxy service or the reverse proxy if you have one. Requests to the other services should be blocked by the firewall.

Content Security Policy

What is a Content Security Policy (CSP) and why is it used in Infinite Scale

A Content Security Policy (CSP) is a feature that helps to prevent or minimize the risk of certain types of security threats. It consists of a series of instructions from a website to a browser, which instruct the browser to place restrictions on the things that the code comprising site is allowed to do. It is mainly used as a defense against cross-site scripting (XSS) attacks, in which an attacker is able to inject malicious code into the victim’s site and includes defending against clickjacking, and helping to ensure that a site’s pages will be loaded over HTTPS.

For Infinite Scale, external resources like an IDP (e.g. Keycloak) or when using web office documents or web apps, require defining a CSP. If not defined, the referenced services will not work.

To create a Content Security Policy (CSP), you need to create a yaml file containing the CSP definitions. To activate the settings, reference the file as value in the PROXY_CSP_CONFIG_FILE_LOCATION environment variable. For each change, a restart of the Infinite Scale deployment or the proxy service is required.

A working example for a CSP can be found in a sub path of the config directory of the ocis_full deployment example which is the base for our Local Production Setup and the Deployment on Hetzner.

See the Content Security Policy (CSP) Quick Reference Guide for a description of directives.

Strict Transport Security Header

Infinite Scale cannot always determine whether the entire communication chain between itself and the client is secure. Consider the following scenarios:

Client - Webserver - Infinite Scale (incomplete)

proxy client webserver ocis incomplete

Client - Webserver - Infinite Scale (complete)

proxy client webserver ocis complete

Client - Loadbalancer - Webserver - Infinite Scale (incomplete)

proxy client loadbalancer ocis incomplete

As you can see in Figure 2, the entire chain is secured by HTTPS, and the headers will be sent accordingly. The other figures illustrate that, although the client has a secure connection, the subsequent connection is insecure. Because the Infinite Scale proxy service can only detect his connection, it sends back headers for an insecure connection.

To mitigate this issue, set the environment variable PROXY_FORCE_STRICT_TRANSPORT_SECURITY to true. This forces the sending of Strict-Transport-Security headers on all responses.

Presigned Urls

Important, also see section caching above.

To authenticate presigned URLs, the proxy service needs to read the signing keys from a store that is populated by the ocs service.

The following stores can be configured via the OCS_PRESIGNEDURL_SIGNING_KEYS_STORE environment variable:

  • nats-js-kv
    Stores data using key-value-store feature of nats jetstream.

  • redis-sentinel
    Stores data in a configured Redis Sentinel cluster.

  • The memory store cannot be used as they do not share the memory from the ocs service signing key memory store, even in a single process.

  • Make sure to configure the same store for pre-signed URLs as here in the proxy service.

Store specific notes:

  • When using redis-sentinel
    The Redis master to use is configured via e.g. OCS_PRESIGNEDURL_SIGNING_KEYS_STORE_NODES in the form of <sentinel-host>:<sentinel-port>/<redis-master> like 10.10.0.200:26379/mymaster.

  • When using nats-js-kv
    It is recommended to set PROXY_PRESIGNEDURL_SIGNING_KEYS_STORE_NODES to the same value as OCS_PRESIGNEDURL_SIGNING_KEYS_STORE_NODES. That way the proxy service uses the same nats instance as the ocs service.

Special Settings

When using the Infinite Scale IDP service instead of an external IDP:

  • Use the environment variable OCIS_URL to define how Infinite Scale can be accessed; mandatory is the use of https as protocol for the URL.

  • If no reverse proxy is set up, the PROXY_TLS environment variable must be set to true because the embedded libreConnect shipped with the IDP service has a hard check if the connection is on TLS and uses the HTTPS protocol. If this mismatches, an error will be logged and no connection from the client can be established.

  • PROXY_TLS can be set to false if a reverse proxy is used and the https connection is terminated at the reverse proxy. When setting to false, the communication between the reverse proxy and Infinite Scale is not secured. If set to true, you must provide certificates.

Metrics

For details on monitoring see the Metrics for Prometheus documentation.

Caching

Important, also see section Presigned Urls below.

The proxy service can use a configured store via the global OCIS_CACHE_STORE environment variable.

Note that for each global environment variable, an independent service-based one might be available additionally. For precedences see Environment Variable Notes. Check the configuration section below. Supported stores are:

Store Type Description

memory

Basic in-memory store. Will not survive a restart.
Usually the default for caches. See the store environment variable for which one is used.

nats-js-kv

Stores data using key-value-store feature of NATS JetStream.
Usually the default for stores, see the store environment variable for which one is used.

redis-sentinel

Stores data in a configured Redis Sentinel cluster.

noop

Stores nothing. Useful for testing. Not recommended in production environments.

The proxy service can only be scaled if not using the memory store and the stores are configured identically over all instances!
If you have used one of the deprecated stores of a former version, you should reconfigure to use one of the supported ones as the deprecated stores will be removed in a later version.
Store specific notes
  • When using redis-sentinel:
    The Redis master to use is configured via e.g. OCIS_CACHE_STORE_NODES in the form of <sentinel-host>:<sentinel-port>/<redis-master> like 10.10.0.200:26379/mymaster.

  • When using nats-js-kv:

    • It is recommended to set OCIS_CACHE_STORE_NODES to the same value as OCIS_EVENTS_ENDPOINT. That way the cache uses the same nats instance as the event bus. See the Event Bus Configuration for more details.

    • Authentication can be added, if configured, via OCIS_CACHE_AUTH_USERNAME and OCIS_CACHE_AUTH_PASSWORD.

    • It is possible to set OCIS_CACHE_DISABLE_PERSISTENCE to instruct nats to not persist cache data on disc.

Event Bus Configuration

The Infinite Scale event bus can be configured by a set of environment variables.

  • In case of an orchestrated installation like with Docker or Kubernetes, the event bus must be an external service for scalability like a Redis Sentinel cluster or a key-value-store NATS JetStream. Both named stores are supported and also used in Caching and Persistence. The store used is not part of the Infinite Scale installation and must be separately provided and configured.

  • Note that from a configuration point of view, caching and persistence are independent of the event bus configuration.

Note that for each global environment variable, a service-based one might be available additionally. For precedences see Environment Variable Notes. Check the configuration section below.

Without the aim of completeness, see the list of environment variables to configure the event bus:

Envvar Description

OCIS_EVENTS_ENDPOINT

The address of the event system.

OCIS_EVENTS_CLUSTER

The clusterID of the event system. Mandatory when using NATS as event system.

OCIS_EVENTS_ENABLE_TLS

Enable TLS for the connection to the events broker.

OCIS_INSECURE

Whether to verify the server TLS certificates.

OCIS_EVENTS_AUTH_USERNAME

The username to authenticate with the events broker.

OCIS_EVENTS_AUTH_PASSWORD

The password to authenticate with the events broker.

Configuration

Environment Variables

The proxy service is configured via the following environment variables. Read the Environment Variable Types documentation for important details. Column IV shows with which release the environment variable has been introduced.

404: Not Found

  • 8.2.0

404: Not Found

YAML Example

  • 8.2.0

404: Not Found