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);
|
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
|
@GET
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
@Path("/dashboards/uid/{uid}")
|
@Path("/dashboards/uid/{uid}")
|
||||||
@ -123,6 +140,22 @@ public interface GrafanaAPIProxyService {
|
|||||||
)
|
)
|
||||||
Response getDashboard(@Context HttpHeaders headers, @Context UriInfo requestUriInfo) throws ClassNotFoundException;
|
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
|
@GET
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
@Consumes(MediaType.APPLICATION_JSON)
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
@ -140,6 +173,23 @@ public interface GrafanaAPIProxyService {
|
|||||||
)
|
)
|
||||||
Response getAnnotations(@Context HttpHeaders headers, @Context UriInfo requestUriInfo) throws ClassNotFoundException;
|
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
|
@GET
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
@Path("/alerts/states-for-dashboard")
|
@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.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.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.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 io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.core.exception.MaliciousQueryAttempt;
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
@ -56,9 +58,13 @@ public class GrafanaAPIProxyServiceImpl implements GrafanaAPIProxyService {
|
|||||||
@Override
|
@Override
|
||||||
public Response queryDatasource(JsonObject body, @Context HttpHeaders headers, @Context UriInfo requestUriInfo) {
|
public Response queryDatasource(JsonObject body, @Context HttpHeaders headers, @Context UriInfo requestUriInfo) {
|
||||||
try {
|
try {
|
||||||
|
GrafanaConfiguration configuration = GrafanaConfigurationManager.getInstance().getGrafanaConfiguration();
|
||||||
GrafanaPanelIdentifier panelIdentifier = GrafanaRequestHandlerUtil.getPanelIdentifier(headers);
|
GrafanaPanelIdentifier panelIdentifier = GrafanaRequestHandlerUtil.getPanelIdentifier(headers);
|
||||||
|
boolean queryValidationConfig = configuration.getValidationConfig().getDSQueryValidation();
|
||||||
|
if (queryValidationConfig) {
|
||||||
GrafanaMgtAPIUtils.getGrafanaQueryService().buildSafeQuery(body, panelIdentifier.getDashboardId(),
|
GrafanaMgtAPIUtils.getGrafanaQueryService().buildSafeQuery(body, panelIdentifier.getDashboardId(),
|
||||||
panelIdentifier.getPanelId(), requestUriInfo.getRequestUri());
|
panelIdentifier.getPanelId(), requestUriInfo.getRequestUri());
|
||||||
|
}
|
||||||
return GrafanaRequestHandlerUtil.proxyPassPostRequest(body, requestUriInfo, panelIdentifier.getOrgId());
|
return GrafanaRequestHandlerUtil.proxyPassPostRequest(body, requestUriInfo, panelIdentifier.getOrgId());
|
||||||
} catch (MaliciousQueryAttempt e) {
|
} catch (MaliciousQueryAttempt e) {
|
||||||
return Response.status(Response.Status.BAD_REQUEST).entity(
|
return Response.status(Response.Status.BAD_REQUEST).entity(
|
||||||
@ -83,6 +89,15 @@ public class GrafanaAPIProxyServiceImpl implements GrafanaAPIProxyService {
|
|||||||
return proxyPassPostRequest(body, headers, requestUriInfo);
|
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
|
@GET
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
@Path("/dashboards/uid/{uid}")
|
@Path("/dashboards/uid/{uid}")
|
||||||
@ -91,6 +106,14 @@ public class GrafanaAPIProxyServiceImpl implements GrafanaAPIProxyService {
|
|||||||
return proxyPassGetRequest(headers, requestUriInfo);
|
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
|
@GET
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
@Consumes(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) {
|
public Response getAnnotations(@Context HttpHeaders headers, @Context UriInfo requestUriInfo) {
|
||||||
return proxyPassGetRequest(headers, 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
|
@GET
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
@Path("/alerts/states-for-dashboard")
|
@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.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.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.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.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.GrafanaConstants;
|
||||||
import io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.core.util.GrafanaUtil;
|
import io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.core.util.GrafanaUtil;
|
||||||
@ -120,20 +122,24 @@ public class GrafanaRequestHandlerUtil {
|
|||||||
return path;
|
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);
|
String referer = headers.getHeaderString(GrafanaConstants.REFERER_HEADER);
|
||||||
if (referer == null) {
|
if (referer == null) {
|
||||||
String errMsg = "Request does not contain Referer header";
|
String errMsg = "Request does not contain Referer header";
|
||||||
log.error(errMsg);
|
log.error(errMsg);
|
||||||
throw new RefererNotValid(errMsg);
|
throw new RefererNotValid(errMsg);
|
||||||
}
|
}
|
||||||
|
GrafanaConfiguration configuration = GrafanaConfigurationManager.getInstance().getGrafanaConfiguration();
|
||||||
|
boolean dashboardIntegrationConfig = configuration.getValidationConfig().getDashboardIntegration();
|
||||||
GrafanaPanelIdentifier panelIdentifier = GrafanaUtil.getPanelIdentifierFromReferer(referer);
|
GrafanaPanelIdentifier panelIdentifier = GrafanaUtil.getPanelIdentifierFromReferer(referer);
|
||||||
|
if (!dashboardIntegrationConfig) {
|
||||||
if (panelIdentifier.getDashboardId() == null ||
|
if (panelIdentifier.getDashboardId() == null ||
|
||||||
panelIdentifier.getPanelId() == null || panelIdentifier.getOrgId() == null) {
|
panelIdentifier.getPanelId() == null || panelIdentifier.getOrgId() == null) {
|
||||||
String errMsg = "Referer must contain dashboardId, panelId and orgId";
|
String errMsg = "Referer must contain dashboardId, panelId, and orgId";
|
||||||
log.error(errMsg);
|
log.error(errMsg);
|
||||||
throw new RefererNotValid(errMsg);
|
throw new RefererNotValid(errMsg);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return panelIdentifier;
|
return panelIdentifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -19,6 +19,7 @@
|
|||||||
package io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.core.config;
|
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.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 io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.core.config.xml.bean.User;
|
||||||
|
|
||||||
import javax.xml.bind.annotation.XmlElement;
|
import javax.xml.bind.annotation.XmlElement;
|
||||||
@ -30,6 +31,7 @@ import java.util.List;
|
|||||||
public class GrafanaConfiguration {
|
public class GrafanaConfiguration {
|
||||||
|
|
||||||
private User adminUser;
|
private User adminUser;
|
||||||
|
private ValidationConfig validationConfig;
|
||||||
private List<CacheConfiguration> caches;
|
private List<CacheConfiguration> caches;
|
||||||
|
|
||||||
@XmlElement(name = "AdminUser")
|
@XmlElement(name = "AdminUser")
|
||||||
@ -37,6 +39,15 @@ public class GrafanaConfiguration {
|
|||||||
return adminUser;
|
return adminUser;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@XmlElement(name = "ValidationConfig")
|
||||||
|
public ValidationConfig getValidationConfig() {
|
||||||
|
return validationConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValidationConfig(ValidationConfig validationConfig) {
|
||||||
|
this.validationConfig = validationConfig;
|
||||||
|
}
|
||||||
|
|
||||||
public void setAdminUser(User user) {
|
public void setAdminUser(User user) {
|
||||||
this.adminUser = 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>
|
<Username>admin</Username>
|
||||||
<Password>admin</Password>
|
<Password>admin</Password>
|
||||||
</AdminUser>
|
</AdminUser>
|
||||||
|
<ValidationConfig>
|
||||||
|
<!-- Enable/Disable data source query validation. -->
|
||||||
|
<DSQueryValidation>true</DSQueryValidation>
|
||||||
|
<!-- Enable/Disable dashboard integration. -->
|
||||||
|
<DashboardIntegration>false</DashboardIntegration>
|
||||||
|
</ValidationConfig>
|
||||||
</GrafanaConfiguration>
|
</GrafanaConfiguration>
|
||||||
|
|||||||
@ -32,4 +32,10 @@
|
|||||||
<Username>admin</Username>
|
<Username>admin</Username>
|
||||||
<Password>admin</Password>
|
<Password>admin</Password>
|
||||||
</AdminUser>
|
</AdminUser>
|
||||||
|
<ValidationConfig>
|
||||||
|
<!-- Enable/Disable data source query validation. -->
|
||||||
|
<DSQueryValidation>true</DSQueryValidation>
|
||||||
|
<!-- Enable/Disable dashboard integration. -->
|
||||||
|
<DashboardIntegration>false</DashboardIntegration>
|
||||||
|
</ValidationConfig>
|
||||||
</GrafanaConfiguration>
|
</GrafanaConfiguration>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user