The aim of this document is to explain how to configure and deploy OperatorFabric.
1. Deployment
For now OperatorFabric consist of Docker images available either by compiling the project or by using images releases from Dockerhub
Service images are all based on openjdk:8-jre-alpine.
For simple one instance per service deployment, you can find a sample deployment as a docker-compose file here
To run OperatorFabric in development mode, see the development environment documentation .
2. User computer
From the user perspective, OperatorFabric is compatible with recent versions of chrome, edge and firefox and has no specific hardware performance constraints.
Be aware that if you use OperatorFabric in realtime you should prevent user’s computers to go in "sleep mode".
In particular, if you are using edge have a look to github.com/opfab/operatorfabric-core/issues/2754
3. Configuration
OperatorFabric has multiple services to configure.
See the architecture documentation for more information on the different services.
All services are SpringBoot applications and use jetty as an embedded servlet container. As such, they share some common configuration which is described in the following documentation:
Configuration is centralized in the config directory, the dev sub-directory is specific to development environments while the docker sub-directory is a specific configuration meant for use in a full docker environment.
3.1. Business service configuration
3.1.1. Specify an external configuration
When starting docker in the full docker environment an external environment file could be provided like:
cd ./config/docker ./docker-compose.sh ~/config/local.env
In the provided environment file the Spring active profiles can be set.
SPRING_PROFILES_ACTIVE=docker,local
This way the configuration file 'cards-publication-local.yml' can be provided in the same configuration directory and can be read by SpringBoot
3.1.2. Shared service configuration
The configuration shared by all services is in a yaml file, you can find an example with the file /config/docker/common-docker.yml. In this file you will find, among others, the parameters below :
name | default | mandatory? | Description |
---|---|---|---|
operatorfabric.servicesUrls.users |
yes |
Indicates where the Users service can we reached (to get information about the current user). |
3.1.3. Service specific configurations
Each service has a specific yaml configuration file. It should a least contain the name of the service:
spring:
application:
name: businessconfig
Examples of configuration of each service can be found either under config/docker or config/dev depending on the type of deployment you’re looking for.
3.1.3.1. Businessconfig service
The businessconfig service has this specific property :
name | default | mandatory? | Description |
---|---|---|---|
operatorfabric.businessconfig.storage.path |
null |
no |
File path to data storage folder |
3.1.3.2. Users service
The user service has these specific properties :
name | default | mandatory? | Description |
---|---|---|---|
operatorfabric.users.default.users |
null |
no |
Array of user objects to create upon startup if they don’t exist |
operatorfabric.users.default.user-settings |
null |
no |
Array of user settings objects to create upon startup if they don’t exist |
operatorfabric.users.default.groups |
null |
no |
Array of group objects to create upon startup if they don’t exist |
operatorfabric.users.default.entities |
null |
no |
Array of entity objects to create upon startup if they don’t exist |
3.1.3.3. Cards-publication service
The cards-publication service has these specific properties :
name | default | mandatory? | Description |
---|---|---|---|
checkAuthenticationForCardSending |
true |
no |
If false, OperatorFabric will not require user authentication to send or delete a card via endpoint /cards (it does not concern user cards which always need authentication). Be careful when setting the value to false, nginx conf must be adapted for security reasons (see security warning in the reference nginx.conf) |
authorizeToSendCardWithInvalidProcessState |
false |
no |
If true, OperatorFabric will allow to publish a card referring a not existent process or state |
checkPerimeterForCardSending |
true |
no |
If true, OperatorFabric will check user perimeter for card sending via endpoint /cards (it does not concern user cards which are always controlled). |
spring.kafka.consumer.group-id |
null |
no |
If set, support for receiving cards via Kafka is enabled |
spring.deserializer.value.delegate.class |
io.confluent.kafka.serializers. KafkaAvroDeserializer |
yes |
Deserializer used to convert the received bytes into objects |
spring.serializer.value.delegate.class |
io.confluent.kafka.serializers. KafkaAvroSerializer |
yes |
Serializer used to convert cards to bytes |
spring.kafka.producer.bootstrap-servers |
no |
comma separated list of URL(s) of the broker(s) / bootstrap server(s) |
|
opfab.kafka.topics.card.topicname |
opfab |
no |
Name of the topic to read the messages from |
opfab.kafka.topics.response-card.topicname |
opfab |
no |
Name of the topic to place the response cards to |
opfab.kafka.schema.registry.url |
yes |
URL of the schema registry. Can be set to the empty string "" is no registry is used |
3.1.3.4. Cards-consultation service
The cards-consultation service has these specific properties :
name | default | mandatory? | Description |
---|---|---|---|
checkIfUserIsAlreadyConnected |
true |
no |
If false, OperatorFabric will allow a user to have several sessions opened at the same time. However, it may cause synchronization problems between the sessions using the same login, so it is recommended to let it to true, its default value. |
3.1.3.5. External devices service
The external devices service can be configured with the following properties:
name | default | mandatory? | Description |
---|---|---|---|
operatorfabric.externaldevices.watchdog.enabled |
false |
no |
If true, watchdog signals will be sent to external devices to show that the OperatorFabric is running and connected. |
operatorfabric.externaldevices.watchdog.cron |
|
no |
CRON expression determining when watchdog signals should be sent to external devices. |
operatorfabric.externaldevices.watchdog.signalId |
0 |
no |
Id the signal the external devices are expecting as watchdog |
3.2. Web UI Configuration
OperatorFabric Web UI service is built on top of a NGINX server. It serves the Angular SPA to browsers and act as a reverse proxy for other services.
3.2.1. NGINX configuration
An external nginx.conf
file configures the OperatorFabric Nginx instance named web-ui
service.
Those files are mounted as docker volumes. There are two of them in OperatorFabric, one in config/dev
and one in config/docker
.
The one in config/dev
is set with
permissive CORS
rules to enable web development using ng serve
within the ui/main
project.It’s possible to use ng serve
with the one in config/docker
version also. To do so use the conf file named
nginx-cors-permissive.conf
by configuring the /docker-compose.yml
with the following line:
- "./nginx-cors-permissive.conf:/etc/nginx/conf.d/default.conf"
instead of:
- "./nginx.conf:/etc/nginx/conf.d/default.conf"
The line customized in the nginx configuration file must end with à semicolon (';') otherwise the Nginx server will stop immediately |
3.2.2. UI properties
The properties lie in the web-ui.json
.The following table describes their meaning and how to use them. An example file can be found in the config/docker directory.
name | default | mandatory? | Description |
---|---|---|---|
security.provider-realm |
yes |
The realm name in keycloak server settings page. This is used for the log out process to know which realm should be affected. |
|
security.provider-url |
yes |
The keycloak server instance |
|
security.logout-url |
yes |
The keycloak logout URL. Is a composition of: - Your keycloak instance and the auth keyword (ex: www.keycloakurl.com/auth), but we also support domains without auth (ex: www.keycloakurl.com/customPath) - The realm name (Ex: dev) - The redirect URL (redirect_uri): The redirect URL after success authentication |
|
security.changePasswordUrl |
no |
URL to change the user password (if the top-right menu item "Change password" is visible) |
|
security.oauth2.flow.mode |
PASSWORD |
no |
authentication mode, available options:
|
security.oauth2.flow.provider |
null |
no |
provider name to display on log in button |
security.oauth2.flow.delegate-url |
null |
no |
Url to redirect the browser to for authentication. Mandatory with:
|
feed.card.time.display |
BUSINESS |
no |
card time display mode in the feed. Values :
|
feed.defaultSorting |
"unread" |
no |
Default card sorting option in feed page, possible values are : "unread", "date", "severity", "startDate", "endDate". |
feed.defaultAcknowledgmentFilter |
"notack" |
no |
Default card acknowlegment filtering option in feed page, possible values are : "notack", "ack", "all". |
feed.card.hideResponseFilter |
false |
no |
Control if you want to show or hide the response filter in the feed page |
feed.card.hideApplyFiltersToTimeLineChoice |
false |
no |
Control if you want to show or hide the option of applying filters or not to timeline in the feed page |
feed.card.hideAckAllCardsFeature |
true |
no |
Control if you want to show or hide the option for acknowledging all the visible cards of the feed |
feed.card.secondsBeforeLttdForClockDisplay |
180 |
no |
Number of seconds before lttd when a clock is activated in cards on the feed |
feed.card.maxNbOfCardsToDisplay |
100 |
no |
Max number of card visible in feed (This limit is used for performance reasons, setting the value too high can have consequences on browser response times) |
feed.card.titleUpperCase |
true |
no |
If set to true, the card titles are in UPPERCASE. (Option applies to the 'Card Feed', 'Archives' and 'Monitoring') |
feed.timeline.domains |
["TR", "J", "7D", "W", "M", "Y"] |
no |
List of domains to show on the timeline, possible domains are : "TR", "J", "7D", "W", "M", "Y". |
feed.enableGroupedCards |
false |
no |
(Experimental feature): If true cards with the same tags are grouped together. Clicking on the grouped card will show the other cards with the same tags in the feed. |
feed.geomap.enable |
false |
no |
(Experimental feature): If true a geographical map will be shown and cards that have geographical coordinates will be drawn on the map. |
feed.geomap.defaultDataProjection |
EPSG:4326 |
no |
The default data projection of |
feed.geomap.initialLongitude |
0 |
no |
The initial longitude of the map when no cards with geographical coordinates are present. |
feed.geomap.initialLatitude |
0 |
no |
The initial latitude of the map when no cards with geographical coordinates are present. |
feed.geomap.initialZoom |
1 |
no |
Initial zoom level of the map. |
feed.geomap.zoomToLocation |
14 |
no |
Zoom level when zooming to a location of a selected card. |
feed.geomap.maxZoom |
11 |
no |
Max zoom level, to prevent zooming in too much when only one card is shown (or multiple cards in close proximity). |
feed.geomap.zoomDuration |
500 |
no |
Time in milliseconds it takes to zoom the map to the specific location. Set to 0 to disable the zoom animation. |
feed.geomap.enableGraph |
false |
no |
Show a graph on the map with number of cards per severity. |
feed.geomap.bglayer.xyz.url |
null |
no |
Custom xyz/tiled background layer service URL, Replaces OSM background layer (Add endpoint with {x}{y}{z} variables. Example: "https://service.pdok.nl/brt/achtergrondkaart/wmts/v2_0/grijs/EPSG:3857/{z}/{x}/{y}.png". |
feed.geomap.bglayer.xyz.tileSize |
null |
no |
Custom xyz/tiled background layer tile size (Int value, example: 256. Required when using custom background layer). |
feed.geomap.bglayer.xyz.crossOrigin |
null |
no |
Custom xyz/tiled background layer crossOrigin setting. |
i18n.supported.locales |
no |
List of supported locales (Only fr and en so far) Values should be taken from the TZ database. |
|
archive.filters.page.size |
10 |
no |
The page size of archive filters |
archive.history.size |
100 |
no |
The maximum size of card history visible |
archive.filters.tags.list |
no |
List of tags to choose from in the corresponding filter in archives page |
|
archive.filters.publishDate.days |
10 |
no |
The default search period (days) for publish date filter in archives page |
logging.filters.tags.list |
no |
List of tags to choose from in the corresponding filter in logging page |
|
logging.filters.publishDate.days |
10 |
no |
The default search period (days) for publish date filter in logging page |
settings.styleWhenNightDayModeDesactivated |
no |
Style to apply if not using day night mode, possible value are DAY or NIGHT |
|
settings.dateFormat |
Value from the browser configuration |
no |
Format for date rendering (example : DD/MM/YYYY ) |
settings.timeFormat |
Value from the browser configuration |
no |
Format for time rendering (example : HH:mm ) |
settings.dateTimeFormat |
Value from the browser configuration |
no |
Format for date and time rendering (example : HH:mm DD/MM/YYYY ) |
settings.locale |
en |
no |
Default user locale (use en if not set) |
settings.playSoundForAlarm |
false |
no |
If set to true, a sound is played when Alarm cards are added or updated in the feed |
settings.playSoundForAction |
false |
no |
If set to true, a sound is played when Action cards are added or updated in the feed |
settings.playSoundForCompliant |
false |
no |
If set to true, a sound is played when Compliant cards are added or updated in the feed |
settings.playSoundForInformation |
false |
no |
If set to true, a sound is played when Information cards are added or updated in the feed |
settings.playSoundOnExternalDevice |
false |
no |
If set to true (and |
settings.replayEnabled |
false |
no |
If set to true, sounds are replayed every |
settings.replayInterval |
5 |
no |
Interval between sound replays (see |
settings.remoteLoggingEnabled |
false |
no |
If set to true, some logs form the UI are sent to the back and write in the log file of the cards-consultation service |
settingsScreen.hiddenSettings |
no |
Array of string indicating which field(s) we want to hide in the settings screen. Possible values : |
|
about |
none |
no |
Declares application names and their version into web-ui about section.
|
logo.base64 |
medium OperatorFabric icon |
no |
The encoding result of converting the svg logo to Base64, use this online tool to encode your svg. If it is not set, a medium (32px) OperatorFabric icon is displayed. |
logo.height |
40 |
no |
The height of the logo (in px) (only taken into account if logo.base64 is set). The value cannot be more than 48px (if it is set to more than 48px, it will be ignored and set to 48px). |
logo.width |
40 |
no |
The width of the logo (in px) (only taken into account if logo.base64 is set). |
title |
OperatorFabric |
no |
Title of the application, displayed on the browser |
environmentName |
no |
Name of the environment to display in the top-right corner (examples: PROD , TEST .. ), if the value not set the environment name is not shown . |
|
environmentColor |
blue |
no |
Color of the background of the environment name. The format of color is css, for example : |
showUserEntitiesOnTopRightOfTheScreen |
false |
no |
if set to true the users entities will be displayed under the login on top right of the screen |
usercard.useDescriptionFieldForEntityList |
false |
no |
If true, show entity |
externalDevicesEnabled |
false |
no |
If true, users have the opportunity to play sounds on external devices rather than in the browser. See |
secondsToCloseSession |
60 |
no |
Number of seconds between logout and token expiration |
selectActivityAreaOnLogin |
false |
no |
if set to true the users belonging to multiple Entities will be required to configure activity area on login |
checkIfUrlIsLocked |
true |
no |
if set to false, an OperatorFabric url can be used by several tabs in the same browser. Note that there can only be one token per browser for a given OperatorFabric url, so the first session will be replaced by the second one |
IMPORTANT:
To declare settings parameters, you now need to group all fields under settings: { }
For example:
Replace the following invalid settings config
"settings.replayInterval": 10,
"settings.replayEnabled": true,
"settings": {
"about": {
"keycloack": {
"name": "Keycloak",
"rank": 2,
"version": "6.0.1"
},
}
"locale": "en",
"dateTimeFormat": "HH:mm DD/MM/YYYY",
"dateFormat": "DD/MM/YYYY",
"styleWhenNightDayModeDesactivated": "NIGHT"
},
By this valid one :
"settings": {
"replayInterval": 10,
"replayEnabled": true,
"about": {
"keycloack": {
"name": "Keycloak",
"rank": 2,
"version": "6.0.1"
},
}
"locale": "en",
"dateTimeFormat": "HH:mm DD/MM/YYYY",
"dateFormat": "DD/MM/YYYY",
"styleWhenNightDayModeDesactivated": "NIGHT"
},
3.3. Security Configuration
Configure the security concern throughout several files:
-
nginx.conf
of the nginx server -
config/dev/common-dev.yml
orconfig/docker/common-docker.yml
, called common.yml in the following chapters -
web-ui.json
served by theweb-ui
service;
For each user it is possible to configure a list of authorized source ip addresses by setting the authorizedIPAddresses
field in User object.
3.3.1. Authentication configuration
There are 3 OAuth2 Authentication flows available into OperatorFabric UI:
-
password grant: referred as
PASSWORD
mode flow; -
code flow : referred as
CODE
mode flow; -
implicit flow: referred as
IMPLICIT
mode flow.
Alternatively there is also another flow available:
-
none flow: referred as
NONE
mode flow.
The NONE
flow assumes that the application is behind a secured proxy wich handles login and token generation.
Calls to backend services will get a valid token added to the headers and the token will not be visible for the (web)client.
3.3.1.1. Nginx Configuration
The UI calls need some mapping to reach the Authentication Provider. In the default OperatorFabric configuration it’s a
docker keycloak instance
, called keycloak
in the project docker-compose.yml
files.
There are 3 properties to configure within nginx.conf
file:
-
$KeycloakBaseUrl
: the base url of keycloak; -
$OperatorFabricRealm
: the realm configure within keycloak instance to provide authentication to OperatorFabric; -
$ClientPairOFAuthentication
: base64 encoded string of the pair of client authentication used by OperatorFabric to log to the Authentication Provider (keycloak). The cient-id and the client-secret are separated by a colon(':').
Example of the # Url of the Authentication provider set $KeycloakBaseUrl "http://keycloak:8080"; # Realm associated to OperatorFabric within the Authentication provider set $OperatorFabricRealm "dev"; # base64 encoded pair of authentication in the form of 'client-id:secret-id' set $ClientPairOFAuthentication "b3BmYWItY2xpZW50Om9wZmFiLWtleWNsb2FrLXNlY3JldA==" ; where |
3.3.1.2. Configuration file common.yml
name | default | mandatory? | Description |
---|---|---|---|
spring.security.provider-url |
null |
no |
The keycloak instance url. |
spring.security.provider-realm |
null |
no |
The realm name within the keycloak instance. |
spring.security.oauth2.resourceserver.jwt.jwk-set-uri |
null |
yes |
The url providing the certificat used to verify the jwt signature |
example of
where |
3.3.1.3. Configuration file web-ui.json
Nginx web server serves this file. OperatorFabric creates and uses a custom Docker image containing an Nginx server with a docker volume containing this file. The two docker-compose environments contain an example of it. The path in the image to it is /usr/share/nginx/html/opfab/web-ui.json
.
For OAuth2 security concerns into this file, there are two ways to configure it, based on the Oauth2 chosen flow. There are several common properties:
-
security.provider-realm
: OAuth2 provider realm under which the OpertaroFabric client is declared; -
security.provider-url
: url of the keycloak server instance. -
security.logout-url
: url used when a user is logged out of the UI; -
security.oauth2.flow.provider
: name of the OAuth2 provider; -
security.oauth2.flow.delegate-url
: url used to connect to the Authentication provider; -
security.oauth2.flow.mode
: technical way to be authenticated by the Autentication provider.
3.3.1.4. OAuth2 PASSWORD or CODE Flows
These two modes share the same way of declaring the delegate URL.
CODE
is the default mode of authentication for deploy
docker-compose environment.
-
security.oauth2.flow.mode
toPASSWORD
orCODE
; -
security.oauth2.flow.delegate-url
with the URL of the OAuth2 leading to the protocol used for authentication.
Example of Configuration For CODE Flow
{
"security": {
"oauth2": {
"flow": {
"mode": "CODE",
"provider": "Opfab Keycloak",
"delegate-url": "http://localhost:89/auth/realms/dev/protocol/openid-connect/auth?response_type=code&client_id=opfab-client"
},
"logout-url":"http://localhost:89/auth/realms/dev/protocol/openid-connect/logout?redirect_uri=http://localhost:2002/",
"provider-realm": "dev",
"provider-url": "http://localhost:89"
}
}
}
Within the delegate-url
property dev
is the keycloak client realm of OperatorFabric.
For keycloak instance used for development purposes, this delegate-url
correspond to the realm under which the client opfab-client
is registred.
Here, the client-id
value is opfab-client
which is define as client under the realm
named dev
on the dev keycloak instance.
3.3.1.5. OAuth2 IMPLICIT Flow
It had its own way of configuration. To enable IMPLICIT Flow authentication the following properties need to be set:
-
security.oauth2.flow.mode
toIMPLICIT
; -
security.oauth2.flow.delegate-url
with the URL of the OAuth2 leading to the.well-known/openid-configuration
end-point used for authentication configuration.
Example of configuration for IMPLICIT Flow
{
"operatorfabric": {
"security": {
"oauth2": {
"flow": {
"mode": "IMPLICIT",
"provider": "Opfab Keycloak",
"delegate-url": "http://localhost:89/auth/realms/dev"
},
"logout-url":"http://localhost:89/auth/realms/dev/protocol/openid-connect/logout?redirect_uri=http://localhost:2002/",
"provider-realm": "dev",
"provider-url": "http://localhost:89"
}
}
}
}
Within the delegate-url
property dev
is the keycloak client realm of OperatorFabric.
For keycloak instance used for development purposes, this delegate-url
correspond to the realm under which the client opfab-client
is registred.
The url look up by the implicit ui mechanism is localhost:89/auth/realms/dev/.well-known/openid-configuration
.
3.3.1.6. NONE Flow
The configuration for the NONE flow is a bit different because the token isn’t handled/visible in the front-end.
Nginx
The following variables can be removed:
-
$KeycloakBaseUrl
-
$OperatorFabricRealm
-
$ClientPairOFAuthentication
The locations for handling tokens can be edited to return a 401 by default. If one of these locations is called, the token generated by the secured proxy has expired.
location /auth/check_token {
return 401;
}
location /auth/token {
return 401;
}
location /auth/code/ {
return 401;
}
Web-ui.json
Set the security.oauth2.flow.mode to NONE
;
Set the security.oauth2.client-id to Your Oauth client ID
;
Use the security.jwt.login-claim to select value from the token will be used to identify your account. In this example preferred_username
is used;
Settings that are not required are:
-
delegate-url
-
provider-realm
Example of configuration
{
"operatorfabric": {
"security": {
"jwt": {
"expire-claim": "exp",
"login-claim": "preferred_username"
},
"oauth2": {
"client-id": "OAUTHCLIENTID",
"flow": {
"mode": "NONE",
"provider": "My Secured Proxy"
},
"logout-url":"http://my-secured-proxy/OAUTHTENANTID/oauth2/logout?client_id=OAUTHCLIENTID&post_logout_redirect_uri=https%3A%2F%2Flocalhost:2002%2Fui%2Fui/",
"provider-url": "http://my-secured-proxy/"
}
}
}
}
3.3.2. User creation
Setting automated user creation==. Creation user requires a user id. Given name and family name are optional.
name | default | mandatory? | Description |
---|---|---|---|
operatorfabric.security.jwt.login-claim |
sub |
no |
Jwt claim is used as a user login or id |
operatorfabric.security.jwt.given-name-claim |
given-name |
no |
Jwt claim is used to set the user’s given name |
operatorfabric.security.jwt.family-name-claim |
family-name |
no |
Jwt claim is used to set the user’s family name |
3.3.3. Alternative way to manage groups (and/or entities)
By default, OperatorFabric
manages groups (and/or entities) through the user's collection in the database.
Another mode can be defined, the JWT mode. The groups (and/or entities) come from the authentication token.
The administrator of the authentication service has to set what claims define a group (and/or entity).
In the Operator-Fabric
configuration, the opfab administrator has to set properties to retrieve those groups (and/or entities).
name | default | mandatory? | Description |
---|---|---|---|
operatorfabric.security.jwt.groups.mode |
OPERATOR_FABRIC |
no |
Set the group mode, possible values JWT or OPERATOR_FABRIC |
operatorfabric.security.jwt.groups.rolesClaim.rolesClaimStandard.path |
no |
path in the JWT to retrieve the claim that defines a group |
|
operatorfabric.security.jwt.groups.rolesClaim.rolesClaimStandardArray.path |
no |
path in the JWT to retrieve the claim that defines an array of groups |
|
operatorfabric.security.jwt.groups.rolesClaim.rolesClaimStandardList.path |
no |
path in the JWT to retrieve the claim that defines a list of group |
|
operatorfabric.security.jwt.groups.rolesClaim.rolesClaimStandardList.separator |
no |
set the separator value of the list of group |
|
operatorfabric.security.jwt.groups.rolesClaim.rolesClaimCheckExistPath.path |
no |
path in the JWT to check if that path does exist, if it does, use the roleValue as a group |
|
operatorfabric.security.jwt.groups.rolesClaim.rolesClaimCheckExistPath.roleValue |
no |
set the value of the group if the path exists |
|
operatorfabric.security.jwt.entitiesIdClaim |
no |
set the name of the field in the token |
|
operatorfabric.security.jwt.gettingEntitiesFromToken |
no |
boolean indicating if you want the entities of the user to come from the token and not mongoDB (possible values : true/false) |
application.yml
operatorfabric:
security:
jwt:
entitiesIdClaim: entitiesId
gettingEntitiesFromToken: true
groups:
mode: JWT # value possible JWT | OPERATOR_FABRIC
rolesClaim:
rolesClaimStandard:
- path: "ATTR1"
- path: "ATTR2"
rolesClaimStandardArray:
- path: "resource_access/opfab-client/roles"
rolesClaimStandardList:
- path: "roleFieldList"
separator: ";"
rolesClaimCheckExistPath:
- path: "resource_access/AAA"
roleValue: "roleAAA"
- path: "resource_access/BBB"
roleValue: "roleBBB"
JWT example
{
"jti": "5ff87583-10bd-4946-8753-9d58171c8b7f",
"exp": 1572979628,
"nbf": 0,
"iat": 1572961628,
"iss": "http://localhost:89/auth/realms/dev",
"aud": [
"AAA",
"BBB",
"account"
],
"sub": "example_user",
"typ": "Bearer",
"azp": "opfab-client",
"auth_time": 0,
"session_state": "960cbec4-fcb2-47f2-a155-975832e61300",
"acr": "1",
"realm_access": {
"roles": [
"offline_access",
"uma_authorization"
]
},
"resource_access": {
"AAA": {
"roles": [
"role_AAA"
]
},
"BBB": {
"roles": [
"role_BBB"
]
},
"opfab-client": {
"roles": [
"USER"
]
},
"account": {
"roles": [
"manage-account",
"manage-account-links",
"view-profile"
]
}
},
"scope": "openid ATTR2 email ATTR1 profile roleFieldList",
"email_verified": false,
"name": "example_firtstname example_lastname",
"ATTR2": "roleATTR2",
"ATTR1": "roleATTR1",
"preferred_username": "example_user",
"given_name": "example_firtstname",
"entitiesId": "ENTITY1",
"family_name": "example_lastname",
"email": "example_user@mail.com",
"roleFieldList": "roleA;roleB;roleC"
}
As the result, the group will be [ATTR1, ATTR2, roleA, roleB, roleC, USER, roleBBB, roleAAA]
3.3.4. Adding certification authorities or certificates to the Java keystore
If you’re using certificates (for example for Keycloak) that are not from a certification authority trusted by the JVM, this will cause errors such as this one:
Caused by: sun.security.validator. ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:397) at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:302) at sun.security.validator.Validator.validate(Validator.java:262) at sun.security.ssl.X509TrustManager Impl.validate(x509TrustManagerImpl.java:330) at sun.security.ssl.X509TrustManagerImpl.checkTrusted(x509TrustManagerImpl.java:237) at sun.security.ssl.X509TrustManager Impl.checkServerTrusted(x509TrustManager Impl.java:132) at sun.security.ssl.clientHandshaker.serverCertificate(ClientHandshaker.java:1621) 94 common frames omitted Caused by: sun.security.provider.certpath. SunCertPathBuilderException: unable to find valid certification path to requested target at sun.security.provider.certpath. SunCertPathBuilder.build(SunCertPathBuilder.java:141) at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:126) at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:280) at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:392) ... 100 common frames omitted
If that is the case, you can pass the additional authorities or certificates that you use to the containers at runtime.
To do so, put the relevant files (*.der files for example) under src/main/docker/certificates.
-
This directory should only contain the files to be added to the keystore.
-
The files can be nested inside directories.
-
Each certificate will be added with its filename as alias. For example, the certificate in file mycertificate.der will be added under alias mycertificate. As a consequence, filenames should be unique or it will cause an error.
-
If you need to add or remove certificates while the container is already running, the container will have to be restarted for the changes to be taken into account.
If you would like certificates to be sourced from a different location, replace the volumes declarations in the deploy docker-compose.yml file with the selected location:
volumes: - "path/to/my/selected/location:/certificates_to_add"
instead of
volumes: - "../../../../src/main/docker/certificates:/certificates_to_add"
The steps described here assume you’re running OperatorFabric in docker mode using the deploy docker-compose, but they can be adapted for single container deployments and development mode. |
If you want to check that the certificates were correctly added, you can do so with the following steps:
-
Open a bash shell in the container you want to check
docker exec -it deploy_businessconfig_1 bash
-
Run the following command
$JAVA_HOME/bin/keytool -list -v -keystore /tmp/cacerts -storepass changeit
You can also look at the default list of authorities and certificates trusted by the JVM with this command:
$JAVA_HOME/bin/keytool -list -v -keystore $JAVA_HOME/jre/lib/security/cacerts -storepass changeit
3.4. OperatorFabric Mongo configuration
We only use URI configuration for mongo through the usage of the
,
it allows us to share the same configuration behavior for simple or cluster
configuration and with both spring classic and reactive mongo configuration.
See mongo connection string for the complete URI syntax.spring.data.mongodb.uris
3.4.1. Define time to live for archived cards
By default, archived cards will remain stored in the database forever. It is possible to have them automatically removed after a specified duration by using the TTL index feature of mongoDB on their publishDate field.
For example, to have cards expire after 10 days (864000s), enter the following commands in the mongo shell:
use operator-fabric
db.archivedCards.createIndex( { "publishDate": 1 }, { expireAfterSeconds: 864000 } )
You cannot use createIndex() to change the value of expireAfterSeconds of an existing index. Instead use the collMod database command in conjunction with the index collection flag. Otherwise, to change the value of the option of an existing index, you must drop the index first and recreate. |
3.5. OperatorFabric Kafka configuration
Next to publishing cards to OperatorFabric using the REST API, OperatorFabric also supports publishing cards via a Kafka Topic. In the default configuration Kafka is disabled. To enable Kafka you need to set the consumer group to the consumer group you assign to the OpFab Kafka consumer. This can be any group-id, as long as it isn’t used by other consumers (unless you explicitly want multiple consumers for the same group).
You can set the group_id by uncommenting the kafka.consumer.group_id
in the cards-publication.yml
kafka:
consumer:
group-id: opfab-command
By default, the consumer will consume messages from the opfab
topic.
See Spring for Apache Kafka for more information on the Spring Kafka implementation.
With the default settings, the Kafka consumer expects a broker running on http//127.0.0.1:9092 and a schema registry on 127.0.0.1:8081.
Operator Fabric is also able to publish response cards to a Kafka topic. The default topic name opfab-response
. You can specify which response cards
are to be returned via Kafka by setting the external-recipients
in the cards-publication
yaml file. Instead of setting http://
URL you should set it to kafka:
external-recipients:
recipients:
- id: "processAction"
url: "http://localhost:8090/test"
propagateUserToken: true
- id: "mykafka"
url: "kafka:topicname"
propagateUserToken: false
Note that topicname
is a placeholder for now. All response cards are returned via the same Kafka response topic, as specified in the opfab.kafka.topics.response-card
field.
Also note enabling Kafka does not disable the REST interface.
Example Kafka configuration plain:
spring:
application:
name: cards-publication
deserializer:
value:
delegate:
class: org.opfab.cards.publication.kafka.consumer.KafkaAvroWithoutRegistryDeserializer
serializer:
value:
delegate:
class: org.opfab.cards.publication.kafka.producer.KafkaAvroWithoutRegistrySerializer
kafka:
consumer:
group-id: OPFAB
properties:
specific:
avro:
reader: true
producer:
client-id: operatorfabric-producer
bootstrap-servers: kafka-server:9092
opfab:
kafka:
topics:
card:
topicname: m_opfab-card-commands_dev
response-card:
topicname: m_opfab-card-response_dev
Example Kafka configuration SASL:
spring:
application:
name: cards-publication
deserializer:
value:
delegate:
class: org.opfab.cards.publication.kafka.consumer.KafkaAvroWithoutRegistryDeserializer
serializer:
value:
delegate:
class: org.opfab.cards.publication.kafka.producer.KafkaAvroWithoutRegistrySerializer
kafka:
consumer:
group-id: OPFAB
security:
protocol: SASL_SSL
properties:
specific:
avro:
reader: true
sasl:
mechanism: SCRAM-SHA-256
jaas:
config: org.apache.kafka.common.security.scram.ScramLoginModule required username="kafkaUsername" password="kafkaPassword";
producer:
client-id: operatorfabric-producer
security:
protocol: SASL_SSL
properties:
sasl:
mechanism: SCRAM-SHA-256
jaas:
config: org.apache.kafka.common.security.scram.ScramLoginModule required username="kafkaUsername" password="kafkaPassword";
bootstrap-servers: kafka-server:9094
ssl:
trust-store-type: PKCS12
trust-store-password: truststorePassword
trust-store-location: file:///etc/truststore.pkcs
properties:
ssl:
endpoint:
identification:
algorithm: ""
opfab:
kafka:
topics:
card:
topicname: opfab-card-commands
response-card:
topicname: opfab-card-response
Example Kafka configuration Kerberos:
spring:
application:
name: cards-publication
deserializer:
key:
delegate:
class: org.apache.kafka.common.serialization.StringDeserializer
value:
delegate:
class: org.opfab.cards.publication.kafka.consumer.KafkaAvroWithoutRegistryDeserializer
serializer:
value:
delegate:
class: org.opfab.cards.publication.kafka.producer.KafkaAvroWithoutRegistrySerializer
kafka:
security:
protocol: SASL_SSL
properties:
sasl.mechanism: GSSAPI
sasl:
jaas:
config: com.sun.security.auth.module.Krb5LoginModule required useKeyTab=true keyTab="/etc/kafkaUsername.keytab" storeKey=true useTicketCache=false serviceName="kafka" principal="kafkaUsername@DOMAIN";
bootstrap-servers: kafka-server:9094
ssl:
trust-store-type: pkcs12
trust-store-password: truststorePassword
trust-store-location: file:///etc/truststore.pkcs12
consumer:
group-id: OPFAB
key-deserializer: org.springframework.kafka.support.serializer.ErrorHandlingDeserializer
value-deserializer: org.springframework.kafka.support.serializer.ErrorHandlingDeserializer
properties:
spring:
deserializer:
key:
delegate:
class: org.apache.kafka.common.serialization.StringDeserializer
value:
delegate:
class: org.opfab.cards.publication.kafka.consumer.KafkaAvroWithoutRegistryDeserializer
producer:
client-id: OPFAB
value-serializer: org.opfab.cards.publication.kafka.producer.KafkaAvroWithoutRegistrySerializer
opfab:
kafka:
topics:
card:
topicname: opfab-card-commands
response-card:
topicname: opfab-card-response
4. RabbitMQ
4.1. Docker container
In development mode, the simplest way to deploy a RabbitMQ server is to create a RabbitMQ docker container. A docker-compose file is provided to allow quick setup of a convenient RabbitMQ server.
4.2. Server installation
This section is dedicated to production deployment of RabbitMQ. It is not complete and needs to be tailored to any specific production environment.
4.2.1. Download & Installation
Download and install RabbitMQ following the official procedure for the target environment
4.2.2. Used ports
If RabbitMQ may not bind to the following ports, it won’t start :
-
4369: epmd, a peer discovery service used by RabbitMQ nodes and CLI tools
-
5672, 5671: used by AMQP 0-9-1 and 1.0 clients without and with TLS
-
25672: used for inter-node and CLI tools communication (Erlang distribution server port) and is allocated from a dynamic range (limited to a single port by default, computed as AMQP port + 20000). Unless external connections on these ports are really necessary (e.g. the cluster uses federation or CLI tools are used on machines outside the subnet), these ports should not be publicly exposed. See networking guide for details.
-
35672-35682: used by CLI tools (Erlang distribution client ports) for communication with nodes and is allocated from a dynamic range (computed as server distribution port + 10000 through server distribution port + 10010). See networking guide for details.
-
15672: HTTP API clients, management UI and rabbitmqadmin (only if the management plugin is enabled)
-
61613, 61614: STOMP clients without and with TLS (only if the STOMP plugin is enabled)
-
1883, 8883: (MQTT clients without and with TLS, if the MQTT plugin is enabled)
-
15674: STOMP-over-WebSockets clients (only if the Web STOMP plugin is enabled)
-
15675: MQTT-over-WebSockets clients (only if the Web MQTT plugin is enabled)
4.2.3. Production configuration
See the guide for production configuration guidelines
5. Monitoring
Operator Fabric provides end points for monitoring via prometheus. The monitoring is available for the four following services: user, businessconfig, cards-consultation, cards-publication. You can start a test prometheus instance via config/monitoring/startPrometheus.sh
, the monitoring will be accessible on localhost:9090/
6. Logging Administration
Operator Fabric includes the ability to view and configure the log levels at runtime through APIs. It is possible to configure and view an individual logger configuration, which is made up of both the explicitly configured logging level as well as the effective logging level given to it by the logging framework. These levels can be one of:
-
TRACE
-
DEBUG
-
INFO
-
WARN
-
ERROR
-
FATAL
-
OFF
-
null
null indicates that there is no explicit configuration.
Querying and setting logging levels is restricted to administrators.
To view the configured logging level for a given logger it is possible to send a GET request to the '/actuator/logger' URI as follows:
curl http://<server>:<port>/actuator/loggers/${logger} -H "Authorization: Bearer ${token}" -H "Content-type:application/json"
where ${token}
is a valid OAuth2 JWT for a user with administration privileges
and ${logger}
is the logger (ex: org.opfab)
The response will be a json object like the following:
{ "configuredLevel" : "INFO", "effectiveLevel" : "INFO" }
To configure a given logger, POST a json entity to the '/actuator/logger' URI, as follows:
curl -i -X POST http://<server>:<port>/actuator/loggers/${logger} -H "Authorization: Bearer ${token}" -H 'Content-Type: application/json' -d '{"configuredLevel": "DEBUG"}'
To “reset” the specific level of the logger (and use the default configuration instead) it is possible to pass a value of null as the configuredLevel.
7. Users, Groups and Entities Administration
A new operator call John Doe, who has OAuth granted right to connect ot current OperatorFabric
instance, need to receive cards within current OperatorFabric
instance.
As a user of OperatorFabric, he needs to be added to the system with a login
(john-doe-operator), his firstName
(John) and his lastName
(Doe).
As there is no Administration GUI
for the moment, it must be performed through command line, as detailed in the Users API.
7.1. Users
7.1.1. List all users
First of all, list the users (who are the recipients in OperatorFabric) of the system with the following commands:
Httpie
http http://localhost:2103/users "Authorization:Bearer $token" "Content-Type:application/type"
cURL
curl -v http://localhost:2103/users -H "Authorization:Bearer $token" -H "Content-Type:application/type"
response
HTTP/1.1 200 OK [ { "firstName": null, "groups": [ "ADMIN" ], "entities": [ "ENTITY1_FR", "ENTITY2_FR" ], "lastName": null, "login": "admin" }, { "firstName": null, "groups": [ "RTE", "ADMIN", "CORESO", "ReadOnly", "TEST" ], "lastName": null, "login": "operator3_fr" }, { "firstName": null, "groups": [ "ELIA" ], "lastName": null, "login": "elia-operator" }, { "firstName": null, "groups": [ "CORESO" ], "lastName": null, "login": "coreso-operator" }, { "firstName": null, "groups": [ "Dispatcher", "ReadOnly", "TEST" ], "entities": [ "ENTITY1_FR" ], "lastName": null, "login": "operator1_fr" }, { "firstName": null, "groups": [ "Planner", "ReadOnly" ], "entities": [ "ENTITY2_FR" ], "lastName": null, "login": "operator2_fr" }, ]
7.1.2. Create a new User
We are sure that no John-doe-operator exists in our OperatorFabric instance. We can add him in our OperatorFabric instance using the following command use httpie:
echo '{"login":"john-doe-operator","firstName":"Jahne","lastName":"Doe"}' | http POST http://localhost:2103/users "Authorization:Bearer $token" "Content-Type:application/json"
Or here cURL:
curl -X POST http://localhost:2103/users -H "Authorization:Bearer $token" -H "Content-Type:application/json" --data '{"login":"john-doe-operator","firstName":"Jahne","lastName":"Doe"}'
response
HTTP/1.1 200 OK { "firstName": "Jahne", "lastName": "Doe", "login": "john-doe-operator" }
7.1.3. Fetch user details
It’s always a good thing to verify if all the information has been correctly recorded in the system:
with httpie:
http -b http://localhost:2103/users/john-doe-operator "Authorization:Bearer $token" "Content-Type:application/json"
or with cURL:
curl http://localhost:2103/users/john-doe-operator -H "Authorization:Bearer $token" -H "Content-Type:application/json"
response
HTTP/1.1 200 OK { "firstName": "Jahne", "groups": [], "entities": [], "lastName": "Doe", "login": "john-doe-operator" }
7.1.4. Update user details
As shown by this result, the firstName of the new operator has been misspelled.
We need
to update the existing user
with john-doe-operator
login.
To correct this mistake, the following commands can be used:
with httpie:
echo '{"login":"john-doe-operator","lastName":"Doe","firstName":"John"}' | http PUT http://localhost:2103/users/john-doe-operator "Authorization:Bearer $token" "Content-Type:application/json"
or with cURL:
curl -X PUT http://localhost:2103/users/john-doe-operator -H "Authorization:Bearer $token" -H "Content-Type:application/json" --data '{"login":"john-doe-operator","firstName":"John","lastName":"Doe"}'
response
HTTP/1.1 200 OK { "firstName": "John", "lastName": "Doe", "login": "john-doe-operator" }
7.2. Groups/Entities
All the commands below :
-
List groups
-
Create a new group
-
Fetch details of a given group
-
Update details of a group
-
Add a user to a group
-
Remove a user from a group
are available for both groups and entities. In order not to overload the documentation, we will only detail group endpoints.
7.2.1. List groups (or entities)
This operator is the first member of a new group operator called the OPERATORS
, which doesn’t exist for the moment in
the system. As shown when we
list the groups
existing in the server.
Httpie
http http://localhost:2103/groups "Authorization:Bearer $token" "Content-Type:application/type"
cURL
curl http://localhost:2103/groups -H "Authorization:Bearer $token" -H "Content-Type:application/json"
response
HTTP/1.1 200 OK [ { "description": "The admin group", "name": "ADMIN group", "id": "ADMIN" }, { "description": "RTE TSO Group", "name": "RTE group", "id": "RTE" }, { "description": "ELIA TSO group", "name": "ELIA group", "id": "ELIA" }, { "description": "CORESO Group", "name": "CORESO group", "id": "CORESO" }, { "description": "Dispatcher Group", "name": "Dispatcher", "id": "Dispatcher" }, { "description": "Planner Group", "name": "Planner", "id": "Planner" }, { "description": "ReadOnly Group", "name": "ReadOnly", "id": "ReadOnly" } ]
7.2.2. Create a new group (or entity)
Firstly, the group called OPERATORS
has to be
added to the system
using the following command:
using httpie:
echo '{"id":"OPERATORS","decription":"This is the brand new group of operator"}' | http POST http://localhost:2103/groups "Authorization:Bearer $token" "Content-Type:application/json"
using cURL:
curl -X POST http://localhost:2103/groups -H "Authorization:Bearer $token" -H "Content-Type:application/json" --data '{"id":"OPERATORS","decription":"This is the brand new group of operator"}'
response
HTTP/1.1 200 OK { "perimeters": [], "description": null, "name": null, "id": "OPERATORS" }
7.2.3. Fetch details of a given group (or entity)
The result returned seems strange, to verify if it’s the correct answer by
displaying the details of the group
called OPERATORS
, use the following command:
using httpie:
http http://localhost:2103/groups/OPERATORS "Authorization:Bearer $token" "Content-Type:application/json"
using cURL:
curl http://localhost:2103/groups/OPERATORS -H "Authorization:Bearer $token" -H "Content-Type:application/json"
response
HTTP/1.1 200 OK { "perimeters": [], "description": null, "name": null, "id": "OPERATORS" }
7.2.4. Update details of a group (or entity)
The description is really null. After verification, in our first command used to create the group, the attribute for the description is misspelled. Using the following command to update the group with the correct spelling, the new group of operator gets a proper description:
with httpie:
echo '{"id":"OPERATORS","description":"This is the brand-new group of operator"}' | http -b PUT http://localhost:2103/groups/OPERATORS "Authorization:Bearer $token" "Content-Type:application/json"
with cURL:
curl -X PUT http://localhost:2103/groups/OPERATORS -H "Authorization:Bearer $token" -H "Content-Type:application/json" --data '{"id":"OPERATORS","description":"This is the brand-new group of operator"}'
response
{ "perimeters": [] "description": "This is the brand-new group of operator", "name": null, "id": "OPERATORS" }
7.2.5. Add a user to a group (or entity)
As both new group and new user are correct it’s time to make the user a member of the group . To achieve this, use the following command:
with httpie:
echo '["john-doe-operator"]' | http PATCH http://localhost:2103/groups/OPERATORS/users "Authorization:Bearer $token" "Content-Type:application/json"
with cURL:
curl -X PATCH http://localhost:2103/groups/OPERATORS/users -H "Authorization:Bearer $token" -H "Content-Type:application/json" --data '["john-doe-operator"]'
response
HTTP/1.1 200 OK
Let’s verify that the changes are correctly recorded by fetching the :
http http://localhost:2103/users/john-doe-operator "Authorization:Bearer $token" "Content-Type:application/json"
with cURL
curl http://localhost:2103/users/john-doe-operator -H "Authorization:Bearer $token" -H "Content-Type:application/json"
response
HTTP/1.1 200 OK { "firstName": "John", "groups": ["OPERATORS"], "entities": [], "lastName": "Doe", "login": "john-doe-operator" }
It’s now possible to send cards either specifically to john-doe-operator
or more generally to the OPERATORS
group.
7.2.6. Remove a user from a group (or entity)
When John Doe is no longer in charge of hypervising cards for OPERATORS
group, this group has to be removed from his login by using the following command:
with httpie:
http DELETE http://localhost:2103/groups/OPERATORS/users/john-doe-operator "Authorization:Bearer $token"
with cURL:
curl -X DELETE -H "Authorization:Bearer $token" http://localhost:2103/groups/OPERATORS/users/john-doe-operator
response
HTTP/1.1 200 OK { "login":"john-doe-operator"," firstName":"John", "lastName":"Doe", "groups":[], "entities":[] }
A last command to verify that OPERATORS
is no longer linked to john-doe-operator
:
with httpie:
http http://localhost:2103/users/john-doe-operator "Authorization:Bearer $token" "Content-Type:application/json"
with cURL:
curl http://localhost:2103/users/john-doe-operator -H "Authorization:Bearer $token" -H "Content-Type:application/json"
response
HTTP/1.1 200 OK { "firstName": "John", "groups": [], "entities": [], "lastName": "Doe", "login": "john-doe-operator" }
7.2.7. Entity parents
Entities have a 'parents' attribute instead of a 'perimeters' one. This attribute is a string array. Each element of the array is the id of another Entity. When adding or patching an Entity into the system, operatorFabric performs a cycle detection. On a positive cycle detection cancels the addition or the patch.
7.2.7.1. Add a new Entity without a cycle in the parent declaration
using httpie:
echo '{"id":"NEW_ENTITY","name":"Last New Entity","description":"This is the last new entity","parents": ["ENTITY1_FR"]}' \ | http POST http://localhost:2103/entities "Authorization:Bearer $token" "Content-Type:application/json"
using cURL:
curl http://localhost:2103/entities -H "Authorization:Bearer $token" -H "Content-Type:application/json" \ --data '{"id":"NEW_ENTITY","name":"Last New Entity","description":"This is the last new entity","parents": ["ENTITY1_FR"]}'
response
HTTP/1.1 200 OK { "id": "NEW_ENTITY", "parents": ["ENTITY1_FR"], "name": "Last New Entity", "description":"This is the last new entity", "labels":[] }
7.2.7.2. Add a new Entity with a cycle
For simplicity, in this example the new entity will declare itself as a parent. This auto-referencing triggers a cycle detection.
using httpie:
echo '{"id":"NEW_ENTITY","name":"Last New Entity","description":"This is the last new entity","parents": ["NEW_ENTITY"]}' | http POST http://localhost:2103/entities "Authorization:Bearer $token" "Content-Type:application/json"
using cURL:
curl http://localhost:2103/entities -H "Authorization:Bearer $token" -H "Content-Type:application/json" --data '{"id":"NEW_ENTITY","name":"Last New Entity","description":"This is the last new entity","parents": ["NEW_ENTITY"]}'
response
{ "status":"BAD_REQUEST", "message":"A cycle has been detected: NEW_ENTITY->NEW_ENTITY" }
with a 400
as http status return.
8. Service port table
By default all service built artifacts are configured with server.port set to 8080
If you run the services using bootRun
Gradle task, the run_all.sh
script or the full docker docker-compose
(found under config/docker),
the used ports are:
Port | Service | Forwards to | Description |
---|---|---|---|
89 |
KeyCloak |
89 |
KeyCloak api port |
2002 |
web-ui |
8080 |
Web ui and gateway (Nginx server) |
2100 |
businessconfig |
8080 |
Businessconfig management service http (REST) |
2102 |
cards-publication |
8080 |
Cards publication service http (REST) |
2103 |
users |
8080 |
Users management service http (REST) |
2104 |
cards-consultation |
8080 |
Cards consultation service http (REST) |
2105 |
external-devices |
8080 |
External devices management service http (REST) |
4100 |
businessconfig |
5005 |
java debug port |
4102 |
cards-publication |
5005 |
java debug port |
4103 |
users |
5005 |
java debug port |
4104 |
cards-consultation |
5005 |
java debug port |
4105 |
external-devices |
5005 |
java debug port |
27017 |
mongo |
27017 |
mongo api port |
5672 |
rabbitmq |
5672 |
amqp api port |
15672 |
rabbitmq |
15672 |
rabbitmq api port |
9. Restricted operations (administration)
Some operations are restricted to users with the ADMIN role, either because they are administration operations with the potential to impact the OperatorFabric instance as a whole, or because they give access to information that should be private to a user.
Below is a quick recap of these restricted operations.
Any action (read, create/update or delete) regarding a single user’s data (their personal info such as their first and last name, as well as their settings) can be performed either by the user in question or by a user with the ADMIN role.
Any action on a list of users or on the groups (or entities) (if authorization is managed in OperatorFabric) can only be performed by a user with the ADMIN role.
Any write (create, update or delete) action on bundles can only be performed by a user with the ADMIN role. As such, administrators are responsible for the quality and security of the provided bundles. In particular, as it is possible to use scripts in templates, they should perform a security check to make sure that there is no XSS risk.
The ADMIN role doesn’t grant any special privileges when it comes to card consultation (be they current or archived), so a user with the ADMIN role will only see cards that have been addressed to them (or to one of their groups (or entities)), just like any other user. |