Skip to main content
Version: 13.x (Current)

Secure Access

In order to ensure that only authorized people can access Data Catalog system and consequently visualize or change its state, it is important to properly set up a security layer.

In the following page are described the requirements and a procedure that can be executed to achieve the goal of securing Data Catalog application. This procedure is inspired by this guide which employs Mia-Platform Marketplace components and exploits Mia-Platform Console features.

note

Please, bear in mind that there are many ways for securing the access to an application and the one provided here is meant to be a streamlined guide which may be followed, adapted according to your needs or taken just as an inspiration for building your security layer.

Requirements

  • access to Data Catalog, which automatically scaffold the configurations regarding microservices, collections, endpoints and variables needed for releasing Data Catalog solution and protecting its access. Generated resources need to be further customized depending on your needs and credentials.
  • an introduction to Envoy, which is employed as API Gateway by the application. It is also possible to employ Nginx as API Gateway, though the focus of this guide is on the former.
  • an Identity Provider, which manages users' identities. The one employed throughout this guide is Okta, although any other Identity Provider supported by the Mia-Platform Authentication Service can be adopted in place of Okta within this guide.

Authentication Flow

In this section are described which resources should be configured in order to properly protect the access to the Data Catalog solution.

Services

Upon application instantiation, the following services should have been generated for handling the authentication flow:

  • api-gateway, which is the entrypoint of your project requests
  • authentication-service, which is the service that interacts with your Identity Provider to verify your users identity
  • crud-service, which allows to query via HTTP requests the underlying database where users are stored
  • login-site, a simple frontend employed for handling the authentication flow in user browser

Api Gateway

For the current use case no further configuration is needed for this service in Console Design area. However, if there is a need for updating any specific detail, please look for more information at the dedicated documentation page.

Authentication Service

caution

In order to follow through this guide it is necessary to ensure that at least version v3.10.0 of Authentication Service has been configured.
Earlier versions do not fully support permissions key in /user-info details and therefore they would not be retrieved when checking for user's authorization

The service configuration is created with a set of preconfigured variables, such as the connection to Redis (see the paragraph below), and a config map that lists the supported applications. Within the config map that contains the known applications it is already possible to find the definition of an application that uses Okta as Identity Provider.

tip

In case you would prefer using another Identity Provider, please read the authentication-service documentation to learn which ones are supported and how to configure the desired one in place of Okta.

The configuration of included application only requires to set up few public and secret environment variables to be operational. These variables are summarized in the tables below, divided for location where they should be stored. In fact, the former ones should be added under the Variables tab of Project Overview area, while the latter can be configured in the Public Variables of the Design section.

Secret VariableExplanation
DC_OKTA_CLIENT_IDclient id obtained when registering this specific application on Okta
DC_OKTA_CLIENT_SECRETclient secret obtained when registering this specific application on Okta
DC_REDIS_HOSTSconnection string to Redis host that will support authentication flow
Public VariableExplanation
OKTA_BASE_URLbase url where your Identity Provider is exposed
DC_APP_IDapplication identifier employed when registering this specific application on Okta (e.g. fabric-data-catalog)
DC_PROVIDER_IDprovider identifier employed when registering this specific application on Okta (e.g. okta-development)
DC_REDIS_SCOPEredis scope in case of a multi-tenant architecture
DC_BASE_URLbase url where the project is exposed
note

After the creation of the Data Catalog application, the public variables specified above should already appear in the corresponding section, each of them with an empty value.

Filling the variables listed above allows to generate a complete configuration at deploy time. An example of such configuration for Okta can be fond in the panel below.

Authentication Service | Configuration Example (with variables to be interpolated)
config.json
{
"apps": {
"{{DC_APP_ID}}": {
"providers": {
"{{DC_PROVIDER_ID}}": {
"order": 10,
"type": "okta",
"label": "Login with Okta",
"clientId": "{{DC_OKTA_CLIENT_ID}}",
"clientSecret": "{{DC_OKTA_CLIENT_SECRET}}",
"baseUrl": "{{OKTA_BASE_URL}}",
"authUrl": "{{OKTA_BASE_URL}}/oauth2/v1/authorize",
"tokenUrl": "{{OKTA_BASE_URL}}/oauth2/v1/token",
"userInfoUrl": "{{OKTA_BASE_URL}}/oauth2/v1/userinfo",
"userSettingsURL": "{{OKTA_BASE_URL}}/enduser/settings",
"logoutUrl": "{{OKTA_BASE_URL}}/oauth2/v1/logout",
"scope": [
"openid",
"profile",
"email",
"offline_access"
]
}
},
"redirectUrl": "{{DC_BASE_URL}}/web-login/oauth/callback",
"defaultRedirectUrlOnSuccessfulLogin": "/",
"authorizeStateRequired": true,
"realm": "data-fabric",
"isWebsiteApp": true,
"issuer": "{{DC_APP_ID}}",
"defaultGroups": []
}
}
}

In addition to previous configurations, the service needs to mount a private key as a secret. This key is employed to sign JWTs that are set as session id for authenticated users. In case the service has been instantiated through the Data Catalog application, a secret has already been associated (but not created) to the service, which is named authentication-service-secrets.

caution

These instructions below assume that the tool employed for deploying Console projects is mlp. Please, remember to adapt them according to your actual deployment tool and/or secret management configuration.

In order for the Console to automatically create the secret at deploy time it is then necessary to edit the file mlp.yaml, that can be found within your project repository root folder, and extend it with the following entry under the secrets key:

mlp.yaml
secrets:
# ...
- name: "authentication-service-secrets"
when: "always"
data:
- from: "literal"
key: "private-key.pem"
value: "{{DC_JWT_CLIENT_PRIVATE_KEY}}"
# ...

This will create at deploy time a K8s secret named authentication-service-secrets, which will contains a property private-key.pem mapped to the value of the interpolated variable DC_JWT_CLIENT_PRIVATE_KEY.
To provide the proper value, please generate a private key, for example as follows,

ssh-keygen -t rsa -b 4096 -m PEM -f private.key

and then create the corresponding environment variable DC_JWT_CLIENT_PRIVATE_KEY in the Variables tab of Console Project Overview area.
Finally, please ensure that on the authentication-service, located under the Microservices section in the Console Design area, the environment MIA_JWT_TOKEN_PRIVATE_KEY_FILE_PATH is set to /secrets/private-key.pem (where the folder is driven by the secret mount path and the file name corresponds to the key property set in the mlp.yaml configuration entry).

In case more details are needed on this latter part, please head over to the authentication-service documentation page.

Login Site

No further configuration is needed for this service.

tip

In case it is needed to embed Data Catalog solution within Mia-Platform Console, please ensure that login site version greater or equal to v8.1.2 which supports handling authentication both via redirect and as popup when requested from an iFrame.

CRUD Service

No further configuration is needed for this service, other than ensuring that environment variable MONGODB_URL is correctly set, that is either interpolated from a Project Secret Variable or loaded from a K8s secret.

Redis Configuration

In case you don't already have a Redis instance configured dedicated for authentication purposes, in the steps below it described how to configure your own in-memory only instance:

  • enter your project Design area and select Microservices section

  • click on the button Create a Microservice button and select From Docker image

  • in the form that is opened enter redis-auth as name and bitnami/redis:6.2.14 and Docker image name and click the Create button

  • upon the service page opens, head over Container Ports card and edit the predefined one to use port 6379 for port and target port

  • in the Runtime card enable readiness and liveness probes on TCP port to ensure the service is working properly once released

  • additionally, in the Microservice card set the memory and cpu request/limits as follows:

    • memory 15m / 50m;
    • cpu 15m / 50m;
  • now, let's move to the environment variables tab and add the following variables:

    • REDIS_PASSWORD set to {{CP_REDIS_MASTER_PASSWORD}}
  • finally, switching to the Config Maps tab, let's create a config map named cp-redis-auth-configuration that should be mounted at /opt/bitnami/redis/mounted-etc/. In this config map a file named redis.conf should be created. Within this file it is possible to insert the Redis configurations shown below.

    redis.conf
    ## GENERIC ##
    port 6379
    # listen on all the interfaces for incoming connections
    bind 0.0.0.0

    ## NO DISK PERSISTENCE ##
    save ""
    appendonly no

    ## SECURITY ##
    protected-mode yes

    # NOTE: +@connection is necessary to be placed after -@dangerous, otherwise the user won't have the permissions to connect to Redis
    user {{DC_REDIS_USERNAME}} on +@all -@dangerous +@connection allkeys allchannels >{{DC_REDIS_PASSWORD}}

    # disable default user
    user default off

The provided Redis configuration describes disk persistence management (in-memory only) and introduce a dedicated user with their ACLs. To complete the configuration it is necessary to create the following secret environment variables in the Project Overview area:

Secret VariableExplanation
DC_REDIS_MASTER_PASSWORDroot password to allow Redis start (not used by any service - it can be loaded from a secret when configured within the service environment variables)
DC_REDIS_USERNAMEusername of the Redis account to be employed by the authentication-service for accessing Redis
DC_REDIS_PASSWORDpassword of the Redis account to be employed by the authentication-service for accessing Redis

Endpoints

Below is reported the list of endpoints related to the authentication flow that are created with the instantiation of Data Catalog application. Please ensure that they are exposed with the proper security options.

EndpointServiceAuthentication RequiredUser Group Permission
/web-loginlogin-site-true
/authorizeauthentication-service-true
/oauth/tokenauthentication-service-true
/logoutauthentication-service-true
/refreshtokenauthentication-servicetrue
/userinfoauthentication-servicetrue
/appsauthentication-service-true

Knowing these endpoints are exposed, it is now possible to configure the redirect URLs that some Identity Providers, such as Okta or Auth0, require to complete the application registration. These endpoints will be then employed during the authentication flow to constrain the redirects the Identity Provider can perform. In this case the endpoint that should be configured are the following ones:

  • Sign-in redirect URIs → <project-base-url>/web-login/oauth/callback
  • Sign-out redirect URIs → <project-base-url>/logout

where <project-base-url> is the base url where the project of interest is exposed to.

Collections

The authentication flow via the authentication-service requires also the introduction of a CRUD Collection, where users details are saved upon successful login. These user information can then be employed in the authorization flow, which is described later.
By default the Data Catalog application creates the collection for you and instantiates the CRUD Service, which is employed by the authentication service to access the collection. Additionally, below it is also provided the collection definition ready for being imported, in case it may be necessary to move or replicate the collection in another Console project.

Data Catalog Users Collection Definition (import ready)
{
"data": {
"collections": {
"users": {
"id": "users",
"name": "users",
"fields": [
{
"name": "_id",
"type": "ObjectId",
"required": true,
"nullable": false,
"description": "_id"
},
{
"name": "creatorId",
"type": "string",
"required": true,
"nullable": false,
"description": "creatorId"
},
{
"name": "createdAt",
"type": "Date",
"required": true,
"nullable": false,
"description": "createdAt"
},
{
"name": "updaterId",
"type": "string",
"required": true,
"nullable": false,
"description": "updaterId"
},
{
"name": "updatedAt",
"type": "Date",
"required": true,
"nullable": false,
"description": "updatedAt"
},
{
"name": "__STATE__",
"type": "string",
"required": true,
"nullable": false,
"description": "__STATE__"
},
{
"name": "name",
"type": "string",
"required": false,
"nullable": false,
"sensitivityValue": 0,
"encryptionEnabled": false,
"encryptionSearchable": false
},
{
"name": "groups",
"type": "Array_string",
"required": false,
"nullable": false,
"sensitivityValue": 0,
"encryptionEnabled": false,
"encryptionSearchable": false
},
{
"name": "username",
"type": "string",
"required": false,
"nullable": false,
"sensitivityValue": 0,
"encryptionEnabled": false,
"encryptionSearchable": false
},
{
"name": "email",
"type": "string",
"required": false,
"nullable": false,
"sensitivityValue": 0,
"encryptionEnabled": false,
"encryptionSearchable": false
},
{
"name": "providerId",
"type": "string",
"required": true,
"nullable": false,
"sensitivityValue": 0,
"encryptionEnabled": false,
"encryptionSearchable": false
},
{
"name": "providerUserId",
"type": "string",
"required": true,
"nullable": false,
"sensitivityValue": 0,
"encryptionEnabled": false,
"encryptionSearchable": false
},
{
"name": "realm",
"type": "string",
"required": false,
"nullable": false,
"sensitivityValue": 0,
"encryptionEnabled": false,
"encryptionSearchable": false
},
{
"name": "metadata",
"type": "RawObject",
"required": false,
"nullable": false,
"sensitivityValue": 0,
"encryptionEnabled": false,
"encryptionSearchable": false
},
{
"name": "permissions",
"type": "Array_string",
"required": false,
"nullable": false,
"sensitivityValue": 0,
"encryptionEnabled": false,
"encryptionSearchable": false
}
],
"internalEndpoints": [
{
"basePath": "/users",
"defaultState": "PUBLIC"
}
],
"type": "collection",
"indexes": [
{
"name": "_id",
"type": "normal",
"unique": true,
"fields": [
{
"name": "_id",
"order": 1
}
]
},
{
"name": "createdAt",
"type": "normal",
"unique": false,
"fields": [
{
"name": "createdAt",
"order": -1
}
]
},
{
"name": "stateIndex",
"type": "normal",
"unique": false,
"fields": [
{
"name": "__STATE__",
"order": 1
}
]
},
{
"name": "nameSearch",
"type": "normal",
"unique": false,
"fields": [
{
"name": "email",
"order": 1
},
{
"name": "name",
"order": 1
},
{
"name": "__STATE__",
"order": 1
}
]
},
{
"name": "upsertSupport",
"type": "normal",
"unique": false,
"fields": [
{
"name": "providerId",
"order": 1
},
{
"name": "providerUserId",
"order": 1
},
{
"name": "realm",
"order": 1
}
]
}
],
"description": "Collection of users",
"tags": [
"collection"
]
}
}
},
"metadata": {
"branchName": "master",
"exportTimestamp": "2024-09-13T07:00:00.000Z",
"isImported": false,
"pathRefType": "revisions",
"projectId": "",
"projectName": ""
}
}

Advanced

In this section are described additional tweaks to be carried out on the API Gateway (Envoy), that enhance the interaction with the runtime system and allow this solution to support authentication.

These modifications should be inserted in the proper file in the Advanced section of the Console Design area, under the key api-gateway-envoy.

Console advanced tab in Design section showing &#39;api-gateway-envoy&#39; configuration

note

Before proceeding, be sure to have configured Data Catalog endpoints accordingly to their specific documentation.

Automatic redirect upon receiving 401 HTTP error

This configuration edit should be inserted in the file local-replies.yml and it enforces a redirect to the login page every time a 401 HTTP error is encountered by the system. This ensures that the users authenticate before returning to the page they were trying to browse.

api-gateway-envoy/local-replies.yml
- listener_name: frontend
filter:
status_code_filter:
comparison:
op: EQ
value:
default_value: 401
runtime_key: key_b
status_code: 302
body:
inline_string: |-
<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<title>302 Found</title>
</head>
</html>
headers_to_add:
- header:
key: "Location"
value: "/web-login?appId={{DC_APP_ID}}&providerId={{DC_PROVIDER_ID}}&redirect=%REQ(:PATH)%"
append: false
- header:
key: "Set-Cookie"
value: "sid=; Max-Age=0"
append: false
note

If you're using API Gateway with Nginx, please consider using this approach for automatic redirects.

Authorization Flow

In this section are described which resources and permissions should be configured in order to properly grant the access to the Data Catalog solution only to authorized users.

Services

Upon application instantiation, the following services should have been generated for handling the authorization flow within your project:

  • authentication-service, which is in charge of verifying whether an authenticated user has been granted the permissions to access the resource they are requesting. This service works in tandem with api-gateway and authentication-service to fulfill its role;

Authorization Service

This service is introduced when creating the application and it is already preconfigured with all the necessary configurations. In case the service already exists in your project, please ensure the following environment variables on the service contain the these values below:

Environment VariableValue
HEADERS_TO_PROXYconnection,upgrade,sec-websocket-protocol,sec-websocket-version,x-request-id,request-id,cookie,authorization,client-type,host,x-forwarded-host
USERINFO_URLhttp://authentication-service/userinfo
USER_PROPERTIES_TO_PROXYprovider,email,username,name,permissions,metadata

In order to support real-time updates in the Data Catalog system, it is important to allow proxying the following headers:

In addition, USER_PROPERTIES_TO_PROXY must be edited to include also permissions key, so that permissions property is loaded, checked and then forwarded to the underlying components.

Endpoints

In addition to the endpoints described in the Authentication Flow section, here are described the ones that expose all the functionalities of Data Catalog system, both the frontend and backend components.

EndpointServiceAuthentication RequiredUser Group Permission
/api/connectionsfabric-bfffalse
/api/data-catalogfabric-bffpermissions["update:bulk-action"]
/api/job-runnerfabric-bffpermissions["admin:connections"]
/api/open-lineagefabric-bfffalse
/data-catalogdata-catalog-fetrue

Routes

In order to finely control which operations a user can carry out over Data Catalog APIs, a set of permissions has been devised, which is listed here:

PermissionContext
admin:connectionsallow user to manage data catalog connections
read:data-assetsallow visualizing data catalog records and their metadata
update:metadata-assetsenable editing metadata associated to data catalog records
update:bulk-actionallow users performing the same operation in bulk over multiple data catalog records
update:lineageallow users to update lineage information of assets
caution

Please ensure that all these endpoints and subsequent routes are set with Authentication Required in their security details tab.

Connections API

The permissions described in the table above needs then to be applied to all the different routes exposed over /api/connections/*, so that each operation is covered with the correct grant.

RouteTypeMethodUser Group Permissions
/itemsRESTGETpermissions["admin:connections"]
/itemsRESTPOSTpermissions["admin:connections"]
/items/:idRESTPATCHpermissions["admin:connections"]
/items/:idRESTDELETEpermissions["admin:connections"]

Data Catalog API

The permissions described in the table above needs then to be applied to all the different routes exposed over /api/data-catalog/*, so that each operation is covered with the correct grant.

RouteTypeMethodUser Group Permissions
/assets/searchRESTGETpermissions["read:data-assets"]
/assets/search-parentsRESTGETpermissions["read:data-assets"]
/tags/countRESTGETpermissions["read:data-assets"]
/tags/itemsRESTGETpermissions["read:data-assets"]
/tags/searchRESTGETpermissions["read:data-assets"]
/sors/:dataset-idRESTGETpermissions["read:data-assets"]
/sors/:dataset-id/custom-properties/:nameRESTPOSTpermissions["update:metadata-assets"]
/sors/:dataset-id/custom-properties/:nameRESTPATCHpermissions["update:metadata-assets"]
/sors/:dataset-id/custom-properties/:nameRESTDELETEpermissions["update:metadata-assets"]
/sors/:dataset-id/descriptionRESTPATCHpermissions["update:metadata-assets"]
/sors/:dataset-id/tagsRESTPATCHpermissions["update:metadata-assets"]
/tables/:dataset-idRESTGETpermissions["read:data-assets"]
/tables/:dataset-id/custom-properties/:nameRESTPOSTpermissions["update:metadata-assets"]
/tables/:dataset-id/custom-properties/:nameRESTPATCHpermissions["update:metadata-assets"]
/tables/:dataset-id/custom-properties/:nameRESTDELETEpermissions["update:metadata-assets"]
/tables/:dataset-id/descriptionRESTPATCHpermissions["update:metadata-assets"]
/tables/:dataset-id/tagsRESTPATCHpermissions["update:metadata-assets"]
/columns/:dataset-id/:field-nameRESTGETpermissions["read:data-assets"]
/columns/:dataset-id/:field-name/custom-properties/:nameRESTPOSTpermissions["update:metadata-assets"]
/columns/:dataset-id/:field-name/custom-properties/:nameRESTPATCHpermissions["update:metadata-assets"]
/columns/:dataset-id/:field-name/custom-properties/:nameRESTDELETEpermissions["update:metadata-assets"]
/columns/:dataset-id/:field-name/descriptionRESTPATCHpermissions["update:metadata-assets"]
/columns/:dataset-id/:field-name/tagsRESTPATCHpermissions["update:metadata-assets"]
/metadata-registry/countRESTGETpermissions["read:data-assets"]
/metadata-registry/itemsRESTGETpermissions["read:data-assets"]
/metadata-registry/itemsRESTPOSTpermissions["update:metadata-assets"]
/metadata-registry/items/:nameRESTGETpermissions["read:data-assets"]
/metadata-registry/items/:nameRESTPATCHpermissions["update:metadata-assets"]
/metadata-registry/items/:nameRESTDELETEpermissions["update:metadata-assets"]
/metadata-registry/searchRESTGETpermissions["read:data-assets"]
/bulk-actionsWebsocketGETpermissions["update:bulk-action"]

Job Runner API

The permissions described in the table above needs then to be applied to all the different routes exposed over /api/job-runner/*, so that each operation is covered with the correct grant.

RouteTypeMethodUser Group Permissions
/secret-namesRESTGETpermissions["admin:connections"]
/agent/abortRESTPOSTpermissions["admin:connections"]
/agent/syncRESTPOSTpermissions["admin:connections"]
/agent/dsnRESTGETpermissions["admin:connections"]
/agent/driversRESTGETpermissions["admin:connections"]
/feedbackWebsocketGETpermissions["admin:connections"]

Open Lineage API

The permissions described in the table above needs then to be applied to all the different routes exposed over /api/open-lineage/*, so that each operation is covered with the correct grant.

RouteTypeMethodUser Group Permissions
/jobs/from/dataset/:id/direction/:directionRESTGETpermissions["read:data-assets"]
/jobs/from/system/:id/direction/:directionRESTGETpermissions["read:data-assets"]
/jobs/itemsRESTPOSTpermissions["update:lineage"]
/jobs/items/:idRESTPATCHpermissions["update:lineage"]
/jobs/items/:idRESTDELETEpermissions["update:lineage"]
/dataset/items/:idRESTGETpermissions["read:data-assets"]
/dataset/itemsRESTPOSTpermissions["update:lineage"]
/dataset/items/:idRESTPATCHpermissions["update:lineage"]
/dataset/items/:idRESTDELETEpermissions["update:lineage"]
/facets/storage/items/:idRESTGETpermissions["read:data-assets"]
/facets/storage/items/:idRESTDELETEpermissions["update:lineage"]

Users Management

Controlling which users can access the Data Catalog system and their assigned permissions can be done either via directly editing database records or calling CRUD Service APIs. However, having a front-end to execute these actions would be a nice add-on to simplify these actions and to reduce errors related to possible mis-configurations.

This can be achieved thanks to the Microfrontend Composer tool, which allows crafting and configuring web pages and applications. In particular, it is possible to build the pages for listing the users,

An example of application that can be created is shown in the picture below:

Users Management UI

Example of Users Management UI that is generated by the Data Catalog application

Microfrontend Composer

caution

In order to use Microfrontend Composer in Console it is necessary to purchase the dedicated license. Nonetheless, the application will create tha user management pages, but those won't be easily editable from the Composer configurator.

Upon application instantiation, a predefined set of web pages are created and ready to be used once the project is deployed. In case you would like to customize those pages here are provided their configuration, one for Data Catalog users, one for the roles and one for their bindings. These configuration can be loaded either as config map of micro-lc service or within the advanced tab of the corresponding page in the Composer.

Data Catalog Users Page
users-config.json
{
"definitions": {
"dataSchema": {
"type": "object",
"required": [
"providerId",
"providerUserId"
],
"properties": {
"_id": {
"formOptions": {
"hiddenOnInsert": true,
"readOnlyOnUpdate": true
},
"type": "string",
"visualizationOptions": {
"hidden": true
}
},
"creatorId": {
"formOptions": {
"hiddenOnInsert": true,
"readOnlyOnUpdate": true,
"disabled": false,
"hidden": true
},
"type": "string",
"visualizationOptions": {
"hidden": true
}
},
"createdAt": {
"formOptions": {
"hiddenOnInsert": true,
"readOnlyOnUpdate": true,
"disabled": false,
"hidden": true
},
"dateOptions": {
"displayFormat": "YYYY-MM-DD hh:mm"
},
"format": "date-time",
"type": "string",
"visualizationOptions": {
"hidden": true
}
},
"updaterId": {
"formOptions": {
"hiddenOnInsert": true,
"readOnlyOnUpdate": true,
"hiddenOnUpdate": true
},
"type": "string",
"visualizationOptions": {
"hidden": true
}
},
"updatedAt": {
"formOptions": {
"hiddenOnInsert": true,
"readOnlyOnUpdate": true,
"hiddenOnUpdate": false,
"hidden": true
},
"dateOptions": {
"displayFormat": "YYYY-MM-DD hh:mm"
},
"format": "date-time",
"type": "string",
"visualizationOptions": {
"hidden": true
}
},
"__STATE__": {
"enum": [
"PUBLIC",
"DRAFT",
"TRASH",
"DELETED"
],
"formOptions": {
"readOnlyOnUpdate": true,
"readOnly": false,
"placeholder": "PUBLIC"
},
"type": "string",
"visualizationOptions": {
"hidden": true
}
},
"name": {
"type": "string",
"formOptions": {
"readOnly": true
}
},
"groups": {
"type": "array",
"items": {
"type": "string"
}
},
"username": {
"type": "string",
"formOptions": {
"readOnly": true
},
"visualizationOptions": {
"hidden": true
}
},
"email": {
"type": "string",
"formOptions": {
"readOnly": true
},
"visualizationOptions": {
"hidden": true
}
},
"providerId": {
"type": "string",
"formOptions": {
"readOnly": true
}
},
"providerUserId": {
"type": "string",
"formOptions": {
"readOnly": true
},
"visualizationOptions": {
"hidden": true
}
},
"realm": {
"type": "string",
"formOptions": {
"readOnlyOnInsert": false,
"readOnly": true
},
"visualizationOptions": {
"hidden": true
}
},
"permissions": {
"type": "array",
"items": {
"type": "string",
"enum": [
"read:pipelines",
"control:pipelines",
"read:connections",
"update:connections",
"delete:connections",
"read:runtimes",
"update:runtimes",
"read:data-assets",
"update:metadata-assets",
"read:users",
"update:users",
"update:bulk-action",
"update:lineage",
"admin:connections",
"admin:producers"
]
},
"dataSchema": {
"type": "array",
"items": {
"type": "string",
"enum": [
"read:pipelines",
"control:pipelines",
"read:connections",
"update:connections",
"delete:connections",
"read:runtimes",
"update:runtimes",
"read:data-assets",
"update:metadata-assets",
"read:users",
"update:users",
"update:bulk-action",
"update:lineage",
"admin:connections",
"admin:producers"
]
}
}
},
"metadata": {
"type": "object",
"visualizationOptions": {
"hidden": true
}
}
}
}
},
"content": {
"content": [
{
"content": [
{
"tag": "div",
"content": [
{
"properties": {
"content": "Users"
},
"tag": "bk-title"
},
{
"tag": "bk-refresh-button",
"attributes": {
"style": "margin-left: 14px; align-self: end;"
}
},
{
"tag": "div",
"attributes": {
"style": "flex-grow: 1;"
}
},
{
"properties": {
"placeholder": "Search..."
},
"tag": "bk-search-bar"
},
{
"properties": {
"content": "",
"clickConfig": {
"type": "event",
"actionConfig": {
"label": "filter",
"payload": {}
}
},
"type": "outlined",
"iconId": "FunnelPlotOutlined"
},
"tag": "bk-button"
}
],
"attributes": {
"style": "display: flex; flex-direction: row; gap: 10px; padding: 0 20px;"
}
},
{
"tag": "div",
"attributes": {
"style": "width: 100%; display: flex; justify-content: space-between;"
},
"content": [
{
"attributes": {
"style": "flex-grow: 1;"
},
"properties": {
"tabs": [
{
"key": "public",
"title": "Public",
"filters": [
{
"property": "__STATE__",
"operator": "equal",
"value": "PUBLIC"
}
],
"order": 0
},
{
"title": "Draft",
"key": "draft",
"order": 2,
"filters": [
{
"property": "__STATE__",
"operator": "equal",
"value": "DRAFT"
}
]
},
{
"title": "Trash",
"filters": [
{
"property": "__STATE__",
"operator": "equal",
"value": "TRASH"
}
],
"order": 3,
"key": "trash"
}
]
},
"tag": "bk-tabs"
},
{
"attributes": {
"style": "margin-right: 4px"
},
"properties": {
"dataSchema": {
"$ref": "#/definitions/dataSchema"
},
"filters": []
},
"tag": "bk-filters-manager"
}
]
},
{
"tag": "div",
"attributes": {
"style": "padding: 0 20px;"
},
"content": {
"tag": "bk-breadcrumbs",
"properties": {
"dataSchema": {
"$ref": "#/definitions/dataSchema"
}
}
}
}
],
"tag": "header",
"attributes": {
"style": "display: flex; flex-direction: column; padding-top: 10px; background-color: white;"
}
},
{
"content": [
{
"properties": {
"dataSchema": {
"$ref": "#/definitions/dataSchema"
},
"rowActions": {
"kind": "icons",
"actions": [
{
"label": "Delete",
"icon": "fas fa-trash",
"kind": "event",
"content": "delete-data",
"meta": {
"actionId": "delete-data"
},
"requireConfirm": true
}
]
},
"fitParentContainer": true
},
"tag": "bk-table"
},
{
"properties": {
"requireConfirm": {
"onClose": true,
"onSave": true
},
"dataSchema": {
"$ref": "#/definitions/dataSchema"
},
"width": "70vw",
"allowObjectAsTable": false,
"editorHeight": "30vh",
"allowNavigation": true
},
"tag": "bk-form-modal"
},
{
"tag": "bk-confirmation-modal"
},
{
"properties": {
"rootElementSelectors": "main.micro-lc-layout-content",
"successEventMap": {
"create-data": {
"title": "Success",
"content": "Data successfully created",
"type": "success"
},
"update-data": {
"title": "Success",
"content": "Data successfully updated",
"type": "success"
},
"delete-data": {
"title": "Success",
"content": "Data successfully deleted",
"type": "success"
}
},
"errorEventMap": {
"create-data": {
"title": "Error",
"content": "An error occurred during order creation",
"type": "error"
},
"update-data": {
"title": "Error",
"content": "An error occurred during order updated",
"type": "error"
},
"delete-data": {
"title": "Error",
"content": "An error occurred during order deletion",
"type": "error"
}
}
},
"tag": "bk-notifications",
"attributes": {}
}
],
"tag": "main",
"attributes": {
"style": "flex-grow: 1; background-color: #f0f2f5; padding: 20px; overflow-y: auto;"
}
},
{
"content": [
{
"properties": {
"dataSchema": {
"$ref": "#/definitions/dataSchema"
},
"width": "40vw"
},
"tag": "bk-filter-drawer"
}
],
"tag": "aside"
},
{
"content": [
{
"tag": "bk-bulk-delete"
},
{
"tag": "bk-bulk-actions",
"properties": {
"dataSchema": {
"$ref": "#/definitions/dataSchema"
}
}
},
{
"tag": "div",
"attributes": {
"style": "flex-grow: 1;"
}
},
{
"tag": "bk-footer",
"attributes": {
"style": "display: flex; justify-content: end; align-items: center;"
}
},
{
"tag": "bk-pagination",
"properties": {
"pageSize": 10
}
}
],
"tag": "footer",
"attributes": {
"style": "display: flex; flex-direction: row; flex-wrap: wrap; padding: 10px 20px; background-color: white; gap: 10px; position: sticky; bottom: 0; z-index: 10"
}
},
{
"properties": {
"basePath": "/v2/authz/users",
"dataSchema": {
"$ref": "#/definitions/dataSchema"
}
},
"tag": "bk-crud-client"
}
],
"tag": "div",
"attributes": {
"style": "width: 100%; height: 100%; display: flex; flex-direction: column; position: relative;"
}
},
"sources": [
"https://cdn.mia-platform.eu/backoffice/bk-web-components/{{BACK_KIT_VERSION}}/dist/bk-web-components.esm.js"
]
}

Screenshot of Microfrontend Composer homepage

The screenshot above shows what the Composer tool should look like based on the application configuration. Before deploying, please verify that micro-lc public variables have been created, that are:

Public VariableCurrent Version ValueMinimum Version Value
MICRO_LC_VERSION2.4.02.4.0
MICRO_LC_MANAGER_VERSION3.1.13.1.1
BACK_KIT_VERSION1.5.61.5.6

These variables are employed by the Console to define the version of the service and libraries used by micro-lc at deploy time. They can be upgraded whenever an update is available.

tip

Besides the Users Page, the Composer comes with two additional pages of type iFrame:

  • docs: page showing Data Catalog documentation from this website;
  • job_runner_ui: page showing the application's grpcui interacting with the Job Runner service. See here to learn more about the interactions with Job Runner.

Endpoints

Here are reported the endpoints that should be exposed from the project in order to enable users managements:

EndpointServiceAuthentication RequiredUser Group Permission
/micro-lc-configurationsmicro-lctrue
/mgmtmicro-lctrue
/authz/userscrudpermissions["read:users"] || permissions["update:users"]
/ui/job-runnergrpcuipermissions["admin:producers"] || permissions["admin:connections"]

Routes

In additions to endpoints definitions provided above, in order to further refine who can manage the users and their permissions for Data Catalog system, each endpoint sub-route should define the specific permission grant that user require to own in order to successfully access the requested resource. The following table provides a recap of each route with the needed permissions.

EndpointTypeMethodUser Group Permissions
/mgmt/usersRESTGETpermissions["read:users"] || permissions["update:users"]
/authz/users/RESTGETpermissions["read:users"]
/authz/users/exportRESTGETpermissions["read:users"]
/authz/users/countRESTGETpermissions["read:users"]
/authz/users/:idRESTGETpermissions["read:users"]
/authz/users/RESTPOSTpermissions["update:users"]
/authz/users/bulkRESTPOSTpermissions["update:users"]
/authz/users/upsert-oneRESTPOSTpermissions["update:users"]
/authz/users/stateRESTPOSTpermissions["update:users"]
/authz/users/:id/stateRESTPOSTpermissions["update:users"]
/authz/users/RESTDELETEpermissions["update:users"]
/authz/users/:idRESTDELETEpermissions["update:users"]
/authz/users/RESTPATCHpermissions["update:users"]
/authz/users/RESTPATCHpermissions["update:users"]
caution

Please ensure that all these endpoints and routes are set with Authentication Required in their security details tab.

The First User

Upon releasing this user management solution, the users table will be empty. Consequently, nobody may enter the application from frontend at the beginning. To grant the permissions to the admin user, that is the one that usually first performs the login procedure, it is necessary to either edit the database record associated to such user and insert the needed permissions, or to temporarily remove the permissions from /authz/users/ endpoint's routes till at least the first user has been granted the read/edit users permissions.

Below is presented the procedure to grant the needed permissions for managing users of Data Catalog application.

Let's start by observing a record of users collection:

{
"_id" : ObjectId("6606e94a0e85630ccda72486"),
"__STATE__" : "PUBLIC",
"providerId" : "okta",
"providerUserId" : "user-id",
"realm" : "my-kingdom",
"createdAt" : ISODate("2024-03-29T16:00:00.000+0000"),
"creatorId" : "public",
"email" : "alice@platform.world",
"groups" : [],
"name" : "Alice",
"updatedAt" : ISODate("2024-09-13T14:00:00.000+0000"),
"updaterId" : "public",
"username" : "",
"permissions": [
// add here the necessary permissions, such as "read:users", "update:users"
]
}

The above document is created the first time a user logs in through the configured Authentication Flow. As it can be seen, the user does not belong to any groups nor it owns any permissions. In order to grant Alice the rank of user master (admin) it is sufficient to add these permissions as strings to the permissions array:

  • read:users
  • update:users

Afterward, Alice user needs to log out of the application and login again to obtain such permissions and be able to manage further application users.

note

We acknowledge this procedure of managing users does not provide a seamless experience. We are working to improve this and reduce configuration friction.

Managing User Permissions

Every time a user logs in for the first time in the Data Catalog application, the users collection is filled with the corresponding user record. Consequently, in order for them to be able to access Data Catalog features they need to receive the proper permissions, that can be granted through the dedicated UI.

Opening the users management frontend, which can be reached by default at the path /mgmt/users under the domain exposed by your Mia-Platform Console project, the first thing that be observed is the users table. This table lists all the users that ever logged in Data Catalog application, alongside their details and permissions.

To update a user's permissions, please search for such user and click on its entry in the table. It will open a modal window showing a set of user's details and scrolling it will be possible to access the list of permissions.

Users Management UI

Modal window showing the permissions field with the values that can be set in the array

Once the needed permissions are added to the permissions, click the Update Data button to store the changes. Now, the user who has just received the new permissions must log out and login again to be able to access Data Catalog UI with the new set of grants.