From 1c6f899875eff48409d90dc2b5326f475c091fbb Mon Sep 17 00:00:00 2001 From: DedunuKarunarathne <46235093+DedunuKarunarathne@users.noreply.github.com> Date: Tue, 5 Nov 2024 09:31:13 +0530 Subject: [PATCH 1/2] Make non-admin user read-only with a config Make non-admin user read-only with a config. Fixes: https://github.com/wso2/micro-integrator/issues/3729 --- .../dashboard/bootstrap/DashboardServer.java | 13 +++++++++ .../commons/auth/AuthenticationFilter.java | 8 +++++ .../web-app/src/auth/AuthManager.js | 29 +++++++++++++++++++ .../web-app/src/commons/TableRowCreator.js | 3 +- .../commons/sideDrawers/commons/TracingRow.js | 4 ++- 5 files changed, 55 insertions(+), 2 deletions(-) diff --git a/monitoring-dashboard/components/org.wso2.ei.dashboard.bootstrap/src/main/java/org/wso2/ei/dashboard/bootstrap/DashboardServer.java b/monitoring-dashboard/components/org.wso2.ei.dashboard.bootstrap/src/main/java/org/wso2/ei/dashboard/bootstrap/DashboardServer.java index 21e658440..16b9a87ba 100644 --- a/monitoring-dashboard/components/org.wso2.ei.dashboard.bootstrap/src/main/java/org/wso2/ei/dashboard/bootstrap/DashboardServer.java +++ b/monitoring-dashboard/components/org.wso2.ei.dashboard.bootstrap/src/main/java/org/wso2/ei/dashboard/bootstrap/DashboardServer.java @@ -24,6 +24,7 @@ import com.nimbusds.oauth2.sdk.id.ClientID; import com.nimbusds.oauth2.sdk.id.Issuer; import io.asgardeo.java.oidc.sdk.config.model.OIDCAgentConfig; +import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.eclipse.jetty.server.Connector; @@ -120,6 +121,9 @@ public class DashboardServer { private static SSOConfig ssoConfig; private static Thread shutdownHook; private static SecretResolver secretResolver = new SecretResolver(); + private static boolean makeNonAdminUsersReadOnly; + private static final String TOML_MAKE_NON_ADMIN_USERS_READ_ONLY = "user_access.make_non_admin_users_read_only"; + private static final String MAKE_NON_ADMIN_USERS_READ_ONLY = "make_non_admin_users_read_only"; private static final Logger logger = LogManager.getLogger(DashboardServer.class); @@ -313,6 +317,15 @@ private void loadConfigurations(Map parsedConfigs) { properties.put(IS_USER_STORE_FILE_BASED, String.valueOf(isFileBased)); } + String makeNonAdminUsersReadOnlySystemValue = System.getProperty(MAKE_NON_ADMIN_USERS_READ_ONLY); + if (StringUtils.isNotEmpty(makeNonAdminUsersReadOnlySystemValue)) { + makeNonAdminUsersReadOnly = Boolean.parseBoolean(makeNonAdminUsersReadOnlySystemValue); + } else { + makeNonAdminUsersReadOnly = Boolean.parseBoolean( + String.valueOf(parsedConfigs.get(TOML_MAKE_NON_ADMIN_USERS_READ_ONLY))); + } + properties.put(MAKE_NON_ADMIN_USERS_READ_ONLY, String.valueOf(makeNonAdminUsersReadOnly)); + System.setProperties(properties); } diff --git a/monitoring-dashboard/components/org.wso2.ei.dashboard.core/src/main/java/org/wso2/ei/dashboard/core/commons/auth/AuthenticationFilter.java b/monitoring-dashboard/components/org.wso2.ei.dashboard.core/src/main/java/org/wso2/ei/dashboard/core/commons/auth/AuthenticationFilter.java index 70be0f482..bedc6e8f9 100644 --- a/monitoring-dashboard/components/org.wso2.ei.dashboard.core/src/main/java/org/wso2/ei/dashboard/core/commons/auth/AuthenticationFilter.java +++ b/monitoring-dashboard/components/org.wso2.ei.dashboard.core/src/main/java/org/wso2/ei/dashboard/core/commons/auth/AuthenticationFilter.java @@ -52,6 +52,7 @@ public class AuthenticationFilter implements ContainerRequestFilter { private static final String AUTHENTICATION_SCHEME = "Bearer"; private static final List adminOnlyPaths = Arrays.asList("/log-configs", "/users"); + private static final String MAKE_NON_ADMIN_USERS_READ_ONLY = "make_non_admin_users_read_only"; @Context private HttpServletRequest servletRequest; @@ -63,6 +64,8 @@ public void filter(ContainerRequestContext requestContext) { Map cookies = requestContext.getCookies(); String token; SecurityHandler securityHandler; + Boolean makeNonAdminUsersReadOnly = Boolean.valueOf(System.getProperty(MAKE_NON_ADMIN_USERS_READ_ONLY)); + String httpMethod = requestContext.getMethod(); if (isTokenBasedAuthentication(authorizationHeader)) { token = authorizationHeader.substring(AUTHENTICATION_SCHEME.length()).trim(); @@ -87,6 +90,11 @@ public void filter(ContainerRequestContext requestContext) { if (isAdminResource(requestContext) && !securityHandler.isAuthorized(config, token)) { abortWithUnauthorized(requestContext); + } else if (!"GET".equalsIgnoreCase(httpMethod) && makeNonAdminUsersReadOnly && + !securityHandler.isAuthorized(config, token)) { + // For non-admin resources, request except GET are blocked + // if the 'makeNonAdminUsersReadOnly' is set to 'true' + abortWithUnauthorized(requestContext); } } diff --git a/monitoring-dashboard/components/org.wso2.micro.integrator.dashboard.web/web-app/src/auth/AuthManager.js b/monitoring-dashboard/components/org.wso2.micro.integrator.dashboard.web/web-app/src/auth/AuthManager.js index e6781f1eb..9792f5390 100644 --- a/monitoring-dashboard/components/org.wso2.micro.integrator.dashboard.web/web-app/src/auth/AuthManager.js +++ b/monitoring-dashboard/components/org.wso2.micro.integrator.dashboard.web/web-app/src/auth/AuthManager.js @@ -172,4 +172,33 @@ export default class AuthManager { static getBasePath() { return window.location.protocol+'//'+window.location.hostname+(window.location.port ? ':'+window.location.port: '') + "/dashboard/api"; } + + /** + * Check whether the user is an admin user. + * @returns {boolean} true if the user is an admin user + */ + static isAdminUser() { + const userName = AuthManager.getUser(); + return userName?.scope === "admin"; + } + + /** + * Check if non-admin users are read-only based on a config. + * @returns {boolean} true if non-admin users are read-only + */ + static isNonAdminUserReadOnly() { + const makeNonAdminUsersReadOnly = window.userAccess.makeNonAdminUsersReadOnly; + return makeNonAdminUsersReadOnly === true; + } + + /** + * Check if the current user has edit permissions. + * All the admin users can edit and if the 'isNonAdminUserReadOnly' is false, + * non-admin users also can edit + * @returns {boolean} true if the user has edit permissions + */ + static hasEditPermission() { + return AuthManager.isAdminUser() || !AuthManager.isNonAdminUserReadOnly(); + } + } diff --git a/monitoring-dashboard/components/org.wso2.micro.integrator.dashboard.web/web-app/src/commons/TableRowCreator.js b/monitoring-dashboard/components/org.wso2.micro.integrator.dashboard.web/web-app/src/commons/TableRowCreator.js index 6a34536a4..ba24b9fb0 100644 --- a/monitoring-dashboard/components/org.wso2.micro.integrator.dashboard.web/web-app/src/commons/TableRowCreator.js +++ b/monitoring-dashboard/components/org.wso2.micro.integrator.dashboard.web/web-app/src/commons/TableRowCreator.js @@ -234,6 +234,7 @@ function SwitchStatusCell(props) { const { pageId, artifactName, nodeId, status, retrieveData} = props; var isActive = status; const globalGroupId = useSelector(state => state.groupId); + const hasEditPermission = AuthManager.hasEditPermission(); const changeState = () => { isActive = !isActive @@ -254,7 +255,7 @@ function SwitchStatusCell(props) { }); } - return + return } function LogConfigLevelDropDown(props) { diff --git a/monitoring-dashboard/components/org.wso2.micro.integrator.dashboard.web/web-app/src/commons/sideDrawers/commons/TracingRow.js b/monitoring-dashboard/components/org.wso2.micro.integrator.dashboard.web/web-app/src/commons/sideDrawers/commons/TracingRow.js index 4f887fe05..4a1895ea4 100644 --- a/monitoring-dashboard/components/org.wso2.micro.integrator.dashboard.web/web-app/src/commons/sideDrawers/commons/TracingRow.js +++ b/monitoring-dashboard/components/org.wso2.micro.integrator.dashboard.web/web-app/src/commons/sideDrawers/commons/TracingRow.js @@ -23,10 +23,12 @@ import { TableCell, TableRow } from '@material-ui/core'; import { useSelector } from 'react-redux'; import Switch from "react-switch"; import HTTPClient from '../../../utils/HTTPClient'; +import AuthManager from "../../../auth/AuthManager"; export default function TracingRow(props) { const {pageId, artifactName, nodeId, tracing, retrieveUpdatedArtifact} = props; var isTracingEnabled = false; + const hasEditPermission = AuthManager.hasEditPermission(); if(tracing === 'enabled') { isTracingEnabled = true; @@ -63,7 +65,7 @@ export default function TracingRow(props) { Tracing From fb32ce477be235d4e6116319d62b72e88a926cc6 Mon Sep 17 00:00:00 2001 From: DedunuKarunarathne <46235093+DedunuKarunarathne@users.noreply.github.com> Date: Tue, 5 Nov 2024 11:53:14 +0530 Subject: [PATCH 2/2] Add configs --- .../config-parser/templates/server/www/conf/config.js.j2 | 5 +++++ .../distribution/src/main/resources/conf/deployment.toml | 3 +++ 2 files changed, 8 insertions(+) diff --git a/monitoring-dashboard/distribution/src/main/resources/conf/config-parser/templates/server/www/conf/config.js.j2 b/monitoring-dashboard/distribution/src/main/resources/conf/config-parser/templates/server/www/conf/config.js.j2 index b92691262..1f99c7a79 100644 --- a/monitoring-dashboard/distribution/src/main/resources/conf/config-parser/templates/server/www/conf/config.js.j2 +++ b/monitoring-dashboard/distribution/src/main/resources/conf/config-parser/templates/server/www/conf/config.js.j2 @@ -76,3 +76,8 @@ window.sso = { window.userStore = { type : "{{user_store.type | default('file_based') }}" }; + +window.userAccess = { + makeNonAdminUsersReadOnly: {{ user_access.make_non_admin_users_read_only | default(false) }} +}; + diff --git a/monitoring-dashboard/distribution/src/main/resources/conf/deployment.toml b/monitoring-dashboard/distribution/src/main/resources/conf/deployment.toml index af3e05123..afe861ed6 100644 --- a/monitoring-dashboard/distribution/src/main/resources/conf/deployment.toml +++ b/monitoring-dashboard/distribution/src/main/resources/conf/deployment.toml @@ -29,3 +29,6 @@ password = "wso2carbon" #user.name = "admin" #user.password = "admin" #user.is_admin = true + +[user_access] +make_non_admin_users_read_only = false