I have create api key with admin role. When I try to create dashboard with dashboard api it gives 403

Created api key with the admin role.

API - api/dashboards/db

RESPONSE - 403 {
“message”: “Access denied to save dashboard”
}

EXPECTED RESPONSE: Dashboard should be created.

Hi!
What version of Grafana do you use?
Could you provide JSON body?

@paveldanilin

Please find required details below. It used to work properly when I ran grafana from source for development.

Grafana version - Grafana v6.6.0-pre
Dashboard JSON

{
  "dashboard": {
    "title": "Dapp",
    "style": "dark",
    "editable": true,
    "panels": [
      {
        "content": "<div style=\"display: flex;-webkit-box-align: center;align-items: center;margin-bottom: 3rem;\"><a href='www.dappquery.com' title='Dapp' target='_blank'><img src=\"https://mintbase.io/logos/logo_white_300_300.png\" style=\"width: 40px;height: 40px;margin-right: 0.8rem;\"><a/> <div style=\"display:block;font-family: Lato, sans-serif;letter-spacing: 1px;color: rgb(255, 255, 255);font-size: 2em;font-weight: 100;\">Dapp</div></div>",
        "datasource": null,
        "gridPos": {
          "h": 2,
          "w": 24,
          "y": 3,
          "x": 1
        },
        "mode": "html",
        "options": {},
        "timeFrom": null,
        "timeShift": null,
        "title": "",
        "type": "text",
        "transparent": true
      },
      {
        "datasource": "dapp_1_production",
        "cacheTimeout": null,
        "colorBackground": false,
        "colorPostfix": false,
        "colorPrefix": false,
        "colorValue": true,
        "colors": [
          "#56A64B",
          "rgba(237, 129, 40, 0.89)",
          "#d44a3a"
        ],
        "description": "",
        "format": "none",
        "gauge": {
          "maxValue": 100,
          "minValue": 0,
          "show": false,
          "thresholdLabels": false,
          "thresholdMarkers": true
        },
        "gridPos": {
          "h": 6,
          "w": 6,
          "x": 1,
          "y": 10
        },
        "interval": null,
        "links": [],
        "mappingType": 1,
        "mappingTypes": [
          {
            "name": "value to text",
            "value": 1
          },
          {
            "name": "range to text",
            "value": 2
          }
        ],
        "maxDataPoints": 100,
        "nullPointMode": "connected",
        "nullText": null,
        "options": {},
        "postfix": " <br/><br/><br/>  Total Store Launche till today",
        "postfixFontSize": "30%",
        "prefix": "TOTAL STORE LAUNCHE <br/><br/><br/>",
        "prefixFontSize": "50%",
        "rangeMaps": [
          {
            "from": "null",
            "text": "N/A",
            "to": "null"
          }
        ],
        "sparkline": {
          "fillColor": "rgba(31, 118, 189, 0.18)",
          "full": true,
          "lineColor": "rgb(31, 120, 193)",
          "show": false,
          "ymax": null,
          "ymin": null
        },
        "tableColumn": "",
        "targets": [
          {
            "format": "table",
            "group": [
              {
                "params": [
                  "$__interval",
                  "none"
                ],
                "type": "time"
              }
            ],
            "metricColumn": "none",
            "rawQuery": true,
            "rawSql": "SELECT\n  count(*) as \"count\"\nFROM store_launches",
            "refId": "A",
            "select": [
              [
                {
                  "params": [
                    "value"
                  ],
                  "type": "column"
                }
              ]
            ],
            "table": "policy_updates",
            "timeColumn": "created_at",
            "timeColumnType": "timestamptz",
            "where": []
          }
        ],
        "thresholds": "",
        "timeFrom": null,
        "timeShift": null,
        "title": "",
        "transparent": true,
        "type": "singlestat",
        "valueFontSize": "100%",
        "valueMaps": [],
        "valueName": "total"
      },
      {
        "datasource": "dapp_1_production",
        "aliasColors": {},
        "bars": false,
        "dashLength": 10,
        "dashes": false,
        "description": "",
        "fill": 2,
        "fillGradient": 10,
        "gridPos": {
          "h": 12,
          "w": 22,
          "x": 1,
          "y": 23
        },
        "hiddenSeries": false,
        "hideTimeOverride": false,
        "interval": "",
        "legend": {
          "alignAsTable": false,
          "avg": false,
          "current": false,
          "max": false,
          "min": false,
          "rightSide": true,
          "show": false,
          "total": false,
          "values": false
        },
        "lines": true,
        "linewidth": 5,
        "nullPointMode": "null",
        "options": {
          "dataLinks": []
        },
        "percentage": false,
        "pointradius": 2,
        "points": false,
        "renderer": "flot",
        "seriesOverrides": [],
        "spaceLength": 10,
        "stack": false,
        "steppedLine": false,
        "targets": [
          {
            "format": "time_series",
            "group": [],
            "metricColumn": "none",
            "rawQuery": true,
            "rawSql": "SELECT\n  CAST(timestamp as integer) AS \"time\",\n  ROW_NUMBER() OVER (order by timestamp) AS \"value\"\nFROM store_launches\nORDER BY 1",
            "refId": "A",
            "select": [],
            "table": "transfers",
            "timeColumn": "\"timestamp\"",
            "timeColumnType": "float8",
            "where": [
              {
                "name": "$__unixEpochFilter",
                "params": [],
                "type": "macro"
              }
            ]
          }
        ],
        "thresholds": [],
        "timeFrom": null,
        "timeRegions": [],
        "timeShift": null,
        "title": "TOTAL STORE LAUNCHE CHANGING OVER TIME",
        "tooltip": {
          "shared": true,
          "sort": 0,
          "value_type": "individual"
        },
        "transparent": true,
        "type": "graph",
        "xaxis": {
          "buckets": null,
          "mode": "time",
          "name": null,
          "show": true,
          "values": []
        },
        "yaxes": [
          {
            "format": "short",
            "label": "Store Launche",
            "logBase": 1,
            "max": null,
            "min": null,
            "show": true
          },
          {
            "format": "short",
            "label": "",
            "logBase": 1,
            "max": null,
            "min": null,
            "show": true
          }
        ],
        "yaxis": {
          "align": false,
          "alignLevel": null
        }
      },
      {
        "content": "<div style=\"padding-top:20px\">\n        <a href=\"https://dappquery.com\" target=\"_blank\" class=\"btn pull-right\" title=\"Powered by Dappquery!\" style=\"text-decoration:none;border-radius:10px;font-size: 15px;color: #fff;font-weight: 100;padding: 30px 20px;margin-right:-160px;\">Powered by &nbsp;\n          <img src='https://duhy7tdvrc6v6.cloudfront.net/assets/img/dappquery_logo.png' alt='Dappquery logo' width=20%/>\n        </a>\n</div>",
        "datasource": null,
        "gridPos": {
          "h": 3,
          "w": 24,
          "y": 27,
          "x": 1
        },
        "mode": "html",
        "options": {},
        "timeFrom": null,
        "timeShift": null,
        "title": "",
        "type": "text",
        "transparent": true
      }
    ],
    "time": {
      "from": "now-2y",
      "to": "now"
    }
  }
}

I managed to reproduce the error only when I use API key with the Viewer role.
But it works fine for Admin/Editor role.
Is it possible to recreate the API key again and change it to your client?
I think you are not able to pass this guard:

func (g *dashboardGuardianImpl) CanSave() (bool, error) {
return g.HasPermission(m.PERMISSION_EDIT)
}

The first check inside HasPermission is to ensure that you are Admin, if you get the error more likely you are not Admin.

@paveldanilin

I can reconfirm that role is admin for the keys. Attached screenshot.

Are there any errors in log?
Could you turn on the debug mode of logging and provide a log during the request?

@paveldanilin
Below are the logs.

t=2020-06-02T06:59:38+0000 lvl=dbug msg="User denied access to execute action" logger=dashboard.permissions userId=0 orgId=1 uname= dashId=0 action=Edit
t=2020-06-02T06:59:38+0000 lvl=eror msg="Access denied to save dashboard" logger=context userId=0 orgId=1 uname= error="Access denied to save dashboard"
t=2020-06-02T06:59:38+0000 lvl=info msg="Request Completed" logger=context userId=0 orgId=1 uname= method=POST path=/api/dashboards/db status=403 remote_addr=172.31.81.138 time_ms=14 size=45 referer=

This is now fixed. It was issue with nginx setup. It was not forwarding headers.

Thanks for your time @paveldanilin

1 Like