Proxy

Warning

This feature is experimental. Configuration migration will have to be done manually according to the announced changes.

Warning

Configuration is entirely the user responsibility as the composer is not able to validate it.

What is done

The proxy allows users to access resources (web pages, …) on the dashboard that are not accessible from the current network. Each resources can be protected using groups set on Keycloak.

The proxy will give access to a resource defined by an endpoint and a port https://<stack-hostname>:<proxy-port>/<endpoint>.

Example:

  • Using different endpoints:

    • demo.onsphere.ch:8000/service1 to give access to service 1.

    • demo.onsphere.ch:8000/service2 to give access to service 2.

  • Using different ports:

    • demo.onsphere.ch:8001/ to give access to service 1.

    • demo.onsphere.ch:8002/ to give access to service 2.

How it is done

Requirements

Endpoint definition

The proxy is done via a nginx configuration.

location /google/ {
    proxy_pass https://www.google.ch/;
    proxy_hide_header x-frame-options;
    proxy_redirect https://www.google.ch/ https://osp-stack-1.onsphere.local:8000/google/;
}

This configuration must be added to the container and replace /etc/nginx/conf.d/default.conf. It can be done using a config or a volume.

Note

The module default configuration includes a configuration providing the following endpoints :

  • / : Accessible by everyone.

  • /google : Accessible by any user member of the group “data-access”.

  • /service. Accessible by any user member of the group “service”.

Authentication

The module will access Keycloak to authenticate the user and authorize the access to an endpoint. The logic is defined in the configuration and uses lua as scripting language.

Note

We recommend using the same host for the proxy and the stack to avoid problem with the session created by the proxy.

Keycloak parameters

To work with the Keycloak instance integrated on the stack some parameters need to be modified on the client dashboard or you can create another one if needed.

  • redirectUris must contain the proxy URL. (Example: https://osp-stack-1.onsphere.local:8000/*).

  • User groups mapper must have id.token.claim set to true.

Note

Configuration of the default dashboard client can be retrieved on the branch osp-keycloak-advanced-configuration.

Session variable

Warning

The following session variables are mandatory to ensure a proper logout when changing user.

set $session_cookie_samesite    None;
set $session_name               osp-proxy-session;
set $session_cookie_httponly    off;

SSL

You can use your own certificate to access the proxy or use the default one provided by OnSphere.

Warning

The lua_ssl_trusted_certificate /path/to/ca.crt; must define the certificate to access Keycloak if it uses a self-signed certificate.

Access management

Access management can be done on a server or on a location block. It is done on a access_by_lua block with the following syntax:

access_by_lua '
    -- lua code
';

The first part needed to access Keycloak is to define the access parameters.

local opts = {
    redirect_uri = "https://osp-stack-1.onsphere.local:8000/google/redirect",
    accept_none_alg = true,
    discovery = "https://osp-stack-1.onsphere.local:5000/auth/realms/onsphere/.well-known/openid-configuration",
    client_id = "dashboard",
    ssl_verify = true,
    renew_access_token_on_expiry = true,
    session_contents = {id_token=true}
}
  • redirect_uri: URL used by Keycloak to redirect the user after the connection. This must point on the proxy endpoint with a /redirect as sub-endpoint. The openid client needs it to complete the login process.

  • discovery: URL pointing to Keycloak to use for the authentication and to discover the openid configuration.

  • client_id: The client to use for the connection.

The second part authenticates the user.

local res, err = openidc.authenticate(opts)

Note

If the same instance of Keycloak and realm is used to connect to the frontend and the proxy, the user will be automatically authenticated without interaction.

The last part manages the authorization.

The err is the result of the operation and indicates if a error occurs. The res contains the token returned by Keycloak.

ngx is used to return early and send a response to the client.

if err then
    ngx.status = 403
    ngx.header["Content-type"] = "text/plain"
    ngx.say(err)
    ngx.exit(ngx.HTTP_FORBIDDEN)
end

local authorized = false
if res.id_token.groups ~= nil then
    for _,v in pairs(res.id_token.groups) do
        if v == "data-access" then
            authorized = true
            break
        end
    end
end

if authorized == false then
    ngx.status = 401
    ngx.header["Content-type"] = "text/plain"
    ngx.say("User not authorized")
    ngx.exit(ngx.HTTP_UNAUTHORIZED)
end