mirror of
https://repository.entgra.net/community/device-mgt-core.git
synced 2025-10-06 02:01:45 +00:00
Add necessary improvements and configs for grafana version 10.3.3 (#396)
Co-authored-by: Sasini_Sandamali <sasini@entgra.io> Reviewed-on: https://repository.entgra.net/community/device-mgt-core/pulls/396 Co-authored-by: Sasini Sandamali <sasini@entgra.io> Co-committed-by: Sasini Sandamali <sasini@entgra.io>
This commit is contained in:
parent
a7a29891da
commit
01d76c6dbd
@ -107,6 +107,23 @@ public interface GrafanaAPIProxyService {
|
||||
)
|
||||
Response frontendMetrics(JsonObject body, @Context HttpHeaders headers, @Context UriInfo requestUriInfo);
|
||||
|
||||
@POST
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Path("/user/auth-tokens/rotate")
|
||||
@ApiOperation(
|
||||
produces = MediaType.APPLICATION_JSON,
|
||||
httpMethod = "POST",
|
||||
value = "Rotate authentication tokens",
|
||||
tags = "Analytics",
|
||||
extensions = {
|
||||
@Extension(properties = {
|
||||
@ExtensionProperty(name = SCOPE, value = "grafana:api:view")
|
||||
})
|
||||
}
|
||||
)
|
||||
Response rotateAuthToken(JsonObject body, @Context HttpHeaders headers, @Context UriInfo requestUriInfo);
|
||||
|
||||
@GET
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Path("/dashboards/uid/{uid}")
|
||||
@ -123,6 +140,22 @@ public interface GrafanaAPIProxyService {
|
||||
)
|
||||
Response getDashboard(@Context HttpHeaders headers, @Context UriInfo requestUriInfo) throws ClassNotFoundException;
|
||||
|
||||
@GET
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Path("/folders/{uid}")
|
||||
@ApiOperation(
|
||||
produces = MediaType.APPLICATION_JSON,
|
||||
httpMethod = "GET",
|
||||
value = "Grafana dashboard folder information",
|
||||
tags = "Analytics",
|
||||
extensions = {
|
||||
@Extension(properties = {
|
||||
@ExtensionProperty(name = SCOPE, value = "grafana:api:view")
|
||||
})
|
||||
}
|
||||
)
|
||||
Response getFolders(@Context HttpHeaders headers, @Context UriInfo requestUriInfo) throws ClassNotFoundException;
|
||||
|
||||
@GET
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@ -140,6 +173,23 @@ public interface GrafanaAPIProxyService {
|
||||
)
|
||||
Response getAnnotations(@Context HttpHeaders headers, @Context UriInfo requestUriInfo) throws ClassNotFoundException;
|
||||
|
||||
@GET
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Path("/prometheus/grafana/api/v1/rules")
|
||||
@ApiOperation(
|
||||
produces = MediaType.APPLICATION_JSON,
|
||||
httpMethod = "GET",
|
||||
value = "Accessing Grafana Prometheus rule information",
|
||||
tags = "Analytics",
|
||||
extensions = {
|
||||
@Extension(properties = {
|
||||
@ExtensionProperty(name = SCOPE, value = "grafana:api:view")
|
||||
})
|
||||
}
|
||||
)
|
||||
Response prometheusRuleInfo(@Context HttpHeaders headers, @Context UriInfo requestUriInfo) throws ClassNotFoundException;
|
||||
|
||||
@GET
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Path("/alerts/states-for-dashboard")
|
||||
|
||||
@ -26,6 +26,8 @@ import io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.api.impl.util.Grafa
|
||||
import io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.api.impl.util.GrafanaRequestHandlerUtil;
|
||||
import io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.common.exception.GrafanaManagementException;
|
||||
import io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.core.bean.GrafanaPanelIdentifier;
|
||||
import io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.core.config.GrafanaConfiguration;
|
||||
import io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.core.config.GrafanaConfigurationManager;
|
||||
import io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.core.exception.MaliciousQueryAttempt;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
@ -56,9 +58,13 @@ public class GrafanaAPIProxyServiceImpl implements GrafanaAPIProxyService {
|
||||
@Override
|
||||
public Response queryDatasource(JsonObject body, @Context HttpHeaders headers, @Context UriInfo requestUriInfo) {
|
||||
try {
|
||||
GrafanaConfiguration configuration = GrafanaConfigurationManager.getInstance().getGrafanaConfiguration();
|
||||
GrafanaPanelIdentifier panelIdentifier = GrafanaRequestHandlerUtil.getPanelIdentifier(headers);
|
||||
GrafanaMgtAPIUtils.getGrafanaQueryService().buildSafeQuery(body, panelIdentifier.getDashboardId(),
|
||||
panelIdentifier.getPanelId(), requestUriInfo.getRequestUri());
|
||||
boolean queryValidationConfig = configuration.getValidationConfig().getDSQueryValidation();
|
||||
if (queryValidationConfig) {
|
||||
GrafanaMgtAPIUtils.getGrafanaQueryService().buildSafeQuery(body, panelIdentifier.getDashboardId(),
|
||||
panelIdentifier.getPanelId(), requestUriInfo.getRequestUri());
|
||||
}
|
||||
return GrafanaRequestHandlerUtil.proxyPassPostRequest(body, requestUriInfo, panelIdentifier.getOrgId());
|
||||
} catch (MaliciousQueryAttempt e) {
|
||||
return Response.status(Response.Status.BAD_REQUEST).entity(
|
||||
@ -83,6 +89,15 @@ public class GrafanaAPIProxyServiceImpl implements GrafanaAPIProxyService {
|
||||
return proxyPassPostRequest(body, headers, requestUriInfo);
|
||||
}
|
||||
|
||||
@POST
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Path("/user/auth-tokens/rotate")
|
||||
@Override
|
||||
public Response rotateAuthToken(JsonObject body, @Context HttpHeaders headers, @Context UriInfo requestUriInfo) {
|
||||
return proxyPassPostRequest(body, headers, requestUriInfo);
|
||||
}
|
||||
|
||||
@GET
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Path("/dashboards/uid/{uid}")
|
||||
@ -91,6 +106,14 @@ public class GrafanaAPIProxyServiceImpl implements GrafanaAPIProxyService {
|
||||
return proxyPassGetRequest(headers, requestUriInfo);
|
||||
}
|
||||
|
||||
@GET
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Path("/folders/{uid}")
|
||||
@Override
|
||||
public Response getFolders(@Context HttpHeaders headers, @Context UriInfo requestUriInfo) {
|
||||
return proxyPassGetRequest(headers, requestUriInfo);
|
||||
}
|
||||
|
||||
@GET
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@ -99,6 +122,16 @@ public class GrafanaAPIProxyServiceImpl implements GrafanaAPIProxyService {
|
||||
public Response getAnnotations(@Context HttpHeaders headers, @Context UriInfo requestUriInfo) {
|
||||
return proxyPassGetRequest(headers, requestUriInfo);
|
||||
}
|
||||
|
||||
@GET
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Path("/prometheus/grafana/api/v1/rules")
|
||||
@Override
|
||||
public Response prometheusRuleInfo(@Context HttpHeaders headers, @Context UriInfo requestUriInfo) {
|
||||
return proxyPassGetRequest(headers, requestUriInfo);
|
||||
}
|
||||
|
||||
@GET
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Path("/alerts/states-for-dashboard")
|
||||
|
||||
@ -22,6 +22,8 @@ import io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.api.bean.ErrorRespo
|
||||
import io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.api.exception.RefererNotValid;
|
||||
import io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.common.exception.GrafanaManagementException;
|
||||
import io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.core.bean.GrafanaPanelIdentifier;
|
||||
import io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.core.config.GrafanaConfiguration;
|
||||
import io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.core.config.GrafanaConfigurationManager;
|
||||
import io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.core.exception.GrafanaEnvVariablesNotDefined;
|
||||
import io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.core.util.GrafanaConstants;
|
||||
import io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.core.util.GrafanaUtil;
|
||||
@ -120,19 +122,23 @@ public class GrafanaRequestHandlerUtil {
|
||||
return path;
|
||||
}
|
||||
|
||||
public static GrafanaPanelIdentifier getPanelIdentifier(HttpHeaders headers) throws RefererNotValid {
|
||||
public static GrafanaPanelIdentifier getPanelIdentifier(HttpHeaders headers) throws RefererNotValid, GrafanaManagementException {
|
||||
String referer = headers.getHeaderString(GrafanaConstants.REFERER_HEADER);
|
||||
if(referer == null) {
|
||||
if (referer == null) {
|
||||
String errMsg = "Request does not contain Referer header";
|
||||
log.error(errMsg);
|
||||
throw new RefererNotValid(errMsg);
|
||||
}
|
||||
GrafanaConfiguration configuration = GrafanaConfigurationManager.getInstance().getGrafanaConfiguration();
|
||||
boolean dashboardIntegrationConfig = configuration.getValidationConfig().getDashboardIntegration();
|
||||
GrafanaPanelIdentifier panelIdentifier = GrafanaUtil.getPanelIdentifierFromReferer(referer);
|
||||
if(panelIdentifier.getDashboardId() == null ||
|
||||
panelIdentifier.getPanelId() == null || panelIdentifier.getOrgId() == null) {
|
||||
String errMsg = "Referer must contain dashboardId, panelId and orgId";
|
||||
log.error(errMsg);
|
||||
throw new RefererNotValid(errMsg);
|
||||
if (!dashboardIntegrationConfig) {
|
||||
if (panelIdentifier.getDashboardId() == null ||
|
||||
panelIdentifier.getPanelId() == null || panelIdentifier.getOrgId() == null) {
|
||||
String errMsg = "Referer must contain dashboardId, panelId, and orgId";
|
||||
log.error(errMsg);
|
||||
throw new RefererNotValid(errMsg);
|
||||
}
|
||||
}
|
||||
return panelIdentifier;
|
||||
}
|
||||
|
||||
@ -19,6 +19,7 @@
|
||||
package io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.core.config;
|
||||
|
||||
import io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.core.config.xml.bean.CacheConfiguration;
|
||||
import io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.core.config.xml.bean.ValidationConfig;
|
||||
import io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.core.config.xml.bean.User;
|
||||
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
@ -30,6 +31,7 @@ import java.util.List;
|
||||
public class GrafanaConfiguration {
|
||||
|
||||
private User adminUser;
|
||||
private ValidationConfig validationConfig;
|
||||
private List<CacheConfiguration> caches;
|
||||
|
||||
@XmlElement(name = "AdminUser")
|
||||
@ -37,6 +39,15 @@ public class GrafanaConfiguration {
|
||||
return adminUser;
|
||||
}
|
||||
|
||||
@XmlElement(name = "ValidationConfig")
|
||||
public ValidationConfig getValidationConfig() {
|
||||
return validationConfig;
|
||||
}
|
||||
|
||||
public void setValidationConfig(ValidationConfig validationConfig) {
|
||||
this.validationConfig = validationConfig;
|
||||
}
|
||||
|
||||
public void setAdminUser(User user) {
|
||||
this.adminUser = user;
|
||||
}
|
||||
|
||||
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (c) 2018 - 2024, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
|
||||
*
|
||||
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
|
||||
* Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.core.config.xml.bean;
|
||||
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
|
||||
@XmlRootElement(name = "ValidationConfig")
|
||||
public class ValidationConfig {
|
||||
private boolean dsQueryValidation;
|
||||
private boolean dashboardIntegration;
|
||||
|
||||
@XmlElement(name = "DSQueryValidation")
|
||||
public boolean getDSQueryValidation() {
|
||||
return dsQueryValidation;
|
||||
}
|
||||
|
||||
public void setDSQueryValidation(boolean dsQueryValidation) {
|
||||
this.dsQueryValidation = dsQueryValidation;
|
||||
}
|
||||
|
||||
@XmlElement(name = "DashboardIntegration")
|
||||
public boolean getDashboardIntegration() {
|
||||
return dashboardIntegration;
|
||||
}
|
||||
|
||||
public void setDashboardIntegration(boolean dashboardIntegration) {
|
||||
this.dashboardIntegration = dashboardIntegration;
|
||||
}
|
||||
}
|
||||
@ -32,4 +32,10 @@
|
||||
<Username>admin</Username>
|
||||
<Password>admin</Password>
|
||||
</AdminUser>
|
||||
<ValidationConfig>
|
||||
<!-- Enable/Disable data source query validation. -->
|
||||
<DSQueryValidation>true</DSQueryValidation>
|
||||
<!-- Enable/Disable dashboard integration. -->
|
||||
<DashboardIntegration>false</DashboardIntegration>
|
||||
</ValidationConfig>
|
||||
</GrafanaConfiguration>
|
||||
|
||||
@ -32,4 +32,10 @@
|
||||
<Username>admin</Username>
|
||||
<Password>admin</Password>
|
||||
</AdminUser>
|
||||
<ValidationConfig>
|
||||
<!-- Enable/Disable data source query validation. -->
|
||||
<DSQueryValidation>true</DSQueryValidation>
|
||||
<!-- Enable/Disable dashboard integration. -->
|
||||
<DashboardIntegration>false</DashboardIntegration>
|
||||
</ValidationConfig>
|
||||
</GrafanaConfiguration>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user