diff --git a/components/org.wso2.micro.integrator.extensions/org.wso2.micro.integrator.management.apis/src/main/java/org/wso2/micro/integrator/management/apis/ApiResource.java b/components/org.wso2.micro.integrator.extensions/org.wso2.micro.integrator.management.apis/src/main/java/org/wso2/micro/integrator/management/apis/ApiResource.java index 22904cb650..c159bc82ad 100644 --- a/components/org.wso2.micro.integrator.extensions/org.wso2.micro.integrator.management.apis/src/main/java/org/wso2/micro/integrator/management/apis/ApiResource.java +++ b/components/org.wso2.micro.integrator.extensions/org.wso2.micro.integrator.management.apis/src/main/java/org/wso2/micro/integrator/management/apis/ApiResource.java @@ -38,6 +38,8 @@ import org.json.JSONObject; import org.wso2.carbon.inbound.endpoint.internal.http.api.APIResource; import org.wso2.micro.core.util.NetworkUtils; +import org.wso2.micro.integrator.management.apis.security.handler.SecurityUtils; +import org.wso2.micro.integrator.security.user.api.UserStoreException; import java.io.IOException; import java.net.MalformedURLException; @@ -51,6 +53,7 @@ import java.util.stream.Collectors; import static org.wso2.micro.integrator.management.apis.Constants.SEARCH_KEY; +import static org.wso2.micro.integrator.management.apis.Constants.USERNAME_PROPERTY; public class ApiResource extends APIResource { @@ -90,7 +93,17 @@ public boolean invoke(MessageContext messageContext) { populateApiList(messageContext); } } else { - handlePost(messageContext, axisMsgCtx); + String userName = (String) messageContext.getProperty(USERNAME_PROPERTY); + try { + if (SecurityUtils.canUserEdit(userName)) { + handlePost(messageContext, axisMsgCtx); + } else { + Utils.sendForbiddenFaultResponse(axisMsgCtx); + } + } catch (UserStoreException e) { + LOG.error("Error occurred while retrieving the user data", e); + Utils.setJsonPayLoad(axisMsgCtx, Utils.createJsonErrorObject("Error occurred while retrieving the user data")); + } } return true; } diff --git a/components/org.wso2.micro.integrator.extensions/org.wso2.micro.integrator.management.apis/src/main/java/org/wso2/micro/integrator/management/apis/CarbonAppResource.java b/components/org.wso2.micro.integrator.extensions/org.wso2.micro.integrator.management.apis/src/main/java/org/wso2/micro/integrator/management/apis/CarbonAppResource.java index 5b5c849d16..56ef291d2f 100644 --- a/components/org.wso2.micro.integrator.extensions/org.wso2.micro.integrator.management.apis/src/main/java/org/wso2/micro/integrator/management/apis/CarbonAppResource.java +++ b/components/org.wso2.micro.integrator.extensions/org.wso2.micro.integrator.management.apis/src/main/java/org/wso2/micro/integrator/management/apis/CarbonAppResource.java @@ -43,6 +43,7 @@ import org.wso2.micro.core.util.AuditLogger; import org.wso2.micro.integrator.initializer.deployment.application.deployer.CappDeployer; import org.wso2.micro.integrator.management.apis.security.handler.SecurityUtils; +import org.wso2.micro.integrator.security.user.api.UserStoreException; import java.io.BufferedInputStream; import java.io.File; @@ -71,6 +72,7 @@ import static org.wso2.micro.integrator.management.apis.Constants.LIST; import static org.wso2.micro.integrator.management.apis.Constants.NOT_FOUND; import static org.wso2.micro.integrator.management.apis.Constants.SEARCH_KEY; +import static org.wso2.micro.integrator.management.apis.Constants.USERNAME_PROPERTY; public class CarbonAppResource extends APIResource { @@ -111,6 +113,7 @@ public boolean invoke(MessageContext messageContext) { if (messageContext.getProperty(Constants.USERNAME_PROPERTY) != null) { performedBy = messageContext.getProperty(Constants.USERNAME_PROPERTY).toString(); } + String userName = (String) messageContext.getProperty(USERNAME_PROPERTY); switch (httpMethod) { case Constants.HTTP_GET: { String param = Utils.getQueryParameter(messageContext, "carbonAppName"); @@ -131,11 +134,29 @@ public boolean invoke(MessageContext messageContext) { break; } case Constants.HTTP_POST: { - handlePost(performedBy, axis2MessageContext); + try { + if (SecurityUtils.canUserEdit(userName)) { + handlePost(performedBy, axis2MessageContext); + } else { + Utils.sendForbiddenFaultResponse(axis2MessageContext); + } + } catch (UserStoreException e) { + log.error("Error occurred while retrieving the user data", e); + Utils.setJsonPayLoad(axis2MessageContext,Utils.createJsonErrorObject("Error occurred while retrieving the user data")); + } break; } case Constants.HTTP_DELETE: { - handleDelete(performedBy, messageContext, axis2MessageContext); + try { + if (SecurityUtils.canUserEdit(userName)) { + handleDelete(performedBy, messageContext, axis2MessageContext); + } else { + Utils.sendForbiddenFaultResponse(axis2MessageContext); + } + } catch (UserStoreException e) { + log.error("Error occurred while retrieving the user data", e); + Utils.setJsonPayLoad(axis2MessageContext,Utils.createJsonErrorObject("Error occurred while retrieving the user data")); + } break; } default: { diff --git a/components/org.wso2.micro.integrator.extensions/org.wso2.micro.integrator.management.apis/src/main/java/org/wso2/micro/integrator/management/apis/ConfigsResource.java b/components/org.wso2.micro.integrator.extensions/org.wso2.micro.integrator.management.apis/src/main/java/org/wso2/micro/integrator/management/apis/ConfigsResource.java index e59f3c32aa..33a7f3db1f 100644 --- a/components/org.wso2.micro.integrator.extensions/org.wso2.micro.integrator.management.apis/src/main/java/org/wso2/micro/integrator/management/apis/ConfigsResource.java +++ b/components/org.wso2.micro.integrator.extensions/org.wso2.micro.integrator.management.apis/src/main/java/org/wso2/micro/integrator/management/apis/ConfigsResource.java @@ -24,11 +24,15 @@ import org.apache.synapse.config.SynapseConfiguration; import org.apache.synapse.transport.passthru.config.PassThroughCorrelationConfigDataHolder; import org.json.JSONObject; +import org.wso2.micro.integrator.management.apis.security.handler.SecurityUtils; +import org.wso2.micro.integrator.security.user.api.UserStoreException; import java.io.IOException; import java.util.HashSet; import java.util.Set; +import static org.wso2.micro.integrator.management.apis.Constants.USERNAME_PROPERTY; + /** * This resource will handle requests coming to configs/. */ @@ -63,6 +67,7 @@ public boolean invoke(MessageContext messageContext, LOG.debug("Handling" + httpMethod + "request"); } JSONObject response; + String userName = (String) messageContext.getProperty(USERNAME_PROPERTY); try { switch (httpMethod) { case Constants.HTTP_GET: { @@ -70,7 +75,12 @@ public boolean invoke(MessageContext messageContext, break; } case Constants.HTTP_PUT: { - response = handlePut(axis2MessageContext); + if (SecurityUtils.canUserEdit(userName)) { + response = handlePut(axis2MessageContext); + } else { + Utils.sendForbiddenFaultResponse(axis2MessageContext); + response = Utils.createJsonError("", axis2MessageContext, Constants.FORBIDDEN); + } break; } default: { @@ -85,6 +95,10 @@ public boolean invoke(MessageContext messageContext, } catch (IOException e) { LOG.error("Error when parsing JSON payload", e); response = Utils.createJsonErrorObject("Error while parsing JSON payload"); + } catch (UserStoreException e) { + LOG.error("Error occurred while retrieving the user data", e); + response = Utils.createJsonError("Error occurred while retrieving the user data", + axis2MessageContext, Constants.FORBIDDEN); } Utils.setJsonPayLoad(axis2MessageContext, response); return true; diff --git a/components/org.wso2.micro.integrator.extensions/org.wso2.micro.integrator.management.apis/src/main/java/org/wso2/micro/integrator/management/apis/ConnectorResource.java b/components/org.wso2.micro.integrator.extensions/org.wso2.micro.integrator.management.apis/src/main/java/org/wso2/micro/integrator/management/apis/ConnectorResource.java index 0e8790ddcb..f318c2e4aa 100644 --- a/components/org.wso2.micro.integrator.extensions/org.wso2.micro.integrator.management.apis/src/main/java/org/wso2/micro/integrator/management/apis/ConnectorResource.java +++ b/components/org.wso2.micro.integrator.extensions/org.wso2.micro.integrator.management.apis/src/main/java/org/wso2/micro/integrator/management/apis/ConnectorResource.java @@ -37,6 +37,8 @@ import org.wso2.micro.integrator.initializer.ServiceBusUtils; import org.wso2.micro.integrator.initializer.persistence.MediationPersistenceManager; import org.wso2.micro.integrator.initializer.deployment.synapse.deployer.SynapseAppDeployer; +import org.wso2.micro.integrator.management.apis.security.handler.SecurityUtils; +import org.wso2.micro.integrator.security.user.api.UserStoreException; import java.io.IOException; @@ -50,6 +52,7 @@ import static org.wso2.micro.integrator.management.apis.Constants.ITEM_TYPE_IMPORT; import static org.wso2.micro.integrator.management.apis.Constants.SEARCH_KEY; +import static org.wso2.micro.integrator.management.apis.Constants.USERNAME_PROPERTY; /** * API Resource to manage connectors deployed @@ -98,21 +101,25 @@ public boolean invoke(MessageContext messageContext, } axis2MessageContext.removeProperty(Constants.NO_ENTITY_BODY); } else { - + String userName = (String) messageContext.getProperty(USERNAME_PROPERTY); try { - if (!JsonUtil.hasAJsonPayload(axis2MessageContext)) { - Utils.setJsonPayLoad(axis2MessageContext, Utils.createJsonErrorObject("POST method required json payload")); - } else { - JsonObject payload = Utils.getJsonPayload(axis2MessageContext); - String performedBy = Constants.ANONYMOUS_USER; - if (messageContext.getProperty(Constants.USERNAME_PROPERTY) != null) { - performedBy = messageContext.getProperty(Constants.USERNAME_PROPERTY).toString(); - } - if (payload.has(NAME_ATTRIBUTE) && payload.has(STATUS_ATTRIBUTE) && payload.has(PACKAGE_ATTRIBUTE)) { - changeConnectorState(performedBy, axis2MessageContext, payload, synapseConfiguration); + if (SecurityUtils.canUserEdit(userName)) { + if (!JsonUtil.hasAJsonPayload(axis2MessageContext)) { + Utils.setJsonPayLoad(axis2MessageContext, Utils.createJsonErrorObject("POST method required json payload")); } else { - Utils.setJsonPayLoad(axis2MessageContext, Utils.createJsonErrorObject("Missing parameters in payload")); + JsonObject payload = Utils.getJsonPayload(axis2MessageContext); + String performedBy = Constants.ANONYMOUS_USER; + if (messageContext.getProperty(Constants.USERNAME_PROPERTY) != null) { + performedBy = messageContext.getProperty(Constants.USERNAME_PROPERTY).toString(); + } + if (payload.has(NAME_ATTRIBUTE) && payload.has(STATUS_ATTRIBUTE) && payload.has(PACKAGE_ATTRIBUTE)) { + changeConnectorState(performedBy, axis2MessageContext, payload, synapseConfiguration); + } else { + Utils.setJsonPayLoad(axis2MessageContext, Utils.createJsonErrorObject("Missing parameters in payload")); + } } + } else { + Utils.sendForbiddenFaultResponse(axis2MessageContext); } } catch (AxisFault axisFault) { LOG.error("Error when updating connector status", axisFault); @@ -120,6 +127,9 @@ public boolean invoke(MessageContext messageContext, } catch (IOException e) { LOG.error("Error when parsing JSON payload", e); Utils.setJsonPayLoad(axis2MessageContext, Utils.createJsonErrorObject("Error when parsing JSON payload")); + } catch (UserStoreException e) { + LOG.error("Error occurred while retrieving the user data", e); + Utils.setJsonPayLoad(axis2MessageContext, Utils.createJsonErrorObject("Error occurred while retrieving the user data")); } } return true; diff --git a/components/org.wso2.micro.integrator.extensions/org.wso2.micro.integrator.management.apis/src/main/java/org/wso2/micro/integrator/management/apis/Constants.java b/components/org.wso2.micro.integrator.extensions/org.wso2.micro.integrator.management.apis/src/main/java/org/wso2/micro/integrator/management/apis/Constants.java index 1fc357340f..de916b2400 100644 --- a/components/org.wso2.micro.integrator.extensions/org.wso2.micro.integrator.management.apis/src/main/java/org/wso2/micro/integrator/management/apis/Constants.java +++ b/components/org.wso2.micro.integrator.extensions/org.wso2.micro.integrator.management.apis/src/main/java/org/wso2/micro/integrator/management/apis/Constants.java @@ -155,6 +155,7 @@ public class Constants { // toml properties public static String FILE_BASED_USER_STORE_ENABLE = "internal_apis.file_user_store.enable"; + public static String MAKE_NON_ADMIN_USERS_READ_ONLY = "user_access.make_non_admin_users_read_only"; public static final String AUDIT_LOG_TYPE_ENDPOINT = "endpoint"; public static final String AUDIT_LOG_TYPE_USER = "user"; diff --git a/components/org.wso2.micro.integrator.extensions/org.wso2.micro.integrator.management.apis/src/main/java/org/wso2/micro/integrator/management/apis/EndpointResource.java b/components/org.wso2.micro.integrator.extensions/org.wso2.micro.integrator.management.apis/src/main/java/org/wso2/micro/integrator/management/apis/EndpointResource.java index 52f1798666..8d2bf45e95 100644 --- a/components/org.wso2.micro.integrator.extensions/org.wso2.micro.integrator.management.apis/src/main/java/org/wso2/micro/integrator/management/apis/EndpointResource.java +++ b/components/org.wso2.micro.integrator.extensions/org.wso2.micro.integrator.management.apis/src/main/java/org/wso2/micro/integrator/management/apis/EndpointResource.java @@ -33,6 +33,8 @@ import org.apache.synapse.endpoints.Endpoint; import org.json.JSONObject; import org.wso2.micro.core.util.AuditLogger; +import org.wso2.micro.integrator.management.apis.security.handler.SecurityUtils; +import org.wso2.micro.integrator.security.user.api.UserStoreException; import javax.xml.namespace.QName; import java.io.IOException; @@ -50,7 +52,7 @@ import static org.wso2.micro.integrator.management.apis.Constants.SEARCH_KEY; import static org.wso2.micro.integrator.management.apis.Constants.STATUS; import static org.wso2.micro.integrator.management.apis.Constants.TRACING; - +import static org.wso2.micro.integrator.management.apis.Constants.USERNAME_PROPERTY; public class EndpointResource implements MiApiResource { @@ -93,20 +95,28 @@ public boolean invoke(MessageContext messageContext, populateEndpointList(messageContext, synapseConfiguration); } } else { + String userName = (String) messageContext.getProperty(USERNAME_PROPERTY); try { - if (!JsonUtil.hasAJsonPayload(axis2MessageContext)) { - Utils.setJsonPayLoad(axis2MessageContext, Utils.createJsonErrorObject("JSON payload is missing")); - return true; - } - JsonObject payload = Utils.getJsonPayload(axis2MessageContext); - if (payload.has(Constants.NAME) && payload.has(STATUS)) { - changeEndpointStatus(performedBy, axis2MessageContext, synapseConfiguration, payload); + if (SecurityUtils.canUserEdit(userName)) { + if (!JsonUtil.hasAJsonPayload(axis2MessageContext)) { + Utils.setJsonPayLoad(axis2MessageContext, Utils.createJsonErrorObject("JSON payload is missing")); + return true; + } + JsonObject payload = Utils.getJsonPayload(axis2MessageContext); + if (payload.has(Constants.NAME) && payload.has(STATUS)) { + changeEndpointStatus(performedBy, axis2MessageContext, synapseConfiguration, payload); + } else { + handleTracing(performedBy, payload, messageContext, axis2MessageContext); + } } else { - handleTracing(performedBy, payload, messageContext, axis2MessageContext); + Utils.sendForbiddenFaultResponse(axis2MessageContext); } } catch (IOException e) { LOG.error("Error when parsing JSON payload", e); Utils.setJsonPayLoad(axis2MessageContext, Utils.createJsonErrorObject("Error when parsing JSON payload")); + } catch (UserStoreException e) { + LOG.error("Error occurred while retrieving the user data", e); + Utils.setJsonPayLoad(axis2MessageContext, Utils.createJsonErrorObject("Error occurred while retrieving the user data")); } } diff --git a/components/org.wso2.micro.integrator.extensions/org.wso2.micro.integrator.management.apis/src/main/java/org/wso2/micro/integrator/management/apis/ExternalVaultResource.java b/components/org.wso2.micro.integrator.extensions/org.wso2.micro.integrator.management.apis/src/main/java/org/wso2/micro/integrator/management/apis/ExternalVaultResource.java index fa2248406e..f1f237378e 100644 --- a/components/org.wso2.micro.integrator.extensions/org.wso2.micro.integrator.management.apis/src/main/java/org/wso2/micro/integrator/management/apis/ExternalVaultResource.java +++ b/components/org.wso2.micro.integrator.extensions/org.wso2.micro.integrator.management.apis/src/main/java/org/wso2/micro/integrator/management/apis/ExternalVaultResource.java @@ -25,8 +25,10 @@ import org.apache.synapse.core.axis2.Axis2MessageContext; import org.json.JSONObject; import org.wso2.carbon.inbound.endpoint.internal.http.api.APIResource; +import org.wso2.micro.integrator.management.apis.security.handler.SecurityUtils; import org.wso2.micro.integrator.mediation.security.vault.external.ExternalVaultException; import org.wso2.micro.integrator.mediation.security.vault.external.hashicorp.HashiCorpVaultLookupHandlerImpl; +import org.wso2.micro.integrator.security.user.api.UserStoreException; import java.io.IOException; import java.util.HashSet; @@ -34,6 +36,7 @@ import static org.wso2.micro.integrator.management.apis.Constants.BAD_REQUEST; import static org.wso2.micro.integrator.management.apis.Constants.NOT_FOUND; +import static org.wso2.micro.integrator.management.apis.Constants.USERNAME_PROPERTY; public class ExternalVaultResource extends APIResource { @@ -64,7 +67,17 @@ public boolean invoke(MessageContext messageContext) { if ("hashicorp".equalsIgnoreCase(pathParam)) { if (Utils.isDoingPOST(axis2MessageContext)) { - handleHashiCorpPost(axis2MessageContext); + String userName = (String) messageContext.getProperty(USERNAME_PROPERTY); + try { + if (SecurityUtils.canUserEdit(userName)) { + handleHashiCorpPost(axis2MessageContext); + } else { + Utils.sendForbiddenFaultResponse(axis2MessageContext); + } + } catch (UserStoreException e) { + LOG.error("Error occurred while retrieving the user data", e); + Utils.setJsonPayLoad(axis2MessageContext, Utils.createJsonErrorObject("Error occurred while retrieving the user data")); + } } else { JSONObject response = Utils.createJsonError("No such method for management/external-vault/" + pathParam, axis2MessageContext, NOT_FOUND); diff --git a/components/org.wso2.micro.integrator.extensions/org.wso2.micro.integrator.management.apis/src/main/java/org/wso2/micro/integrator/management/apis/InboundEndpointResource.java b/components/org.wso2.micro.integrator.extensions/org.wso2.micro.integrator.management.apis/src/main/java/org/wso2/micro/integrator/management/apis/InboundEndpointResource.java index 510875f954..a7d7f9065c 100644 --- a/components/org.wso2.micro.integrator.extensions/org.wso2.micro.integrator.management.apis/src/main/java/org/wso2/micro/integrator/management/apis/InboundEndpointResource.java +++ b/components/org.wso2.micro.integrator.extensions/org.wso2.micro.integrator.management.apis/src/main/java/org/wso2/micro/integrator/management/apis/InboundEndpointResource.java @@ -30,6 +30,8 @@ import org.json.JSONArray; import org.json.JSONObject; import org.wso2.carbon.inbound.endpoint.internal.http.api.APIResource; +import org.wso2.micro.integrator.management.apis.security.handler.SecurityUtils; +import org.wso2.micro.integrator.security.user.api.UserStoreException; import java.io.IOException; @@ -43,6 +45,7 @@ import static org.wso2.micro.integrator.management.apis.Constants.SEARCH_KEY; import static org.wso2.micro.integrator.management.apis.Constants.SYNAPSE_CONFIGURATION; +import static org.wso2.micro.integrator.management.apis.Constants.USERNAME_PROPERTY; public class InboundEndpointResource extends APIResource { @@ -80,7 +83,17 @@ public boolean invoke(MessageContext messageContext) { populateInboundEndpointList(messageContext); } } else { - handlePost(messageContext, axisMsgCtx); + String userName = (String) messageContext.getProperty(USERNAME_PROPERTY); + try { + if (SecurityUtils.canUserEdit(userName)) { + handlePost(messageContext, axisMsgCtx); + } else { + Utils.sendForbiddenFaultResponse(axisMsgCtx); + } + } catch (UserStoreException e) { + LOG.error("Error occurred while retrieving the user data", e); + Utils.setJsonPayLoad(axisMsgCtx, Utils.createJsonErrorObject("Error occurred while retrieving the user data")); + } } return true; } diff --git a/components/org.wso2.micro.integrator.extensions/org.wso2.micro.integrator.management.apis/src/main/java/org/wso2/micro/integrator/management/apis/LoggingResource.java b/components/org.wso2.micro.integrator.extensions/org.wso2.micro.integrator.management.apis/src/main/java/org/wso2/micro/integrator/management/apis/LoggingResource.java index 697eb98f94..aeaa4be53d 100644 --- a/components/org.wso2.micro.integrator.extensions/org.wso2.micro.integrator.management.apis/src/main/java/org/wso2/micro/integrator/management/apis/LoggingResource.java +++ b/components/org.wso2.micro.integrator.extensions/org.wso2.micro.integrator.management.apis/src/main/java/org/wso2/micro/integrator/management/apis/LoggingResource.java @@ -32,6 +32,8 @@ import org.wso2.carbon.inbound.endpoint.internal.http.api.APIResource; import org.wso2.carbon.utils.ServerConstants; import org.wso2.micro.core.util.AuditLogger; +import org.wso2.micro.integrator.management.apis.security.handler.SecurityUtils; +import org.wso2.micro.integrator.security.user.api.UserStoreException; import java.io.File; import java.io.FileInputStream; @@ -50,6 +52,7 @@ import static org.wso2.micro.integrator.management.apis.Constants.NO_ENTITY_BODY; import static org.wso2.micro.integrator.management.apis.Constants.ROOT_LOGGER; import static org.wso2.micro.integrator.management.apis.Constants.SEARCH_KEY; +import static org.wso2.micro.integrator.management.apis.Constants.USERNAME_PROPERTY; public class LoggingResource extends APIResource { @@ -127,49 +130,60 @@ public boolean invoke(MessageContext messageContext) { return true; } } else { - if (jsonPayload.has(Constants.LOGGING_LEVEL)) { - String logLevel = jsonPayload.getString(Constants.LOGGING_LEVEL); - if (!isValidLogLevel(logLevel)) { - // 400-Bad Request Invalid loggingLevel - jsonBody = createJsonError("Invalid log level " + logLevel, "", axis2MessageContext); - } else { - if (jsonPayload.has(Constants.LOGGER_NAME)) { - String loggerName = jsonPayload.getString(Constants.LOGGER_NAME); - boolean isRootLogger = Constants.ROOT_LOGGER.equals(loggerName); - boolean hasLoggerClass = jsonPayload.has(LOGGER_CLASS); - String performedBy = Constants.ANONYMOUS_USER; - if (messageContext.getProperty(Constants.USERNAME_PROPERTY) != null) { - performedBy = messageContext.getProperty(Constants.USERNAME_PROPERTY).toString(); - } - JSONObject info = new JSONObject(); - info.put(Constants.LOGGER_NAME, loggerName); - info.put(Constants.LOGGING_LEVEL, logLevel); - if (isRootLogger || !hasLoggerClass) { - // update existing logger - jsonBody = updateLoggerData(performedBy, info, axis2MessageContext, loggerName, logLevel); + String userName = (String) messageContext.getProperty(USERNAME_PROPERTY); + try { + if (SecurityUtils.canUserEdit(userName)) { + if (jsonPayload.has(Constants.LOGGING_LEVEL)) { + String logLevel = jsonPayload.getString(Constants.LOGGING_LEVEL); + if (!isValidLogLevel(logLevel)) { + // 400-Bad Request Invalid loggingLevel + jsonBody = createJsonError("Invalid log level " + logLevel, "", axis2MessageContext); } else { - try { - if (isLoggerExist(loggerName)) { - String errorMsg = "Specified logger name ('" + loggerName - + "') already exists, try updating the level instead"; - jsonBody = createJsonError(errorMsg, "", axis2MessageContext); + if (jsonPayload.has(Constants.LOGGER_NAME)) { + String loggerName = jsonPayload.getString(Constants.LOGGER_NAME); + boolean isRootLogger = Constants.ROOT_LOGGER.equals(loggerName); + boolean hasLoggerClass = jsonPayload.has(LOGGER_CLASS); + String performedBy = Constants.ANONYMOUS_USER; + if (messageContext.getProperty(Constants.USERNAME_PROPERTY) != null) { + performedBy = messageContext.getProperty(Constants.USERNAME_PROPERTY).toString(); + } + JSONObject info = new JSONObject(); + info.put(Constants.LOGGER_NAME, loggerName); + info.put(Constants.LOGGING_LEVEL, logLevel); + if (isRootLogger || !hasLoggerClass) { + // update existing logger + jsonBody = updateLoggerData(performedBy, info, axis2MessageContext, loggerName, logLevel); } else { - String loggerClass = jsonPayload.getString(LOGGER_CLASS); - jsonBody = updateLoggerData(performedBy, info, - axis2MessageContext, loggerName, loggerClass, logLevel); + try { + if (isLoggerExist(loggerName)) { + String errorMsg = "Specified logger name ('" + loggerName + + "') already exists, try updating the level instead"; + jsonBody = createJsonError(errorMsg, "", axis2MessageContext); + } else { + String loggerClass = jsonPayload.getString(LOGGER_CLASS); + jsonBody = updateLoggerData(performedBy, info, + axis2MessageContext, loggerName, loggerClass, logLevel); + } + } catch (IOException exception) { + jsonBody = createJsonError(EXCEPTION_MSG, exception, axis2MessageContext); + } } - } catch (IOException exception) { - jsonBody = createJsonError(EXCEPTION_MSG, exception, axis2MessageContext); + } else { + // 400-Bad Request logger name is missing + jsonBody = createJsonError("Logger name is missing", "", axis2MessageContext); } } } else { - // 400-Bad Request logger name is missing - jsonBody = createJsonError("Logger name is missing", "", axis2MessageContext); + // 400-Bad Request logLevel is missing + jsonBody = createJsonError("Log level is missing", "", axis2MessageContext); } + } else { + Utils.sendForbiddenFaultResponse(axis2MessageContext); + jsonBody = createJsonError("User is not Authorized to edit", "", axis2MessageContext); } - } else { - // 400-Bad Request logLevel is missing - jsonBody = createJsonError("Log level is missing", "", axis2MessageContext); + } catch (UserStoreException e) { + log.error("Error occurred while retrieving the user data", e); + jsonBody = createJsonError("Error occurred while retrieving the user data", e, axis2MessageContext); } } Utils.setJsonPayLoad(axis2MessageContext, jsonBody); diff --git a/components/org.wso2.micro.integrator.extensions/org.wso2.micro.integrator.management.apis/src/main/java/org/wso2/micro/integrator/management/apis/MessageProcessorResource.java b/components/org.wso2.micro.integrator.extensions/org.wso2.micro.integrator.management.apis/src/main/java/org/wso2/micro/integrator/management/apis/MessageProcessorResource.java index d7aff04532..00a4793550 100644 --- a/components/org.wso2.micro.integrator.extensions/org.wso2.micro.integrator.management.apis/src/main/java/org/wso2/micro/integrator/management/apis/MessageProcessorResource.java +++ b/components/org.wso2.micro.integrator.extensions/org.wso2.micro.integrator.management.apis/src/main/java/org/wso2/micro/integrator/management/apis/MessageProcessorResource.java @@ -36,6 +36,8 @@ import org.json.JSONObject; import org.wso2.carbon.inbound.endpoint.internal.http.api.APIResource; import org.wso2.micro.core.util.AuditLogger; +import org.wso2.micro.integrator.management.apis.security.handler.SecurityUtils; +import org.wso2.micro.integrator.security.user.api.UserStoreException; import java.io.IOException; import java.io.InputStream; @@ -53,6 +55,7 @@ import static org.wso2.micro.integrator.management.apis.Constants.NAME; import static org.wso2.micro.integrator.management.apis.Constants.SEARCH_KEY; import static org.wso2.micro.integrator.management.apis.Constants.STATUS; +import static org.wso2.micro.integrator.management.apis.Constants.USERNAME_PROPERTY; /** * Represents message processor resources defined in the synapse configuration. @@ -108,19 +111,28 @@ public boolean invoke(MessageContext messageContext) { } axis2MessageContext.removeProperty(Constants.NO_ENTITY_BODY); } else if (Utils.isDoingPOST(axis2MessageContext)) { + String userName = (String) messageContext.getProperty(USERNAME_PROPERTY); try { - if (!JsonUtil.hasAJsonPayload(axis2MessageContext)) { - return false; - } - JsonObject payload = getJsonPayload(messageContext); - if (payload.has(NAME) && payload.has(STATUS)) { - changeProcessorStatus(messageContext, payload); + if (SecurityUtils.canUserEdit(userName)) { + if (!JsonUtil.hasAJsonPayload(axis2MessageContext)) { + return false; + } + JsonObject payload = getJsonPayload(messageContext); + if (payload.has(NAME) && payload.has(STATUS)) { + changeProcessorStatus(messageContext, payload); + } else { + Utils.setJsonPayLoad(axis2MessageContext, Utils.createJsonErrorObject("Missing parameters in payload")); + } } else { - Utils.setJsonPayLoad(axis2MessageContext, Utils.createJsonErrorObject("Missing parameters in payload")); + Utils.sendForbiddenFaultResponse(axis2MessageContext); } + } catch (IOException e) { LOG.error("Error when parsing JSON payload", e); Utils.setJsonPayLoad(axis2MessageContext, Utils.createJsonErrorObject("Error when parsing JSON payload")); + } catch (UserStoreException e) { + LOG.error("Error occurred while retrieving the user data", e); + Utils.setJsonPayLoad(axis2MessageContext, Utils.createJsonErrorObject("Error occurred while retrieving the user data")); } } return true; diff --git a/components/org.wso2.micro.integrator.extensions/org.wso2.micro.integrator.management.apis/src/main/java/org/wso2/micro/integrator/management/apis/MetaDataResource.java b/components/org.wso2.micro.integrator.extensions/org.wso2.micro.integrator.management.apis/src/main/java/org/wso2/micro/integrator/management/apis/MetaDataResource.java index 05e66c4b78..30c757af9a 100644 --- a/components/org.wso2.micro.integrator.extensions/org.wso2.micro.integrator.management.apis/src/main/java/org/wso2/micro/integrator/management/apis/MetaDataResource.java +++ b/components/org.wso2.micro.integrator.extensions/org.wso2.micro.integrator.management.apis/src/main/java/org/wso2/micro/integrator/management/apis/MetaDataResource.java @@ -28,6 +28,8 @@ import org.wso2.micro.core.util.CoreServerInitializerHolder; import org.wso2.micro.integrator.core.services.CarbonServerConfigurationService; import org.wso2.micro.integrator.core.util.MicroIntegratorBaseUtils; +import org.wso2.micro.integrator.management.apis.security.handler.SecurityUtils; +import org.wso2.micro.integrator.security.user.api.UserStoreException; import java.io.IOException; import java.util.HashSet; @@ -35,6 +37,8 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import static org.wso2.micro.integrator.management.apis.Constants.USERNAME_PROPERTY; + /** * This class serves metadata related to the server. */ @@ -66,54 +70,62 @@ public boolean invoke(MessageContext messageContext, axis2MessageContext.removeProperty(Constants.NO_ENTITY_BODY); return true; } else { + String userName = (String) messageContext.getProperty(USERNAME_PROPERTY); try { - if (!JsonUtil.hasAJsonPayload(axis2MessageContext)) { - Utils.setJsonPayLoad(axis2MessageContext, Utils.createJsonErrorObject("JSON payload is missing.")); - return true; - } - JsonObject payload = Utils.getJsonPayload(axis2MessageContext); - if (payload.has(Constants.STATUS)) { - ExecutorService executorService = Executors.newFixedThreadPool(Runtime.getRuntime() - .availableProcessors()); - Runnable runnable = null; - switch (payload.get(Constants.STATUS).getAsString()) { - case "shutdown": - runnable = this::shutdownServer; - Utils.setJsonPayLoad(axis2MessageContext, - createJsonResponse("The server will start to shutdown.")); - break; - case "shutdownGracefully": - runnable = this::gracefullyShutdownServer; - Utils.setJsonPayLoad(axis2MessageContext, - createJsonResponse("The server will start to shutdown gracefully.")); - break; - case "restart": - runnable = this::restart; - Utils.setJsonPayLoad(axis2MessageContext, - createJsonResponse("The server will start to restart.")); - break; - case "restartGracefully": - runnable = this::gracefullyRestartServer; - Utils.setJsonPayLoad(axis2MessageContext, - createJsonResponse("The server will start to restart gracefully.")); - break; - default: - LOG.error("Invalid server status received."); - Utils.setJsonPayLoad(axis2MessageContext, - Utils.createJsonErrorObject("Invalid server status received.")); + if (SecurityUtils.canUserEdit(userName)) { + if (!JsonUtil.hasAJsonPayload(axis2MessageContext)) { + Utils.setJsonPayLoad(axis2MessageContext, Utils.createJsonErrorObject("JSON payload is missing.")); + return true; } - if (runnable != null) { - executorService.execute(runnable); + JsonObject payload = Utils.getJsonPayload(axis2MessageContext); + if (payload.has(Constants.STATUS)) { + ExecutorService executorService = Executors.newFixedThreadPool(Runtime.getRuntime() + .availableProcessors()); + Runnable runnable = null; + switch (payload.get(Constants.STATUS).getAsString()) { + case "shutdown": + runnable = this::shutdownServer; + Utils.setJsonPayLoad(axis2MessageContext, + createJsonResponse("The server will start to shutdown.")); + break; + case "shutdownGracefully": + runnable = this::gracefullyShutdownServer; + Utils.setJsonPayLoad(axis2MessageContext, + createJsonResponse("The server will start to shutdown gracefully.")); + break; + case "restart": + runnable = this::restart; + Utils.setJsonPayLoad(axis2MessageContext, + createJsonResponse("The server will start to restart.")); + break; + case "restartGracefully": + runnable = this::gracefullyRestartServer; + Utils.setJsonPayLoad(axis2MessageContext, + createJsonResponse("The server will start to restart gracefully.")); + break; + default: + LOG.error("Invalid server status received."); + Utils.setJsonPayLoad(axis2MessageContext, + Utils.createJsonErrorObject("Invalid server status received.")); + } + if (runnable != null) { + executorService.execute(runnable); + } + } else { + LOG.error("Invalid payload structure received."); + Utils.setJsonPayLoad(axis2MessageContext, + Utils.createJsonErrorObject("Invalid payload structure received.")); } } else { - LOG.error("Invalid payload structure received."); - Utils.setJsonPayLoad(axis2MessageContext, - Utils.createJsonErrorObject("Invalid payload structure received.")); + Utils.sendForbiddenFaultResponse(axis2MessageContext); } } catch (IOException e) { LOG.error("Error when parsing JSON payload.", e); Utils.setJsonPayLoad(axis2MessageContext, Utils.createJsonErrorObject("Error when parsing JSON payload.")); + } catch (UserStoreException e) { + LOG.error("Error occurred while retrieving the user data", e); + Utils.setJsonPayLoad(axis2MessageContext, Utils.createJsonErrorObject("Error occurred while retrieving the user data")); } } return true; diff --git a/components/org.wso2.micro.integrator.extensions/org.wso2.micro.integrator.management.apis/src/main/java/org/wso2/micro/integrator/management/apis/ProxyServiceResource.java b/components/org.wso2.micro.integrator.extensions/org.wso2.micro.integrator.management.apis/src/main/java/org/wso2/micro/integrator/management/apis/ProxyServiceResource.java index 840dc29675..2a716fe550 100644 --- a/components/org.wso2.micro.integrator.extensions/org.wso2.micro.integrator.management.apis/src/main/java/org/wso2/micro/integrator/management/apis/ProxyServiceResource.java +++ b/components/org.wso2.micro.integrator.extensions/org.wso2.micro.integrator.management.apis/src/main/java/org/wso2/micro/integrator/management/apis/ProxyServiceResource.java @@ -33,6 +33,8 @@ import org.json.JSONObject; import org.wso2.carbon.inbound.endpoint.internal.http.api.APIResource; import org.wso2.micro.core.util.AuditLogger; +import org.wso2.micro.integrator.management.apis.security.handler.SecurityUtils; +import org.wso2.micro.integrator.security.user.api.UserStoreException; import org.wso2.micro.service.mgt.ServiceAdmin; import org.wso2.micro.service.mgt.ServiceMetaData; @@ -50,6 +52,7 @@ import static org.wso2.micro.integrator.management.apis.Constants.SEARCH_KEY; import static org.wso2.micro.integrator.management.apis.Constants.STATUS; import static org.wso2.micro.integrator.management.apis.Constants.SYNAPSE_CONFIGURATION; +import static org.wso2.micro.integrator.management.apis.Constants.USERNAME_PROPERTY; public class ProxyServiceResource extends APIResource { @@ -101,27 +104,35 @@ public boolean invoke(MessageContext messageContext) { } axis2MessageContext.removeProperty(Constants.NO_ENTITY_BODY); } else { + String userName = (String) messageContext.getProperty(USERNAME_PROPERTY); try { - if (!JsonUtil.hasAJsonPayload(axis2MessageContext)) { - Utils.setJsonPayLoad(axis2MessageContext, Utils.createJsonErrorObject("JSON payload is missing")); - return true; - } - JsonObject payload = Utils.getJsonPayload(axis2MessageContext); - String performedBy = Constants.ANONYMOUS_USER; - if (messageContext.getProperty(Constants.USERNAME_PROPERTY) != null) { - performedBy = messageContext.getProperty(Constants.USERNAME_PROPERTY).toString(); - } - JSONObject info = new JSONObject(); - String name = payload.get(NAME).getAsString(); - info.put(PROXY_NAME, name); - if (payload.has(NAME) && payload.has(STATUS)) { - changeProxyState(performedBy, info, messageContext, axis2MessageContext, payload); + if (SecurityUtils.canUserEdit(userName)) { + if (!JsonUtil.hasAJsonPayload(axis2MessageContext)) { + Utils.setJsonPayLoad(axis2MessageContext, Utils.createJsonErrorObject("JSON payload is missing")); + return true; + } + JsonObject payload = Utils.getJsonPayload(axis2MessageContext); + String performedBy = Constants.ANONYMOUS_USER; + if (messageContext.getProperty(Constants.USERNAME_PROPERTY) != null) { + performedBy = messageContext.getProperty(Constants.USERNAME_PROPERTY).toString(); + } + JSONObject info = new JSONObject(); + String name = payload.get(NAME).getAsString(); + info.put(PROXY_NAME, name); + if (payload.has(NAME) && payload.has(STATUS)) { + changeProxyState(performedBy, info, messageContext, axis2MessageContext, payload); + } else { + handleTracing(performedBy, info, payload, messageContext, axis2MessageContext); + } } else { - handleTracing(performedBy, info, payload, messageContext, axis2MessageContext); + Utils.sendForbiddenFaultResponse(axis2MessageContext); } } catch (IOException e) { LOG.error("Error when parsing JSON payload", e); Utils.setJsonPayLoad(axis2MessageContext, Utils.createJsonErrorObject("Error when parsing JSON payload")); + } catch (UserStoreException e) { + LOG.error("Error occurred while retrieving the user data", e); + Utils.setJsonPayLoad(axis2MessageContext,Utils.createJsonErrorObject("Error occurred while retrieving the user data")); } } return true; diff --git a/components/org.wso2.micro.integrator.extensions/org.wso2.micro.integrator.management.apis/src/main/java/org/wso2/micro/integrator/management/apis/SequenceResource.java b/components/org.wso2.micro.integrator.extensions/org.wso2.micro.integrator.management.apis/src/main/java/org/wso2/micro/integrator/management/apis/SequenceResource.java index d90afd5f40..f06bafae3d 100644 --- a/components/org.wso2.micro.integrator.extensions/org.wso2.micro.integrator.management.apis/src/main/java/org/wso2/micro/integrator/management/apis/SequenceResource.java +++ b/components/org.wso2.micro.integrator.extensions/org.wso2.micro.integrator.management.apis/src/main/java/org/wso2/micro/integrator/management/apis/SequenceResource.java @@ -30,6 +30,8 @@ import org.apache.synapse.mediators.base.SequenceMediator; import org.json.JSONObject; import org.wso2.carbon.inbound.endpoint.internal.http.api.APIResource; +import org.wso2.micro.integrator.management.apis.security.handler.SecurityUtils; +import org.wso2.micro.integrator.security.user.api.UserStoreException; import java.io.IOException; @@ -42,6 +44,7 @@ import java.util.stream.Collectors; import static org.wso2.micro.integrator.management.apis.Constants.SEARCH_KEY; +import static org.wso2.micro.integrator.management.apis.Constants.USERNAME_PROPERTY; public class SequenceResource extends APIResource { @@ -80,7 +83,17 @@ public boolean invoke(MessageContext messageContext) { populateSequenceList(messageContext); } } else { - handlePost(messageContext, axisMsgCtx); + String userName = (String) messageContext.getProperty(USERNAME_PROPERTY); + try { + if (SecurityUtils.canUserEdit(userName)) { + handlePost(messageContext, axisMsgCtx); + } else { + Utils.sendForbiddenFaultResponse(axisMsgCtx); + } + } catch (UserStoreException e) { + LOG.error("Error occurred while retrieving the user data", e); + Utils.setJsonPayLoad(axisMsgCtx, Utils.createJsonErrorObject("Error occurred while retrieving the user data")); + } } return true; } diff --git a/components/org.wso2.micro.integrator.extensions/org.wso2.micro.integrator.management.apis/src/main/java/org/wso2/micro/integrator/management/apis/TemplateResource.java b/components/org.wso2.micro.integrator.extensions/org.wso2.micro.integrator.management.apis/src/main/java/org/wso2/micro/integrator/management/apis/TemplateResource.java index d658472a76..be3fcfcf60 100644 --- a/components/org.wso2.micro.integrator.extensions/org.wso2.micro.integrator.management.apis/src/main/java/org/wso2/micro/integrator/management/apis/TemplateResource.java +++ b/components/org.wso2.micro.integrator.extensions/org.wso2.micro.integrator.management.apis/src/main/java/org/wso2/micro/integrator/management/apis/TemplateResource.java @@ -31,6 +31,8 @@ import org.json.JSONArray; import org.json.JSONObject; import org.wso2.carbon.inbound.endpoint.internal.http.api.APIResource; +import org.wso2.micro.integrator.management.apis.security.handler.SecurityUtils; +import org.wso2.micro.integrator.security.user.api.UserStoreException; import java.io.IOException; @@ -42,6 +44,7 @@ import java.util.stream.Collectors; import static org.wso2.micro.integrator.management.apis.Constants.SEARCH_KEY; +import static org.wso2.micro.integrator.management.apis.Constants.USERNAME_PROPERTY; /** * Represents template resources defined in the synapse configuration. @@ -97,21 +100,29 @@ public boolean invoke(MessageContext msgCtx) { } } else { JSONObject response; + String userName = (String) msgCtx.getProperty(USERNAME_PROPERTY); try { - JsonObject payload = Utils.getJsonPayload(axis2MsgCtx); - if (payload.has(TEMPLATE_TYPE_PARAM)) { - templateTypeParam = payload.get(TEMPLATE_TYPE_PARAM).getAsString(); - } - if (payload.has(Constants.NAME) && SEQUENCE_TEMPLATE_TYPE.equals(templateTypeParam)) { - String seqTempName = payload.get(Constants.NAME).getAsString(); - response = handleTracing(seqTempName, msgCtx, axis2MsgCtx); + if (SecurityUtils.canUserEdit(userName)) { + JsonObject payload = Utils.getJsonPayload(axis2MsgCtx); + if (payload.has(TEMPLATE_TYPE_PARAM)) { + templateTypeParam = payload.get(TEMPLATE_TYPE_PARAM).getAsString(); + } + if (payload.has(Constants.NAME) && SEQUENCE_TEMPLATE_TYPE.equals(templateTypeParam)) { + String seqTempName = payload.get(Constants.NAME).getAsString(); + response = handleTracing(seqTempName, msgCtx, axis2MsgCtx); + } else { + response = Utils.createJsonError("Unsupported operation", axis2MsgCtx, Constants.BAD_REQUEST); + } + Utils.setJsonPayLoad(axis2MsgCtx, response); } else { - response = Utils.createJsonError("Unsupported operation", axis2MsgCtx, Constants.BAD_REQUEST); + Utils.sendForbiddenFaultResponse(axis2MsgCtx); } - Utils.setJsonPayLoad(axis2MsgCtx, response); } catch (IOException e) { LOG.error("Error when parsing JSON payload", e); Utils.setJsonPayLoad(axis2MsgCtx, Utils.createJsonErrorObject("Error when parsing JSON payload")); + } catch (UserStoreException e) { + LOG.error("Error occurred while retrieving the user data", e); + Utils.setJsonPayLoad(axis2MsgCtx, Utils.createJsonErrorObject("Error occurred while retrieving the user data")); } } return true; diff --git a/components/org.wso2.micro.integrator.extensions/org.wso2.micro.integrator.management.apis/src/main/java/org/wso2/micro/integrator/management/apis/security/handler/SecurityUtils.java b/components/org.wso2.micro.integrator.extensions/org.wso2.micro.integrator.management.apis/src/main/java/org/wso2/micro/integrator/management/apis/security/handler/SecurityUtils.java index ef00e46a5c..392d42e8bb 100644 --- a/components/org.wso2.micro.integrator.extensions/org.wso2.micro.integrator.management.apis/src/main/java/org/wso2/micro/integrator/management/apis/security/handler/SecurityUtils.java +++ b/components/org.wso2.micro.integrator.extensions/org.wso2.micro.integrator.management.apis/src/main/java/org/wso2/micro/integrator/management/apis/security/handler/SecurityUtils.java @@ -121,4 +121,30 @@ public static boolean isAdmin(String username) throws UserStoreException { return MicroIntegratorSecurityUtils.isAdmin(username); } } + + /** + * Checks if non-admin users are treated as read-only users based on the configuration. + * + * @return {@code true} if non-admin users are read-only according to the config, {@code false} otherwise. + */ + private static boolean isNonAdminUsersReadOnly() { + return (Boolean) ConfigParser.getParsedConfigs().getOrDefault(Constants.MAKE_NON_ADMIN_USERS_READ_ONLY, false); + } + + /** + * Determines if the specified user has permission to edit. + * + * Admin users always have edit permissions. For non-admin users, the edit permission depends + * on the configuration: if make_non_admin_users_read_only == true, they cannot edit; otherwise, they can. + * + * @param userName the name of the user to check for edit permissions + * @return {@code true} if the user has edit permissions, {@code false} otherwise + * @throws UserStoreException if there is an error accessing the user store + */ + public static boolean canUserEdit(String userName) throws UserStoreException { + if (userName == null) { + return true; + } + return isAdmin(userName) || !isNonAdminUsersReadOnly(); + } } diff --git a/distribution/src/resources/config-tool/deployment-full.toml b/distribution/src/resources/config-tool/deployment-full.toml index efed1b64bc..812e83a38d 100644 --- a/distribution/src/resources/config-tool/deployment-full.toml +++ b/distribution/src/resources/config-tool/deployment-full.toml @@ -1389,3 +1389,6 @@ phase_name = "Transport" [[transport.phase_order.phases]] phase_name = "MsgOutObservation" + +[user_access] +make_non_admin_users_read_only = false