From 3b9f0e6ef2cb2c37db20ff94bbdeb10e2c2008bc Mon Sep 17 00:00:00 2001 From: Marcus Efraimsson Date: Tue, 5 Mar 2019 18:03:07 +0100 Subject: [PATCH 1/9] fix allow anonymous initial bind for ldap search --- pkg/login/ldap.go | 13 ++++++- pkg/login/ldap_test.go | 84 ++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 93 insertions(+), 4 deletions(-) diff --git a/pkg/login/ldap.go b/pkg/login/ldap.go index c15cb865bd3..8bb331b7e59 100644 --- a/pkg/login/ldap.go +++ b/pkg/login/ldap.go @@ -18,6 +18,7 @@ import ( type ILdapConn interface { Bind(username, password string) error + UnauthenticatedBind(username string) error Search(*ldap.SearchRequest) (*ldap.SearchResult, error) StartTLS(*tls.Config) error Close() @@ -259,7 +260,17 @@ func (a *ldapAuther) initialBind(username, userPassword string) error { bindPath = fmt.Sprintf(a.server.BindDN, username) } - if err := a.conn.Bind(bindPath, userPassword); err != nil { + bindFn := func() error { + return a.conn.Bind(bindPath, userPassword) + } + + if userPassword == "" { + bindFn = func() error { + return a.conn.UnauthenticatedBind(bindPath) + } + } + + if err := bindFn(); err != nil { a.log.Info("Initial bind failed", "error", err) if ldapErr, ok := err.(*ldap.Error); ok { diff --git a/pkg/login/ldap_test.go b/pkg/login/ldap_test.go index ef20feb1373..dabafee65a6 100644 --- a/pkg/login/ldap_test.go +++ b/pkg/login/ldap_test.go @@ -13,6 +13,70 @@ import ( ) func TestLdapAuther(t *testing.T) { + Convey("initialBind", t, func() { + Convey("Given bind dn and password configured", func() { + conn := &mockLdapConn{} + var actualUsername, actualPassword string + conn.bindProvider = func(username, password string) error { + actualUsername = username + actualPassword = password + return nil + } + ldapAuther := &ldapAuther{ + conn: conn, + server: &LdapServerConf{ + BindDN: "cn=%s,o=users,dc=grafana,dc=org", + BindPassword: "bindpwd", + }, + } + err := ldapAuther.initialBind("user", "pwd") + So(err, ShouldBeNil) + So(ldapAuther.requireSecondBind, ShouldBeTrue) + So(actualUsername, ShouldEqual, "cn=user,o=users,dc=grafana,dc=org") + So(actualPassword, ShouldEqual, "bindpwd") + }) + + Convey("Given bind dn configured", func() { + conn := &mockLdapConn{} + var actualUsername, actualPassword string + conn.bindProvider = func(username, password string) error { + actualUsername = username + actualPassword = password + return nil + } + ldapAuther := &ldapAuther{ + conn: conn, + server: &LdapServerConf{ + BindDN: "cn=%s,o=users,dc=grafana,dc=org", + }, + } + err := ldapAuther.initialBind("user", "pwd") + So(err, ShouldBeNil) + So(ldapAuther.requireSecondBind, ShouldBeFalse) + So(actualUsername, ShouldEqual, "cn=user,o=users,dc=grafana,dc=org") + So(actualPassword, ShouldEqual, "pwd") + }) + + Convey("Given empty bind dn and password", func() { + conn := &mockLdapConn{} + unauthenticatedBindWasCalled := false + var actualUsername string + conn.unauthenticatedBindProvider = func(username string) error { + unauthenticatedBindWasCalled = true + actualUsername = username + return nil + } + ldapAuther := &ldapAuther{ + conn: conn, + server: &LdapServerConf{}, + } + err := ldapAuther.initialBind("user", "pwd") + So(err, ShouldBeNil) + So(ldapAuther.requireSecondBind, ShouldBeTrue) + So(unauthenticatedBindWasCalled, ShouldBeTrue) + So(actualUsername, ShouldBeEmpty) + }) + }) Convey("When translating ldap user to grafana user", t, func() { @@ -365,12 +429,26 @@ func TestLdapAuther(t *testing.T) { } type mockLdapConn struct { - result *ldap.SearchResult - searchCalled bool - searchAttributes []string + result *ldap.SearchResult + searchCalled bool + searchAttributes []string + bindProvider func(username, password string) error + unauthenticatedBindProvider func(username string) error } func (c *mockLdapConn) Bind(username, password string) error { + if c.bindProvider != nil { + return c.bindProvider(username, password) + } + + return nil +} + +func (c *mockLdapConn) UnauthenticatedBind(username string) error { + if c.unauthenticatedBindProvider != nil { + return c.unauthenticatedBindProvider(username) + } + return nil } From a3da8dc6739735372397f3f0e7f3c845f62e4f48 Mon Sep 17 00:00:00 2001 From: Jon Ferreira Date: Tue, 5 Mar 2019 15:04:10 -0500 Subject: [PATCH 2/9] Expose onQueryChange to angular plugins --- public/app/features/explore/QueryEditor.tsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/public/app/features/explore/QueryEditor.tsx b/public/app/features/explore/QueryEditor.tsx index 1d329f1c56e..d158f6bb9f3 100644 --- a/public/app/features/explore/QueryEditor.tsx +++ b/public/app/features/explore/QueryEditor.tsx @@ -43,6 +43,9 @@ export default class QueryEditor extends PureComponent { this.props.onQueryChange(target); this.props.onExecuteQuery(); }, + onQueryChange: () => { + this.props.onQueryChange(target); + }, events: exploreEvents, panel: { datasource, targets: [target] }, dashboard: {}, From f5aba3681485c0b56294fb3a75a7b1bd4537efae Mon Sep 17 00:00:00 2001 From: ryan Date: Tue, 5 Mar 2019 21:56:52 -0800 Subject: [PATCH 3/9] add ScopedVars to replace function --- packages/grafana-ui/src/types/panel.ts | 3 +- .../dashboard/dashgrid/PanelChrome.test.tsx | 35 +++++++++++++++++++ .../dashboard/dashgrid/PanelChrome.tsx | 10 ++++-- 3 files changed, 45 insertions(+), 3 deletions(-) create mode 100644 public/app/features/dashboard/dashgrid/PanelChrome.test.tsx diff --git a/packages/grafana-ui/src/types/panel.ts b/packages/grafana-ui/src/types/panel.ts index ae205100c13..260ff78df76 100644 --- a/packages/grafana-ui/src/types/panel.ts +++ b/packages/grafana-ui/src/types/panel.ts @@ -1,8 +1,9 @@ import { ComponentClass } from 'react'; import { TimeSeries, LoadingState, TableData } from './data'; import { TimeRange } from './time'; +import { ScopedVars } from './datasource'; -export type InterpolateFunction = (value: string, format?: string | Function) => string; +export type InterpolateFunction = (value: string, scopedVars?: ScopedVars, format?: string | Function) => string; export interface PanelProps { panelData: PanelData; diff --git a/public/app/features/dashboard/dashgrid/PanelChrome.test.tsx b/public/app/features/dashboard/dashgrid/PanelChrome.test.tsx new file mode 100644 index 00000000000..d6242b9db22 --- /dev/null +++ b/public/app/features/dashboard/dashgrid/PanelChrome.test.tsx @@ -0,0 +1,35 @@ +import { PanelChrome } from './PanelChrome'; + +jest.mock('sass/_variables.generated.scss', () => ({ + panelhorizontalpadding: 10, + panelVerticalPadding: 10, +})); + +describe('PanelChrome', () => { + let chrome: PanelChrome; + + beforeEach(() => { + chrome = new PanelChrome({ + panel: { + scopedVars: { + aaa: { value: 'AAA', text: 'upperA' }, + bbb: { value: 'BBB', text: 'upperB' }, + }, + }, + dashboard: {}, + plugin: {}, + isFullscreen: false, + }); + }); + + it('Should replace a panel variable', () => { + const out = chrome.replaceVariables('hello $aaa'); + expect(out).toBe('hello AAA'); + }); + + it('It should prefer the diret variables', () => { + const extra = { aaa: { text: '???', value: 'XXX' } }; + const out = chrome.replaceVariables('hello $aaa and $bbb', extra); + expect(out).toBe('hello XXX and BBB'); + }); +}); diff --git a/public/app/features/dashboard/dashgrid/PanelChrome.tsx b/public/app/features/dashboard/dashgrid/PanelChrome.tsx index 80ce2f39b70..149d0f3deee 100644 --- a/public/app/features/dashboard/dashgrid/PanelChrome.tsx +++ b/public/app/features/dashboard/dashgrid/PanelChrome.tsx @@ -19,6 +19,7 @@ import { profiler } from 'app/core/profiler'; import { DashboardModel, PanelModel } from '../state'; import { PanelPlugin } from 'app/types'; import { DataQueryResponse, TimeRange, LoadingState, PanelData, DataQueryError } from '@grafana/ui'; +import { ScopedVars } from '@grafana/ui'; import variables from 'sass/_variables.generated.scss'; import templateSrv from 'app/features/templating/template_srv'; @@ -85,8 +86,13 @@ export class PanelChrome extends PureComponent { }); }; - replaceVariables = (value: string, format?: string) => { - return templateSrv.replace(value, this.props.panel.scopedVars, format); + replaceVariables = (value: string, extraVars?: ScopedVars, format?: string) => { + let vars = this.props.panel.scopedVars; + if (extraVars) { + vars = vars ? { ...vars, ...extraVars } : extraVars; + } + console.log('VARiables', vars); + return templateSrv.replace(value, vars, format); }; onDataResponse = (dataQueryResponse: DataQueryResponse) => { From 948729e951978d7ecae1970b7ece2712bb689e77 Mon Sep 17 00:00:00 2001 From: ryan Date: Tue, 5 Mar 2019 22:00:12 -0800 Subject: [PATCH 4/9] remove console.log --- public/app/features/dashboard/dashgrid/PanelChrome.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/public/app/features/dashboard/dashgrid/PanelChrome.tsx b/public/app/features/dashboard/dashgrid/PanelChrome.tsx index 149d0f3deee..0a9d1d44ceb 100644 --- a/public/app/features/dashboard/dashgrid/PanelChrome.tsx +++ b/public/app/features/dashboard/dashgrid/PanelChrome.tsx @@ -91,7 +91,6 @@ export class PanelChrome extends PureComponent { if (extraVars) { vars = vars ? { ...vars, ...extraVars } : extraVars; } - console.log('VARiables', vars); return templateSrv.replace(value, vars, format); }; From aa38a9e0b49c17e37b0b246a558fe791457dd89e Mon Sep 17 00:00:00 2001 From: ryan Date: Tue, 5 Mar 2019 22:14:28 -0800 Subject: [PATCH 5/9] typescript functions on replace --- public/app/features/templating/template_srv.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/public/app/features/templating/template_srv.ts b/public/app/features/templating/template_srv.ts index 11e90cbb5f7..e0d35295556 100644 --- a/public/app/features/templating/template_srv.ts +++ b/public/app/features/templating/template_srv.ts @@ -1,7 +1,7 @@ import kbn from 'app/core/utils/kbn'; import _ from 'lodash'; import { variableRegex } from 'app/features/templating/variable'; -import { TimeRange } from '@grafana/ui/src'; +import { TimeRange, ScopedVars } from '@grafana/ui/src'; function luceneEscape(value) { return value.replace(/([\!\*\+\-\=<>\s\&\|\(\)\[\]\{\}\^\~\?\:\\/"])/g, '\\$1'); @@ -220,7 +220,7 @@ export class TemplateSrv { return values; } - replace(target, scopedVars?, format?) { + replace(target: string, scopedVars?: ScopedVars, format?: string | Function) { if (!target) { return target; } From 3dd7d407183c5d0e574d96d7f46a2290e983976b Mon Sep 17 00:00:00 2001 From: ryan Date: Tue, 5 Mar 2019 22:18:42 -0800 Subject: [PATCH 6/9] fix comments --- public/app/features/dashboard/dashgrid/PanelChrome.test.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/app/features/dashboard/dashgrid/PanelChrome.test.tsx b/public/app/features/dashboard/dashgrid/PanelChrome.test.tsx index d6242b9db22..7136a14a907 100644 --- a/public/app/features/dashboard/dashgrid/PanelChrome.test.tsx +++ b/public/app/features/dashboard/dashgrid/PanelChrome.test.tsx @@ -27,7 +27,7 @@ describe('PanelChrome', () => { expect(out).toBe('hello AAA'); }); - it('It should prefer the diret variables', () => { + it('But it should prefer the local variable value', () => { const extra = { aaa: { text: '???', value: 'XXX' } }; const out = chrome.replaceVariables('hello $aaa and $bbb', extra); expect(out).toBe('hello XXX and BBB'); From 5524dacc9d28a601745f9b44a12cf60347e3f07e Mon Sep 17 00:00:00 2001 From: ryan Date: Tue, 5 Mar 2019 23:00:43 -0800 Subject: [PATCH 7/9] use explore icon --- public/app/features/panel/metrics_panel_ctrl.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/app/features/panel/metrics_panel_ctrl.ts b/public/app/features/panel/metrics_panel_ctrl.ts index ceebfd82335..028585ae21e 100644 --- a/public/app/features/panel/metrics_panel_ctrl.ts +++ b/public/app/features/panel/metrics_panel_ctrl.ts @@ -224,7 +224,7 @@ class MetricsPanelCtrl extends PanelCtrl { items.push({ text: 'Explore', click: 'ctrl.explore();', - icon: 'fa fa-fw fa-rocket', + icon: 'gicon gicon-explore', shortcut: 'x', }); } From 909d425008a74c93ea2fb58f5a4a69a7205b4e40 Mon Sep 17 00:00:00 2001 From: ryan Date: Tue, 5 Mar 2019 23:40:03 -0800 Subject: [PATCH 8/9] cleanup plugin versions --- public/app/features/plugins/partials/plugin_edit.html | 4 ++-- public/app/plugins/datasource/cloudwatch/plugin.json | 3 +-- public/app/plugins/datasource/elasticsearch/plugin.json | 5 +---- public/app/plugins/datasource/graphite/plugin.json | 3 +-- public/app/plugins/datasource/influxdb/plugin.json | 3 +-- public/app/plugins/datasource/mysql/plugin.json | 3 +-- public/app/plugins/datasource/opentsdb/plugin.json | 3 +-- public/app/plugins/datasource/postgres/plugin.json | 3 +-- public/app/plugins/datasource/prometheus/plugin.json | 3 +-- public/app/plugins/panel/alertlist/plugin.json | 3 +-- public/app/plugins/panel/dashlist/plugin.json | 3 +-- public/app/plugins/panel/graph/plugin.json | 3 +-- public/app/plugins/panel/heatmap/plugin.json | 3 +-- public/app/plugins/panel/pluginlist/plugin.json | 3 +-- public/app/plugins/panel/singlestat/plugin.json | 3 +-- public/app/plugins/panel/table/plugin.json | 3 +-- public/app/plugins/panel/text/plugin.json | 3 +-- 17 files changed, 18 insertions(+), 36 deletions(-) diff --git a/public/app/features/plugins/partials/plugin_edit.html b/public/app/features/plugins/partials/plugin_edit.html index 16cdfc1d1b2..d84196c47b0 100644 --- a/public/app/features/plugins/partials/plugin_edit.html +++ b/public/app/features/plugins/partials/plugin_edit.html @@ -25,7 +25,7 @@