【问题标题】:Grafana-web visual read-only/kiosk mode for integration in enterprise appGrafana-web 可视化只读/kiosk 模式,用于集成到企业应用程序中
【发布时间】:2017-03-24 04:19:13
【问题描述】:

项目中需要将 grafana-web 完全集成到企业应用中。

一些要点是:

  • 不显示 grafana 菜单(仪表板通过 API 读取并集成在应用程序菜单中)
  • 为用户隐藏 Playground 按钮(即使 grafana 提供只读模式,也只能防止保存而不是玩弄设置/数据)
  • 对于某些用户允许编辑模式(添加行、仪表板设置、仪表板保存...)
  • 禁用所有用户的共享
  • 所有这些都是前端的视觉怪癖,安全级别低(恶意用户仍然可以绕过隐藏按钮,这没关系)
  • 创建/删除仪表板是通过由企业应用中的按钮触发的 API 完成的

由于 Grafana 没有这样的东西,我正在考虑将其加载到 iframe 和 XSS 中以隐藏按钮(两个 UI 将从同一个域加载)。

【问题讨论】:

    标签: grafana


    【解决方案1】:

    我完全理解并接受 Torkel 和 Grafana 团队决定在前端不使用只读模式,因为“邪恶”用户可以轻松地在其周围查询后端,因此从安全角度来看,他们是正确的。

    但正如您所见,一些边缘案例/项目需要这样做,即使只是视觉上的怪癖。

    警告:为了确保你明白,这是 grafana-web 的视觉样式,不提供任何安全性,“邪恶”用户仍然可以访问所有内容。

    以下是我的实现方式:

    • 所有用户在 Grafana 中都有编辑权限(按钮仅在前端隐藏)
    • 将 grafana-web 加载到 iframe 中
    • iframe 要么有一个遮罩(也可以移动 iframe 我们的视图或使其完全透明)
    • 在 iframe DOMContentLoaded 处理程序上,我们在 iframe 文档上注册一个 MutationObserver 以在按钮添加到 DOM 时捕获和隐藏按钮,使用 Rafael Weinstein 的惊人的 Mutation Summary 库。
    • 在这个阶段隐藏按钮是否已经渲染,以防 Observer 注册到较晚(这是对 Angular 渲染的竞争条件)
    • 移除遮罩(将 iframe 移动到可见区域,制作 opac ...)

    这是由 DOMContentLoaded 触发的定制器代码:

    // Don't forget to load the mutation-summary.js lib
    
    function iframeLoad (iframe) {
        // Disable this if you want users to have access to playground buttons like:
        // add Rows, edit Panels, dashboard settings ...
        readOnlyMode = true;
    
        // This is the iframe "window"
        var iframe_window = iframe.contentWindow;
    
        // This is the iframe "document" under which the MutationObserver will look for DOM changes
        var iframe_document = iframe.contentDocument;
    
        var queries = [{
            // This is the main menu of grafana
            element: '.navbar-brand-btn' 
        },{ 
            // This is the dashboard selection right of the main menu
            element: '.navbar-page-btn' 
        },{ 
            // This is the share button appearing inside the .dashnav-action-icons, we don't want to allow
            // this to anybody, as it's exposes the real url, thus bypassing this code
            element: 'li[ng-show="::dashboardMeta.canShare"]' 
        },{ 
            // This is the dashboard delete button, under dashboard setting button
            element: 'a[ng-click="deleteDashboard();"]' 
        }];
    
    
        if ( readOnlyMode ) {
            queries.push({ 
                // This is the three vertical dots button to open the row menu/edit
                element: '.dash-row-menu-grip' 
            });
            queries.push({
                // This is the bottom "+ ADD ROW" button
                element: '.add-row-panel-hint'
            });
            queries.push({
                // This is the share button right of the dashboard menu
                element: '.dashnav-action-icons' 
            });
            queries.push({
                // This is the "Panel" menu triggered by clicking the Panel name
                element: '.panel-menu' 
            });
        }
    
    
        var observer;
        observer = new MutationSummary({
            callback: function (changes) {
                changes.forEach(function (change) {
                    change.added.forEach(function (el) {
                        iframe_window.angular.element(el).addClass('ng-hide');
                    });
                });
    
                // Normally we disconnect here to free resources, but on new dashboards
                // the buttons will be re-rendered by Angular, so we keep this to block that behaviour
                //observer.disconnect();
            },
            queries: queries,
            rootNode: iframe_document
        });
    
    
        // Hide the elements if they are already generated before we registred the Observer
        // is a race condition afterall "Angular rendering" vs "registering the Observer"
        queries.forEach( function (el) {
            if ( iframe_window && iframe_window.angular ) {
                iframe_window.angular.element(el.element).addClass('ng-hide');
            }
        });
    
        // Remove the mask or move the iframe into view if needed
        // [YOUR CODE HERE]
    
    
    }
    

    此方法已针对 grafana 版本 4.0.0-1476697633pre1(以及当前在 play.grafana.org 中运行的版本)进行了测试

    【讨论】:

      猜你喜欢
      • 2014-09-29
      • 1970-01-01
      • 2016-11-25
      • 2011-04-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-02-23
      • 1970-01-01
      相关资源
      最近更新 更多