PageSourceSearch

https://docs.mia-platform.eu/assets/js/0bcebea9.37bcbbaa.js

js mia-platform.eu collected 2026-10-02 06:06:14 UTC 79,238 bytes, 1 lines download raw bytes

1"use strict";(self.webpackChunkmia_platform_docs=self.webpackChunkmia_platform_docs||[]).push([["14225"],{526319(e,n,t){t.r(n),t.d(n,{metadata:()=>i,default:()=>h,frontMatter:()=>d,contentTitle:()=>a,toc:()=>c,assets:()=>o});var i=JSON.parse('{"id":"products/fast_data/runtime_management/secure_access","title":"Secure Access","description":"In order to ensure that only authorized people can access Fast Data Runtime Management system and consequently","source":"@site/versioned_docs/version-15.1.0/products/fast_data/runtime_management/secure_access.md","sourceDirName":"products/fast_data/runtime_management","slug":"/products/fast_data/runtime_management/secure_access","permalink":"/docs/products/fast_data/runtime_management/secure_access","draft":false,"unlisted":false,"tags":[],"version":"15.1.0","frontMatter":{"id":"secure_access","title":"Secure Access","sidebar_label":"Secure Access"},"sidebar":"fastData","previous":{"title":"Database Preparation","permalink":"/docs/products/fast_data/runtime_management/cp_database_setup"},"next":{"title":"Compatibility Matrix","permalink":"/docs/products/fast_data/runtime_management/compatibility_matrix"}}'),s=t(474848),r=t(28453);let d={id:"secure_access",title:"Secure Access",sidebar_label:"Secure Access"},a,o={},c=[{value:"Requirements",id:"requirements",level:2},{value:"Authentication Flow",id:"authentication-flow",level:2},{value:"Services",id:"services",level:3},{value:"Api Gateway",id:"api-gateway",level:4},{value:"Authentication Service",id:"authentication-service",level:4},{value:"Login Site",id:"login-site",level:4},{value:"CRUD Service",id:"crud-service",level:4},{value:"Redis Configuration",id:"redis-configuration",level:4},{value:"Endpoints",id:"endpoints",level:3},{value:"Collections",id:"collections",level:3},{value:"Advanced",id:"advanced",level:3},{value:"Automatic redirect upon receiving 401 HTTP error",id:"automatic-redirect-upon-receiving-401-http-error",level:4},{value:"Authorization Flow",id:"authorization-flow",level:2},{value:"Services",id:"services-1",level:3},{value:"Authorization Service",id:"authorization-service",level:4},{value:"Endpoints",id:"endpoints-1",level:3},{value:"Routes",id:"routes",level:3},{value:"Users Management",id:"users-management",level:2},{value:"Microfrontend Composer",id:"microfrontend-composer",level:3},{value:"Endpoints",id:"endpoints-2",level:3},{value:"Routes",id:"routes-1",level:3},{value:"The First User",id:"the-first-user",level:3},{value:"Managing User Permissions",id:"managing-user-permissions",level:3}];function l(e){let n={a:"a",admonition:"admonition",blockquote:"blockquote",br:"br",code:"code",em:"em",h2:"h2",h3:"h3",h4:"h4",img:"img",li:"li",p:"p",pre:"pre",strong:"strong",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,r.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.p,{children:"In order to ensure that only authorized people can access Fast Data Runtime Management system and consequently\nvisualize or change its state, it is important to properly set up a security layer."}),"\n",(0,s.jsxs)(n.p,{children:["In the following page are described the requirements and a procedure that can be executed to achieve the goal of securing Fast Data Runtime Management application.\nThis procedure is inspired by this ",(0,s.jsx)(n.a,{href:"/docs/products/console/tutorials/configure-marketplace-components/auth-architecture/external-idp-internal-session",children:"guide"}),"\nwhich employs Mia-Platform Marketplace components and exploits Mia-Platform Console features."]}),"\n",(0,s.jsx)(n.admonition,{type:"note",children:(0,s.jsx)(n.p,{children:"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\nmay be followed, adapted according to your needs or taken just as an inspiration for building your security layer."})}),"\n",(0,s.jsx)(n.h2,{id:"requirements",children:"Requirements"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["access to ",(0,s.jsx)(n.a,{href:"/docs/runtime-components/
1applications/fast-data-control-plane/overview",children:"Fast Data Control Plane"})," application, which automatically\nscaffold the configurations regarding microservices, collections, endpoints and variables needed for controlling Fast Data\nRuntime Management solution and protecting its access. Generated resources need to be further customized depending on your needs and credentials."]}),"\n",(0,s.jsxs)(n.li,{children:["an introduction to ",(0,s.jsx)(n.a,{href:"https://envoyproxy.io/",children:"Envoy"}),", which is employed as API Gateway by the application. It is also\npossible to employ ",(0,s.jsx)(n.a,{href:"https://www.nginx.com/",children:"Nginx"})," as API Gateway, though the focus of this guide is on the former."]}),"\n",(0,s.jsxs)(n.li,{children:["an Identity Provider, which manages users' identities. The one employed throughout this guide is ",(0,s.jsx)(n.a,{href:"https://www.okta.com/",children:"Okta"}),",\nalthough any other Identity Provider supported by the Mia-Platform ",(0,s.jsx)(n.a,{href:"/docs/runtime-components/plugins/authentication-service/overview",children:"Authentication Service"}),"\ncan be adopted in place of Okta within this guide."]}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"authentication-flow",children:"Authentication Flow"}),"\n",(0,s.jsx)(n.p,{children:"In this section are described which resources should be configured in order to properly protect the access to the Fast Data\nRuntime Management solution."}),"\n",(0,s.jsx)(n.h3,{id:"services",children:"Services"}),"\n",(0,s.jsx)(n.p,{children:"Upon application instantiation, the following services should have been generated for handling the authentication flow:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.a,{href:"/docs/runtime-components/plugins/envoy-api-gateway/overview",children:(0,s.jsx)(n.code,{children:"api-gateway"})}),", which is the entrypoint of your project requests"]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.a,{href:"/docs/runtime-components/plugins/authentication-service/overview",children:(0,s.jsx)(n.code,{children:"authentication-service"})}),", which is the service that interacts with your Identity Provider to verify your users identity"]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.a,{href:"/docs/runtime-components/plugins/crud-service/overview_and_usage",children:(0,s.jsx)(n.code,{children:"crud-service"})}),", which allows to query via HTTP requests the underlying\ndatabase where users are stored"]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"login-site"}),", a simple frontend employed for handling the authentication flow in user browser"]}),"\n"]}),"\n",(0,s.jsx)(n.h4,{id:"api-gateway",children:"Api Gateway"}),"\n",(0,s.jsxs)(n.p,{children:["For the current use case no further configuration is needed for this service in Console ",(0,s.jsx)(n.em,{children:"Design"})," area. However, if there\nis a need for updating any specific detail, please look for more information at the dedicated ",(0,s.jsx)(n.a,{href:"/docs/runtime-components/plugins/envoy-api-gateway/overview",children:"documentation page"}),"."]}),"\n",(0,s.jsx)(n.h4,{id:"authentication-service",children:"Authentication Service"}),"\n",(0,s.jsx)(n.admonition,{type:"caution",children:(0,s.jsxs)(n.p,{children:["In order to follow through this guide it is necessary to ensure that at least version ",(0,s.jsx)(n.code,{children:"v3.10.0"})," of Authentication Service has been configured.",(0,s.jsx)(n.br,{}),"\n","Earlier versions do not fully support ",(0,s.jsx)(n.code,{children:"permissions"})," key in ",(0,s.jsx)(n.code,{children:"/user-info"})," details and therefore they would not be retrieved\nwhen checking for user's authorization"]})}),"\n",(0,s.jsxs)(n.p,{children:["The service configuration is created with a set of preconfigured variables, such as the connection to Redis\n(see the ",(0,s.jsx)(n.a,{href:"#redis-configuration",children:"paragraph below"}),"), and a config map that lists the supported applications.\nWithin the config map that contains the known applications it is already possible\nto find the definition of an application that uses Okta as Identity Provider."]}),"\n",(0,s.jsx)(n.admonition,{type:"tip",children:(0,s.jsxs)(n.p,{children:["In case you would prefer using another Identity Provider, please read the ",(0,s.jsx)(n.a,{href:"/docs/runtime-components/plugins/authentication-service/configuration",children:"authentication-service documentation"})," to learn\nwhich ones are supported and how to configure the desired one in place of Okta."]})}),"\n",(0,s.jsxs)(n.p,{children:["The configuration of included application only requires to set up few public and secret environment variables to be operational.\nThese variables are summarized in the tables below, divided for location where they should be stored. In fact, the former ones\nshould be added under the ",(0,s.jsx)(n.em,{children:"Variables"})," tab of ",(0,s.jsx)(n.em,{children:"Project Overview"})," area, while the latter can be configured in the ",(0,s.jsx)(n.em,{children:"Public Variables"})," of the ",(0,s.jsx)(n.em,{children:"Design"})," section."]}),"\n",(0,s.jsxs)(n.table,{children:[(0,s.jsx)(n.thead,{children:(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.th,{children:"Secret Variable"}),(0,s.jsx)(n.th,{children:"Explanation"})]})}),(0,s.jsxs)(n.tbody,{children:[(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"CP_OKTA_CLIENT_ID"}),(0,s.jsx)(n.td,{children:"client id obtained when registering this specific application on Okta"})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"CP_OKTA_CLIENT_SECRET"}),(0,s.jsx)(n.td,{children:"client secret obtained when registering this specific application on Okta"})]})]})]}),"\n",(0,s.jsxs)(n.table,{children:[(0,s.jsx)(n.thead,{children:(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.th,{children:"Public Variable"}),(0,s.jsx)(n.th,{children:"Explanation"})]})}),(0,s.jsxs)(n.tbody,{children:[(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"OKTA_BASE_URL"}),(0,s.jsx)(n.td,{children:"base url where your Identity Provider is exposed"})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"CP_APP_ID"}),(0,s.jsxs)(n.td,{children:["application identifier employed when registering this specific application on Okta (e.g. ",(0,s.jsx)(n.code,{children:"fast-data-control-plane"}),")"]})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"CP_PROVIDER_ID"}),(0,s.jsxs)(n.td,{children:["provider identifier employed when registering this specific application on Okta (e.g. ",(0,s.jsx)(n.code,{children:"okta-development"}),")"]})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"CP_REDIS_SCOPE"}
1),(0,s.jsx)(n.td,{children:"redis scope in case of a multi-tenant architecture"})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"CP_BASE_URL"}),(0,s.jsx)(n.td,{children:"base url where the project is exposed"})]})]})]}),"\n",(0,s.jsx)(n.admonition,{type:"note",children:(0,s.jsx)(n.p,{children:"After the creation of the Control Plane application, the public variables specified above should already appear in the\ncorresponding section, each of them with an empty value."})}),"\n",(0,s.jsx)(n.p,{children:"Filling the variables listed above allows to generate a complete configuration at deploy time. An example of such configuration for Okta\ncan be fond in the panel below."}),"\n",(0,s.jsx)(n.p,{children:"Authentication Service | Configuration Example (with variables to be interpolated)"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-json",metastring:"title=config.json",children:'{\n  "apps": {\n    "{{CP_APP_ID}}": {\n      "providers": {\n        "{{CP_PROVIDER_ID}}": {\n          "order": 10,\n          "type": "okta",\n          "label": "Login with Okta",\n          "clientId": "{{CP_OKTA_CLIENT_ID}}",\n          "clientSecret": "{{CP_OKTA_CLIENT_SECRET}}",\n          "baseUrl": "{{OKTA_BASE_URL}}",\n          "authUrl": "{{OKTA_BASE_URL}}/oauth2/v1/authorize",\n          "tokenUrl": "{{OKTA_BASE_URL}}/oauth2/v1/token",\n          "userInfoUrl": "{{OKTA_BASE_URL}}/oauth2/v1/userinfo",\n          "userSettingsURL": "{{OKTA_BASE_URL}}/enduser/settings",\n          "logoutUrl": "{{OKTA_BASE_URL}}/oauth2/v1/logout",\n          "scope": [\n            "openid",\n            "profile",\n            "email",\n            "offline_access"\n          ]\n        }\n      },\n      "redirectUrl": "{{CP_BASE_URL}}/web-login/oauth/callback",\n      "defaultRedirectUrlOnSuccessfulLogin": "/",\n      "authorizeStateRequired": true,\n      "realm": "console",\n      "isWebsiteApp": true,\n      "issuer": "{{CP_APP_ID}}",\n      "defaultGroups": []\n    }\n  }\n}\n'})}),"\n",(0,s.jsxs)(n.p,{children:["In addition to previous configurations, the service needs to mount a private key as a 
1secret. This key is employed to\nsign JWTs that are set as ",(0,s.jsx)(n.em,{children:"session id"})," for authenticated users. In case the service has been instantiated through the\n",(0,s.jsx)(n.code,{children:"Fast Data Control Plane"})," application, a secret has already been associated (",(0,s.jsx)(n.em,{children:"but not created"}),") to the service, which is named ",(0,s.jsx)(n.code,{children:"authentication-service-secrets"}),"."]}),"\n",(0,s.jsx)(n.admonition,{type:"caution",children:(0,s.jsxs)(n.p,{children:["These instructions below assume that the tool employed for deploying Console projects is ",(0,s.jsx)(n.a,{href:"/docs/runtime-components/tools/mlp/overview",children:(0,s.jsx)(n.code,{children:"mlp"})}),".\nPlease, remember to adapt them according to your actual deployment tool and/or secret management configuration."]})}),"\n",(0,s.jsxs)(n.p,{children:["In order for the Console to automatically create the secret at deploy time it is then necessary to edit the file ",(0,s.jsx)(n.code,{children:"mlp.yaml"}),",\nthat can be found within your project repository root folder, and extend it with the following entry under the ",(0,s.jsx)(n.code,{children:"secrets"})," key:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-yaml",metastring:"title=mlp.yaml",children:'secrets:\n  # ...\n  - name: "authentication-service-secrets"\n    when: "always"\n    data:\n      - from: "literal"\n        key: "private-key.pem"\n        value: "{{CP_JWT_CLIENT_PRIVATE_KEY}}"\n  # ...\n'})}),"\n",(0,s.jsxs)(n.p,{children:["This will create at deploy time a K8s secret named ",(0,s.jsx)(n.code,{children:"authentication-service-secrets"}),", which will contains a property ",(0,s.jsx)(n.code,{children:"private-key.pem"})," mapped\nto the value of the interpolated variable ",(0,s.jsx)(n.code,{children:"CP_JWT_CLIENT_PRIVATE_KEY"}),".",(0,s.jsx)(n.br,{}),"\n","To provide the proper value, please generate a private key, for example as follows,"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-shell",children:"ssh-keygen -t rsa -b 4096 -m PEM -f private.key\n"})}),"\n",(0,s.jsxs)(n.p,{children:["and then create the corresponding environment variable ",(0,s.jsx)(n.code,{children:"CP_JWT_CLIENT_PRIVATE_KEY"})," in the ",(0,s.jsx)(n.em,{children:"Variables"})," tab of ",(0,s.jsx)(n.em,{children:"Console Project Overview"})," area.",(0,s.jsx)(n.br,{}),"\n","Finally, please ensure that on the ",(0,s.jsx)(n.code,{children:"authentication-service"}),", located under the ",(0,s.jsx)(n.em,{children:"Microservices"})," section in the Console ",(0,s.jsx)(n.em,{children:"Design"})," area,\nthe environment ",(0,s.jsx)(n.code,{children:"MIA_JWT_TOKEN_PRIVATE_KEY_FILE_PATH"})," is set to ",(0,s.jsx)(n.code,{children:"/secrets/private-key.pem"})," (where the folder is driven\nby the secret mount path and the file name corresponds to the ",(0,s.jsx)(n.code,{children:"key"})," property set in the ",(0,s.jsx)(n.code,{children:"mlp.yaml"})," configuration entry)."]}),"\n",(0,s.jsxs)(n.p,{children:["In case more details are needed on this latter part, please head over to the ",(0,s.jsx)(n.code,{children:"authentication-service"})," ",(0,s.jsx)(n.a,{href:"/docs/runtime-components/plugins/authentication-service/usage#asymmetric-signing-algorithm-rsa256",children:"documentation page"}),"."]}),"\n",(0,s.jsx)(n.h4,{id:"login-site",children:"Login Site"}),"\n",(0,s.jsx)(n.p,{children:"No further configuration is needed for this service."}),"\n",(0,s.jsx)(n.admonition,{type:"tip",children:(0,s.jsxs)(n.p,{children:["In case it is needed to ",(0,s.jsx)(n.a,{href:"/docs/products/fast_data/runtime_management/control_plane_frontend#embed-as-console-extension",children:"embed Fast Data Control Plane solution within Mia-Platform Console"}),",\nplease ensure that login site version greater or equal to ",(0,s.jsx)(n.code,{children:"v8.1.2"})," which supports handling authentication both via redirect and as popup\nwhen requested from an iFrame."]})}),"\n",(0,s.jsx)(n.h4,{id:"crud-service",children:"CRUD Service"}),"\n",(0,s.jsxs)(n.p,{children:["No further configuration is needed for this service, other than ensuring that environment variable ",(0,s.jsx)(n.code,{children:"MONGODB_URL"})," is correctly set,\nthat is either interpolated from a ",(0,s.jsx)(n.a,{href:"/docs/products/console/project-configuration/manage-environment-variables/",children:"Project Secret Variable"})," or loaded from a K8s secret."]}),"\n",(0,s.jsx)(n.h4,{id:"redis-configuration",children:"Redis Configuration"}),"\n",(0,s.jsx)(n.p,{children:"In case you don't already have a Redis instance configured dedicated for authentication purposes, in the steps below it described how to configure\nyour own in-memory only instance:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:["enter your project ",(0,s.jsx)(n.em,{children:"Design"})," area and select ",(0,s.jsx)(n.em,{children:"Microservices"})," section"]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:["click on the button ",(0,s.jsx)(n.em,{children:"Create a Microservice"})," button and select ",(0,s.jsx)(n.em,{children:"From Docker image"})]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:["in the form that is opened enter ",(0,s.jsx)(n.code,{children:"redis-auth"})," as name and ",(0,s.jsx)(n.code,{children:"bitnami/redis:6.2.14"})," and Docker image name and click the ",(0,s.jsx)(n.code,{children:"Create"})," button"]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:["upon the service page opens, head over ",(0,s.jsx)(n.em,{children:"Container Ports"})," card and edit the predefined one to use port ",(0,s.jsx)(n.code,{children:"6379"})," for ",(0,s.jsx)(n.em,{children:"port"})," and ",(0,s.jsx)(n.em,{children:"target port"})]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:["in the ",(0,s.jsx)(n.em,{children:"Runtime"})," card enable readiness and liveness probes on TCP port to ensure the service is working properly once released"]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:["additionally, in the ",(0,s.jsx)(n.em,{children:"Microservice"})," card set the memory and cpu request/limits as follows:"]}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"memory \u2192 15m / 50m;"}),"\n",(0,s.jsx)(n.li,{children:"cpu \u2192 15m / 50m;"}),"\n"]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"now, let's move to the environment variables tab and add the following variables:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"REDIS_PASSWORD"})," set to ",(0,s.jsx)(n.code,{children:"{{CP_REDIS_MASTER_PASSWORD}}"})]}),"\n"]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:["finally, switching to the ",(0,s.jsx)(n.em,{children:"Config Maps"})," tab, let's create a config map named ",(0,s.jsx)(n.code,{children:"cp-redis-auth-configuration"}
1)," that should be mounted\nat ",(0,s.jsx)(n.code,{children:"/opt/bitnami/redis/mounted-etc/"}),". In this config map a file named ",(0,s.jsx)(n.code,{children:"redis.conf"})," should be created. Within this file it is possible\nto insert the Redis configurations shown below."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-text",metastring:"title=redis.conf",children:'## GENERIC ##\nport 6379\n# listen on all the interfaces for incoming connections\nbind 0.0.0.0\n\n## NO DISK PERSISTENCE ##\nsave ""\nappendonly no\n\n## SECURITY ##\nprotected-mode yes\n\n# NOTE: +@connection is necessary to be placed after -@dangerous, otherwise the user won\'t have the permissions to connect to Redis\nuser {{CP_REDIS_USERNAME}} on +@all -@dangerous +@connection allkeys allchannels >{{CP_REDIS_PASSWORD}}\n\n# disable default user\nuser default off\n'})}),"\n"]}),"\n"]}),"\n",(0,s.jsxs)(n.p,{children:["The provided Redis configuration describes disk persistence management (in-memory only) and introduce a dedicated user with their ACLs.\nTo complete the configuration it is necessary to create the following secret environment variables in the ",(0,s.jsx)(n.em,{children:"Project Overview"})," area:"]}),"\n",(0,s.jsxs)(n.table,{children:[(0,s.jsx)(n.thead,{children:(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.th,{children:"Secret Variable"}),(0,s.jsx)(n.th,{children:"Explanation"})]})}),(0,s.jsxs)(n.tbody,{children:[(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"CP_REDIS_MASTER_PASSWORD"}),(0,s.jsx)(n.td,{children:"root password to allow Redis start (not used by any service - it can be loaded from a secret when configured within the service environment variables)"})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"CP_REDIS_USERNAME"}),(0,s.jsx)(n.td,{children:"username of the Redis account to be employed by the authentication-service for accessing Redis"})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"CP_REDIS_PASSWORD"}),(0,s.jsx)(n.td,{children:"password of the Redis account to be employed by the authentication-service for accessing Redis"})]})]})]}),"\n",(0,s.jsx)(n.h3,{id:"endpoints",children:"Endpoints"}),"\n",(0,s.jsx)(n.p,{children:"Below is reported the list of endpoints related to the authentication flow that are created with the instantiation of Control Plane application. Please\nensure that they are exposed with the proper security options."}),"\n",(0,s.jsxs)(n.table,{children:[(0,s.jsx)(n.thead,{children:(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.th,{children:"Endpoint"}),(0,s.jsx)(n.th,{children:"Service"}),(0,s.jsx)(n.th,{style:{textAlign:"center"},children:"Authentication Required"}),(0,s.jsx)(n.th,{children:"User Group Permission"})]})}),(0,s.jsxs)(n.tbody,{children:[(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"/web-login"})}),(0,s.jsx)(n.td,{children:"login-site"}),(0,s.jsx)(n.td,{style:{textAlign:"center"},children:"-"}),(0,s.jsx)(n.td,{children:"true"})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"/authorize"})}),(0,s.jsx)(n.td,{children:"authentication-service"}),(0,s.jsx)(n.td,{style:{textAlign:"center"},children:"-"}),(0,s.jsx)(n.td,{children:"true"})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"/oauth/token"})}),(0,s.jsx)(n.td,{children:"authentication-service"}),(0,s.jsx)(n.td,{style:{textAlign:"center"},children:"-"}),(0,s.jsx)(n.td,{children:"true"})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"/logout"})}),(0,s.jsx)(n.td,{children:"authentication-service"}),(0,s.jsx)(n.td,{style:{textAlign:"center"},children:"-"}),(0,s.jsx)(n.td,{children:"true"})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"/refreshtoken"})}),(0,s.jsx)(n.td,{children:"authentication-service"}),(0,s.jsx)(n.td,{style:{textAlign:"center"},children:"\u2705"}),(0,s.jsx)(n.td,{children:"true"})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"/userinfo"})}),(0,s.jsx)(n.td,{children:"authentication-service"}),(0,s.jsx)(n.td,{style:{textAlign:"center"},children:"\u2705"}),(0,s.jsx)(n.td,{children:"true"})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"/apps"})}),(0,s.jsx)(n.td,{children:"authentication-service"}),(0,s.jsx)(n.td,{style:{textAlign:"center"},children:"-"}),(0,s.jsx)(n.td,{children:"true"})]})]})]}),"\n",(0,s.jsx)(n.p,{children:"Knowing these endpoints are exposed, it is now possible to configure the redirect urls that some Identity Providers,\nsuch as Okta or Auth0, require to complete the application registration.\nThese endpoints will be then employed during the authentication flow to constrain the redirects\nthe Identity Provider can perform. In this case the endpoint that should be configured are the following ones:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["Sign-in redirect URIs \u2192 ",(0,s.jsx)(n.code,{children:"<project-base-url>/web-login/oauth/callback"})]}),"\n",(0,s.jsxs)(n.li,{children:["Sign-out redirect URIs \u2192 ",(0,s.jsx)(n.code,{children:"<project-base-url>/logout"})]}),"\n"]}),"\n",(0,s.jsxs)(n.p,{children:["where ",(0,s.jsx)(n.code,{children:"<project-base-url>"})," is the base url where the project of interest is exposed to."]}),"\n",(0,s.jsx)(n.h3,{id:"collections",children:"Collections"}),"\n",(0,s.jsxs)(n.p,{children:["The authentication flow via the ",(0,s.jsx)(n.code,{children:"authentication-service"})," requires also the introduction of a CRUD Collection, where\nusers details are saved upon successful login. These user information can then be employed in the authorization flow, which is\ndescribed later.",(0,s.jsx)(n.br,{}),"\n","By default the ",(0,s.jsx)(n.code,{children:"Fast Data Control Plane"})," application creates the collection for you and instantiates the CRUD Service,\nwhich is employed by the authentication service to access the collection. Additionally, below it is also provided the\ncollection definition ready for being imported, in case it may be necessary to move or replicate the collection in another Console project."]}),"\n",(0,s.jsx)(n.p,{children:"Control Plane Users Collection Definition (import ready)"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-json",children:'{\n  "data": {\n    "collections": {\n      "users": {\n        "id": "users",\n        "name": "users",\n        "fields": [\n          {\n            "name": "_id",\n            "type": "ObjectId",\n            "required": true,\n            "nullable": false,\n            "description": "_id"\n          },\n          {\n            "name": "creatorId",\n            "type": "string",\n            "required": true,\n            "nullable": false,\n            "description": "creatorId"\n          },\n          {\n            "name": "createdAt",\n            "type": "Date",\n            "required": true,\n            "nullable": false,\n            "description": "createdAt"\n          },\n          {\n            "name": "updaterId",\n            "type": "string",\n            "required": true,\n            "nullable": false,\n            "description": "updaterId"\n          },\n          {\n            "name": "updatedAt",\n            "type": "Date",\n            "required": true,\n            "nullable": false,\n            "description": "updatedAt"\n          },\n          {\n            "name": "__STATE__",\n            "type": "string",\n            "required": true,\n            "nullable": false,\n            "description": "__STATE__"\n          },\n          {\n            "name": "name",\n            "type": "string",\n            "required": false,\n            "nullable": false,\n            "sensitivityValue": 0,\n            "encryptionEnabled": false,\n            "encryptionSearchable": false\n          },\n          {\n            "name": "groups",\n            "type": "Array_string",\n            "required": false,\n            "nullable": false,\n            "sensitivityValue": 0,\n            "encryptionEnabled": false,\n            "encryptionSearchable": false\n          },\n          {\n            "name": "username",\n            "type": "string",\n            "required": false,\n            "nullable": false,\n            "sensitivityValue": 0,\n            "encryptionEnabled": false,\n            "encryptionSearchable": false\n          },\n          {\n            "name": "email",\n            "type": "string",\n            "required": false,\n            "nullable": false,\n            "sensitivityValue": 0,\n            "encryptionEnabled": false,\n            "encryptionSearchable": false\n          },\n          {\n            "name": "providerId",\n            "type": "string",\n            "required": true,\n            "nullable": false,\n            "sensitivityValue": 0,\n            "encryptionEnabled": false,\n            "encryptionSearchable": false\n          },\n          {\n            "name": "providerUserId",\n            "type": "string",\n            "required": true,\n            "nullable": false,\n            "sensitivityValue": 0,\n            "encryptionEnabled": false,\n            "encryptionSearchable": false\n          },\n          {\n            "name": "realm",\n            "type": "string",\n            "required": false,\n            "nullable": false,\n            "sensitivityValue": 0,\n            "encryptionEnabled": false,\n            "encryptionSearchable": false\n          },\n          {\n            "name": "metadata",\n            "type": "RawObject",\n            "required": false,\n            "nullable": false,\n            "sensitivityValue": 0,\n            "encryptionEnabled": false,\n            "encryptionSearchable": false\n          },\n          {\n            "name": "permissions",\n            "type": "Array_string",\n            "required": false,\n            "nullable": false,\n            "sensitivityValue": 0,\n            "encryptionEnabled": false,\n            "encryptionSearchable": false\n          }\n        ],\n        "internalEndpoints": [\n          {\n            "basePath": "/users",\n            "defaultState": "PUBLIC"\n          }\n        ],\n        "type": "collection",\n        "indexes": [\n          {\n            "name": "_id",\n            "type": "normal",\n            "unique": true,\n            "fields": [\n              {\n                "name": "_id",\n                "order": 1\n              }\n            ]\n          },\n          {\n            "name": "createdAt",\n            "type": "normal",\n            "unique": false,\n            "fields": [\n              {\n                "name": "createdAt",\n                "order": -1\n              }\n            ]\n          },\n          {\n            "name": "stateIndex",\n            "type": "normal",\n            "unique": false,\n            "fields": [\n              {\n                "name": "__STATE__",\n                "order": 1\n              }\n            ]\n          },\n          {\n            "name": "nameSearch",\n            "type": "normal",\n            "unique": false,\n            "fields": [\n              {\n                "name": "email",\n                "order": 1\n              },\n              {\n                "name": "name",\n                "order": 1\n              },\n              {\n                "name": "__STATE__",\n                "order": 1\n              }\n            ]\n          },\n          {\n            "name": "upsertSupport",\n            "type": "normal",\n            "unique": false,\n            "fields": [\n              {\n                "name": "providerId",\n                "order": 1\n              },\n              {\n                "name": "providerUserId",\n                "order": 1\n              },\n              {\n                "name": "realm",\n                "order": 1\n              }\n            ]\n          }\n        ],\n        "description": "Collection of users",\n        "tags": [\n          "collection"\n        ]\n      }\n    }\n  },\n  "metadata": {\n    "branchName": "master",\n    "exportTimestamp": "2024-09-13T07:00:00.000Z",\n    "isImported": false,\n    "pathRefType": "revisions",\n    "projectId": "",\n    "projectName": ""\n  }\n}\n'})}),"\n",(0,s.jsx)(n.h3,{id:"advanced",children:"Advanced"}),"\n",(0,s.jsx)(n.p,{children:"In this section are described additional tweaks to be carried out on the API Gateway (Envoy), that enhance the interaction with\nthe runtime system and allow this solution to support authentication."}),"\n",(0,s.jsxs)(n.p,{children:["These modifications should be inserted in the proper file in the ",(0,s.jsx)(n.strong,{children:"Advanced"})," section of the Console ",(0,s.jsx)(n.em,{children:"Design"})," area, under\nthe key ",(0,s.jsx)(n.code,{children:"api-gateway-envoy"}),"."]}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{alt:"Console advanced tab in Design section showing &#39;api-gateway-envoy&#39; configuration",src:t(963911).A+"",width:"2255",height:"880"})}),"\n",(0,s.jsx)(n.admonition,{type:"note",children:(0,s.jsxs)(n.p,{children:["Before proceeding, be sure to have configured Control Plane endpoints accordingly to their ",(0,s.jsx)(n.a,{href:"/docs/products/fast_data/runtime_management/control_plane#endpoints",children:"specific documentation"}),"."]})}),"\n",(0,s.jsx)(n.h4,{id:"automatic-redirect-upon-receiving-401-http-error",children:"Automatic redirect upon receiving 401 HTTP error"}),"\n",(0,s.jsxs)(n.p,{children:["This configuration edit should be inserted in the file ",(0,s.jsx)(n.code,{children:"local-replies.yml"})," and it enforces a redirect to the login\npage every time a 401 HTTP error is encountered by the system. This ensures that the users authenticate before returning\nto the page they were trying to browse."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-yml",metastring:"title=api-gateway-envoy/local-replies.yml",children:'- listener_name: frontend\n  filter:\n    status_code_filter:\n      comparison:\n        op: 
1EQ\n        value:\n          default_value: 401\n          runtime_key: key_b\n  status_code: 302\n  body:\n    inline_string: |-\n      <html>\n        <head>\n          <meta http-equiv="content-type" content="text/html;charset=utf-8">\n            <title>302 Found</title>\n        </head>\n      </html>\n  headers_to_add:\n    - header:\n        key: "Location"\n        value: "/web-login?appId={{CP_APP_ID}}&providerId={{CP_PROVIDER_ID}}&redirect=%REQ(:PATH)%"\n      append: false\n    - header:\n        key: "Set-Cookie"\n        value: "sid=; Max-Age=0"\n      append: false\n'})}),"\n",(0,s.jsx)(n.admonition,{type:"note",children:(0,s.jsxs)(n.p,{children:["If you're using API Gateway with Nginx, please consider using ",(0,s.jsx)(n.a,{href:"/docs/runtime-components/applications/secure-api-gateway/configuration#nginx",children:"this approach for automatic redirects"}),"."]})}),"\n",(0,s.jsx)(n.h2,{id:"authorization-flow",children:"Authorization Flow"}),"\n",(0,s.jsx)(n.p,{children:"In this section are described which resources and permissions should be configured in order to properly grant the access\nto the Fast Data Runtime Management solution only to authorized users."}),"\n",(0,s.jsx)(n.h3,{id:"services-1",children:"Services"}),"\n",(0,s.jsx)(n.p,{children:"Upon application instantiation, the following services should have been generated for handling the authorization flow within your project:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.a,{href:"/docs/runtime-components/plugins/authorization-service/overview",children:(0,s.jsx)(n.code,{children:"authentication-service"})}),", which is in charge of verifying whether an\nauthenticated user has been granted the permissions to access the resource they are requesting. This service works in tandem\nwith ",(0,s.jsx)(n.code,{children:"api-gateway"})," and ",(0,s.jsx)(n.code,{children:"authentication-service"})," to fulfill its role;"]}),"\n"]}),"\n",(0,s.jsx)(n.h4,{id:"authorization-service",children:"Authorization Service"}),"\n",(0,s.jsx)(n.p,{children:"This service is introduced when creating the application and it is already preconfigured with all the necessary configurations.\nIn case the service already exists in your project, please ensure the following environment variables on the service contain\nthe these values below:"}),"\n",(0,s.jsxs)(n.table,{children:[(0,s.jsx)(n.thead,{children:(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.th,{children:"Environment Variable"}),(0,s.jsx)(n.th,{children:"Value"})]})}),(0,s.jsxs)(n.tbody,{children:[(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"HEADERS_TO_PROXY"}),(0,s.jsx)(n.td,{children:"connection,upgrade,sec-websocket-protocol,sec-websocket-version,x-request-id,request-id,cookie,authorization,client-type,host,x-forwarded-host"})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"USERINFO_URL"}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.a,{href:"http://authentication-service/userinfo",children:"http://authentication-service/userinfo"})})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"USER_PROPERTIES_TO_PROXY"}),(0,s.jsx)(n.td,{children:"provider,email,username,name,permissions,metadata"})]})]})]}),"\n",(0,s.jsx)(n.p,{children:"In order to support real-time updates in the Fast Data Runtime Management system, it is important to allow proxying the following\nheaders:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Connection",children:(0,s.jsx)(n.code,{children:"connection"})})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Upgrade",children:(0,s.jsx)(n.code,{children:"upgrade"})})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"https://developer.mozilla.org/en-US/docs/Web/HTTP/Protocol_upgrade_mechanism#websocket-specific_headers",children:(0,s.jsx)(n.code,{children:"sec-websocket-protocol"})})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"https://developer.mozilla.org/en-US/docs/Web/HTTP/Protocol_upgrade_mechanism#websocket-specific_headers",children:(0,s.jsx)(n.code,{children:"sec-websocket-version"})})}),"\n"]}),"\n",(0,s.jsxs)(n.p,{children:["In addition, ",(0,s.jsx)(n.code,{children:"USER_PROPERTIES_TO_PROXY"})," must be edited to include also ",(0,s.jsx)(n.code,{children:"permissions"})," key, so that ",(0,s.jsx)(n.code,{children:"permissions"})," property is loaded, checked\nand then forwarded to the underlying components."]}),"\n",(0,s.jsx)(n.h3,{id:"endpoints-1",children:"Endpoints"}),"\n",(0,s.jsxs)(n.p,{children:["In addition to the endpoints described 
1in the ",(0,s.jsx)(n.a,{href:"#endpoints",children:"Authentication Flow"})," section, here are described the ones that expose\nall the functionalities of Fast Data Runtime Management system, both the frontend and backend components."]}),"\n",(0,s.jsxs)(n.table,{children:[(0,s.jsx)(n.thead,{children:(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.th,{children:"Endpoint"}),(0,s.jsx)(n.th,{children:"Service"}),(0,s.jsx)(n.th,{style:{textAlign:"center"},children:"Authentication Required"}),(0,s.jsx)(n.th,{children:"User Group Permission"})]})}),(0,s.jsxs)(n.tbody,{children:[(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"/fast-data"})}),(0,s.jsx)(n.td,{children:"fabric-bff"}),(0,s.jsx)(n.td,{style:{textAlign:"center"},children:"\u2705"}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"false"})})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"/control-plane"})}),(0,s.jsx)(n.td,{children:"control-plane-fe"}),(0,s.jsx)(n.td,{style:{textAlign:"center"},children:"\u2705"}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"true"})})]})]})]}),"\n",(0,s.jsx)(n.h3,{id:"routes",children:"Routes"}),"\n",(0,s.jsx)(n.p,{children:"In order to finely control which operations a user can carry out over Control Plane APIs, a set of permissions has been devised, which\nis listed here:"}),"\n",(0,s.jsxs)(n.table,{children:[(0,s.jsx)(n.thead,{children:(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.th,{children:"Permission"}),(0,s.jsx)(n.th,{children:"Context"})]})}),(0,s.jsxs)(n.tbody,{children:[(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"read:pipelines"})}),(0,s.jsx)(n.td,{children:"allows listing runtimes, their status and visualizing their pipelines list and structure"})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"control:pipelines"})}),(0,s.jsxs)(n.td,{children:["enables changing pipelines state (",(0,s.jsx)(n.code,{children:"pause"})," / ",(0,s.jsx)(n.code,{children:"resume"}),")"]})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"update:runtimes"})}),(0,s.jsx)(n.td,{children:"enables creating, updating or deleting runtime views"})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"read:users"})}),(0,s.jsx)(n.td,{children:"enables a user to access the user management application in read-only mode"})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"update:users"})}),(0,s.jsx)(n.td,{children:"enables a user to edit users details in the user management application"})]})]})]}),"\n",(0,s.jsxs)(n.admonition,{type:"caution",children:[(0,s.jsx)(n.p,{children:"Please, beware that:"}),(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["these ",(0,s.jsx)(n.strong,{children:"permissions are Company-wise"}),", that is once a user gets the permissions to update a pipeline state, it can\nchange it for all the pipelines. Currently, there is no filter mechanism that allows a user to manage only Fast Data Runtimes of projects\nthey can access to;"]}),"\n",(0,s.jsxs)(n.li,{children:["the ",(0,s.jsx)(n.strong,{children:"default permissions configuration make them independent one from another"}),". A users needs to obtain both\n",(0,s.jsx)(n.em,{children:"read"})," and ",(0,s.jsx)(n.em,{children:"update"})," permissions to use all the ",(0,s.jsx)(n.em,{children:"Control Plane UI"})," features and fully manage Fast Data Runtimes.",(0,s.jsx)(n.br,{}),"\n","For example, a user with ",(0,s.jsx)(n.code,{children:"control:pipelines"})," permissions can effectively change the state of a pipeline, but only in case it knows\nthe pipeline identifier beforehand, since it cannot list the existing pipelines;"]}),"\n"]})]}),"\n",(0,s.jsx)(n.p,{children:"The permissions described in the table above needs then to be applied to all the different routes exposed by Control Plane application,\nso that each operation is covered with the correct grant."}),"\n",(0,s.jsxs)(n.table,{children:[(0,s.jsx)(n.thead,{children:(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.th,{children:"Endpoint"}),(0,s.jsx)(n.th,{children:"Type"}),(0,s.jsx)(n.th,{children:"Method"}),(0,s.jsx)(n.th,{children:"User Group Permissions"})]})}),(0,s.jsxs)(n.tbody,{children:[(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"/fast-data/feedback"})}),(0,s.jsx)(n.td,{children:"Websocket"}),(0,s.jsx)(n.td,{children:"HEAD"}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:'permissions["read:pipelines"]'})})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"/fast-data/feedback"})}),(0,s.jsx)(n.td,{children:"Websocket"}),(0,s.jsx)(n.td,{children:"GET"}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:'permissions["read:pipelines"]'})})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"/fast-data/control"})}),(0,s.jsx)(n.td,{children:"REST"}),(0,s.jsx)(n.td,{children:"HEAD"}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:'permissions["control:pipelines"]'})})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"/fast-data/control"})}),(0,s.jsx)(n.td,{children:"REST"}),(0,s.jsx)(n.td,{children:"POST"}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:'permissions["control:pipelines"]'})})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"/fast-data/runtimes/items"})}),(0,s.jsx)(n.td,{children:"REST"}),(0,s.jsx)(n.td,{children:"GET"}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:'permissions["read:pipelines"]'})})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"/fast-data/runtimes/items"})}),(0,s.jsx)(n.td,{children:"REST"}),(0,s.jsx)(n.td,{children:"POST"}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:'permissions["update:runtimes"]'})})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"/fast-data/runtimes/items/:id"})}),(0,s.jsx)(n.td,{children:"REST"}),(0,s.jsx)(n.td,{children:"GET"}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:'permissions["read:pipelines"]'})})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"/fast-data/runtimes/items/:id"})}),(0,s.jsx)(n.td,{children:"REST"}),(0,s.jsx)(n.td,{children:"PATCH"}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:'permissions["update:runtimes"]'})})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"/fast-data/runtimes/items/:id"})}),(0,s.jsx)(n.td,{children:"REST"}),(0,s.jsx)(n.td,{children:"DELETE"}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:'permissions["update:runtimes"]'})})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"/fast-data/runtimes/items/:id/pipelines"})}),(0,s.jsx)(n.td,{children:"REST"}),(0,s.jsx)(n.td,{children:"GET"}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:'permissions["read:pipelines"]'})})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"/fast-data/runtimes/stats"})}),(0,s.jsx)(n.td,{children:"REST"}),(0,s.jsx)(n.td,{children:"GET"}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:'permissions["read:pipelines"]'})})]})]})]}),"\n",(0,s.jsx)(n.admonition,{type:"caution",children:(0,s.jsxs)(n.p,{children:["Please ensure that all these endpoints and subsequent routes are set with ",(0,s.jsx)(n.em,{children:"Authentication Required"})," in their security details tab."]})}),"\n",(0,s.jsxs)(n.p,{children:["Furthermore, when ",(0,s.jsx)(n.strong,{children:"publicly"})," exposing the gRPC services of main Control Plane instance, we recommend to introduce a security measure to prevent\nunwanted communications. This can be obtained by setting a ",(0,s.jsx)(n.a,{href:"https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication#basic_authentication_scheme",children:"Basic Authentication"}),"\non your ingress controller or an ",(0,s.jsx)(n.a,{href:"/docs/products/console/api-console/api-design/api-key",children:"API key"})," to be verified by the Authorization Service."]}),"\n",(0,s.jsxs)(n.p,{children:["Configuration of an API Key can be carried out directly in Console as explained ",(0,s.jsx)(n.a,{href:"/docs/products/console/api-console/api-design/api-key#create-a-new-api-key",children:"here"}),",\nwhereas in this ",(0,s.jsx)(n.a,{href:"/docs/products/console/api-console/api-design/endpoints#manage-the-security-of-your-endpoints",children:"documentation page"})," is explained\nhow to protect an endpoint with it.\nIn the table below are listed which exposed endpoints should be protected by API Key,\nassuming the name assigned to the ",(0,s.jsx)(n.code,{children:"clientType"})," is ",(0,s.jsx)(n.code,{children:"control_plane_operator"}),":"]}),"\n",(0,s.jsxs)(n.table,{children:[(0,s.jsx)(n.thead,{children:(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.th,{children:"Endpoint"}),(0,s.jsx)(n.th,{children:"Type"}),(0,s.jsx)(n.th,{style:{textAlign:"center"},children:"API Key required"}),(0,s.jsx)(n.th,{children:"User Group Permissions"})]})}),(0,s.jsxs)(n.tbody,{children:[(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"/grpc.reflection.v1.ServerReflection"})}),(0,s.jsx)(n.td,{children:"gRPC"}),(0,s.jsx)(n.td,{style:{textAlign:"center"},children:"\u2713"}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:'clientType == "control_plane_operator"'})})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"/grpc.reflection.v1alpha.ServerReflection"})}),(0,s.jsx)(n.td,{children:"gRPC"}),(0,s.jsx)(n.td,{style:{textAlign:"center"},children:"\u2713"}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:'clientType == "control_plane_operator"'})})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"/control_plane_fabric.RuntimeManagement"})}),(0,s.jsx)(n.td,{children:"gRPC"}),(0,s.jsx)(n.td,{style:{textAlign:"center"},children:"\u2713"}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:'clientType == "control_plane_operator"'})})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"/control_plane_fabric.ControlPlane"})}),(0,s.jsx)(n.td,{children:"gRPC"}),(0,s.jsx)(n.td,{style:{textAlign:"center"},children:"\u2713"}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:'clientType == "control_plane_operator"'})})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"/control_plane_fabric.FastDataControl"})}),(0,s.jsx)(n.td,{children:"gRPC"}),(0,s.jsx)(n.td,{style:{textAlign:"center"},children:"\u2713"}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:'clientType == "control_plane_operator"'})})]})]})]}),"\n",(0,s.jsx)(n.admonition,{type:"tip",children:(0,s.jsxs)(n.p,{children:["Upon securing gRPC endpoints with an API Key, please remember to ",(0,s.jsx)(n.a,{href:"/docs/products/fast_data/runtime_management/control_plane_operator#upstream",children:"add the needed header"}),"\n(",(0,s.jsx)(n.code,{children:"secret"}),") to the configuration of all your ",(0,s.jsx)(n.em,{children:"Control Plane Operators"}),"."]})}),"\n",(0,s.jsx)(n.h2,{id:"users-management",children:"Users Management"}),"\n",(0,s.jsx)(n.p,{children:"Controlling which users can access the Fast Data Runtime Management system and their assigned permissions can be done either\nvia directly editing database records or calling CRUD Service APIs. However, having a front-end to execute these actions\nwould be a nice add-on to simplify these actions and to reduce errors related to possible mis-configurations."}),"\n",(0,s.jsxs)(n.p,{children:["This can be achieved thanks to the ",(0,s.jsx)(n.a,{href:"/docs/products/microfrontend-composer/what-is",children:"Microfrontend Composer"})," tool, which allows crafting\nand configuring web pages and applications. In particular, it is possible to build the pages for listing the users,"]}),"\n",(0,s.jsx)(n.p,{children:"An example of application that can be created is shown in the picture below:"}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{alt:"Users Management UI",src:t(44566).A+"",width:"1920",height:"1080"})}),"\n",(0,s.jsxs)(n.blockquote,{children:["\n",(0,s.jsx)(n.p,{children:"Example of Users Management UI that is generated by the Fast Data Control Plane application"}),"\n"]}),"\n",(0,s.jsx)(n.h3,{id:"microfrontend-composer",children:"Microfrontend Composer"}),"\n",(0,s.jsx)(n.admonition,{type:"caution",children:(0,s.jsxs)(n.p,{children:["In order to use Microfrontend Composer in Console it is necessary to purchase the dedicated license. For more information, please ask to your Mia-Platform referent. Nonetheless,\nthe application will create tha ",(0,s.jsx)(n.em,{children:"user management"})," pages, but those won't be easily editable from the Composer configurator."]})}
1),"\n",(0,s.jsxs)(n.p,{children:["Upon application instantiation, a predefined set of web pages are created and ready to be used once the project is deployed.\nIn case you would like to customize those pages here are provided their configuration, one for control plane users, one for\nthe roles and one for their bindings. These configuration can be loaded either as config map of ",(0,s.jsx)(n.a,{href:"https://micro-lc.io/docs/",children:"micro-lc"})," service\nor within the advanced tab of the corresponding page in the Composer."]}),"\n",(0,s.jsx)(n.p,{children:"Control Plane Users Page"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-json",metastring:"title=users-config.json",children:'{\n  "definitions": {\n    "dataSchema": {\n      "type": "object",\n      "required": [\n        "providerId",\n        "providerUserId"\n      ],\n      "properties": {\n        "_id": {\n          "formOptions": {\n            "hiddenOnInsert": true,\n            "readOnlyOnUpdate": true\n          },\n          "type": "string",\n          "visualizationOptions": {\n            "hidden": true\n          }\n        },\n        "creatorId": {\n          "formOptions": {\n            "hiddenOnInsert": true,\n            "readOnlyOnUpdate": true,\n            "disabled": false,\n            "hidden": true\n          },\n          "type": "string",\n          "visualizationOptions": {\n            "hidden": true\n          }\n        },\n        "createdAt": {\n          "formOptions": {\n            "hiddenOnInsert": true,\n            "readOnlyOnUpdate": true,\n            "disabled": false,\n            "hidden": true\n          },\n          "dateOptions": {\n            "displayFormat": "YYYY-MM-DD hh:mm"\n          },\n          "format": "date-time",\n          "type": "string",\n          "visualizationOptions": {\n            "hidden": true\n          }\n        },\n        "updaterId": {\n          "formOptions": {\n            "hiddenOnInsert": true,\n            "readOnlyOnUpdate": true,\n            "hiddenOnUpdate": true\n          },\n          "type": "string",\n          "visualizationOptions": {\n            "hidden": true\n          }\n        },\n        "updatedAt": {\n          "formOptions": {\n            "hiddenOnInsert": true,\n            "readOnlyOnUpdate": true,\n            "hiddenOnUpdate": false,\n            "hidden": true\n          },\n          "dateOptions": {\n            "displayFormat": "YYYY-MM-DD hh:mm"\n          },\n          "format": "date-time",\n          "type": "string",\n          "visualizationOptions": {\n            "hidden": true\n          }\n        },\n        "__STATE__": {\n          "enum": [\n            "PUBLIC",\n            "DRAFT",\n            "TRASH",\n            "DELETED"\n          ],\n          "formOptions": {\n            "readOnlyOnUpdate": true,\n            "readOnly": false,\n            "placeholder": "PUBLIC"\n          },\n          "type": "string",\n          "visualizationOptions": {\n            "hidden": true\n          }\n        },\n        "name": {\n          "type": "string",\n          "formOptions": {\n            "readOnly": true\n          }\n        },\n        "groups": {\n          "type": "array",\n          "items": {\n            "type": "string"\n          }\n        },\n        "username": {\n          "type": "string",\n          "formOptions": {\n            "readOnly": true\n          },\n          "visualizationOptions": {\n            "hidden": true\n          }\n        },\n        "email": {\n          "type": "string",\n          "formOptions": {\n            "readOnly": true\n          },\n          "visualizationOptions": {\n            "hidden": true\n          }\n        },\n        "providerId": {\n          "type": "string",\n          "formOptions": {\n            "readOnly": true\n          }\n        },\n        "providerUserId": {\n          "type": "string",\n          "formOptions": {\n            "readOnly": true\n          },\n          "visualizationOptions": {\n            "hidden": true\n          }\n        },\n        "realm": {\n          "type": "string",\n          "formOptions": {\n            "readOnlyOnInsert": false,\n            "readOnly": true\n          },\n          "visualizationOptions": {\n            "hidden": true\n          }\n        },\n        "permissions": {\n          "type": "array",\n          "items": {\
1n            "type": "string",\n            "enum": [\n              "read:pipelines",\n              "control:pipelines",\n              "update:runtimes",\n              "read:data-assets",\n              "update:metadata-assets",\n              "read:users",\n              "update:users"\n            ]\n          },\n          "dataSchema": {\n            "type": "array",\n            "items": {\n              "type": "string",\n              "enum": [\n                "read:pipelines",\n                "control:pipelines",\n                "update:runtimes",\n                "read:data-assets",\n                "update:metadata-assets",\n                "read:users",\n                "update:users"\n              ]\n            }\n          }\n        },\n        "metadata": {\n          "type": "object",\n          "visualizationOptions": {\n            "hidden": true\n          }\n        }\n      }\n    }\n  },\n  "content": {\n    "content": [\n      {\n        "content": [\n          {\n            "tag": "div",\n            "content": [\n              {\n                "properties": {\n                  "content": "Users"\n                },\n                "tag": "bk-title"\n              },\n              {\n                "tag": "bk-refresh-button",\n                "attributes": {\n                  "style": "margin-left: 14px; align-self: end;"\n                }\n              },\n              {\n                "tag": "div",\n                "attributes": {\n                  "style": "flex-grow: 1;"\n                }\n              },\n              {\n                "properties": {\n                  "placeholder": "Search..."\n                },\n                "tag": "bk-search-bar"\n              },\n              {\n                "properties": {\n                  "content": "",\n                  "clickConfig": {\n                    "type": "event",\n                    "actionConfig": {\n                      "label": "filter",\n                      "payload": {}\n                    }\n                  },\n                  "type": "outlined",\n                  "iconId": "FunnelPlotOutlined"\n                },\n                "tag": "bk-button"\n              }\n            ],\n            "attributes": {\n              "style": "display: flex; flex-direction: row; gap: 10px; padding: 0 20px;"\n            }\n          },\n          {\n            "tag": "div",\n            "attributes": {\n              "style": "width: 100%; display: flex; justify-content: space-between;"\n            },\n            "content": [\n              {\n                "attributes": {\n                  "style": "flex-grow: 1;"\n                },\n                "properties": {\n                  "tabs": [\n                    {\n                      "key": "public",\n                      "title": "Public",\n                      "filters": [\n                        {\n                          "property": "__STATE__",\n                          "operator": "equal",\n                          "value": "PUBLIC"\n                        }\n                      ],\n                      "order": 0\n                    },\n                    {\n                      "title": "Draft",\n                      "key": "draft",\n                      "order": 2,\n                      "filters": [\n                        {\n                          "property": "__STATE__",\n                          "operator": "equal",\n                          "value": "DRAFT"\n                        }\n                      ]\n                    },\n                    {\n                      "title": "Trash",\n                      "filters": [\n                        {\n                          "property": "__STATE__",\n                          "operator": "equal",\n                          "value": "TRASH"\n                        }\n                      ],\n                      "order": 3,\n                      "key": "trash"\n                    }\n                  ]\n                },\n                "tag": "bk-tabs"\n              },\n              {\n                "attributes": {\n                  "style": "margin-right: 4px"\n                },\n                "properties": {\n                  "dataSchema": {\n                    "$ref": "#/definitions/dataSchema"\n                  },\n                  "filters": []\n                },\n                "tag": "bk-filters-manager"\n              }\n            ]\n          },\n          {\n            "tag": "div",\n            "attributes": {\n              "style": "padding: 0 20px;"\n            },\n            "content": {\n              "tag": "bk-breadcrumbs",\n              "properties": {\n                "dataSchema": {\n                  "$ref": "#/definitions/dataSchema"\n                }\n              }\n            }\n          }\n        ],\n        "tag": "header",\n        "attributes": {\n          "style": "display: flex; flex-direction: column; padding-top: 10px; background-color: white;"\n        }\n      },\n      {\n        "content": [\n          {\n            "properties": {\n              "dataSchema": {\n                "$ref": "#/definitions/dataSchema"\n              },\n              "rowActions": {\n                "kind": "icons",\n                "actions": [\n                  {\n                    "label": "Delete",\n                    "icon": "fas fa-tras
1h",\n                    "kind": "event",\n                    "content": "delete-data",\n                    "meta": {\n                      "actionId": "delete-data"\n                    },\n                    "requireConfirm": true\n                  }\n                ]\n              },\n              "fitParentContainer": true\n            },\n            "tag": "bk-table"\n          },\n          {\n            "properties": {\n              "requireConfirm": {\n                "onClose": true,\n                "onSave": true\n              },\n              "dataSchema": {\n                "$ref": "#/definitions/dataSchema"\n              },\n              "width": "70vw",\n              "allowObjectAsTable": false,\n              "editorHeight": "30vh",\n              "allowNavigation": true\n            },\n            "tag": "bk-form-modal"\n          },\n          {\n            "tag": "bk-confirmation-modal"\n          },\n          {\n            "properties": {\n              "rootElementSelectors": "main.micro-lc-layout-content",\n              "successEventMap": {\n                "create-data": {\n                  "title": "Success",\n                  "content": "Data successfully created",\n                  "type": "success"\n                },\n                "update-data": {\n                  "title": "Success",\n                  "content": "Data successfully updated",\n                  "type": "success"\n                },\n                "delete-data": {\n                  "title": "Success",\n                  "content": "Data successfully deleted",\n                  "type": "success"\n                }\n              },\n              "errorEventMap": {\n                "create-data": {\n                  "title": "Error",\n                  "content": "An error occurred during order creation",\n                  "type": "error"\n                },\n                "update-data": {\n                  "title": "Error",\n                  "content": "An error occurred during order updated",\n                  "type": "error"\n                },\n                "delete-data": {\n                  "title": "Error",\n                  "content": "An error occurred during order deletion",\n                  "type": "error"\n                }\n              }\n            },\n            "tag": "bk-notifications",\n            "attributes": {}\n          }\n        ],\n        "tag": "main",\n        "attributes": {\n          "style": "flex-grow: 1; background-color: #f0f2f5; padding: 20px; overflow-y: auto;"\n        }\n      },\n      {\n        "content": [\n          {\n            "properties": {\n              "dataSchema": {\n                "$ref": "#/definitions/dataSchema"\n              },\n              "width": "40vw"\n            },\n            "tag": "bk-filter-drawer"\n          }\n        ],\n        "tag": "aside"\n      },\n      {\n        "content": [\n          {\n            "tag": "bk-bulk-delete"\n          },\n          {\n            "tag": "bk-bulk-actions",\n            "properties": {\n              "dataSchema": {\n                "$ref": "#/definitions/dataSchema"\n              }\n            }\n          },\n          {\n            "tag": "div",\n            "attributes": {\n              "style": "flex-grow: 1;"\n            }\n          },\n          {\n            "tag": "bk-footer",\n            "attributes": {\n              "style": "display: flex; justify-content: end; align-items: center;"\n            }\n          },\n          {\n            "tag": "bk-pagination",\n            "properties": {\n              "pageSize": 10\n            }\n          }\n        ],\n        "tag": "footer",\n        "attributes": {\n          "style": "display: flex; flex-direction: row; flex-wrap: wrap; padding: 10px 20px; background-color: white; gap: 10px; position: sticky; bottom: 0; z-index: 10"\n        }\n      },\n      {\n        "properties": {\n          "basePath": "/v2/authz/users",\n          "dataSchema": {\n            "$ref": "#/definitions/dataSchema"\n          }\n        }
1,\n        "tag": "bk-crud-client"\n      }\n    ],\n    "tag": "div",\n    "attributes": {\n      "style": "width: 100%; height: 100%; display: flex; flex-direction: column; position: relative;"\n    }\n  },\n  "sources": [\n    "https://cdn.mia-platform.eu/backoffice/bk-web-components/{{BACK_KIT_VERSION}}/dist/bk-web-components.esm.js"\n  ]\n}\n'})}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{alt:"Screenshot of Microfrontend Composer homepage",src:t(591084).A+"",width:"1614",height:"554"})}),"\n",(0,s.jsx)(n.p,{children:"The screenshot above shows what the Composer tool should look like based on the application configuration.\nBefore deploying, please verify that micro-lc public variables have been created, that are:"}),"\n",(0,s.jsxs)(n.table,{children:[(0,s.jsx)(n.thead,{children:(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.th,{children:"Public Variable"}),(0,s.jsx)(n.th,{children:"Current Version Value"}),(0,s.jsx)(n.th,{children:"Minimum Version Value"})]})}),(0,s.jsxs)(n.tbody,{children:[(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"MICRO_LC_VERSION"}),(0,s.jsx)(n.td,{children:"2.4.0"}),(0,s.jsx)(n.td,{children:"2.4.0"})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"MICRO_LC_MANAGER_VERSION"}),(0,s.jsx)(n.td,{children:"3.1.1"}),(0,s.jsx)(n.td,{children:"3.1.1"})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"BACK_KIT_VERSION"}),(0,s.jsx)(n.td,{children:"1.5.6"}),(0,s.jsx)(n.td,{children:"1.5.6"})]})]})]}),"\n",(0,s.jsx)(n.p,{children:"These variables are employed by the Console to define the version of the service and libraries used by micro-lc at deploy time.\nThey can be upgraded whenever an update is available."}),"\n",(0,s.jsx)(n.h3,{id:"endpoints-2",children:"Endpoints"}),"\n",(0,s.jsx)(n.p,{children:"Here are reported the endpoints that should be exposed from the project in order to enable users managements:"}),"\n",(0,s.jsxs)(n.table,{children:[(0,s.jsx)(n.thead,{children:(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.th,{children:"Endpoint"}),(0,s.jsx)(n.th,{children:"Service"}),(0,s.jsx)(n.th,{style:{textAlign:"center"},children:"Authentication Required"}),(0,s.jsx)(n.th,{children:"User Group Permission"})]})}),(0,s.jsxs)(n.tbody,{children:[(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"/micro-lc-configurations"})}),(0,s.jsx)(n.td,{children:"micro-lc"}),(0,s.jsx)(n.td,{style:{textAlign:"center"},children:"\u2705"}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"true"})})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"/mgmt"})}),(0,s.jsx)(n.td,{children:"micro-lc"}),(0,s.jsx)(n.td,{style:{textAlign:"center"},children:"\u2705"}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"true"})})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"/authz/users"})}),(0,s.jsx)(n.td,{children:"crud"}),(0,s.jsx)(n.td,{style:{textAlign:"center"},children:"\u2705"}),(0,s.jsxs)(n.td,{children:[(0,s.jsx)(n.code,{children:'permissions["read:users"]'})," || ",(0,s.jsx)(n.code,{children:'permissions["update:users"]'})]})]})]})]}),"\n",(0,s.jsx)(n.h3,{id:"routes-1",children:"Routes"}),"\n",(0,s.jsx)(n.p,{children:"In additions to endpoints definitions provided above, in order to further refine who can manage the users and their permissions for Fast Data\nRuntime Management system, each endpoint sub-route should define the specific permission grant that user require to own in order to\nsuccessfully access the requested resource. The following table provides a recap of each route with the needed permissions."}),"\n",(0,s.jsxs)(n.table,{children:[(0,s.jsx)(n.thead,{children:(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.th,{children:"Endpoint"}),(0,s.jsx)(n.th,{children:"Type"}),(0,s.jsx)(n.th,{children:"Method"}),(0,s.jsx)(n.th,{children:"User Group Permissions"})]})}),(0,s.jsxs)(n.tbody,{children:[(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"/mgmt/users"})}),(0,s.jsx)(n.td,{children:"REST"}),(0,s.jsx)(n.td,{children:"GET"}),(0,s.jsxs)(n.td,{children:[(0,s.jsx)(n.code,{children:'permissions["read:users"]'})," || ",(0,s.jsx)(n.code,{children:'permissions["update:users"]'})]})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"/authz/users/"})}),(0,s.jsx)(n.td,{children:"REST"}),(0,s.jsx)(n.td,{children:"GET"}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:'permissions["read:users"]'})})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"/authz/users/export"})}),(0,s.jsx)(n.td,{children:"REST"}),(0,s.jsx)(n.td,{children:"GET"}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:'permissions["read:users"]'})})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"/authz/users/count"})}),(0,s.jsx)(n.td,{children:"REST"}),(0,s.jsx)(n.td,{children:"GET"}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:'permissions["read:users"]'})})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"/authz/users/:id"})}),(0,s.jsx)(n.td,{children:"REST"}),(0,s.jsx)(n.td,{children:"GET"}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:'permissions["read:users"]'})})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"/authz/users/"})}),(0,s.jsx)(n.td,{children:"REST"}),(0,s.jsx)(n.td,{children:"POST"}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:'permissions["update:users"]'})})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"/authz/users/bulk"})}),(0,s.jsx)(n.td,{children:"REST"}),(0,s.jsx)(n.td,{children:"POST"}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:'permissions["update:users"]'})})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"/authz/users/upsert-one"})}),(0,s.jsx)(n.td,{children:"REST"}),(0,s.jsx)(n.td,{children:"POST"}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:'permissions["update:users"]'})})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"/authz/users/state"})}),(0,s.jsx)(n.td,{children:"REST"}),(0,s.jsx)(n.td,{children:"POST"}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:'permissions["update:users"]'})})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"/authz/users/:id/state"})}),(0,s.jsx)(n.td,{children:"REST"}),(0,s.jsx)(n.td,{children:"POST"}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:'permissions["update:users"]'})})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"/authz/users/"})}),(0,s.jsx)(n.td,{children:"REST"}),(0,s.jsx)(n.td,{children:"DELETE"}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:'permissions["update:users"]'})})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"/authz/users/:id"})}),(0,s.jsx)(n.td,{children:"REST"}),(0,s.jsx)(n.td,{children:"DELETE"}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:'permissions["update:users"]'})})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"/authz/users/"})}),(0,s.jsx)(n.td,{children:"REST"}),(0,s.jsx)(n.td,{children:"PATCH"}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:'permissions["update:users"]'})})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"/authz/users/"})}),(0,s.jsx)(n.td,{children:"REST"}),(0,s.jsx)(n.td,{children:"PATCH"}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:'permissions["update:users"]'})})]})]})]}),"\n",(0,s.jsx)(n.admonition,{type:"caution",children:(0,s.jsxs)(n.p,{children:["Please ensure that all these endpoints and routes are set with ",(0,s.jsx)(n.em,{children:"Authentication Required"})," in their security details tab."]})}),"\n",(0,s.jsx)(n.h3,{id:"the-first-user",children:"The First User"}),"\n",(0,s.jsxs)(n.p,{children:["Upon releasing this user management solution, the users table will be empty. Consequently, nobody may enter\nthe application from frontend at the beginning. To grant the permissions to the ",(0,s.jsx)(n.code,{children:"admin"})," user, that is the one that usually first\nperforms the login procedure, it is necessary to either edit the database record associated to such user and insert the needed permissions,\nor to temporarily remove the permissions from ",(0,s.jsx)(n.code,{children:"/authz/users/"})," endpoint's routes till at least the first user\nhas been granted the read/edit users permissions."]}),"\n",(0,s.jsx)(n.p,{children:"Below is presented the procedure to grant the needed permissions for managing users of Fast Data Control Plane application."}),"\n",(0,s.jsxs)(n.p,{children:["Let's start by observing a record of ",(0,s.jsx)(n.code,{children:"users"})," collection:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-json",children:'{\n  "_id" : ObjectId("6606e94a0e85630ccda72486"),\n  "__STATE__" : "PUBLIC",\n  "providerId" : "okta",\n  "providerUserId" : "user-id",\n  "realm" : "my-kingdom",\n  "createdAt" : ISODate("2024-03-29T16:00:00.000+0000"),\n  "creatorId" : "public",\n  "email" : "[email protected]",\n  "groups" : [],\n  "name" : "Alice",\n  "updatedAt" : ISODate("2024-09-13T14:00:00.000+0000"),\n  "updaterId" : "public",\n  "username" : "",\n  "permissions": [\n    // add here the necessary permissions, such as "read:users", "update:users"\n  ]\n}\n'})}),"\n",(0,s.jsxs)(n.p,{children:["The above document is created the first time a user logs in through the configured Authentication Flow. As it can be seen,\nthe user does not belong to any ",(0,s.jsx)(n.code,{children:"groups"})," nor it owns any ",(0,s.jsx)(n.code,{children:"permissions"}),". In order to grant ",(0,s.jsx)(n.code,{children:"Alice"})," the rank of ",(0,s.jsx)(n.em,{children:"user master"})," (admin)\nit is sufficient to add these permissions as strings to the ",(0,s.jsx)(n.code,{children:"permissions"})," array:"]}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.code,{children:"read:users"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.code,{children:"update:users"})}),"\n"]}),"\n",(0,s.jsxs)(n.p,{children:["Afterward, ",(0,s.jsx)(n.code,{children:"Alice"})," user needs to log out of the application and login again to obtain such permissions\nand be able to manage further application users."]}),"\n",(0,s.jsx)(n.admonition,{type:"note",children:(0,s.jsx)(n.p,{children:"We acknowledge this procedure of managing users does not provide a seamless experience.\nWe are working to improve this and reduce configuration friction."})}),"\n",(0,s.jsx)(n.h3,{id:"managing-user-permissions",children:"Managing User Permissions"}),"\n",(0,s.jsxs)(n.p,{children:["Every time a user logs in for the first time in the Fast Data Control Plane application, the ",(0,s.jsx)(n.em,{children:"users"})," collection\nis filled with the corresponding user record. Consequently, in order for them to be able to access Fast Data Control Plane\nfeatures they need to receive the proper permissions, that can be granted through the dedicated UI."]}),"\n",(0,s.jsxs)(n.p,{children:["Opening the ",(0,s.jsx)(n.a,{href:"#users-management",children:"users management frontend"}),", which can be reached by default at the path ",(0,s.jsx)(n.code,{children:"/mgmt/users"})," under the domain\nexposed by your Mia-Platform Console project, the first thing that be observed is the users table. This\ntable lists all the users that ever logged in Fast Data Control Plane application, alongside their details and permissions."]}),"\n",(0,s.jsx)(n.p,{children:"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\nshowing a set of user's details and scrolling it will be possible to access the list of permissions."}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{alt:"Users Management UI",src:t(789290).A+"",width:"1920",height:"1080"})}),"\n",(0,s.jsxs)(n.blockquote,{children:["\n",(0,s.jsxs)(n.p,{children:["Modal window showing the ",(0,s.jsx)(n.code,{children:"permissions"})," field with the values that can be set in the array"]}),"\n"]}),"\n",(0,s.jsxs)(n.p,{children:["Once the needed permissions are added to the ",(0,s.jsx)(n.code,{children:"permissions"}),", click the ",(0,s.jsx)(n.em,{children:"Update Data"})," button to store the changes.\nNow, the user who has just received the new permissions ",(0,s.jsx)(n.strong,{children:"must log out and login again"})," to be able to access Fast Data\nControl Plane UI with the new set of grants."]})]})}function h(e={}){let{wrapper:n}={...(0,r.R)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(l,{...e})}):l(e)}},963911(e,n,t){t.d(n,{A:()=>i});let i=t.p+"assets/images/advanced_section_envoy-170f0bd61245914a3979a14d04ca2b64.png"},789290(e,n,t){t.d(n,{A:()=>i});let i=t.p+"assets/images/edit_user_permissions-ea487ffc3a8d81c52a9aa16fd5cd4dfa.png"},591084(e,n,t){t.d(n,{A:()=>i});let i=t.p+"assets/images/microfrontend_composer-5707576873e70073d69db47f26c881f1.png"},44566(e,n,t){t.d(n,{A:()=>i});let i=t.p+"assets/images/users_management_ui-cc4e74d7367fc0572505b386f3102f91.png"},28453(e,n,t){t.d(n,{R:()=>d,x:()=>a});var i=t(296540);let s={},r=i.createContext(s);function d(e){let n=i.useContext(r);return i.useMemo(function(){return"function"==typeof e?e(n):{...n,...e}},[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:d(e.components),i.createElement(r.Provider,{value:n},e.children)}}}]);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.