[v8.3.x] Sync security changes (#45067)

* "Release: Updated versions in package to 8.3.5"

* [v8.3.x] Fix for CVE-2022-21702 (#225)

Fix for CVE-2022-21702

* Update yarn.lock for 8.3.5

* resolve conflicts

(cherry picked from commit bb38cfcba4b4f824060ff385d858c63f50b72d74)

* csrf checks for v8.3.5 (#234)

* Fix lint

* Cherry pick e2e test server changes

Co-authored-by: Marcus Efraimsson <marcus.efraimsson@gmail.com>
Co-authored-by: Kevin Minehart <kmineh0151@gmail.com>
Co-authored-by: Serge Zaitsev <serge.zaitsev@grafana.com>
This commit is contained in:
Dimitris Sotirakis
2022-02-08 15:35:38 +01:00
committed by GitHub
co-authored by Marcus Efraimsson Kevin Minehart Serge Zaitsev
parent 667f884db1
commit f42d0b9beb
30 changed files with 252 additions and 92 deletions
+7 -1
View File
@@ -7,7 +7,13 @@ aliases = ["/docs/grafana/latest/http_api/team/"]
# Team API
This API can be used to create/update/delete Teams and to add/remove users to Teams. All actions require that the user has the Admin role for the organization.
This API can be used to manage Teams and Team Memberships.
Access to these API endpoints is restricted as follows:
- All authenticated users are able to view details of teams they are a member of.
- Organization Admins are able to manage all teams and team members.
- If the `editors_can_admin` configuration flag is enabled, Organization Editors are able to view details of all teams and to manage teams that they are Admin members of.
## Team Search With Paging
+2 -4
View File
@@ -1,8 +1,6 @@
{
"npmClient": "yarn",
"useWorkspaces": true,
"packages": [
"packages/*"
],
"version": "8.3.4"
"packages": ["packages/*"],
"version": "8.3.5"
}
+1 -1
View File
@@ -3,7 +3,7 @@
"license": "AGPL-3.0-only",
"private": true,
"name": "grafana",
"version": "8.3.4",
"version": "8.3.5",
"repository": "github:grafana/grafana",
"scripts": {
"api-tests": "jest --notify --watch --config=devenv/e2e-api-tests/jest.js",
+2 -2
View File
@@ -2,7 +2,7 @@
"author": "Grafana Labs",
"license": "Apache-2.0",
"name": "@grafana/data",
"version": "8.3.4",
"version": "8.3.5",
"description": "Grafana Data Library",
"keywords": [
"typescript"
@@ -22,7 +22,7 @@
},
"dependencies": {
"@braintree/sanitize-url": "5.0.2",
"@grafana/schema": "8.3.4",
"@grafana/schema": "8.3.5",
"@types/d3-interpolate": "^1.4.0",
"d3-interpolate": "1.4.0",
"date-fns": "2.21.3",
+1 -1
View File
@@ -2,7 +2,7 @@
"author": "Grafana Labs",
"license": "Apache-2.0",
"name": "@grafana/e2e-selectors",
"version": "8.3.4",
"version": "8.3.5",
"description": "Grafana End-to-End Test Selectors Library",
"keywords": [
"cli",
+2 -2
View File
@@ -2,7 +2,7 @@
"author": "Grafana Labs",
"license": "Apache-2.0",
"name": "@grafana/e2e",
"version": "8.3.4",
"version": "8.3.5",
"description": "Grafana End-to-End Test Library",
"keywords": [
"cli",
@@ -49,7 +49,7 @@
"@babel/core": "7.14.6",
"@babel/preset-env": "7.14.7",
"@cypress/webpack-preprocessor": "5.9.1",
"@grafana/e2e-selectors": "8.3.4",
"@grafana/e2e-selectors": "8.3.5",
"@grafana/tsconfig": "^1.0.0-rc1",
"@mochajs/json-file-reporter": "^1.2.0",
"babel-loader": "8.2.2",
+4 -4
View File
@@ -2,7 +2,7 @@
"author": "Grafana Labs",
"license": "Apache-2.0",
"name": "@grafana/runtime",
"version": "8.3.4",
"version": "8.3.5",
"description": "Grafana Runtime Library",
"keywords": [
"grafana",
@@ -23,9 +23,9 @@
},
"dependencies": {
"@emotion/css": "11.1.3",
"@grafana/data": "8.3.4",
"@grafana/e2e-selectors": "8.3.4",
"@grafana/ui": "8.3.4",
"@grafana/data": "8.3.5",
"@grafana/e2e-selectors": "8.3.5",
"@grafana/ui": "8.3.5",
"@sentry/browser": "5.25.0",
"history": "4.10.1",
"lodash": "4.17.21",
+1 -1
View File
@@ -2,7 +2,7 @@
"author": "Grafana Labs",
"license": "Apache-2.0",
"name": "@grafana/schema",
"version": "8.3.4",
"version": "8.3.5",
"description": "Grafana Schema Library",
"keywords": [
"typescript"
+3 -3
View File
@@ -2,7 +2,7 @@
"author": "Grafana Labs",
"license": "Apache-2.0",
"name": "@grafana/toolkit",
"version": "8.3.4",
"version": "8.3.5",
"description": "Grafana Toolkit",
"keywords": [
"grafana",
@@ -28,10 +28,10 @@
"dependencies": {
"@babel/core": "7.13.14",
"@babel/preset-env": "7.13.12",
"@grafana/data": "8.3.4",
"@grafana/data": "8.3.5",
"@grafana/eslint-config": "2.5.1",
"@grafana/tsconfig": "^1.0.0-rc1",
"@grafana/ui": "8.3.4",
"@grafana/ui": "8.3.5",
"@jest/core": "26.6.3",
"@rushstack/eslint-patch": "1.0.6",
"@types/command-exists": "^1.2.0",
+4 -4
View File
@@ -2,7 +2,7 @@
"author": "Grafana Labs",
"license": "Apache-2.0",
"name": "@grafana/ui",
"version": "8.3.4",
"version": "8.3.5",
"description": "Grafana Components Library",
"keywords": [
"grafana",
@@ -33,9 +33,9 @@
"@emotion/css": "11.1.3",
"@emotion/react": "11.1.5",
"@grafana/aws-sdk": "0.0.3",
"@grafana/data": "8.3.4",
"@grafana/e2e-selectors": "8.3.4",
"@grafana/schema": "8.3.4",
"@grafana/data": "8.3.5",
"@grafana/e2e-selectors": "8.3.5",
"@grafana/schema": "8.3.5",
"@grafana/slate-react": "0.22.10-grafana",
"@monaco-editor/react": "4.2.2",
"@popperjs/core": "2.5.4",
+3 -3
View File
@@ -1,6 +1,6 @@
{
"name": "@jaegertracing/jaeger-ui-components",
"version": "8.3.4",
"version": "8.3.5",
"main": "src/index.ts",
"types": "src/index.ts",
"license": "Apache-2.0",
@@ -30,8 +30,8 @@
"dependencies": {
"@emotion/css": "11.1.3",
"@emotion/react": "11.1.5",
"@grafana/data": "8.3.4",
"@grafana/ui": "8.3.4",
"@grafana/data": "8.3.5",
"@grafana/ui": "8.3.5",
"chance": "^1.0.10",
"classnames": "^2.2.5",
"combokeys": "^3.0.0",
+1 -1
View File
@@ -29,7 +29,7 @@ func (hs *HTTPServer) registerRoutes() {
reqEditorRole := middleware.ReqEditorRole
reqOrgAdmin := middleware.ReqOrgAdmin
reqOrgAdminFolderAdminOrTeamAdmin := middleware.OrgAdminFolderAdminOrTeamAdmin
reqCanAccessTeams := middleware.AdminOrFeatureEnabled(hs.Cfg.EditorsCanAdmin)
reqCanAccessTeams := middleware.AdminOrEditorAndFeatureEnabled(hs.Cfg.EditorsCanAdmin)
reqSnapshotPublicModeOrSignedIn := middleware.SnapshotPublicModeOrSignedIn(hs.Cfg)
redirectFromLegacyPanelEditURL := middleware.RedirectFromLegacyPanelEditURL(hs.Cfg)
authorize := acmiddleware.Middleware(hs.AccessControl)
+1
View File
@@ -422,6 +422,7 @@ func (hs *HTTPServer) addMiddlewaresAndStaticRoutes() {
}
m.Use(middleware.Recovery(hs.Cfg))
m.UseMiddleware(middleware.CSRF(hs.Cfg.LoginCookieName))
hs.mapStatic(m, hs.Cfg.StaticRootPath, "build", "public/build")
hs.mapStatic(m, hs.Cfg.StaticRootPath, "", "public")
+1
View File
@@ -54,6 +54,7 @@ func (t *handleResponseTransport) RoundTrip(req *http.Request) (*http.Response,
return nil, err
}
res.Header.Del("Set-Cookie")
proxyutil.SetProxyResponseHeaders(res.Header)
return res, nil
}
+14
View File
@@ -663,6 +663,20 @@ func TestDataSourceProxy_requestHandling(t *testing.T) {
assert.Equal(t, "important_cookie=important_value", proxy.ctx.Resp.Header().Get("Set-Cookie"))
})
t.Run("When response should set Content-Security-Policy header", func(t *testing.T) {
ctx, ds := setUp(t)
var routes []*plugins.Route
secretsService := secretsManager.SetupTestService(t, fakes.NewFakeSecretsStore())
dsService := datasources.ProvideService(bus.New(), nil, secretsService)
proxy, err := NewDataSourceProxy(ds, routes, ctx, "/render", &setting.Cfg{}, httpClientProvider, &oauthtoken.Service{}, dsService)
require.NoError(t, err)
proxy.HandleRequest()
require.NoError(t, writeErr)
assert.Equal(t, "sandbox", proxy.ctx.Resp.Header().Get("Content-Security-Policy"))
})
t.Run("Data source returns status code 401", func(t *testing.T) {
ctx, ds := setUp(t, setUpCfg{
writeCb: func(w http.ResponseWriter, r *http.Request) {
+7 -1
View File
@@ -83,5 +83,11 @@ func NewApiPluginProxy(ctx *models.ReqContext, proxyPath string, route *plugins.
}
}
return &httputil.ReverseProxy{Director: director}
return &httputil.ReverseProxy{Director: director, ModifyResponse: modifyResponse}
}
func modifyResponse(resp *http.Response) error {
proxyutil.SetProxyResponseHeaders(resp.Header)
return nil
}
+37
View File
@@ -4,6 +4,7 @@ import (
"context"
"io/ioutil"
"net/http"
"net/http/httptest"
"testing"
"github.com/grafana/grafana/pkg/bus"
@@ -13,6 +14,7 @@ import (
"github.com/grafana/grafana/pkg/services/secrets/fakes"
secretsManager "github.com/grafana/grafana/pkg/services/secrets/manager"
"github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/web"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"gopkg.in/macaron.v1"
@@ -245,6 +247,41 @@ func TestPluginProxy(t *testing.T) {
require.NoError(t, err)
require.Equal(t, `{ "url": "https://dynamic.grafana.com", "secret": "123" }`, string(content))
})
t.Run("When proxying a request should set expected response headers", func(t *testing.T) {
requestHandled := false
backendServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(200)
_, _ = w.Write([]byte("I am the backend"))
requestHandled = true
}))
t.Cleanup(backendServer.Close)
responseWriter := web.NewResponseWriter("GET", httptest.NewRecorder())
route := &plugins.Route{
Path: "/",
URL: backendServer.URL,
}
ctx := &models.ReqContext{
SignedInUser: &models.SignedInUser{},
Context: &web.Context{
Req: httptest.NewRequest("GET", "/", nil),
Resp: responseWriter,
},
}
proxy := NewApiPluginProxy(ctx, "", route, "", &setting.Cfg{}, secretsService)
proxy.ServeHTTP(ctx.Resp, ctx.Req)
for {
if requestHandled {
break
}
}
require.Equal(t, "sandbox", ctx.Resp.Header().Get("Content-Security-Policy"))
})
}
// getPluginProxiedRequest is a helper for easier setup of tests based on global config and ReqContext.
+24 -7
View File
@@ -2,6 +2,8 @@ package api
import (
"errors"
"net/http"
"strconv"
"github.com/grafana/grafana/pkg/api/dtos"
"github.com/grafana/grafana/pkg/api/response"
@@ -10,6 +12,7 @@ import (
"github.com/grafana/grafana/pkg/services/sqlstore"
"github.com/grafana/grafana/pkg/services/teamguardian"
"github.com/grafana/grafana/pkg/util"
"github.com/grafana/grafana/pkg/web"
)
// POST /api/teams
@@ -95,16 +98,11 @@ func (hs *HTTPServer) SearchTeams(c *models.ReqContext) response.Response {
page = 1
}
var userIdFilter int64
if hs.Cfg.EditorsCanAdmin && c.OrgRole != models.ROLE_ADMIN {
userIdFilter = c.SignedInUser.UserId
}
query := models.SearchTeamsQuery{
OrgId: c.OrgId,
Query: c.Query("query"),
Name: c.Query("name"),
UserIdFilter: userIdFilter,
UserIdFilter: userFilter(hs.Cfg.EditorsCanAdmin, c),
Page: page,
Limit: perPage,
SignedInUser: c.SignedInUser,
@@ -125,13 +123,32 @@ func (hs *HTTPServer) SearchTeams(c *models.ReqContext) response.Response {
return response.JSON(200, query.Result)
}
// UserFilter returns the user ID used in a filter when querying a team
// 1. If the user is a viewer or editor, this will return the user's ID.
// 2. If EditorsCanAdmin is enabled and the user is an editor, this will return models.FilterIgnoreUser (0)
// 3. If the user is an admin, this will return models.FilterIgnoreUser (0)
func userFilter(editorsCanAdmin bool, c *models.ReqContext) int64 {
userIdFilter := c.SignedInUser.UserId
if (editorsCanAdmin && c.OrgRole == models.ROLE_EDITOR) || c.OrgRole == models.ROLE_ADMIN {
userIdFilter = models.FilterIgnoreUser
}
return userIdFilter
}
// GET /api/teams/:teamId
func (hs *HTTPServer) GetTeamByID(c *models.ReqContext) response.Response {
teamId, err := strconv.ParseInt(web.Params(c.Req)[":teamId"], 10, 64)
if err != nil {
return response.Error(http.StatusBadRequest, "teamId is invalid", err)
}
query := models.GetTeamByIdQuery{
OrgId: c.OrgId,
Id: c.ParamsInt64(":teamId"),
Id: teamId,
SignedInUser: c.SignedInUser,
HiddenUsers: hs.Cfg.HiddenUsers,
UserIdFilter: userFilter(hs.Cfg.EditorsCanAdmin, c),
}
if err := bus.DispatchCtx(c.Req.Context(), &query); err != nil {
+4
View File
@@ -16,6 +16,10 @@ import (
func (hs *HTTPServer) GetTeamMembers(c *models.ReqContext) response.Response {
query := models.GetTeamMembersQuery{OrgId: c.OrgId, TeamId: c.ParamsInt64(":teamId")}
if err := teamguardian.CanAdmin(hs.Bus, query.OrgId, query.TeamId, c.SignedInUser); err != nil {
return response.Error(403, "Not allowed to list team members", err)
}
if err := bus.DispatchCtx(c.Req.Context(), &query); err != nil {
return response.Error(500, "Failed to get Team Members", err)
}
+14 -4
View File
@@ -2,8 +2,10 @@ package macaron
import (
"encoding/json"
"errors"
"fmt"
"io"
"mime"
"net/http"
"reflect"
)
@@ -11,9 +13,16 @@ import (
// Bind deserializes JSON payload from the request
func Bind(req *http.Request, v interface{}) error {
if req.Body != nil {
defer req.Body.Close()
err := json.NewDecoder(req.Body).Decode(v)
if err != nil && err != io.EOF {
m, _, err := mime.ParseMediaType(req.Header.Get("Content-type"))
if err != nil {
return err
}
if m != "application/json" {
return errors.New("bad content type")
}
defer func() { _ = req.Body.Close() }()
err = json.NewDecoder(req.Body).Decode(v)
if err != nil && !errors.Is(err, io.EOF) {
return err
}
}
@@ -29,7 +38,7 @@ func validate(obj interface{}) error {
if validator, ok := obj.(Validator); ok {
return validator.Validate()
}
// Otherwise, use relfection to match `binding:"Required"` struct field tags.
// Otherwise, use reflection to match `binding:"Required"` struct field tags.
// Resolve all pointers and interfaces, until we get a concrete type.
t := reflect.TypeOf(obj)
v := reflect.ValueOf(obj)
@@ -69,6 +78,7 @@ func validate(obj interface{}) error {
return err
}
}
default: // ignore
}
return nil
}
+8 -6
View File
@@ -128,20 +128,22 @@ func Auth(options *AuthOptions) web.Handler {
}
}
// AdminOrFeatureEnabled creates a middleware that allows access
// if the signed in user is either an Org Admin or if the
// feature flag is enabled.
// AdminOrEditorAndFeatureEnabled creates a middleware that allows
// access if the signed in user is either an Org Admin or if they
// are an Org Editor and the feature flag is enabled.
// Intended for when feature flags open up access to APIs that
// are otherwise only available to admins.
func AdminOrFeatureEnabled(enabled bool) web.Handler {
func AdminOrEditorAndFeatureEnabled(enabled bool) web.Handler {
return func(c *models.ReqContext) {
if c.OrgRole == models.ROLE_ADMIN {
return
}
if !enabled {
accessForbidden(c)
if c.OrgRole == models.ROLE_EDITOR && enabled {
return
}
accessForbidden(c)
}
}
+39
View File
@@ -0,0 +1,39 @@
package middleware
import (
"errors"
"net/http"
"net/url"
"strings"
)
func CSRF(loginCookieName string) func(http.Handler) http.Handler {
// As per RFC 7231/4.2.2 these methods are idempotent:
// (GET is excluded because it may have side effects in some APIs)
safeMethods := []string{"HEAD", "OPTIONS", "TRACE"}
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// If request has no login cookie - skip CSRF checks
if _, err := r.Cookie(loginCookieName); errors.Is(err, http.ErrNoCookie) {
next.ServeHTTP(w, r)
return
}
// Skip CSRF checks for "safe" methods
for _, method := range safeMethods {
if r.Method == method {
next.ServeHTTP(w, r)
return
}
}
// Otherwise - verify that Origin matches the server origin
host := strings.Split(r.Host, ":")[0]
origin, err := url.Parse(r.Header.Get("Origin"))
if err != nil || (origin.String() != "" && origin.Hostname() != host) {
http.Error(w, "origin not allowed", http.StatusForbidden)
return
}
next.ServeHTTP(w, r)
})
}
}
+4
View File
@@ -55,8 +55,12 @@ type GetTeamByIdQuery struct {
SignedInUser *SignedInUser
HiddenUsers map[string]struct{}
Result *TeamDTO
UserIdFilter int64
}
// FilterIgnoreUser is used in a get / search teams query when the caller does not want to filter teams by user ID / membership
const FilterIgnoreUser int64 = 0
type GetTeamsByUserQuery struct {
OrgId int64
UserId int64 `json:"userId"`
+2
View File
@@ -374,6 +374,8 @@ func flushStream(plugin backendplugin.Plugin, stream callResourceClientResponseS
w.Header().Add(k, v)
}
}
proxyutil.SetProxyResponseHeaders(w.Header())
w.WriteHeader(resp.Status)
}
+8 -1
View File
@@ -447,7 +447,8 @@ func TestPluginManager_lifecycle_managed(t *testing.T) {
ctx.pluginClient.CallResourceHandlerFunc = func(ctx context.Context,
req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error {
return sender.Send(&backend.CallResourceResponse{
Status: http.StatusOK,
Status: http.StatusOK,
Headers: map[string][]string{},
})
}
@@ -456,7 +457,13 @@ func TestPluginManager_lifecycle_managed(t *testing.T) {
w := httptest.NewRecorder()
err = ctx.manager.callResourceInternal(w, req, backend.PluginContext{PluginID: testPluginID})
require.NoError(t, err)
for {
if w.Flushed {
break
}
}
require.Equal(t, http.StatusOK, w.Code)
require.Equal(t, "sandbox", w.Header().Get("Content-Security-Policy"))
})
})
})
+27 -22
View File
@@ -52,18 +52,6 @@ func getTeamMemberCount(filteredUsers []string) string {
return "(SELECT COUNT(*) FROM team_member WHERE team_member.team_id = team.id) AS member_count "
}
func getTeamSearchSQLBase(filteredUsers []string) string {
return `SELECT
team.id AS id,
team.org_id,
team.name AS name,
team.email AS email,
team_member.permission, ` +
getTeamMemberCount(filteredUsers) +
` FROM team AS team
INNER JOIN team_member ON team.id = team_member.team_id AND team_member.user_id = ? `
}
func getTeamSelectSQLBase(filteredUsers []string) string {
return `SELECT
team.id as id,
@@ -182,17 +170,15 @@ func SearchTeams(ctx context.Context, query *models.SearchTeamsQuery) error {
params := make([]interface{}, 0)
filteredUsers := getFilteredUsers(query.SignedInUser, query.HiddenUsers)
if query.UserIdFilter > 0 {
sql.WriteString(getTeamSearchSQLBase(filteredUsers))
for _, user := range filteredUsers {
params = append(params, user)
}
sql.WriteString(getTeamSelectSQLBase(filteredUsers))
for _, user := range filteredUsers {
params = append(params, user)
}
if query.UserIdFilter != models.FilterIgnoreUser {
sql.WriteString(` INNER JOIN team_member ON team.id = team_member.team_id AND team_member.user_id = ?`)
params = append(params, query.UserIdFilter)
} else {
sql.WriteString(getTeamSelectSQLBase(filteredUsers))
for _, user := range filteredUsers {
params = append(params, user)
}
}
sql.WriteString(` WHERE team.org_id = ?`)
@@ -221,6 +207,8 @@ func SearchTeams(ctx context.Context, query *models.SearchTeamsQuery) error {
team := models.Team{}
countSess := x.Table("team")
countSess.Where("team.org_id=?", query.OrgId)
if query.Query != "" {
countSess.Where(`name `+dialect.LikeStr()+` ?`, queryWithWildcards)
}
@@ -229,6 +217,18 @@ func SearchTeams(ctx context.Context, query *models.SearchTeamsQuery) error {
countSess.Where("name=?", query.Name)
}
// If we're not retrieving all results, then only search for teams that this user has access to
if query.UserIdFilter != models.FilterIgnoreUser {
countSess.
Where(`
team.id IN (
SELECT
team_id
FROM team_member
WHERE team_member.user_id = ?
)`, query.UserIdFilter)
}
count, err := countSess.Count(&team)
query.Result.TotalCount = count
@@ -245,6 +245,11 @@ func GetTeamById(ctx context.Context, query *models.GetTeamByIdQuery) error {
params = append(params, user)
}
if query.UserIdFilter != models.FilterIgnoreUser {
sql.WriteString(` INNER JOIN team_member ON team.id = team_member.team_id AND team_member.user_id = ?`)
params = append(params, query.UserIdFilter)
}
sql.WriteString(` WHERE team.org_id = ? and team.id = ?`)
params = append(params, query.OrgId, query.Id)
+6
View File
@@ -42,3 +42,9 @@ func ClearCookieHeader(req *http.Request, keepCookiesNames []string) {
req.AddCookie(c)
}
}
// SetProxyResponseHeaders sets proxy response headers.
// Sets Content-Security-Policy: sandbox
func SetProxyResponseHeaders(header http.Header) {
header.Set("Content-Security-Policy", "sandbox")
}
@@ -1,6 +1,6 @@
{
"name": "@grafana-plugins/input-datasource",
"version": "8.3.4",
"version": "8.3.5",
"description": "Input Datasource",
"private": true,
"repository": {
@@ -24,9 +24,9 @@
"webpack": "5.58.1"
},
"dependencies": {
"@grafana/data": "8.3.4",
"@grafana/toolkit": "8.3.4",
"@grafana/ui": "8.3.4",
"@grafana/data": "8.3.5",
"@grafana/toolkit": "8.3.5",
"@grafana/ui": "8.3.5",
"jquery": "3.5.1",
"react": "17.0.1",
"react-dom": "17.0.1",
+1
View File
@@ -465,6 +465,7 @@ def release_pipelines(ver_mode='release', trigger=None, environment=None):
return pipelines
def get_e2e_suffix():
if not disable_tests:
return '-e2e'
+20 -20
View File
@@ -2329,9 +2329,9 @@ __metadata:
version: 0.0.0-use.local
resolution: "@grafana-plugins/input-datasource@workspace:plugins-bundled/internal/input-datasource"
dependencies:
"@grafana/data": 8.3.4
"@grafana/toolkit": 8.3.4
"@grafana/ui": 8.3.4
"@grafana/data": 8.3.5
"@grafana/toolkit": 8.3.5
"@grafana/ui": 8.3.5
"@types/jest": 26.0.15
"@types/lodash": 4.14.149
"@types/react": 17.0.30
@@ -2372,12 +2372,12 @@ __metadata:
languageName: node
linkType: hard
"@grafana/data@8.3.4, @grafana/data@workspace:*, @grafana/data@workspace:packages/grafana-data":
"@grafana/data@8.3.5, @grafana/data@workspace:*, @grafana/data@workspace:packages/grafana-data":
version: 0.0.0-use.local
resolution: "@grafana/data@workspace:packages/grafana-data"
dependencies:
"@braintree/sanitize-url": 5.0.2
"@grafana/schema": 8.3.4
"@grafana/schema": 8.3.5
"@grafana/tsconfig": ^1.0.0-rc1
"@rollup/plugin-commonjs": 21.0.1
"@rollup/plugin-json": 4.1.0
@@ -2432,7 +2432,7 @@ __metadata:
languageName: unknown
linkType: soft
"@grafana/e2e-selectors@8.3.4, @grafana/e2e-selectors@workspace:*, @grafana/e2e-selectors@workspace:packages/grafana-e2e-selectors":
"@grafana/e2e-selectors@8.3.5, @grafana/e2e-selectors@workspace:*, @grafana/e2e-selectors@workspace:packages/grafana-e2e-selectors":
version: 0.0.0-use.local
resolution: "@grafana/e2e-selectors@workspace:packages/grafana-e2e-selectors"
dependencies:
@@ -2464,7 +2464,7 @@ __metadata:
"@babel/core": 7.14.6
"@babel/preset-env": 7.14.7
"@cypress/webpack-preprocessor": 5.9.1
"@grafana/e2e-selectors": 8.3.4
"@grafana/e2e-selectors": 8.3.5
"@grafana/tsconfig": ^1.0.0-rc1
"@mochajs/json-file-reporter": ^1.2.0
"@rollup/plugin-commonjs": 21.0.1
@@ -2522,10 +2522,10 @@ __metadata:
resolution: "@grafana/runtime@workspace:packages/grafana-runtime"
dependencies:
"@emotion/css": 11.1.3
"@grafana/data": 8.3.4
"@grafana/e2e-selectors": 8.3.4
"@grafana/data": 8.3.5
"@grafana/e2e-selectors": 8.3.5
"@grafana/tsconfig": ^1.0.0-rc1
"@grafana/ui": 8.3.4
"@grafana/ui": 8.3.5
"@rollup/plugin-commonjs": 21.0.1
"@rollup/plugin-node-resolve": 13.0.6
"@sentry/browser": 5.25.0
@@ -2557,7 +2557,7 @@ __metadata:
languageName: unknown
linkType: soft
"@grafana/schema@8.3.4, @grafana/schema@workspace:*, @grafana/schema@workspace:packages/grafana-schema":
"@grafana/schema@8.3.5, @grafana/schema@workspace:*, @grafana/schema@workspace:packages/grafana-schema":
version: 0.0.0-use.local
resolution: "@grafana/schema@workspace:packages/grafana-schema"
dependencies:
@@ -2607,16 +2607,16 @@ __metadata:
languageName: node
linkType: hard
"@grafana/toolkit@8.3.4, @grafana/toolkit@workspace:*, @grafana/toolkit@workspace:packages/grafana-toolkit":
"@grafana/toolkit@8.3.5, @grafana/toolkit@workspace:*, @grafana/toolkit@workspace:packages/grafana-toolkit":
version: 0.0.0-use.local
resolution: "@grafana/toolkit@workspace:packages/grafana-toolkit"
dependencies:
"@babel/core": 7.13.14
"@babel/preset-env": 7.13.12
"@grafana/data": 8.3.4
"@grafana/data": 8.3.5
"@grafana/eslint-config": 2.5.1
"@grafana/tsconfig": ^1.0.0-rc1
"@grafana/ui": 8.3.4
"@grafana/ui": 8.3.5
"@jest/core": 26.6.3
"@rushstack/eslint-patch": 1.0.6
"@types/command-exists": ^1.2.0
@@ -2700,7 +2700,7 @@ __metadata:
languageName: node
linkType: hard
"@grafana/ui@8.3.4, @grafana/ui@workspace:*, @grafana/ui@workspace:packages/grafana-ui":
"@grafana/ui@8.3.5, @grafana/ui@workspace:*, @grafana/ui@workspace:packages/grafana-ui":
version: 0.0.0-use.local
resolution: "@grafana/ui@workspace:packages/grafana-ui"
dependencies:
@@ -2708,9 +2708,9 @@ __metadata:
"@emotion/css": 11.1.3
"@emotion/react": 11.1.5
"@grafana/aws-sdk": 0.0.3
"@grafana/data": 8.3.4
"@grafana/e2e-selectors": 8.3.4
"@grafana/schema": 8.3.4
"@grafana/data": 8.3.5
"@grafana/e2e-selectors": 8.3.5
"@grafana/schema": 8.3.5
"@grafana/slate-react": 0.22.10-grafana
"@grafana/tsconfig": ^1.0.0-rc1
"@mdx-js/react": 1.6.22
@@ -2923,9 +2923,9 @@ __metadata:
dependencies:
"@emotion/css": 11.1.3
"@emotion/react": 11.1.5
"@grafana/data": 8.3.4
"@grafana/data": 8.3.5
"@grafana/tsconfig": ^1.0.0-rc1
"@grafana/ui": 8.3.4
"@grafana/ui": 8.3.5
"@types/classnames": ^2.2.7
"@types/deep-freeze": ^0.1.1
"@types/grafana__slate-react": "npm:@types/slate-react@0.22.5"