diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..79c4020 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +SOURCES/grafana-7.5.11.tar.gz +SOURCES/grafana-vendor-7.5.11-1.tar.xz +SOURCES/grafana-webpack-7.5.11-1.tar.gz diff --git a/.grafana.metadata b/.grafana.metadata new file mode 100644 index 0000000..d33b818 --- /dev/null +++ b/.grafana.metadata @@ -0,0 +1,3 @@ +cd7bfb63dd91361c1bc9c46d1f889b1f54f7758a SOURCES/grafana-7.5.11.tar.gz +d55ac0b3a8fb3a0ce772442923e2ca3cba1af78f SOURCES/grafana-vendor-7.5.11-1.tar.xz +db79c330e9a56dac2cdcae9b7c07c86112a66237 SOURCES/grafana-webpack-7.5.11-1.tar.gz diff --git a/SOURCES/001-wrappers-grafana-cli.patch b/SOURCES/001-wrappers-grafana-cli.patch new file mode 100644 index 0000000..01fe90e --- /dev/null +++ b/SOURCES/001-wrappers-grafana-cli.patch @@ -0,0 +1,49 @@ +diff --git a/packaging/wrappers/grafana-cli b/packaging/wrappers/grafana-cli +index 9cad151c0d..a786edc596 100755 +--- a/packaging/wrappers/grafana-cli ++++ b/packaging/wrappers/grafana-cli +@@ -5,18 +5,19 @@ + # the system-wide Grafana configuration that was bundled with the package as we + # use the binary. + +-DEFAULT=/etc/default/grafana ++DEFAULT=/etc/sysconfig/grafana-server + + GRAFANA_HOME=/usr/share/grafana + CONF_DIR=/etc/grafana + DATA_DIR=/var/lib/grafana + PLUGINS_DIR=/var/lib/grafana/plugins + LOG_DIR=/var/log/grafana ++LIBEXEC_DIR=/usr/libexec/grafana + + CONF_FILE=$CONF_DIR/grafana.ini + PROVISIONING_CFG_DIR=$CONF_DIR/provisioning + +-EXECUTABLE=$GRAFANA_HOME/bin/grafana-cli ++EXECUTABLE=$LIBEXEC_DIR/grafana-cli + + if [ ! -x $EXECUTABLE ]; then + echo "Program not installed or not executable" +@@ -24,6 +25,7 @@ if [ ! -x $EXECUTABLE ]; then + fi + + # overwrite settings from default file ++#shellcheck disable=SC1090 + if [ -f "$DEFAULT" ]; then + . "$DEFAULT" + fi +@@ -36,4 +38,13 @@ OPTS="--homepath=${GRAFANA_HOME} \ + cfg:default.paths.logs=${LOG_DIR} \ + cfg:default.paths.plugins=${PLUGINS_DIR}'" + +-eval $EXECUTABLE "$OPTS" "$@" ++if [ "$(id -u)" -eq 0 ]; then ++ cd "${GRAFANA_HOME}" ++ exec runuser -u "${GRAFANA_USER}" -- "$EXECUTABLE" "$OPTS" "$@" ++elif [ "$(id -u -n)" = "${GRAFANA_USER}" ]; then ++ cd "${GRAFANA_HOME}" ++ exec "$EXECUTABLE" "$OPTS" "$@" ++else ++ echo "$0: please run this script as user \"${GRAFANA_USER}\" or root." ++ exit 5 ++fi diff --git a/SOURCES/002-manpages.patch b/SOURCES/002-manpages.patch new file mode 100644 index 0000000..36ca294 --- /dev/null +++ b/SOURCES/002-manpages.patch @@ -0,0 +1,144 @@ +diff --git a/docs/man/man1/grafana-cli.1 b/docs/man/man1/grafana-cli.1 +new file mode 100644 +index 0000000000..7ac2af882c +--- /dev/null ++++ b/docs/man/man1/grafana-cli.1 +@@ -0,0 +1,60 @@ ++.TH GRAFANA "1" "October 2021" "Grafana cli version 7.5.11" "User Commands" ++.SH NAME ++grafana-cli \- command line administration for the Grafana metrics dashboard and graph editor ++.SH DESCRIPTION ++.SS "NAME:" ++.IP ++grafana-cli ++.SS "USAGE:" ++.IP ++\fBgrafana\-cli\fP [\fIglobal options\fP] \fIcommand\fP [\fIcommand options\fP] [\fIarguments\fP...] ++.SS "COMMANDS:" ++.TP ++plugins ++Manage plugins for grafana ++.TP ++admin ++Grafana admin commands ++.TP ++help, h ++Shows a list of commands or help for one command ++.SS "GLOBAL OPTIONS:" ++.TP ++\fB\-\-pluginsDir\fR value ++path to the grafana plugin directory (default: "/var/lib/grafana/plugins") [$GF_PLUGIN_DIR] ++.TP ++\fB\-\-repo\fR value ++url to the plugin repository (default: "https://grafana.com/api/plugins") [$GF_PLUGIN_REPO] ++.TP ++\fB\-\-pluginUrl\fR value ++Full url to the plugin zip file instead of downloading the plugin from grafana.com/api [$GF_PLUGIN_URL] ++.TP ++\fB\-\-insecure\fR ++Skip TLS verification (insecure) ++.TP ++\fB\-\-debug\fR, \fB\-d\fR ++enable debug logging ++.TP ++\fB\-\-configOverrides\fR value ++Configuration options to override defaults as a string. e.g. cfg:default.paths.log=/dev/null ++.TP ++\fB\-\-homepath\fR value ++Path to Grafana install/home path, defaults to working directory ++.TP ++\fB\-\-config\fR value ++Path to config file ++.TP ++\fB\-\-help\fR, \fB\-h\fR ++show help ++.TP ++\fB\-\-version\fR, \fB\-v\fR ++print the version ++.SH "SEE ALSO" ++Additional documentation for ++.B grafana-cli ++is available on-line at ++.BR http://docs.grafana.org/administration/cli/ . ++The full documentation for ++.B Grafana ++is available on-line at ++.BR http://docs.grafana.org/ . +diff --git a/docs/man/man1/grafana-server.1 b/docs/man/man1/grafana-server.1 +new file mode 100644 +index 0000000000..c616268b31 +--- /dev/null ++++ b/docs/man/man1/grafana-server.1 +@@ -0,0 +1,72 @@ ++.TH VERSION "1" "October 2021" "Version 7.5.11" "User Commands" ++.SH NAME ++grafana-server \- back-end server for the Grafana metrics dashboard and graph editor ++.SH DESCRIPTION ++.B grafana-server ++is the back-end server for the Grafana metrics dashboard and graph editor. ++The ++.B grafana-server ++program should not normally be run from the command line, ++except when testing or for development purposes. ++Rather it should be managed by ++.BR systemd . ++After installing Grafana, the systemd service should be enabled and started as follows: ++.P ++.in 1i ++.B systemctl daemon-reload ++.br ++.B systemctl enable grafana-server.service ++.br ++.B systemctl start grafana-server.service ++.in ++.P ++.SH OPTIONS ++The ++.B gafana-server ++configuration is specified in ++.BR /etc/grafana/grafana.ini ++and is well documented with comments. ++The command-line options listed below override options of ++the same (or similar) name in the configuration file. ++.P ++.HP ++\fB\-config\fR string ++.IP ++path to config file ++.HP ++\fB\-homepath\fR string ++.IP ++path to grafana install/home path, defaults to working directory ++.HP ++\fB\-packaging\fR string ++.IP ++describes the way Grafana was installed (default "unknown") ++.HP ++\fB\-pidfile\fR string ++.IP ++path to pid file ++.HP ++\fB\-profile\fR ++.IP ++Turn on pprof profiling ++.HP ++\fB\-profile\-port\fR uint ++.IP ++Define custom port for profiling (default 6060) ++.HP ++\fB\-tracing\fR ++.IP ++Turn on tracing ++.HP ++\fB\-tracing\-file\fR string ++.IP ++Define tracing output file (default "trace.out") ++.TP ++\fB\-v\fR ++.IP ++prints current version and exits ++.SH "SEE ALSO" ++The full documentation for ++.B Grafana ++is available on-line at ++.BR http://docs.grafana.org/ . diff --git a/SOURCES/003-fix-dashboard-abspath-test.patch b/SOURCES/003-fix-dashboard-abspath-test.patch new file mode 100644 index 0000000..ad7e5bf --- /dev/null +++ b/SOURCES/003-fix-dashboard-abspath-test.patch @@ -0,0 +1,24 @@ +diff --git a/pkg/services/provisioning/dashboards/file_reader_linux_test.go b/pkg/services/provisioning/dashboards/file_reader_linux_test.go +index 3584bbc242..1a89767b69 100644 +--- a/pkg/services/provisioning/dashboards/file_reader_linux_test.go ++++ b/pkg/services/provisioning/dashboards/file_reader_linux_test.go +@@ -28,6 +28,7 @@ func TestProvisionedSymlinkedFolder(t *testing.T) { + } + + want, err := filepath.Abs(containingID) ++ want, err = filepath.EvalSymlinks(want) + + if err != nil { + t.Errorf("expected err to be nil") +diff --git a/pkg/services/provisioning/dashboards/file_reader_test.go b/pkg/services/provisioning/dashboards/file_reader_test.go +index 946d487d5f..2acef40eed 100644 +--- a/pkg/services/provisioning/dashboards/file_reader_test.go ++++ b/pkg/services/provisioning/dashboards/file_reader_test.go +@@ -318,6 +318,7 @@ func TestDashboardFileReader(t *testing.T) { + } + + absPath1, err := filepath.Abs(unprovision + "/dashboard1.json") ++ absPath1, err = filepath.EvalSymlinks(absPath1) + So(err, ShouldBeNil) + // This one does not exist on disk, simulating a deleted file + absPath2, err := filepath.Abs(unprovision + "/dashboard2.json") diff --git a/SOURCES/004-skip-x86-goldenfiles-tests.patch b/SOURCES/004-skip-x86-goldenfiles-tests.patch new file mode 100644 index 0000000..bb61e0b --- /dev/null +++ b/SOURCES/004-skip-x86-goldenfiles-tests.patch @@ -0,0 +1,69 @@ +diff --git a/packages/grafana-data/src/dataframe/ArrowDataFrame.test.ts b/packages/grafana-data/src/dataframe/ArrowDataFrame.test.ts +index 96efaccfce..bcdd98144f 100644 +--- a/packages/grafana-data/src/dataframe/ArrowDataFrame.test.ts ++++ b/packages/grafana-data/src/dataframe/ArrowDataFrame.test.ts +@@ -52,7 +52,7 @@ describe('Read/Write arrow Table to DataFrame', () => { + expect(after).toEqual(before); + }); + +- test('should read all types', () => { ++ test.skip('should read all types', () => { + const fullpath = path.resolve(__dirname, './__snapshots__/all_types.golden.arrow'); + const arrow = fs.readFileSync(fullpath); + const table = Table.from([arrow]); +diff --git a/packages/grafana-runtime/src/utils/queryResponse.test.ts b/packages/grafana-runtime/src/utils/queryResponse.test.ts +index 0adb915d2c..8985d7beab 100644 +--- a/packages/grafana-runtime/src/utils/queryResponse.test.ts ++++ b/packages/grafana-runtime/src/utils/queryResponse.test.ts +@@ -47,7 +47,7 @@ const emptyResults = { + /* eslint-enable */ + + describe('Query Response parser', () => { +- test('should parse output with dataframe', () => { ++ test.skip('should parse output with dataframe', () => { + const res = toDataQueryResponse(resp); + const frames = res.data; + expect(frames).toHaveLength(2); +@@ -131,7 +131,7 @@ describe('Query Response parser', () => { + `); + }); + +- test('should parse output with dataframe in order of queries', () => { ++ test.skip('should parse output with dataframe in order of queries', () => { + const queries: DataQuery[] = [{ refId: 'B' }, { refId: 'A' }]; + const res = toDataQueryResponse(resp, queries); + const frames = res.data; +@@ -250,7 +250,7 @@ describe('Query Response parser', () => { + expect(ids).toEqual(['A', 'B', 'X']); + }); + +- test('resultWithError', () => { ++ test.skip('resultWithError', () => { + // Generated from: + // qdr.Responses[q.GetRefID()] = backend.DataResponse{ + // Error: fmt.Errorf("an Error: %w", fmt.Errorf("another error")), +diff --git a/pkg/tsdb/influxdb/flux/executor_test.go b/pkg/tsdb/influxdb/flux/executor_test.go +index 7cfc8bd20a..add6b5f3b8 100644 +--- a/pkg/tsdb/influxdb/flux/executor_test.go ++++ b/pkg/tsdb/influxdb/flux/executor_test.go +@@ -68,6 +68,7 @@ func executeMockedQuery(t *testing.T, name string, query queryModel) *backend.Da + } + + func verifyGoldenResponse(t *testing.T, name string) *backend.DataResponse { ++ t.Skip("x86 memory dump is not compatible with other architectures") + dr := executeMockedQuery(t, name, queryModel{MaxDataPoints: 100}) + + err := experimental.CheckGoldenDataResponse(filepath.Join("testdata", fmt.Sprintf("%s.golden.txt", name)), +diff --git a/public/app/plugins/datasource/cloudwatch/specs/datasource.test.ts b/public/app/plugins/datasource/cloudwatch/specs/datasource.test.ts +index afc8ba357b..587092a58d 100644 +--- a/public/app/plugins/datasource/cloudwatch/specs/datasource.test.ts ++++ b/public/app/plugins/datasource/cloudwatch/specs/datasource.test.ts +@@ -78,7 +78,7 @@ describe('CloudWatchDatasource', () => { + }); + + describe('When getting log groups', () => { +- it('should return log groups as an array of strings', async () => { ++ it.skip('should return log groups as an array of strings', async () => { + const response = { + results: { + A: { diff --git a/SOURCES/005-remove-unused-dependencies.patch b/SOURCES/005-remove-unused-dependencies.patch new file mode 100644 index 0000000..19d72f0 --- /dev/null +++ b/SOURCES/005-remove-unused-dependencies.patch @@ -0,0 +1,63 @@ +diff --git a/go.mod b/go.mod +index 426b70ab7a..dc0c9a61ef 100644 +--- a/go.mod ++++ b/go.mod +@@ -21,7 +21,6 @@ require ( + github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b + github.com/centrifugal/centrifuge v0.13.0 + github.com/cortexproject/cortex v1.4.1-0.20201022071705-85942c5703cf +- github.com/crewjam/saml v0.4.6-0.20201227203850-bca570abb2ce + github.com/davecgh/go-spew v1.1.1 + github.com/denisenkom/go-mssqldb v0.0.0-20200910202707-1e08a3fab204 + github.com/facebookgo/ensure v0.0.0-20160127193407-b4ab57deab51 // indirect +@@ -57,7 +56,6 @@ require ( + github.com/jmespath/go-jmespath v0.4.0 + github.com/jonboulle/clockwork v0.2.2 // indirect + github.com/json-iterator/go v1.1.10 +- github.com/jung-kurt/gofpdf v1.16.2 + github.com/lib/pq v1.9.0 + github.com/linkedin/goavro/v2 v2.10.0 + github.com/magefile/mage v1.11.0 +diff --git a/go.sum b/go.sum +index 98874d6a7c..03243066ac 100644 +--- a/go.sum ++++ b/go.sum +@@ -282,8 +282,6 @@ github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsr + github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= + github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= + github.com/crewjam/httperr v0.0.0-20190612203328-a946449404da/go.mod h1:+rmNIXRvYMqLQeR4DHyTvs6y0MEMymTz4vyFpFkKTPs= +-github.com/crewjam/saml v0.4.6-0.20201227203850-bca570abb2ce h1:pAuTpLhCqC20s2RLhUirfw606jReW+8z2U5EvG+0S7E= +-github.com/crewjam/saml v0.4.6-0.20201227203850-bca570abb2ce/go.mod h1:/gCaeLf13J8/621RNZ6TaExji/8xCWcn6UmdJ57wURQ= + github.com/crossdock/crossdock-go v0.0.0-20160816171116-049aabb0122b/go.mod h1:v9FBN7gdVTpiD/+LZ7Po0UKvROyT87uLVxTHVky/dlQ= + github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4= + github.com/cznic/b v0.0.0-20180115125044-35e9bbe41f07/go.mod h1:URriBxXwVq5ijiJ12C7iIZqlA69nTlI+LgI6/pwftG8= +@@ -914,10 +912,6 @@ github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7 + github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= + github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= + github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= +-github.com/jung-kurt/gofpdf v1.0.0/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= +-github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= +-github.com/jung-kurt/gofpdf v1.16.2 h1:jgbatWHfRlPYiK85qgevsZTHviWXKwB1TTiKdz5PtRc= +-github.com/jung-kurt/gofpdf v1.16.2/go.mod h1:1hl7y57EsiPAkLbOwzpzqgx1A30nQCk/YmFV8S2vmK0= + github.com/jwilder/encoding v0.0.0-20170811194829-b4e1701a28ef/go.mod h1:Ct9fl0F6iIOGgxJ5npU/IUOhOhqlVrGjyIZc8/MagT0= + github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88 h1:uC1QfSlInpQF+M0ao65imhwqKnz3Q2z/d8PWZRMQvDM= + github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k= +diff --git a/pkg/extensions/main.go b/pkg/extensions/main.go +index 24031ace2e..081475fc89 100644 +--- a/pkg/extensions/main.go ++++ b/pkg/extensions/main.go +@@ -6,14 +6,12 @@ import ( + + _ "github.com/beevik/etree" + _ "github.com/cortexproject/cortex/pkg/util" +- _ "github.com/crewjam/saml" + _ "github.com/gobwas/glob" + "github.com/grafana/grafana/pkg/registry" + "github.com/grafana/grafana/pkg/services/licensing" + "github.com/grafana/grafana/pkg/services/validations" + _ "github.com/grafana/loki/pkg/logproto" + _ "github.com/grpc-ecosystem/go-grpc-middleware" +- _ "github.com/jung-kurt/gofpdf" + _ "github.com/linkedin/goavro/v2" + _ "github.com/pkg/errors" + _ "github.com/robfig/cron" diff --git a/SOURCES/006-fix-gtime-test-32bit.patch b/SOURCES/006-fix-gtime-test-32bit.patch new file mode 100644 index 0000000..c38a50f --- /dev/null +++ b/SOURCES/006-fix-gtime-test-32bit.patch @@ -0,0 +1,17 @@ +diff --git a/pkg/components/gtime/gtime_test.go b/pkg/components/gtime/gtime_test.go +index 0b1b23a1db..eb9fe718c7 100644 +--- a/pkg/components/gtime/gtime_test.go ++++ b/pkg/components/gtime/gtime_test.go +@@ -20,9 +20,9 @@ func TestParseInterval(t *testing.T) { + {inp: "1d", duration: 24 * time.Hour}, + {inp: "1w", duration: 168 * time.Hour}, + {inp: "2w", duration: 2 * 168 * time.Hour}, +- {inp: "1M", duration: time.Duration(daysInMonth * 24 * int(time.Hour))}, +- {inp: "1y", duration: time.Duration(daysInYear * 24 * int(time.Hour))}, +- {inp: "5y", duration: time.Duration(calculateDays5y() * 24 * int(time.Hour))}, ++ {inp: "1M", duration: time.Duration(int64(daysInMonth) * 24 * int64(time.Hour))}, ++ {inp: "1y", duration: time.Duration(int64(daysInYear) * 24 * int64(time.Hour))}, ++ {inp: "5y", duration: time.Duration(int64(calculateDays5y()) * 24 * int64(time.Hour))}, + {inp: "invalid-duration", err: regexp.MustCompile(`^time: invalid duration "?invalid-duration"?$`)}, + } + for i, tc := range tcs { diff --git a/SOURCES/008-remove-unused-frontend-crypto.patch b/SOURCES/008-remove-unused-frontend-crypto.patch new file mode 100644 index 0000000..2409e23 --- /dev/null +++ b/SOURCES/008-remove-unused-frontend-crypto.patch @@ -0,0 +1,26 @@ +diff --git a/package.json b/package.json +index 9c5a2d93e2..7f65949ea4 100644 +--- a/package.json ++++ b/package.json +@@ -294,6 +294,9 @@ + "whatwg-fetch": "3.1.0" + }, + "resolutions": { ++ "crypto-browserify": "https://registry.yarnpkg.com/@favware/skip-dependency/-/skip-dependency-1.1.1.tgz", ++ "selfsigned": "https://registry.yarnpkg.com/@favware/skip-dependency/-/skip-dependency-1.1.1.tgz", ++ "http-signature": "https://registry.yarnpkg.com/@favware/skip-dependency/-/skip-dependency-1.1.1.tgz", + "caniuse-db": "1.0.30000772", + "react-use-measure": "https://github.com/mckn/react-use-measure.git#remove-cjs-export" + }, +diff --git a/scripts/webpack/webpack.common.js b/scripts/webpack/webpack.common.js +index 3e56d31c37..a03ed1a67a 100644 +--- a/scripts/webpack/webpack.common.js ++++ b/scripts/webpack/webpack.common.js +@@ -66,6 +66,7 @@ module.exports = { + }, + node: { + fs: 'empty', ++ crypto: false, + }, + plugins: [ + new MonacoWebpackPlugin({ diff --git a/SOURCES/009-patch-unused-backend-crypto.patch b/SOURCES/009-patch-unused-backend-crypto.patch new file mode 100644 index 0000000..12be571 --- /dev/null +++ b/SOURCES/009-patch-unused-backend-crypto.patch @@ -0,0 +1,168 @@ +diff --git a/vendor/golang.org/x/crypto/openpgp/elgamal/elgamal.go b/vendor/golang.org/x/crypto/openpgp/elgamal/elgamal.go +new file mode 100644 +index 0000000..871e612 +--- /dev/null ++++ b/vendor/golang.org/x/crypto/openpgp/elgamal/elgamal.go +@@ -0,0 +1,25 @@ ++package elgamal ++ ++import ( ++ "io" ++ "math/big" ++) ++ ++// PublicKey represents an ElGamal public key. ++type PublicKey struct { ++ G, P, Y *big.Int ++} ++ ++// PrivateKey represents an ElGamal private key. ++type PrivateKey struct { ++ PublicKey ++ X *big.Int ++} ++ ++func Encrypt(random io.Reader, pub *PublicKey, msg []byte) (c1, c2 *big.Int, err error) { ++ panic("ElGamal encryption not available") ++} ++ ++func Decrypt(priv *PrivateKey, c1, c2 *big.Int) (msg []byte, err error) { ++ panic("ElGamal encryption not available") ++} +diff --git a/vendor/golang.org/x/crypto/openpgp/packet/packet.go b/vendor/golang.org/x/crypto/openpgp/packet/packet.go +index 9728d61..9f04c2d 100644 +--- a/vendor/golang.org/x/crypto/openpgp/packet/packet.go ++++ b/vendor/golang.org/x/crypto/openpgp/packet/packet.go +@@ -16,7 +16,6 @@ import ( + "math/big" + "math/bits" + +- "golang.org/x/crypto/cast5" + "golang.org/x/crypto/openpgp/errors" + ) + +@@ -487,7 +486,7 @@ func (cipher CipherFunction) KeySize() int { + case Cipher3DES: + return 24 + case CipherCAST5: +- return cast5.KeySize ++ panic("cast5 cipher not available") + case CipherAES128: + return 16 + case CipherAES192: +@@ -517,7 +516,7 @@ func (cipher CipherFunction) new(key []byte) (block cipher.Block) { + case Cipher3DES: + block, _ = des.NewTripleDESCipher(key) + case CipherCAST5: +- block, _ = cast5.NewCipher(key) ++ panic("cast5 cipher not available") + case CipherAES128, CipherAES192, CipherAES256: + block, _ = aes.NewCipher(key) + } +diff --git a/vendor/golang.org/x/crypto/openpgp/packet/symmetrically_encrypted.go b/vendor/golang.org/x/crypto/openpgp/packet/symmetrically_encrypted.go +index 6126030..3a54c5f 100644 +--- a/vendor/golang.org/x/crypto/openpgp/packet/symmetrically_encrypted.go ++++ b/vendor/golang.org/x/crypto/openpgp/packet/symmetrically_encrypted.go +@@ -5,13 +5,12 @@ + package packet + + import ( +- "crypto/cipher" + "crypto/sha1" + "crypto/subtle" +- "golang.org/x/crypto/openpgp/errors" + "hash" + "io" +- "strconv" ++ ++ "golang.org/x/crypto/openpgp/errors" + ) + + // SymmetricallyEncrypted represents a symmetrically encrypted byte string. The +@@ -45,46 +44,7 @@ func (se *SymmetricallyEncrypted) parse(r io.Reader) error { + // packet can be read. An incorrect key can, with high probability, be detected + // immediately and this will result in a KeyIncorrect error being returned. + func (se *SymmetricallyEncrypted) Decrypt(c CipherFunction, key []byte) (io.ReadCloser, error) { +- keySize := c.KeySize() +- if keySize == 0 { +- return nil, errors.UnsupportedError("unknown cipher: " + strconv.Itoa(int(c))) +- } +- if len(key) != keySize { +- return nil, errors.InvalidArgumentError("SymmetricallyEncrypted: incorrect key length") +- } +- +- if se.prefix == nil { +- se.prefix = make([]byte, c.blockSize()+2) +- _, err := readFull(se.contents, se.prefix) +- if err != nil { +- return nil, err +- } +- } else if len(se.prefix) != c.blockSize()+2 { +- return nil, errors.InvalidArgumentError("can't try ciphers with different block lengths") +- } +- +- ocfbResync := OCFBResync +- if se.MDC { +- // MDC packets use a different form of OCFB mode. +- ocfbResync = OCFBNoResync +- } +- +- s := NewOCFBDecrypter(c.new(key), se.prefix, ocfbResync) +- if s == nil { +- return nil, errors.ErrKeyIncorrect +- } +- +- plaintext := cipher.StreamReader{S: s, R: se.contents} +- +- if se.MDC { +- // MDC packets have an embedded hash that we need to check. +- h := sha1.New() +- h.Write(se.prefix) +- return &seMDCReader{in: plaintext, h: h}, nil +- } +- +- // Otherwise, we just need to wrap plaintext so that it's a valid ReadCloser. +- return seReader{plaintext}, nil ++ panic("OCFB cipher not available") + } + + // seReader wraps an io.Reader with a no-op Close method. +@@ -254,37 +214,5 @@ func (c noOpCloser) Close() error { + // written. + // If config is nil, sensible defaults will be used. + func SerializeSymmetricallyEncrypted(w io.Writer, c CipherFunction, key []byte, config *Config) (contents io.WriteCloser, err error) { +- if c.KeySize() != len(key) { +- return nil, errors.InvalidArgumentError("SymmetricallyEncrypted.Serialize: bad key length") +- } +- writeCloser := noOpCloser{w} +- ciphertext, err := serializeStreamHeader(writeCloser, packetTypeSymmetricallyEncryptedMDC) +- if err != nil { +- return +- } +- +- _, err = ciphertext.Write([]byte{symmetricallyEncryptedVersion}) +- if err != nil { +- return +- } +- +- block := c.new(key) +- blockSize := block.BlockSize() +- iv := make([]byte, blockSize) +- _, err = config.Random().Read(iv) +- if err != nil { +- return +- } +- s, prefix := NewOCFBEncrypter(block, iv, OCFBNoResync) +- _, err = ciphertext.Write(prefix) +- if err != nil { +- return +- } +- plaintext := cipher.StreamWriter{S: s, W: ciphertext} +- +- h := sha1.New() +- h.Write(iv) +- h.Write(iv[blockSize-2:]) +- contents = &seMDCWriter{w: plaintext, h: h} +- return ++ panic("OCFB cipher not available") + } diff --git a/SOURCES/010-fips.patch b/SOURCES/010-fips.patch new file mode 100644 index 0000000..f9adee9 --- /dev/null +++ b/SOURCES/010-fips.patch @@ -0,0 +1,140 @@ +diff --git a/vendor/golang.org/x/crypto/internal/boring/boring.go b/vendor/golang.org/x/crypto/internal/boring/boring.go +new file mode 100644 +index 0000000..a9c550e +--- /dev/null ++++ b/vendor/golang.org/x/crypto/internal/boring/boring.go +@@ -0,0 +1,74 @@ ++// Copyright 2017 The Go Authors. All rights reserved. ++// Copyright 2021 Red Hat. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++// +build linux ++// +build !android ++// +build !no_openssl ++// +build !cmd_go_bootstrap ++// +build !msan ++ ++package boring ++ ++// #include "openssl_pbkdf2.h" ++// #cgo LDFLAGS: -ldl ++import "C" ++import ( ++ "bytes" ++ "crypto/sha1" ++ "crypto/sha256" ++ "hash" ++ "unsafe" ++) ++ ++var ( ++ emptySha1 = sha1.Sum([]byte{}) ++ emptySha256 = sha256.Sum256([]byte{}) ++) ++ ++func hashToMD(h hash.Hash) *C.GO_EVP_MD { ++ emptyHash := h.Sum([]byte{}) ++ ++ switch { ++ case bytes.Equal(emptyHash, emptySha1[:]): ++ return C._goboringcrypto_EVP_sha1() ++ case bytes.Equal(emptyHash, emptySha256[:]): ++ return C._goboringcrypto_EVP_sha256() ++ } ++ return nil ++} ++ ++// charptr returns the address of the underlying array in b, ++// being careful not to panic when b has zero length. ++func charptr(b []byte) *C.char { ++ if len(b) == 0 { ++ return nil ++ } ++ return (*C.char)(unsafe.Pointer(&b[0])) ++} ++ ++// ucharptr returns the address of the underlying array in b, ++// being careful not to panic when b has zero length. ++func ucharptr(b []byte) *C.uchar { ++ if len(b) == 0 { ++ return nil ++ } ++ return (*C.uchar)(unsafe.Pointer(&b[0])) ++} ++ ++func Pbkdf2Key(password, salt []byte, iter, keyLen int, h func() hash.Hash) []byte { ++ // println("[debug] using pbkdf2 from OpenSSL") ++ ch := h() ++ md := hashToMD(ch) ++ if md == nil { ++ return nil ++ } ++ ++ out := make([]byte, keyLen) ++ ok := C._goboringcrypto_PKCS5_PBKDF2_HMAC(charptr(password), C.int(len(password)), ucharptr(salt), C.int(len(salt)), C.int(iter), md, C.int(keyLen), ucharptr(out)) ++ if ok != 1 { ++ panic("boringcrypto: PKCS5_PBKDF2_HMAC failed") ++ } ++ return out ++} +diff --git a/vendor/golang.org/x/crypto/internal/boring/notboring.go b/vendor/golang.org/x/crypto/internal/boring/notboring.go +new file mode 100644 +index 0000000..e244fb5 +--- /dev/null ++++ b/vendor/golang.org/x/crypto/internal/boring/notboring.go +@@ -0,0 +1,16 @@ ++// Copyright 2017 The Go Authors. All rights reserved. ++// Copyright 2021 Red Hat. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++// +build !linux !cgo android cmd_go_bootstrap msan no_openssl ++ ++package boring ++ ++import ( ++ "hash" ++) ++ ++func Pbkdf2Key(password, salt []byte, iter, keyLen int, h func() hash.Hash) []byte { ++ panic("boringcrypto: not available") ++} +diff --git a/vendor/golang.org/x/crypto/internal/boring/openssl_pbkdf2.h b/vendor/golang.org/x/crypto/internal/boring/openssl_pbkdf2.h +new file mode 100644 +index 0000000..6dfdf10 +--- /dev/null ++++ b/vendor/golang.org/x/crypto/internal/boring/openssl_pbkdf2.h +@@ -0,0 +1,5 @@ ++#include "/usr/lib/golang/src/crypto/internal/boring/goboringcrypto.h" ++ ++DEFINEFUNC(int, PKCS5_PBKDF2_HMAC, ++ (const char *pass, int passlen, const unsigned char *salt, int saltlen, int iter, EVP_MD *digest, int keylen, unsigned char *out), ++ (pass, passlen, salt, saltlen, iter, digest, keylen, out)) +diff --git a/vendor/golang.org/x/crypto/pbkdf2/pbkdf2.go b/vendor/golang.org/x/crypto/pbkdf2/pbkdf2.go +index 593f653..799a611 100644 +--- a/vendor/golang.org/x/crypto/pbkdf2/pbkdf2.go ++++ b/vendor/golang.org/x/crypto/pbkdf2/pbkdf2.go +@@ -19,8 +19,11 @@ pbkdf2.Key. + package pbkdf2 // import "golang.org/x/crypto/pbkdf2" + + import ( ++ "crypto/boring" + "crypto/hmac" + "hash" ++ ++ xboring "golang.org/x/crypto/internal/boring" + ) + + // Key derives a key from the password, salt and iteration count, returning a +@@ -40,6 +43,10 @@ import ( + // Using a higher iteration count will increase the cost of an exhaustive + // search but will also make derivation proportionally slower. + func Key(password, salt []byte, iter, keyLen int, h func() hash.Hash) []byte { ++ if boring.Enabled() { ++ return xboring.Pbkdf2Key(password, salt, iter, keyLen, h) ++ } ++ + prf := hmac.New(h, password) + hashLen := prf.Size() + numBlocks := (keyLen + hashLen - 1) / hashLen diff --git a/SOURCES/011-CVE-2021-43813.patch b/SOURCES/011-CVE-2021-43813.patch new file mode 100644 index 0000000..375b364 --- /dev/null +++ b/SOURCES/011-CVE-2021-43813.patch @@ -0,0 +1,52 @@ +commit ea77415cfe2cefe46ffce233076a1409abaa8df7 +Author: Will Browne <wbrowne@users.noreply.github.com> +Date: Fri Dec 10 11:29:12 2021 +0000 + + apply fix (#42969) + +diff --git a/pkg/plugins/plugins.go b/pkg/plugins/plugins.go +index e6370a29e7..c7199c716e 100644 +--- a/pkg/plugins/plugins.go ++++ b/pkg/plugins/plugins.go +@@ -491,15 +491,15 @@ func GetPluginMarkdown(pluginId string, name string) ([]byte, error) { + } + + // nolint:gosec +- // We can ignore the gosec G304 warning on this one because `plug.PluginDir` is based +- // on plugin the folder structure on disk and not user input. +- path := filepath.Join(plug.PluginDir, fmt.Sprintf("%s.md", strings.ToUpper(name))) ++ // We can ignore the gosec G304 warning since we have cleaned the requested file path and subsequently ++ // use this with a prefix of the plugin's directory, which is set during plugin loading ++ path := filepath.Join(plug.PluginDir, mdFilepath(strings.ToUpper(name))) + exists, err := fs.Exists(path) + if err != nil { + return nil, err + } + if !exists { +- path = filepath.Join(plug.PluginDir, fmt.Sprintf("%s.md", strings.ToLower(name))) ++ path = filepath.Join(plug.PluginDir, mdFilepath(strings.ToLower(name))) + } + + exists, err = fs.Exists(path) +@@ -511,8 +511,8 @@ func GetPluginMarkdown(pluginId string, name string) ([]byte, error) { + } + + // nolint:gosec +- // We can ignore the gosec G304 warning on this one because `plug.PluginDir` is based +- // on plugin the folder structure on disk and not user input. ++ // We can ignore the gosec G304 warning since we have cleaned the requested file path and subsequently ++ // use this with a prefix of the plugin's directory, which is set during plugin loading + data, err := ioutil.ReadFile(path) + if err != nil { + return nil, err +@@ -520,6 +520,10 @@ func GetPluginMarkdown(pluginId string, name string) ([]byte, error) { + return data, nil + } + ++func mdFilepath(mdFilename string) string { ++ return filepath.Clean(filepath.Join("/", fmt.Sprintf("%s.md", mdFilename))) ++} ++ + // gets plugin filenames that require verification for plugin signing + func collectPluginFilesWithin(rootDir string) ([]string, error) { + var files []string diff --git a/SOURCES/012-use-hmac-sha-256-for-password-reset-tokens.patch b/SOURCES/012-use-hmac-sha-256-for-password-reset-tokens.patch new file mode 100644 index 0000000..91b6b46 --- /dev/null +++ b/SOURCES/012-use-hmac-sha-256-for-password-reset-tokens.patch @@ -0,0 +1,353 @@ +commit f13c08e9f45d7776cb264b17ec41bc4ff51fc0b9 +Author: Andreas Gerstmayr <agerstmayr@redhat.com> +Date: Thu Nov 25 18:49:52 2021 +0100 + + notifications: use HMAC-SHA256 to generate time limit codes + + * changes the time limit code generation function to use HMAC-SHA256 + instead of SHA-1 + * multiple new testcases + +diff --git a/pkg/services/notifications/codes.go b/pkg/services/notifications/codes.go +index ea9beb30cc..1ddf05dc69 100644 +--- a/pkg/services/notifications/codes.go ++++ b/pkg/services/notifications/codes.go +@@ -1,48 +1,53 @@ + package notifications + + import ( +- "crypto/sha1" // #nosec ++ "crypto/hmac" ++ "crypto/sha256" + "encoding/hex" + "fmt" ++ "strconv" + "time" + +- "github.com/unknwon/com" +- + "github.com/grafana/grafana/pkg/models" + "github.com/grafana/grafana/pkg/setting" + ) + +-const timeLimitCodeLength = 12 + 6 + 40 ++const timeLimitStartDateLength = 12 ++const timeLimitMinutesLength = 6 ++const timeLimitHmacLength = 64 ++const timeLimitCodeLength = timeLimitStartDateLength + timeLimitMinutesLength + timeLimitHmacLength + + // create a time limit code +-// code format: 12 length date time string + 6 minutes string + 40 sha1 encoded string +-func createTimeLimitCode(data string, minutes int, startInf interface{}) (string, error) { ++// code format: 12 length date time string + 6 minutes string + 64 HMAC-SHA256 encoded string ++func createTimeLimitCode(payload string, minutes int, startStr string) (string, error) { + format := "200601021504" + + var start, end time.Time +- var startStr, endStr string ++ var endStr string + +- if startInf == nil { ++ if startStr == "" { + // Use now time create code + start = time.Now() + startStr = start.Format(format) + } else { + // use start string create code +- startStr = startInf.(string) +- start, _ = time.ParseInLocation(format, startStr, time.Local) +- startStr = start.Format(format) ++ var err error ++ start, err = time.ParseInLocation(format, startStr, time.Local) ++ if err != nil { ++ return "", err ++ } + } + + end = start.Add(time.Minute * time.Duration(minutes)) + endStr = end.Format(format) + +- // create sha1 encode string +- sh := sha1.New() +- if _, err := sh.Write([]byte(data + setting.SecretKey + startStr + endStr + +- com.ToStr(minutes))); err != nil { +- return "", err ++ // create HMAC-SHA256 encoded string ++ key := []byte(setting.SecretKey) ++ h := hmac.New(sha256.New, key) ++ if _, err := h.Write([]byte(payload + startStr + endStr)); err != nil { ++ return "", fmt.Errorf("cannot create hmac: %v", err) + } +- encoded := hex.EncodeToString(sh.Sum(nil)) ++ encoded := hex.EncodeToString(h.Sum(nil)) + + code := fmt.Sprintf("%s%06d%s", startStr, minutes, encoded) + return code, nil +@@ -50,30 +55,29 @@ func createTimeLimitCode(data string, minutes int, startInf interface{}) (string + + // verify time limit code + func validateUserEmailCode(user *models.User, code string) (bool, error) { +- if len(code) <= 18 { ++ if len(code) < timeLimitCodeLength { + return false, nil + } + +- minutes := setting.EmailCodeValidMinutes + code = code[:timeLimitCodeLength] + + // split code +- start := code[:12] +- lives := code[12:18] +- if d, err := com.StrTo(lives).Int(); err == nil { +- minutes = d ++ startStr := code[:timeLimitStartDateLength] ++ minutesStr := code[timeLimitStartDateLength : timeLimitStartDateLength+timeLimitMinutesLength] ++ minutes, err := strconv.Atoi(minutesStr) ++ if err != nil { ++ return false, fmt.Errorf("invalid time limit code: %v", err) + } + +- // right active code +- data := com.ToStr(user.Id) + user.Email + user.Login + user.Password + user.Rands +- retCode, err := createTimeLimitCode(data, minutes, start) ++ // verify code ++ payload := strconv.FormatInt(user.Id, 10) + user.Email + user.Login + user.Password + user.Rands ++ expectedCode, err := createTimeLimitCode(payload, minutes, startStr) + if err != nil { + return false, err + } +- fmt.Printf("code : %s\ncode2: %s", retCode, code) +- if retCode == code && minutes > 0 { ++ if hmac.Equal([]byte(code), []byte(expectedCode)) && minutes > 0 { + // check time is expired or not +- before, _ := time.ParseInLocation("200601021504", start, time.Local) ++ before, _ := time.ParseInLocation("200601021504", startStr, time.Local) + now := time.Now() + if before.Add(time.Minute*time.Duration(minutes)).Unix() > now.Unix() { + return true, nil +@@ -94,15 +98,15 @@ func getLoginForEmailCode(code string) string { + return string(b) + } + +-func createUserEmailCode(u *models.User, startInf interface{}) (string, error) { ++func createUserEmailCode(user *models.User, startStr string) (string, error) { + minutes := setting.EmailCodeValidMinutes +- data := com.ToStr(u.Id) + u.Email + u.Login + u.Password + u.Rands +- code, err := createTimeLimitCode(data, minutes, startInf) ++ payload := strconv.FormatInt(user.Id, 10) + user.Email + user.Login + user.Password + user.Rands ++ code, err := createTimeLimitCode(payload, minutes, startStr) + if err != nil { + return "", err + } + + // add tail hex username +- code += hex.EncodeToString([]byte(u.Login)) ++ code += hex.EncodeToString([]byte(user.Login)) + return code, nil + } +diff --git a/pkg/services/notifications/codes_test.go b/pkg/services/notifications/codes_test.go +index d2b1f3a617..bea88e0bf5 100644 +--- a/pkg/services/notifications/codes_test.go ++++ b/pkg/services/notifications/codes_test.go +@@ -1,19 +1,129 @@ + package notifications + + import ( ++ "fmt" ++ "strconv" + "testing" ++ "time" + + "github.com/grafana/grafana/pkg/models" + "github.com/grafana/grafana/pkg/setting" + . "github.com/smartystreets/goconvey/convey" ++ "github.com/stretchr/testify/require" + ) + ++func TestTimeLimitCodes(t *testing.T) { ++ user := &models.User{Id: 10, Email: "t@a.com", Login: "asd", Password: "1", Rands: "2"} ++ ++ format := "200601021504" ++ mailPayload := strconv.FormatInt(user.Id, 10) + user.Email + user.Login + user.Password + user.Rands ++ tenMinutesAgo := time.Now().Add(-time.Minute * 10) ++ ++ tests := []struct { ++ desc string ++ payload string ++ start time.Time ++ minutes int ++ valid bool ++ }{ ++ { ++ desc: "code generated 10 minutes ago, 5 minutes valid", ++ payload: mailPayload, ++ start: tenMinutesAgo, ++ minutes: 5, ++ valid: false, ++ }, ++ { ++ desc: "code generated 10 minutes ago, 9 minutes valid", ++ payload: mailPayload, ++ start: tenMinutesAgo, ++ minutes: 9, ++ valid: false, ++ }, ++ { ++ desc: "code generated 10 minutes ago, 10 minutes valid", ++ payload: mailPayload, ++ start: tenMinutesAgo, ++ minutes: 10, ++ // code was valid exactly 10 minutes since evaluating the tenMinutesAgo assignment ++ // by the time this test is run the code is already expired ++ valid: false, ++ }, ++ { ++ desc: "code generated 10 minutes ago, 11 minutes valid", ++ payload: mailPayload, ++ start: tenMinutesAgo, ++ minutes: 11, ++ valid: true, ++ }, ++ { ++ desc: "code generated 10 minutes ago, 20 minutes valid", ++ payload: mailPayload, ++ start: tenMinutesAgo, ++ minutes: 20, ++ valid: true, ++ }, ++ { ++ desc: "code generated 10 minutes ago, 20 minutes valid, tampered payload", ++ payload: mailPayload[:len(mailPayload)-1] + "x", ++ start: tenMinutesAgo, ++ minutes: 20, ++ valid: false, ++ }, ++ } ++ ++ for _, test := range tests { ++ t.Run(test.desc, func(t *testing.T) { ++ code, err := createTimeLimitCode(test.payload, test.minutes, test.start.Format(format)) ++ require.NoError(t, err) ++ ++ isValid, err := validateUserEmailCode(user, code) ++ require.NoError(t, err) ++ require.Equal(t, test.valid, isValid) ++ }) ++ } ++ ++ t.Run("tampered minutes", func(t *testing.T) { ++ code, err := createTimeLimitCode(mailPayload, 5, tenMinutesAgo.Format(format)) ++ require.NoError(t, err) ++ ++ // code is expired ++ isValid, err := validateUserEmailCode(user, code) ++ require.NoError(t, err) ++ require.Equal(t, false, isValid) ++ ++ // let's try to extend the code by tampering the minutes ++ code = code[:12] + fmt.Sprintf("%06d", 20) + code[18:] ++ isValid, err = validateUserEmailCode(user, code) ++ require.NoError(t, err) ++ require.Equal(t, false, isValid) ++ }) ++ ++ t.Run("tampered start string", func(t *testing.T) { ++ code, err := createTimeLimitCode(mailPayload, 5, tenMinutesAgo.Format(format)) ++ require.NoError(t, err) ++ ++ // code is expired ++ isValid, err := validateUserEmailCode(user, code) ++ require.NoError(t, err) ++ require.Equal(t, false, isValid) ++ ++ // let's try to extend the code by tampering the start string ++ oneMinuteAgo := time.Now().Add(-time.Minute) ++ ++ code = oneMinuteAgo.Format(format) + code[12:] ++ isValid, err = validateUserEmailCode(user, code) ++ require.NoError(t, err) ++ require.Equal(t, false, isValid) ++ }) ++} ++ + func TestEmailCodes(t *testing.T) { + Convey("When generating code", t, func() { + setting.EmailCodeValidMinutes = 120 + + user := &models.User{Id: 10, Email: "t@a.com", Login: "asd", Password: "1", Rands: "2"} +- code, err := createUserEmailCode(user, nil) ++ code, err := createUserEmailCode(user, "") + So(err, ShouldBeNil) + + Convey("getLoginForCode should return login", func() { +@@ -27,7 +137,7 @@ func TestEmailCodes(t *testing.T) { + So(isValid, ShouldBeTrue) + }) + +- Convey("Cannot verify in-valid code", func() { ++ Convey("Cannot verify invalid code", func() { + code = "ASD" + isValid, err := validateUserEmailCode(user, code) + So(err, ShouldBeNil) +diff --git a/pkg/services/notifications/notifications.go b/pkg/services/notifications/notifications.go +index beea82f43e..5a575d1415 100644 +--- a/pkg/services/notifications/notifications.go ++++ b/pkg/services/notifications/notifications.go +@@ -149,7 +149,7 @@ func (ns *NotificationService) sendEmailCommandHandler(cmd *models.SendEmailComm + } + + func (ns *NotificationService) sendResetPasswordEmail(cmd *models.SendResetPasswordEmailCommand) error { +- code, err := createUserEmailCode(cmd.User, nil) ++ code, err := createUserEmailCode(cmd.User, "") + if err != nil { + return err + } +diff --git a/pkg/services/notifications/notifications_test.go b/pkg/services/notifications/notifications_test.go +index e7680c3943..fb73e332ea 100644 +--- a/pkg/services/notifications/notifications_test.go ++++ b/pkg/services/notifications/notifications_test.go +@@ -1,12 +1,14 @@ + package notifications + + import ( ++ "regexp" + "testing" + + "github.com/grafana/grafana/pkg/bus" + "github.com/grafana/grafana/pkg/models" + "github.com/grafana/grafana/pkg/setting" + . "github.com/smartystreets/goconvey/convey" ++ "github.com/stretchr/testify/require" + ) + + func TestNotifications(t *testing.T) { +@@ -25,13 +27,28 @@ func TestNotifications(t *testing.T) { + So(err, ShouldBeNil) + + Convey("When sending reset email password", func() { +- err := ns.sendResetPasswordEmail(&models.SendResetPasswordEmailCommand{User: &models.User{Email: "asd@asd.com"}}) ++ user := models.User{Email: "asd@asd.com", Login: "asd@asd.com"} ++ err := ns.sendResetPasswordEmail(&models.SendResetPasswordEmailCommand{User: &user}) + So(err, ShouldBeNil) + + sentMsg := <-ns.mailQueue + So(sentMsg.Body, ShouldContainSubstring, "body") + So(sentMsg.Subject, ShouldEqual, "Reset your Grafana password - asd@asd.com") + So(sentMsg.Body, ShouldNotContainSubstring, "Subject") ++ ++ // find code in mail ++ r, _ := regexp.Compile(`code=(\w+)`) ++ match := r.FindString(sentMsg.Body) ++ code := match[len("code="):] ++ ++ // verify code ++ bus.AddHandler("test", func(query *models.GetUserByLoginQuery) error { ++ query.Result = &user ++ return nil ++ }) ++ query := models.ValidateResetPasswordCodeQuery{Code: code} ++ err = ns.validateResetPasswordCode(&query) ++ require.NoError(t, err) + }) + }) + } diff --git a/SOURCES/Makefile b/SOURCES/Makefile new file mode 100644 index 0000000..dab531d --- /dev/null +++ b/SOURCES/Makefile @@ -0,0 +1,77 @@ +VERSION := $(shell rpm --specfile *.spec --qf '%{VERSION}\n' | head -1) +RELEASE := $(shell rpm --specfile *.spec --qf '%{RELEASE}\n' | head -1 | cut -d. -f1) + +NAME := grafana +RPM_NAME := $(NAME) +SOURCE_DIR := $(NAME)-$(VERSION) +SOURCE_TAR := $(NAME)-$(VERSION).tar.gz +VENDOR_TAR := $(RPM_NAME)-vendor-$(VERSION)-$(RELEASE).tar.xz +WEBPACK_TAR := $(RPM_NAME)-webpack-$(VERSION)-$(RELEASE).tar.gz + +# patches which must be applied before creating the vendor tarball, for example: +# - changes in dependency versions +# - changes in Go module imports (which affect the vendored Go modules) +PATCHES_PRE_VENDOR := \ + 005-remove-unused-dependencies.patch \ + 008-remove-unused-frontend-crypto.patch + +# patches which must be applied before creating the webpack, for example: +# - changes in Node.js sources or vendored dependencies +PATCHES_PRE_WEBPACK := + + +all: $(SOURCE_TAR) $(VENDOR_TAR) $(WEBPACK_TAR) + +$(SOURCE_TAR): + spectool -g $(RPM_NAME).spec + +$(VENDOR_TAR): $(SOURCE_TAR) + # start with a clean state + rm -rf $(SOURCE_DIR) + tar xf $(SOURCE_TAR) + + # Patches to apply before vendoring + for patch in $(PATCHES_PRE_VENDOR); do echo applying $$patch ...; patch -d $(SOURCE_DIR) -p1 --fuzz=0 < $$patch; done + + # Go + cd $(SOURCE_DIR) && go mod vendor -v + # Remove unused crypto + rm $(SOURCE_DIR)/vendor/golang.org/x/crypto/cast5/cast5.go + rm $(SOURCE_DIR)/vendor/golang.org/x/crypto/ed25519/ed25519.go + rm $(SOURCE_DIR)/vendor/golang.org/x/crypto/ed25519/internal/edwards25519/const.go + rm $(SOURCE_DIR)/vendor/golang.org/x/crypto/ed25519/internal/edwards25519/edwards25519.go + rm $(SOURCE_DIR)/vendor/golang.org/x/crypto/openpgp/elgamal/elgamal.go + rm $(SOURCE_DIR)/vendor/golang.org/x/crypto/openpgp/packet/ocfb.go + awk '$$2~/^v/ && $$4 != "indirect" {print "Provides: bundled(golang(" $$1 ")) = " substr($$2, 2)}' $(SOURCE_DIR)/go.mod | \ + sed -E 's/=(.*)-(.*)-(.*)/=\1-\2.\3/g' > $@.manifest + + # Node.js + cd $(SOURCE_DIR) && yarn install --pure-lockfile + # Remove files with licensing issues + find $(SOURCE_DIR) -type d -name 'node-notifier' -prune -exec rm -r {} \; + find $(SOURCE_DIR) -type d -name 'property-information' -prune -exec rm -r {} \; + find $(SOURCE_DIR) -type f -name '*.exe' -delete + rm -r $(SOURCE_DIR)/node_modules/visjs-network/examples + ./list_bundled_nodejs_packages.py $(SOURCE_DIR) >> $@.manifest + + # Create tarball + XZ_OPT=-9 time -p tar cJf $@ \ + $(SOURCE_DIR)/vendor \ + $$(find $(SOURCE_DIR) -type d -name "node_modules" -prune) + +$(WEBPACK_TAR): $(VENDOR_TAR) + # start with a clean state + rm -rf $(SOURCE_DIR) + tar xf $(SOURCE_TAR) + tar xf $(VENDOR_TAR) + + # Patches to apply before creating the webpack + for patch in $(PATCHES_PRE_WEBPACK); do echo applying $$patch ...; patch -d $(SOURCE_DIR) -p1 --fuzz=0 < $$patch; done + + cd $(SOURCE_DIR) && \ + ../build_frontend.sh + + tar cfz $@ $(SOURCE_DIR)/public/build $(SOURCE_DIR)/public/views $(SOURCE_DIR)/plugins-bundled + +clean: + rm -rf *.tar.gz *.tar.xz *.manifest *.rpm $(NAME)-*/ diff --git a/SOURCES/build_frontend.sh b/SOURCES/build_frontend.sh new file mode 100755 index 0000000..fa0fb8e --- /dev/null +++ b/SOURCES/build_frontend.sh @@ -0,0 +1,17 @@ +#!/bin/bash -eu + +# Build the frontend +yarn run build + +# Build the bundled plugins +mkdir plugins-bundled/external +yarn run plugins:build-bundled +for plugin in plugins-bundled/internal/input-datasource; do + mv $plugin $plugin.tmp + mv $plugin.tmp/dist $plugin + rm -rf $plugin.tmp +done +rm plugins-bundled/README.md plugins-bundled/.gitignore plugins-bundled/external.json + +# Fix permissions (webpack sometimes outputs files with mode = 666 due to reasons unknown (race condition/umask issue afaics)) +chmod -R g-w,o-w public/build plugins-bundled diff --git a/SOURCES/distro-defaults.ini b/SOURCES/distro-defaults.ini new file mode 100644 index 0000000..daa0679 --- /dev/null +++ b/SOURCES/distro-defaults.ini @@ -0,0 +1,942 @@ +##################### Grafana Configuration Defaults ##################### +# +# Do not modify this file in grafana installs +# + +# possible values : production, development +app_mode = production + +# instance name, defaults to HOSTNAME environment variable value or hostname if HOSTNAME var is empty +instance_name = ${HOSTNAME} + +#################################### Paths ############################### +[paths] +# Path to where grafana can store temp files, sessions, and the sqlite3 db (if that is used) +data = /var/lib/grafana + +# Temporary files in `data` directory older than given duration will be removed +temp_data_lifetime = 24h + +# Directory where grafana can store logs +logs = /var/log/grafana + +# Directory where grafana will automatically scan and look for plugins +plugins = /var/lib/grafana/plugins + +# folder that contains provisioning config files that grafana will apply on startup and while running. +provisioning = /etc/grafana/provisioning + +#################################### Server ############################## +[server] +# Protocol (http, https, h2, socket) +protocol = http + +# The ip address to bind to, empty will bind to all interfaces +http_addr = + +# The http port to use +http_port = 3000 + +# The public facing domain name used to access grafana from a browser +domain = localhost + +# Redirect to correct domain if host header does not match domain +# Prevents DNS rebinding attacks +enforce_domain = false + +# The full public facing url +root_url = %(protocol)s://%(domain)s:%(http_port)s/ + +# Serve Grafana from subpath specified in `root_url` setting. By default it is set to `false` for compatibility reasons. +serve_from_sub_path = false + +# Log web requests +router_logging = false + +# the path relative working path +static_root_path = public + +# enable gzip +enable_gzip = false + +# https certs & key file +cert_file = +cert_key = + +# Unix socket path +socket = /tmp/grafana.sock + +# CDN Url +cdn_url = + +# Sets the maximum time in minutes before timing out read of an incoming request and closing idle connections. +# `0` means there is no timeout for reading the request. +read_timeout = 0 + +#################################### Database ############################ +[database] +# You can configure the database connection by specifying type, host, name, user and password +# as separate properties or as on string using the url property. + +# Either "mysql", "postgres" or "sqlite3", it's your choice +type = sqlite3 +host = 127.0.0.1:3306 +name = grafana +user = root +# If the password contains # or ; you have to wrap it with triple quotes. Ex """#password;""" +password = +# Use either URL or the previous fields to configure the database +# Example: mysql://user:secret@host:port/database +url = + +# Max idle conn setting default is 2 +max_idle_conn = 2 + +# Max conn setting default is 0 (mean not set) +max_open_conn = + +# Connection Max Lifetime default is 14400 (means 14400 seconds or 4 hours) +conn_max_lifetime = 14400 + +# Set to true to log the sql calls and execution times. +log_queries = + +# For "postgres", use either "disable", "require" or "verify-full" +# For "mysql", use either "true", "false", or "skip-verify". +ssl_mode = disable + +# Database drivers may support different transaction isolation levels. +# Currently, only "mysql" driver supports isolation levels. +# If the value is empty - driver's default isolation level is applied. +# For "mysql" use "READ-UNCOMMITTED", "READ-COMMITTED", "REPEATABLE-READ" or "SERIALIZABLE". +isolation_level = + +ca_cert_path = +client_key_path = +client_cert_path = +server_cert_name = + +# For "sqlite3" only, path relative to data_path setting +path = grafana.db + +# For "sqlite3" only. cache mode setting used for connecting to the database +cache_mode = private + +#################################### Cache server ############################# +[remote_cache] +# Either "redis", "memcached" or "database" default is "database" +type = database + +# cache connectionstring options +# database: will use Grafana primary database. +# redis: config like redis server e.g. `addr=127.0.0.1:6379,pool_size=100,db=0,ssl=false`. Only addr is required. ssl may be 'true', 'false', or 'insecure'. +# memcache: 127.0.0.1:11211 +connstr = + +#################################### Data proxy ########################### +[dataproxy] + +# This enables data proxy logging, default is false +logging = false + +# How long the data proxy waits before timing out, default is 30 seconds. +# This setting also applies to core backend HTTP data sources where query requests use an HTTP client with timeout set. +timeout = 30 + +# How many seconds the data proxy waits before sending a keepalive request. +keep_alive_seconds = 30 + +# How many seconds the data proxy waits for a successful TLS Handshake before timing out. +tls_handshake_timeout_seconds = 10 + +# How many seconds the data proxy will wait for a server's first response headers after +# fully writing the request headers if the request has an "Expect: 100-continue" +# header. A value of 0 will result in the body being sent immediately, without +# waiting for the server to approve. +expect_continue_timeout_seconds = 1 + +# Optionally limits the total number of connections per host, including connections in the dialing, +# active, and idle states. On limit violation, dials will block. +# A value of zero (0) means no limit. +max_conns_per_host = 0 + +# The maximum number of idle connections that Grafana will keep alive. +max_idle_connections = 100 + +# The maximum number of idle connections per host that Grafana will keep alive. +max_idle_connections_per_host = 2 + +# How many seconds the data proxy keeps an idle connection open before timing out. +idle_conn_timeout_seconds = 90 + +# If enabled and user is not anonymous, data proxy will add X-Grafana-User header with username into the request. +send_user_header = false + +#################################### Analytics ########################### +[analytics] +# Server reporting, sends usage counters to stats.grafana.org every 24 hours. +# No ip addresses are being tracked, only simple counters to track +# running instances, dashboard and error counts. It is very helpful to us. +# Change this option to false to disable reporting. +reporting_enabled = false + +# The name of the distributor of the Grafana instance. Ex hosted-grafana, grafana-labs +reporting_distributor = grafana-labs + +# Set to false to disable all checks to https://grafana.com +# for new versions (grafana itself and plugins), check is used +# in some UI views to notify that grafana or plugin update exists +# This option does not cause any auto updates, nor send any information +# only a GET request to https://grafana.com to get latest versions +check_for_updates = false + +# Google Analytics universal tracking code, only enabled if you specify an id here +google_analytics_ua_id = + +# Google Tag Manager ID, only enabled if you specify an id here +google_tag_manager_id = + +#################################### Security ############################ +[security] +# disable creation of admin user on first start of grafana +disable_initial_admin_creation = false + +# default admin user, created on startup +admin_user = admin + +# default admin password, can be changed before first start of grafana, or in profile settings +admin_password = admin + +# used for signing +secret_key = SW2YcwTIb9zpOOhoPsMm + +# disable gravatar profile images +disable_gravatar = false + +# data source proxy whitelist (ip_or_domain:port separated by spaces) +data_source_proxy_whitelist = + +# disable protection against brute force login attempts +disable_brute_force_login_protection = false + +# set to true if you host Grafana behind HTTPS. default is false. +cookie_secure = false + +# set cookie SameSite attribute. defaults to `lax`. can be set to "lax", "strict", "none" and "disabled" +cookie_samesite = lax + +# set to true if you want to allow browsers to render Grafana in a <frame>, <iframe>, <embed> or <object>. default is false. +allow_embedding = false + +# Set to true if you want to enable http strict transport security (HSTS) response header. +# This is only sent when HTTPS is enabled in this configuration. +# HSTS tells browsers that the site should only be accessed using HTTPS. +strict_transport_security = false + +# Sets how long a browser should cache HSTS. Only applied if strict_transport_security is enabled. +strict_transport_security_max_age_seconds = 86400 + +# Set to true if to enable HSTS preloading option. Only applied if strict_transport_security is enabled. +strict_transport_security_preload = false + +# Set to true if to enable the HSTS includeSubDomains option. Only applied if strict_transport_security is enabled. +strict_transport_security_subdomains = false + +# Set to true to enable the X-Content-Type-Options response header. +# The X-Content-Type-Options response HTTP header is a marker used by the server to indicate that the MIME types advertised +# in the Content-Type headers should not be changed and be followed. +x_content_type_options = true + +# Set to true to enable the X-XSS-Protection header, which tells browsers to stop pages from loading +# when they detect reflected cross-site scripting (XSS) attacks. +x_xss_protection = true + +# Enable adding the Content-Security-Policy header to your requests. +# CSP allows to control resources the user agent is allowed to load and helps prevent XSS attacks. +content_security_policy = false + +# Set Content Security Policy template used when adding the Content-Security-Policy header to your requests. +# $NONCE in the template includes a random nonce. +content_security_policy_template = """script-src 'unsafe-eval' 'strict-dynamic' $NONCE;object-src 'none';font-src 'self';style-src 'self' 'unsafe-inline';img-src 'self' data:;base-uri 'self';connect-src 'self' grafana.com;manifest-src 'self';media-src 'none';form-action 'self';""" + +#################################### Snapshots ########################### +[snapshots] +# snapshot sharing options +external_enabled = false +external_snapshot_url = https://snapshots-origin.raintank.io +external_snapshot_name = Publish to snapshot.raintank.io + +# Set to true to enable this Grafana instance act as an external snapshot server and allow unauthenticated requests for +# creating and deleting snapshots. +public_mode = false + +# remove expired snapshot +snapshot_remove_expired = true + +#################################### Dashboards ################## + +[dashboards] +# Number dashboard versions to keep (per dashboard). Default: 20, Minimum: 1 +versions_to_keep = 20 + +# Minimum dashboard refresh interval. When set, this will restrict users to set the refresh interval of a dashboard lower than given interval. Per default this is 5 seconds. +# The interval string is a possibly signed sequence of decimal numbers, followed by a unit suffix (ms, s, m, h, d), e.g. 30s or 1m. +min_refresh_interval = 1s + +# Path to the default home dashboard. If this value is empty, then Grafana uses StaticRootPath + "dashboards/home.json" +default_home_dashboard_path = + +################################### Data sources ######################### +[datasources] +# Upper limit of data sources that Grafana will return. This limit is a temporary configuration and it will be deprecated when pagination will be introduced on the list data sources API. +datasource_limit = 5000 + +#################################### Users ############################### +[users] +# disable user signup / registration +allow_sign_up = false + +# Allow non admin users to create organizations +allow_org_create = false + +# Set to true to automatically assign new users to the default organization (id 1) +auto_assign_org = true + +# Set this value to automatically add new users to the provided organization (if auto_assign_org above is set to true) +auto_assign_org_id = 1 + +# Default role new users will be automatically assigned (if auto_assign_org above is set to true) +auto_assign_org_role = Viewer + +# Require email validation before sign up completes +verify_email_enabled = false + +# Background text for the user field on the login page +login_hint = email or username +password_hint = password + +# Default UI theme ("dark" or "light") +default_theme = dark + +# Path to a custom home page. Users are only redirected to this if the default home dashboard is used. It should match a frontend route and contain a leading slash. +home_page = + +# External user management +external_manage_link_url = +external_manage_link_name = +external_manage_info = + +# Viewers can edit/inspect dashboard settings in the browser. But not save the dashboard. +viewers_can_edit = false + +# Editors can administrate dashboard, folders and teams they create +editors_can_admin = false + +# The duration in time a user invitation remains valid before expiring. This setting should be expressed as a duration. Examples: 6h (hours), 2d (days), 1w (week). Default is 24h (24 hours). The minimum supported duration is 15m (15 minutes). +user_invite_max_lifetime_duration = 24h + +# Enter a comma-separated list of usernames to hide them in the Grafana UI. These users are shown to Grafana admins and to themselves. +hidden_users = + +[auth] +# Login cookie name +login_cookie_name = grafana_session + +# The maximum lifetime (duration) an authenticated user can be inactive before being required to login at next visit. Default is 7 days (7d). This setting should be expressed as a duration, e.g. 5m (minutes), 6h (hours), 10d (days), 2w (weeks), 1M (month). The lifetime resets at each successful token rotation (token_rotation_interval_minutes). +login_maximum_inactive_lifetime_duration = + +# The maximum lifetime (duration) an authenticated user can be logged in since login time before being required to login. Default is 30 days (30d). This setting should be expressed as a duration, e.g. 5m (minutes), 6h (hours), 10d (days), 2w (weeks), 1M (month). +login_maximum_lifetime_duration = + +# How often should auth tokens be rotated for authenticated users when being active. The default is each 10 minutes. +token_rotation_interval_minutes = 10 + +# Set to true to disable (hide) the login form, useful if you use OAuth +disable_login_form = false + +# Set to true to disable the signout link in the side menu. useful if you use auth.proxy +disable_signout_menu = false + +# URL to redirect the user to after sign out +signout_redirect_url = + +# Set to true to attempt login with OAuth automatically, skipping the login screen. +# This setting is ignored if multiple OAuth providers are configured. +oauth_auto_login = false + +# OAuth state max age cookie duration in seconds. Defaults to 600 seconds. +oauth_state_cookie_max_age = 600 + +# limit of api_key seconds to live before expiration +api_key_max_seconds_to_live = -1 + +# Set to true to enable SigV4 authentication option for HTTP-based datasources +sigv4_auth_enabled = false + +#################################### Anonymous Auth ###################### +[auth.anonymous] +# enable anonymous access +enabled = false + +# specify organization name that should be used for unauthenticated users +org_name = Main Org. + +# specify role for unauthenticated users +org_role = Viewer + +# mask the Grafana version number for unauthenticated users +hide_version = false + +#################################### GitHub Auth ######################### +[auth.github] +enabled = false +allow_sign_up = true +client_id = some_id +client_secret = +scopes = user:email,read:org +auth_url = https://github.com/login/oauth/authorize +token_url = https://github.com/login/oauth/access_token +api_url = https://api.github.com/user +allowed_domains = +team_ids = +allowed_organizations = + +#################################### GitLab Auth ######################### +[auth.gitlab] +enabled = false +allow_sign_up = true +client_id = some_id +client_secret = +scopes = api +auth_url = https://gitlab.com/oauth/authorize +token_url = https://gitlab.com/oauth/token +api_url = https://gitlab.com/api/v4 +allowed_domains = +allowed_groups = + +#################################### Google Auth ######################### +[auth.google] +enabled = false +allow_sign_up = true +client_id = some_client_id +client_secret = +scopes = https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email +auth_url = https://accounts.google.com/o/oauth2/auth +token_url = https://accounts.google.com/o/oauth2/token +api_url = https://www.googleapis.com/oauth2/v1/userinfo +allowed_domains = +hosted_domain = + +#################################### Grafana.com Auth #################### +# legacy key names (so they work in env variables) +[auth.grafananet] +enabled = false +allow_sign_up = true +client_id = some_id +client_secret = +scopes = user:email +allowed_organizations = + +[auth.grafana_com] +enabled = false +allow_sign_up = true +client_id = some_id +client_secret = +scopes = user:email +allowed_organizations = + +#################################### Azure AD OAuth ####################### +[auth.azuread] +name = Azure AD +enabled = false +allow_sign_up = true +client_id = some_client_id +client_secret = +scopes = openid email profile +auth_url = https://login.microsoftonline.com/<tenant-id>/oauth2/v2.0/authorize +token_url = https://login.microsoftonline.com/<tenant-id>/oauth2/v2.0/token +allowed_domains = +allowed_groups = + +#################################### Okta OAuth ####################### +[auth.okta] +name = Okta +enabled = false +allow_sign_up = true +client_id = some_id +client_secret = +scopes = openid profile email groups +auth_url = https://<tenant-id>.okta.com/oauth2/v1/authorize +token_url = https://<tenant-id>.okta.com/oauth2/v1/token +api_url = https://<tenant-id>.okta.com/oauth2/v1/userinfo +allowed_domains = +allowed_groups = +role_attribute_path = + +#################################### Generic OAuth ####################### +[auth.generic_oauth] +name = OAuth +enabled = false +allow_sign_up = true +client_id = some_id +client_secret = +scopes = user:email +email_attribute_name = email:primary +email_attribute_path = +login_attribute_path = +name_attribute_path = +role_attribute_path = +id_token_attribute_name = +auth_url = +token_url = +api_url = +allowed_domains = +team_ids = +allowed_organizations = +tls_skip_verify_insecure = false +tls_client_cert = +tls_client_key = +tls_client_ca = + +#################################### Basic Auth ########################## +[auth.basic] +enabled = true + +#################################### Auth Proxy ########################## +[auth.proxy] +enabled = false +header_name = X-WEBAUTH-USER +header_property = username +auto_sign_up = true +# Deprecated, use sync_ttl instead +ldap_sync_ttl = 60 +sync_ttl = 60 +whitelist = +headers = +enable_login_token = false + +#################################### Auth LDAP ########################### +[auth.ldap] +enabled = false +config_file = /etc/grafana/ldap.toml +allow_sign_up = true + +# LDAP background sync (Enterprise only) +# At 1 am every day +sync_cron = "0 0 1 * * *" +active_sync_enabled = true + +#################################### AWS ########################### +[aws] +# Enter a comma-separated list of allowed AWS authentication providers. +# Options are: default (AWS SDK Default), keys (Access && secret key), credentials (Credentials field), ec2_iam_role (EC2 IAM Role) +allowed_auth_providers = default,keys,credentials + +# Allow AWS users to assume a role using temporary security credentials. +# If true, assume role will be enabled for all AWS authentication providers that are specified in aws_auth_providers +assume_role_enabled = true + +# Specify max no of pages to be returned by the ListMetricPages API +list_metrics_page_limit = 500 + +#################################### SMTP / Emailing ##################### +[smtp] +enabled = false +host = localhost:25 +user = +# If the password contains # or ; you have to wrap it with triple quotes. Ex """#password;""" +password = +cert_file = +key_file = +skip_verify = false +from_address = admin@grafana.localhost +from_name = Grafana +ehlo_identity = +startTLS_policy = + +[emails] +welcome_email_on_sign_up = false +templates_pattern = emails/*.html + +#################################### Logging ########################## +[log] +# Either "console", "file", "syslog". Default is console and file +# Use space to separate multiple modes, e.g. "console file" +mode = console file + +# Either "debug", "info", "warn", "error", "critical", default is "info" +level = info + +# optional settings to set different levels for specific loggers. Ex filters = sqlstore:debug +filters = + +# For "console" mode only +[log.console] +level = + +# log line format, valid options are text, console and json +format = console + +# For "file" mode only +[log.file] +level = + +# log line format, valid options are text, console and json +format = text + +# This enables automated log rotate(switch of following options), default is true +log_rotate = true + +# Max line number of single file, default is 1000000 +max_lines = 1000000 + +# Max size shift of single file, default is 28 means 1 << 28, 256MB +max_size_shift = 28 + +# Segment log daily, default is true +daily_rotate = true + +# Expired days of log file(delete after max days), default is 7 +max_days = 7 + +[log.syslog] +level = + +# log line format, valid options are text, console and json +format = text + +# Syslog network type and address. This can be udp, tcp, or unix. If left blank, the default unix endpoints will be used. +network = +address = + +# Syslog facility. user, daemon and local0 through local7 are valid. +facility = + +# Syslog tag. By default, the process' argv[0] is used. +tag = + +[log.frontend] +# Should Sentry javascript agent be initialized +enabled = false + +# Sentry DSN if you want to send events to Sentry. +sentry_dsn = + +# Custom HTTP endpoint to send events captured by the Sentry agent to. Default will log the events to stdout. +custom_endpoint = /log + +# Rate of events to be reported between 0 (none) and 1 (all), float +sample_rate = 1.0 + +# Requests per second limit enforced per an extended period, for Grafana backend log ingestion endpoint (/log). +log_endpoint_requests_per_second_limit = 3 + +# Max requests accepted per short interval of time for Grafana backend log ingestion endpoint (/log) +log_endpoint_burst_limit = 15 + +#################################### Usage Quotas ######################## +[quota] +enabled = false + +#### set quotas to -1 to make unlimited. #### +# limit number of users per Org. +org_user = 10 + +# limit number of dashboards per Org. +org_dashboard = 100 + +# limit number of data_sources per Org. +org_data_source = 10 + +# limit number of api_keys per Org. +org_api_key = 10 + +# limit number of orgs a user can create. +user_org = 10 + +# Global limit of users. +global_user = -1 + +# global limit of orgs. +global_org = -1 + +# global limit of dashboards +global_dashboard = -1 + +# global limit of api_keys +global_api_key = -1 + +# global limit on number of logged in users. +global_session = -1 + +#################################### Alerting ############################ +[alerting] +# Disable alerting engine & UI features +enabled = true +# Makes it possible to turn off alert rule execution but alerting UI is visible +execute_alerts = true + +# Default setting for new alert rules. Defaults to categorize error and timeouts as alerting. (alerting, keep_state) +error_or_timeout = alerting + +# Default setting for how Grafana handles nodata or null values in alerting. (alerting, no_data, keep_state, ok) +nodata_or_nullvalues = no_data + +# Alert notifications can include images, but rendering many images at the same time can overload the server +# This limit will protect the server from render overloading and make sure notifications are sent out quickly +concurrent_render_limit = 5 + +# Default setting for alert calculation timeout. Default value is 30 +evaluation_timeout_seconds = 30 + +# Default setting for alert notification timeout. Default value is 30 +notification_timeout_seconds = 30 + +# Default setting for max attempts to sending alert notifications. Default value is 3 +max_attempts = 3 + +# Makes it possible to enforce a minimal interval between evaluations, to reduce load on the backend +min_interval_seconds = 1 + +# Configures for how long alert annotations are stored. Default is 0, which keeps them forever. +# This setting should be expressed as an duration. Ex 6h (hours), 10d (days), 2w (weeks), 1M (month). +max_annotation_age = + +# Configures max number of alert annotations that Grafana stores. Default value is 0, which keeps all alert annotations. +max_annotations_to_keep = + +#################################### Annotations ######################### +[annotations] +# Configures the batch size for the annotation clean-up job. This setting is used for dashboard, API, and alert annotations. +cleanupjob_batchsize = 100 + +[annotations.dashboard] +# Dashboard annotations means that annotations are associated with the dashboard they are created on. + +# Configures how long dashboard annotations are stored. Default is 0, which keeps them forever. +# This setting should be expressed as a duration. Examples: 6h (hours), 10d (days), 2w (weeks), 1M (month). +max_age = + +# Configures max number of dashboard annotations that Grafana stores. Default value is 0, which keeps all dashboard annotations. +max_annotations_to_keep = + +[annotations.api] +# API annotations means that the annotations have been created using the API without any +# association with a dashboard. + +# Configures how long Grafana stores API annotations. Default is 0, which keeps them forever. +# This setting should be expressed as a duration. Examples: 6h (hours), 10d (days), 2w (weeks), 1M (month). +max_age = + +# Configures max number of API annotations that Grafana keeps. Default value is 0, which keeps all API annotations. +max_annotations_to_keep = + +#################################### Explore ############################# +[explore] +# Enable the Explore section +enabled = true + +#################################### Internal Grafana Metrics ############ +# Metrics available at HTTP API Url /metrics +[metrics] +enabled = true +interval_seconds = 10 +# Disable total stats (stat_totals_*) metrics to be generated +disable_total_stats = false + +#If both are set, basic auth will be required for the metrics endpoint. +basic_auth_username = +basic_auth_password = + +# Metrics environment info adds dimensions to the `grafana_environment_info` metric, which +# can expose more information about the Grafana instance. +[metrics.environment_info] +#exampleLabel1 = exampleValue1 +#exampleLabel2 = exampleValue2 + +# Send internal Grafana metrics to graphite +[metrics.graphite] +# Enable by setting the address setting (ex localhost:2003) +address = +prefix = prod.grafana.%(instance_name)s. + +#################################### Grafana.com integration ########################## +[grafana_net] +url = https://grafana.com + +[grafana_com] +url = https://grafana.com + +#################################### Distributed tracing ############ +[tracing.jaeger] +# jaeger destination (ex localhost:6831) +address = +# tag that will always be included in when creating new spans. ex (tag1:value1,tag2:value2) +always_included_tag = +# Type specifies the type of the sampler: const, probabilistic, rateLimiting, or remote +sampler_type = const +# jaeger samplerconfig param +# for "const" sampler, 0 or 1 for always false/true respectively +# for "probabilistic" sampler, a probability between 0 and 1 +# for "rateLimiting" sampler, the number of spans per second +# for "remote" sampler, param is the same as for "probabilistic" +# and indicates the initial sampling rate before the actual one +# is received from the mothership +sampler_param = 1 +# sampling_server_url is the URL of a sampling manager providing a sampling strategy. +sampling_server_url = +# Whether or not to use Zipkin span propagation (x-b3- HTTP headers). +zipkin_propagation = false +# Setting this to true disables shared RPC spans. +# Not disabling is the most common setting when using Zipkin elsewhere in your infrastructure. +disable_shared_zipkin_spans = false + +#################################### External Image Storage ############## +[external_image_storage] +# Used for uploading images to public servers so they can be included in slack/email messages. +# You can choose between (s3, webdav, gcs, azure_blob, local) +provider = + +[external_image_storage.s3] +endpoint = +path_style_access = +bucket_url = +bucket = +region = +path = +access_key = +secret_key = + +[external_image_storage.webdav] +url = +username = +password = +public_url = + +[external_image_storage.gcs] +key_file = +bucket = +path = +enable_signed_urls = false +signed_url_expiration = + +[external_image_storage.azure_blob] +account_name = +account_key = +container_name = + +[external_image_storage.local] +# does not require any configuration + +[rendering] +# Options to configure a remote HTTP image rendering service, e.g. using https://github.com/grafana/grafana-image-renderer. +# URL to a remote HTTP image renderer service, e.g. http://localhost:8081/render, will enable Grafana to render panels and dashboards to PNG-images using HTTP requests to an external service. +server_url = +# If the remote HTTP image renderer service runs on a different server than the Grafana server you may have to configure this to a URL where Grafana is reachable, e.g. http://grafana.domain/. +callback_url = +# Concurrent render request limit affects when the /render HTTP endpoint is used. Rendering many images at the same time can overload the server, +# which this setting can help protect against by only allowing a certain amount of concurrent requests. +concurrent_render_request_limit = 30 + +[panels] +# here for to support old env variables, can remove after a few months +enable_alpha = false +disable_sanitize_html = false + +[plugins] +enable_alpha = false +app_tls_skip_verify_insecure = false +# Enter a comma-separated list of plugin identifiers to identify plugins that are allowed to be loaded even if they lack a valid signature. +allow_loading_unsigned_plugins = pcp-redis-datasource +marketplace_url = https://grafana.com/grafana/plugins/ + +#################################### Grafana Image Renderer Plugin ########################## +[plugin.grafana-image-renderer] +# Instruct headless browser instance to use a default timezone when not provided by Grafana, e.g. when rendering panel image of alert. +# See ICU’s metaZones.txt (https://cs.chromium.org/chromium/src/third_party/icu/source/data/misc/metaZones.txt) for a list of supported +# timezone IDs. Fallbacks to TZ environment variable if not set. +rendering_timezone = + +# Instruct headless browser instance to use a default language when not provided by Grafana, e.g. when rendering panel image of alert. +# Please refer to the HTTP header Accept-Language to understand how to format this value, e.g. 'fr-CH, fr;q=0.9, en;q=0.8, de;q=0.7, *;q=0.5'. +rendering_language = + +# Instruct headless browser instance to use a default device scale factor when not provided by Grafana, e.g. when rendering panel image of alert. +# Default is 1. Using a higher value will produce more detailed images (higher DPI), but will require more disk space to store an image. +rendering_viewport_device_scale_factor = + +# Instruct headless browser instance whether to ignore HTTPS errors during navigation. Per default HTTPS errors are not ignored. Due to +# the security risk it's not recommended to ignore HTTPS errors. +rendering_ignore_https_errors = + +# Instruct headless browser instance whether to capture and log verbose information when rendering an image. Default is false and will +# only capture and log error messages. When enabled, debug messages are captured and logged as well. +# For the verbose information to be included in the Grafana server log you have to adjust the rendering log level to debug, configure +# [log].filter = rendering:debug. +rendering_verbose_logging = + +# Instruct headless browser instance whether to output its debug and error messages into running process of remote rendering service. +# Default is false. This can be useful to enable (true) when troubleshooting. +rendering_dumpio = + +# Additional arguments to pass to the headless browser instance. Default is --no-sandbox. The list of Chromium flags can be found +# here (https://peter.sh/experiments/chromium-command-line-switches/). Multiple arguments is separated with comma-character. +rendering_args = + +# You can configure the plugin to use a different browser binary instead of the pre-packaged version of Chromium. +# Please note that this is not recommended, since you may encounter problems if the installed version of Chrome/Chromium is not +# compatible with the plugin. +rendering_chrome_bin = + +# Instruct how headless browser instances are created. Default is 'default' and will create a new browser instance on each request. +# Mode 'clustered' will make sure that only a maximum of browsers/incognito pages can execute concurrently. +# Mode 'reusable' will have one browser instance and will create a new incognito page on each request. +rendering_mode = + +# When rendering_mode = clustered you can instruct how many browsers or incognito pages can execute concurrently. Default is 'browser' +# and will cluster using browser instances. +# Mode 'context' will cluster using incognito pages. +rendering_clustering_mode = +# When rendering_mode = clustered you can define maximum number of browser instances/incognito pages that can execute concurrently.. +rendering_clustering_max_concurrency = + +# Limit the maximum viewport width, height and device scale factor that can be requested. +rendering_viewport_max_width = +rendering_viewport_max_height = +rendering_viewport_max_device_scale_factor = + +# Change the listening host and port of the gRPC server. Default host is 127.0.0.1 and default port is 0 and will automatically assign +# a port not in use. +grpc_host = +grpc_port = + +[enterprise] +license_path = + +[feature_toggles] +# enable features, separated by spaces +enable = + +[date_formats] +# For information on what formatting patterns that are supported https://momentjs.com/docs/#/displaying/ + +# Default system date format used in time range picker and other places where full time is displayed +full_date = YYYY-MM-DD HH:mm:ss + +# Used by graph and other places where we only show small intervals +interval_second = HH:mm:ss +interval_minute = HH:mm +interval_hour = MM/DD HH:mm +interval_day = MM/DD +interval_month = YYYY-MM +interval_year = YYYY + +# Experimental feature +use_browser_locale = false + +# Default timezone for user preferences. Options are 'browser' for the browser local timezone or a timezone name from IANA Time Zone database, e.g. 'UTC' or 'Europe/Amsterdam' etc. +default_timezone = browser + +[expressions] +# Enable or disable the expressions functionality. +enabled = true diff --git a/SOURCES/list_bundled_nodejs_packages.py b/SOURCES/list_bundled_nodejs_packages.py new file mode 100755 index 0000000..3158c2c --- /dev/null +++ b/SOURCES/list_bundled_nodejs_packages.py @@ -0,0 +1,47 @@ +#!/usr/bin/env python3 +# +# generates Provides: bundled(npm(...)) = ... lines for each declared dependency and devDependency of package.json +# +import sys +import json +import re +from packaging import version + + +def read_declared_pkgs(package_json_path): + with open(package_json_path) as f: + package_json = json.load(f) + return list(package_json['dependencies'].keys()) + list(package_json['devDependencies'].keys()) + + +def read_installed_pkgs(yarn_lock_path): + with open(yarn_lock_path) as f: + lockfile = f.read() + return re.findall(r'^"?' # can start with a " + r'(.+?)@.+(?:,.*)?:\n' # characters up to @ + r' version "(.+)"', # and the version + lockfile, re.MULTILINE) + + +def list_provides(declared_pkgs, installed_pkgs): + for declared_pkg in declared_pkgs: + # there can be multiple versions installed of one package (transitive dependencies) + # but rpm doesn't support Provides: with a single package and multiple versions + # so let's declare the oldest version here + versions = [version.parse(pkg_version) + for pkg_name, pkg_version in installed_pkgs if pkg_name == declared_pkg] + oldest_version = sorted(versions)[0] + yield f"Provides: bundled(npm({declared_pkg})) = {oldest_version}" + + +if __name__ == "__main__": + if len(sys.argv) != 2: + print(f"usage: {sys.argv[0]} package-X.Y.Z/", file=sys.stdout) + sys.exit(1) + + package_dir = sys.argv[1] + declared_pkgs = read_declared_pkgs(f"{package_dir}/package.json") + installed_pkgs = read_installed_pkgs(f"{package_dir}/yarn.lock") + provides = list_provides(declared_pkgs, installed_pkgs) + for provide in sorted(provides): + print(provide) diff --git a/SPECS/grafana.spec b/SPECS/grafana.spec new file mode 100644 index 0000000..4a986e5 --- /dev/null +++ b/SPECS/grafana.spec @@ -0,0 +1,914 @@ +# gobuild and gotest macros are not available on CentOS Stream +# remove once BZ 1965292 is resolved +# definitions lifted from Fedora 34 podman.spec +%if ! 0%{?gobuild:1} +%define gobuild(o:) GO111MODULE=off go build -buildmode pie -compiler gc -tags="rpm_crashtraceback ${BUILDTAGS:-}" -ldflags "${LDFLAGS:-} -B 0x$(head -c20 /dev/urandom|od -An -tx1|tr -d ' \\n') -extldflags '-Wl,-z,relro -Wl,-z,now -specs=/usr/lib/rpm/redhat/redhat-hardened-ld '" -a -v -x %{?**}; +%endif +%if ! 0%{?gotest:1} +%define gotest() GO111MODULE=off go test -buildmode pie -compiler gc -ldflags "${LDFLAGS:-} -extldflags '-Wl,-z,relro -Wl,-z,now -specs=/usr/lib/rpm/redhat/redhat-hardened-ld '" %{?**}; +%endif + +%global grafana_arches %{lua: go_arches = {} + for arch in rpm.expand("%{go_arches}"):gmatch("%S+") do + go_arches[arch] = 1 + end + for arch in rpm.expand("%{nodejs_arches}"):gmatch("%S+") do + if go_arches[arch] then + print(arch .. " ") + end +end} + +# Specify if the frontend will be compiled as part of the build or +# is attached as a webpack tarball (in case of an unsuitable nodejs version on the build system) +%define compile_frontend 0 + +%if 0%{?rhel} +%define enable_fips_mode 1 +%else +%define enable_fips_mode 0 +%endif + +Name: grafana +Version: 7.5.11 +Release: 4%{?dist} +Summary: Metrics dashboard and graph editor +License: ASL 2.0 +URL: https://grafana.org + +# Source0 contains the tagged upstream sources +Source0: https://github.com/grafana/grafana/archive/v%{version}/%{name}-%{version}.tar.gz + +# Source1 contains the bundled Go and Node.js dependencies +# Note: In case there were no changes to this tarball, the NVR of this tarball +# lags behind the NVR of this package. +Source1: grafana-vendor-%{version}-1.tar.xz + +%if %{compile_frontend} == 0 +# Source2 contains the precompiled frontend +# Note: In case there were no changes to this tarball, the NVR of this tarball +# lags behind the NVR of this package. +Source2: grafana-webpack-%{version}-1.tar.gz +%endif + +# Source3 contains Grafana configuration defaults for distributions +Source3: distro-defaults.ini + +# Source4 contains the Makefile to create the required bundles +Source4: Makefile + +# Source5 contains the script to build the frontend +Source5: build_frontend.sh + +# Source6 contains the script to generate the list of bundled nodejs packages +Source6: list_bundled_nodejs_packages.py + +# Patches +Patch1: 001-wrappers-grafana-cli.patch +Patch2: 002-manpages.patch + +# resolve symlinks before comparing paths +# BUILD/src/github.com/grafana/grafana -> BUILD/grafana-X.Y.Z +Patch3: 003-fix-dashboard-abspath-test.patch + +# Required for s390x +# the golden files include memory dumps from a x86 machine +# integers are stored as little endian on x86, but as big endian on s390x +# therefore loading this memory dump fails on s390x +Patch4: 004-skip-x86-goldenfiles-tests.patch + +Patch5: 005-remove-unused-dependencies.patch + +Patch6: 006-fix-gtime-test-32bit.patch + +Patch8: 008-remove-unused-frontend-crypto.patch + +# The Makefile removes a few files with crypto implementations +# from the vendor tarball, which are not used in Grafana. +# This patch removes all references to the deleted files. +Patch9: 009-patch-unused-backend-crypto.patch + +# This patch modifies the x/crypto/pbkdf2 function to use OpenSSL +# if FIPS mode is enabled. +Patch10: 010-fips.patch + +Patch11: 011-CVE-2021-43813.patch + +Patch12: 012-use-hmac-sha-256-for-password-reset-tokens.patch + +# Intersection of go_arches and nodejs_arches +ExclusiveArch: %{grafana_arches} + +BuildRequires: systemd, golang, go-srpm-macros +%if 0%{?fedora} >= 31 +BuildRequires: go-rpm-macros +%endif + +%if %{compile_frontend} +BuildRequires: nodejs >= 1:14, yarnpkg +%endif + +%if %{enable_fips_mode} +BuildRequires: openssl-devel + +# only required for running the FIPS test +BuildRequires: openssl +%endif + +# omit golang debugsource, see BZ995136 and related +%global dwz_low_mem_die_limit 0 +%global _debugsource_template %{nil} + +%global GRAFANA_USER %{name} +%global GRAFANA_GROUP %{name} +%global GRAFANA_HOME %{_datadir}/%{name} + +# grafana-server service daemon uses systemd +%{?systemd_requires} +Requires(pre): shadow-utils + +%if 0%{?fedora} || 0%{?rhel} > 7 +Recommends: grafana-pcp +%endif + +Obsoletes: grafana-cloudwatch < 7.3.6-1 +Obsoletes: grafana-elasticsearch < 7.3.6-1 +Obsoletes: grafana-azure-monitor < 7.3.6-1 +Obsoletes: grafana-graphite < 7.3.6-1 +Obsoletes: grafana-influxdb < 7.3.6-1 +Obsoletes: grafana-loki < 7.3.6-1 +Obsoletes: grafana-mssql < 7.3.6-1 +Obsoletes: grafana-mysql < 7.3.6-1 +Obsoletes: grafana-opentsdb < 7.3.6-1 +Obsoletes: grafana-postgres < 7.3.6-1 +Obsoletes: grafana-prometheus < 7.3.6-1 +Obsoletes: grafana-stackdriver < 7.3.6-1 +Provides: grafana-cloudwatch = 7.3.6-1 +Provides: grafana-elasticsearch = 7.3.6-1 +Provides: grafana-azure-monitor = 7.3.6-1 +Provides: grafana-graphite = 7.3.6-1 +Provides: grafana-influxdb = 7.3.6-1 +Provides: grafana-loki = 7.3.6-1 +Provides: grafana-mssql = 7.3.6-1 +Provides: grafana-mysql = 7.3.6-1 +Provides: grafana-opentsdb = 7.3.6-1 +Provides: grafana-postgres = 7.3.6-1 +Provides: grafana-prometheus = 7.3.6-1 +Provides: grafana-stackdriver = 7.3.6-1 + +# vendored golang and node.js build dependencies +# this is for security purposes, if nodejs-foo ever needs an update, +# affected packages can be easily identified. +# Note: generated by the Makefile (see README.md) +Provides: bundled(golang(cloud.google.com/go/storage)) = 1.13.0 +Provides: bundled(golang(github.com/BurntSushi/toml)) = 0.3.1 +Provides: bundled(golang(github.com/VividCortex/mysqlerr)) = 0.0.0-20170204212430.6c6b55f8796f +Provides: bundled(golang(github.com/aws/aws-sdk-go)) = 1.37.20 +Provides: bundled(golang(github.com/beevik/etree)) = 1.1.0 +Provides: bundled(golang(github.com/benbjohnson/clock)) = 0.0.0-20161215174838.7dc76406b6d3 +Provides: bundled(golang(github.com/bradfitz/gomemcache)) = 0.0.0-20190913173617.a41fca850d0b +Provides: bundled(golang(github.com/centrifugal/centrifuge)) = 0.13.0 +Provides: bundled(golang(github.com/cortexproject/cortex)) = 1.4.1-0.20201022071705.85942c5703cf +Provides: bundled(golang(github.com/davecgh/go-spew)) = 1.1.1 +Provides: bundled(golang(github.com/denisenkom/go-mssqldb)) = 0.0.0-20200910202707.1e08a3fab204 +Provides: bundled(golang(github.com/facebookgo/inject)) = 0.0.0-20180706035515.f23751cae28b +Provides: bundled(golang(github.com/fatih/color)) = 1.10.0 +Provides: bundled(golang(github.com/gchaincl/sqlhooks)) = 1.3.0 +Provides: bundled(golang(github.com/getsentry/sentry-go)) = 0.10.0 +Provides: bundled(golang(github.com/go-macaron/binding)) = 0.0.0-20190806013118.0b4f37bab25b +Provides: bundled(golang(github.com/go-macaron/gzip)) = 0.0.0-20160222043647.cad1c6580a07 +Provides: bundled(golang(github.com/go-sourcemap/sourcemap)) = 2.1.3+incompatible +Provides: bundled(golang(github.com/go-sql-driver/mysql)) = 1.5.0 +Provides: bundled(golang(github.com/go-stack/stack)) = 1.8.0 +Provides: bundled(golang(github.com/gobwas/glob)) = 0.2.3 +Provides: bundled(golang(github.com/golang/mock)) = 1.5.0 +Provides: bundled(golang(github.com/golang/protobuf)) = 1.4.3 +Provides: bundled(golang(github.com/google/go-cmp)) = 0.5.4 +Provides: bundled(golang(github.com/google/uuid)) = 1.2.0 +Provides: bundled(golang(github.com/gosimple/slug)) = 1.9.0 +Provides: bundled(golang(github.com/grafana/grafana-aws-sdk)) = 0.4.0 +Provides: bundled(golang(github.com/grafana/grafana-plugin-model)) = 0.0.0-20190930120109.1fc953a61fb4 +Provides: bundled(golang(github.com/grafana/grafana-plugin-sdk-go)) = 0.88.0 +Provides: bundled(golang(github.com/grafana/loki)) = 1.6.2-0.20201026154740.6978ee5d7387 +Provides: bundled(golang(github.com/grpc-ecosystem/go-grpc-middleware)) = 1.2.2 +Provides: bundled(golang(github.com/hashicorp/go-hclog)) = 0.15.0 +Provides: bundled(golang(github.com/hashicorp/go-plugin)) = 1.4.0 +Provides: bundled(golang(github.com/hashicorp/go-version)) = 1.2.1 +Provides: bundled(golang(github.com/inconshreveable/log15)) = 0.0.0-20180818164646.67afb5ed74ec +Provides: bundled(golang(github.com/influxdata/influxdb-client-go/v2)) = 2.2.0 +Provides: bundled(golang(github.com/jaegertracing/jaeger)) = 1.22.1-0.20210304164023.2fff3ca58910 +Provides: bundled(golang(github.com/jmespath/go-jmespath)) = 0.4.0 +Provides: bundled(golang(github.com/json-iterator/go)) = 1.1.10 +Provides: bundled(golang(github.com/lib/pq)) = 1.9.0 +Provides: bundled(golang(github.com/linkedin/goavro/v2)) = 2.10.0 +Provides: bundled(golang(github.com/magefile/mage)) = 1.11.0 +Provides: bundled(golang(github.com/mattn/go-isatty)) = 0.0.12 +Provides: bundled(golang(github.com/mattn/go-sqlite3)) = 1.14.6 +Provides: bundled(golang(github.com/mwitkow/go-conntrack)) = 0.0.0-20190716064945.2f068394615f +Provides: bundled(golang(github.com/opentracing/opentracing-go)) = 1.2.0 +Provides: bundled(golang(github.com/patrickmn/go-cache)) = 2.1.0+incompatible +Provides: bundled(golang(github.com/pkg/errors)) = 0.9.1 +Provides: bundled(golang(github.com/prometheus/client_golang)) = 1.9.0 +Provides: bundled(golang(github.com/prometheus/client_model)) = 0.2.0 +Provides: bundled(golang(github.com/prometheus/common)) = 0.18.0 +Provides: bundled(golang(github.com/robfig/cron)) = 0.0.0-20180505203441.b41be1df6967 +Provides: bundled(golang(github.com/robfig/cron/v3)) = 3.0.1 +Provides: bundled(golang(github.com/russellhaering/goxmldsig)) = 1.1.0 +Provides: bundled(golang(github.com/smartystreets/goconvey)) = 1.6.4 +Provides: bundled(golang(github.com/stretchr/testify)) = 1.7.0 +Provides: bundled(golang(github.com/teris-io/shortid)) = 0.0.0-20171029131806.771a37caa5cf +Provides: bundled(golang(github.com/timberio/go-datemath)) = 0.1.1-0.20200323150745.74ddef604fff +Provides: bundled(golang(github.com/ua-parser/uap-go)) = 0.0.0-20190826212731.daf92ba38329 +Provides: bundled(golang(github.com/uber/jaeger-client-go)) = 2.25.0+incompatible +Provides: bundled(golang(github.com/unknwon/com)) = 1.0.1 +Provides: bundled(golang(github.com/urfave/cli/v2)) = 2.3.0 +Provides: bundled(golang(github.com/weaveworks/common)) = 0.0.0-20201119133501.0619918236ec +Provides: bundled(golang(github.com/xorcare/pointer)) = 1.1.0 +Provides: bundled(golang(github.com/yudai/gojsondiff)) = 1.0.0 +Provides: bundled(golang(go.opentelemetry.io/collector)) = 0.21.0 +Provides: bundled(golang(golang.org/x/crypto)) = 0.0.0-20201221181555.eec23a3978ad +Provides: bundled(golang(golang.org/x/net)) = 0.0.0-20210119194325.5f4716e94777 +Provides: bundled(golang(golang.org/x/oauth2)) = 0.0.0-20210113205817.d3ed898aa8a3 +Provides: bundled(golang(golang.org/x/sync)) = 0.0.0-20201207232520.09787c993a3a +Provides: bundled(golang(golang.org/x/time)) = 0.0.0-20200630173020.3af7569d3a1e +Provides: bundled(golang(gonum.org/v1/gonum)) = 0.8.2 +Provides: bundled(golang(google.golang.org/api)) = 0.40.0 +Provides: bundled(golang(google.golang.org/grpc)) = 1.36.0 +Provides: bundled(golang(gopkg.in/ini.v1)) = 1.62.0 +Provides: bundled(golang(gopkg.in/ldap.v3)) = 3.0.2 +Provides: bundled(golang(gopkg.in/macaron.v1)) = 1.4.0 +Provides: bundled(golang(gopkg.in/mail.v2)) = 2.3.1 +Provides: bundled(golang(gopkg.in/redis.v5)) = 5.2.9 +Provides: bundled(golang(gopkg.in/square/go-jose.v2)) = 2.5.1 +Provides: bundled(golang(gopkg.in/yaml.v2)) = 2.4.0 +Provides: bundled(golang(xorm.io/core)) = 0.7.3 +Provides: bundled(golang(xorm.io/xorm)) = 0.8.2 +Provides: bundled(npm(@babel/core)) = 7.6.4 +Provides: bundled(npm(@babel/plugin-proposal-nullish-coalescing-operator)) = 7.8.3 +Provides: bundled(npm(@babel/plugin-proposal-optional-chaining)) = 7.8.3 +Provides: bundled(npm(@babel/plugin-syntax-dynamic-import)) = 7.7.4 +Provides: bundled(npm(@babel/preset-env)) = 7.7.4 +Provides: bundled(npm(@babel/preset-react)) = 7.8.3 +Provides: bundled(npm(@babel/preset-typescript)) = 7.8.3 +Provides: bundled(npm(@emotion/core)) = 10.0.21 +Provides: bundled(npm(@grafana/api-documenter)) = 7.11.2 +Provides: bundled(npm(@grafana/api-extractor)) = 7.10.1 +Provides: bundled(npm(@grafana/aws-sdk)) = 0.0.3 +Provides: bundled(npm(@grafana/eslint-config)) = 2.3.0 +Provides: bundled(npm(@grafana/slate-react)) = 0.22.9-grafana +Provides: bundled(npm(@popperjs/core)) = 2.5.4 +Provides: bundled(npm(@reduxjs/toolkit)) = 1.5.0 +Provides: bundled(npm(@rtsao/plugin-proposal-class-properties)) = 7.0.1-patch.1 +Provides: bundled(npm(@sentry/browser)) = 5.25.0 +Provides: bundled(npm(@sentry/types)) = 5.24.2 +Provides: bundled(npm(@sentry/utils)) = 5.24.2 +Provides: bundled(npm(@testing-library/jest-dom)) = 5.11.5 +Provides: bundled(npm(@testing-library/react)) = 11.1.2 +Provides: bundled(npm(@testing-library/react-hooks)) = 3.2.1 +Provides: bundled(npm(@testing-library/user-event)) = 12.1.3 +Provides: bundled(npm(@torkelo/react-select)) = 3.0.8 +Provides: bundled(npm(@types/angular)) = 1.6.56 +Provides: bundled(npm(@types/angular-route)) = 1.7.0 +Provides: bundled(npm(@types/antlr4)) = 4.7.1 +Provides: bundled(npm(@types/braintree__sanitize-url)) = 4.0.0 +Provides: bundled(npm(@types/classnames)) = 2.2.7 +Provides: bundled(npm(@types/clipboard)) = 2.0.1 +Provides: bundled(npm(@types/common-tags)) = 1.8.0 +Provides: bundled(npm(@types/d3)) = 5.7.2 +Provides: bundled(npm(@types/d3-force)) = 1.2.1 +Provides: bundled(npm(@types/d3-scale-chromatic)) = 1.3.1 +Provides: bundled(npm(@types/debounce-promise)) = 3.1.3 +Provides: bundled(npm(@types/enzyme)) = 3.10.3 +Provides: bundled(npm(@types/enzyme-adapter-react-16)) = 1.0.6 +Provides: bundled(npm(@types/file-saver)) = 2.0.1 +Provides: bundled(npm(@types/hoist-non-react-statics)) = 3.3.1 +Provides: bundled(npm(@types/is-hotkey)) = 0.1.1 +Provides: bundled(npm(@types/jest)) = 26.0.12 +Provides: bundled(npm(@types/jquery)) = 3.3.38 +Provides: bundled(npm(@types/jsurl)) = 1.2.28 +Provides: bundled(npm(@types/lodash)) = 4.14.123 +Provides: bundled(npm(@types/lru-cache)) = 5.1.0 +Provides: bundled(npm(@types/md5)) = 2.1.33 +Provides: bundled(npm(@types/moment-timezone)) = 0.5.13 +Provides: bundled(npm(@types/mousetrap)) = 1.6.3 +Provides: bundled(npm(@types/node)) = 10.14.1 +Provides: bundled(npm(@types/papaparse)) = 5.2.0 +Provides: bundled(npm(@types/prismjs)) = 1.16.0 +Provides: bundled(npm(@types/react)) = 16.9.9 +Provides: bundled(npm(@types/react-beautiful-dnd)) = 12.1.2 +Provides: bundled(npm(@types/react-dom)) = 16.9.2 +Provides: bundled(npm(@types/react-grid-layout)) = 1.1.1 +Provides: bundled(npm(@types/react-loadable)) = 5.5.2 +Provides: bundled(npm(@types/react-redux)) = 7.1.7 +Provides: bundled(npm(@types/react-select)) = 3.0.8 +Provides: bundled(npm(@types/react-test-renderer)) = 16.9.1 +Provides: bundled(npm(@types/react-transition-group)) = 4.2.3 +Provides: bundled(npm(@types/react-virtualized-auto-sizer)) = 1.0.0 +Provides: bundled(npm(@types/react-window)) = 1.8.1 +Provides: bundled(npm(@types/redux-logger)) = 3.0.7 +Provides: bundled(npm(@types/redux-mock-store)) = 1.0.2 +Provides: bundled(npm(@types/reselect)) = 2.2.0 +Provides: bundled(npm(@types/slate)) = 0.47.1 +Provides: bundled(npm(@types/slate-plain-serializer)) = 0.6.1 +Provides: bundled(npm(@types/slate-react)) = 0.22.5 +Provides: bundled(npm(@types/testing-library__jest-dom)) = 5.9.5 +Provides: bundled(npm(@types/testing-library__react-hooks)) = 3.1.0 +Provides: bundled(npm(@types/tinycolor2)) = 1.4.1 +Provides: bundled(npm(@types/uuid)) = 8.3.0 +Provides: bundled(npm(@typescript-eslint/eslint-plugin)) = 4.15.0 +Provides: bundled(npm(@typescript-eslint/parser)) = 4.15.0 +Provides: bundled(npm(@welldone-software/why-did-you-render)) = 4.0.6 +Provides: bundled(npm(@wojtekmaj/enzyme-adapter-react-17)) = 0.3.1 +Provides: bundled(npm(abortcontroller-polyfill)) = 1.4.0 +Provides: bundled(npm(angular)) = 1.8.2 +Provides: bundled(npm(angular-bindonce)) = 0.3.1 +Provides: bundled(npm(angular-mocks)) = 1.6.6 +Provides: bundled(npm(angular-route)) = 1.8.2 +Provides: bundled(npm(angular-sanitize)) = 1.8.2 +Provides: bundled(npm(antlr4)) = 4.8.0 +Provides: bundled(npm(autoprefixer)) = 9.7.4 +Provides: bundled(npm(axios)) = 0.21.1 +Provides: bundled(npm(babel-core)) = 7.0.0-bridge.0 +Provides: bundled(npm(babel-jest)) = 26.6.3 +Provides: bundled(npm(babel-loader)) = 8.0.6 +Provides: bundled(npm(babel-plugin-angularjs-annotate)) = 0.10.0 +Provides: bundled(npm(baron)) = 3.0.3 +Provides: bundled(npm(brace)) = 0.11.1 +Provides: bundled(npm(calculate-size)) = 1.1.1 +Provides: bundled(npm(centrifuge)) = 2.6.4 +Provides: bundled(npm(classnames)) = 2.2.6 +Provides: bundled(npm(clean-webpack-plugin)) = 3.0.0 +Provides: bundled(npm(clipboard)) = 2.0.4 +Provides: bundled(npm(common-tags)) = 1.8.0 +Provides: bundled(npm(core-js)) = 1.2.7 +Provides: bundled(npm(css-loader)) = 3.4.2 +Provides: bundled(npm(d3)) = 5.15.0 +Provides: bundled(npm(d3-force)) = 1.2.1 +Provides: bundled(npm(d3-scale-chromatic)) = 1.5.0 +Provides: bundled(npm(dangerously-set-html-content)) = 1.0.6 +Provides: bundled(npm(debounce-promise)) = 3.1.2 +Provides: bundled(npm(emotion)) = 10.0.27 +Provides: bundled(npm(enzyme)) = 3.11.0 +Provides: bundled(npm(enzyme-to-json)) = 3.4.4 +Provides: bundled(npm(es-abstract)) = 1.18.0-next.1 +Provides: bundled(npm(es6-promise)) = 4.2.8 +Provides: bundled(npm(es6-shim)) = 0.35.5 +Provides: bundled(npm(eslint)) = 2.13.1 +Provides: bundled(npm(eslint-config-prettier)) = 7.2.0 +Provides: bundled(npm(eslint-plugin-jsdoc)) = 31.6.1 +Provides: bundled(npm(eslint-plugin-no-only-tests)) = 2.4.0 +Provides: bundled(npm(eslint-plugin-prettier)) = 3.3.1 +Provides: bundled(npm(eslint-plugin-react)) = 7.22.0 +Provides: bundled(npm(eslint-plugin-react-hooks)) = 4.2.0 +Provides: bundled(npm(eventemitter3)) = 3.1.2 +Provides: bundled(npm(expect.js)) = 0.3.1 +Provides: bundled(npm(expose-loader)) = 0.7.5 +Provides: bundled(npm(fast-text-encoding)) = 1.0.0 +Provides: bundled(npm(file-loader)) = 5.0.2 +Provides: bundled(npm(file-saver)) = 2.0.2 +Provides: bundled(npm(fork-ts-checker-webpack-plugin)) = 1.0.0 +Provides: bundled(npm(gaze)) = 1.1.3 +Provides: bundled(npm(glob)) = 7.1.3 +Provides: bundled(npm(hoist-non-react-statics)) = 2.5.5 +Provides: bundled(npm(html-loader)) = 0.5.5 +Provides: bundled(npm(html-webpack-harddisk-plugin)) = 1.0.1 +Provides: bundled(npm(html-webpack-plugin)) = 3.2.0 +Provides: bundled(npm(husky)) = 4.2.1 +Provides: bundled(npm(immutable)) = 3.8.2 +Provides: bundled(npm(is-hotkey)) = 0.1.4 +Provides: bundled(npm(jest)) = 26.6.3 +Provides: bundled(npm(jest-canvas-mock)) = 2.3.0 +Provides: bundled(npm(jest-date-mock)) = 1.0.8 +Provides: bundled(npm(jest-matcher-utils)) = 26.0.0 +Provides: bundled(npm(jquery)) = 3.5.1 +Provides: bundled(npm(jsurl)) = 0.1.5 +Provides: bundled(npm(lerna)) = 3.22.1 +Provides: bundled(npm(lint-staged)) = 10.0.7 +Provides: bundled(npm(load-grunt-tasks)) = 5.1.0 +Provides: bundled(npm(lodash)) = 4.17.21 +Provides: bundled(npm(lru-cache)) = 4.1.5 +Provides: bundled(npm(md5)) = 2.2.1 +Provides: bundled(npm(memoize-one)) = 4.1.0 +Provides: bundled(npm(mini-css-extract-plugin)) = 0.7.0 +Provides: bundled(npm(mocha)) = 7.0.1 +Provides: bundled(npm(module-alias)) = 2.2.2 +Provides: bundled(npm(moment)) = 2.24.0 +Provides: bundled(npm(moment-timezone)) = 0.5.28 +Provides: bundled(npm(monaco-editor)) = 0.20.0 +Provides: bundled(npm(monaco-editor-webpack-plugin)) = 1.9.0 +Provides: bundled(npm(mousetrap)) = 1.6.5 +Provides: bundled(npm(mousetrap-global-bind)) = 1.1.0 +Provides: bundled(npm(mutationobserver-shim)) = 0.3.3 +Provides: bundled(npm(ngtemplate-loader)) = 2.0.1 +Provides: bundled(npm(nodemon)) = 2.0.2 +Provides: bundled(npm(optimize-css-assets-webpack-plugin)) = 5.0.4 +Provides: bundled(npm(papaparse)) = 5.3.0 +Provides: bundled(npm(postcss-browser-reporter)) = 0.6.0 +Provides: bundled(npm(postcss-loader)) = 3.0.0 +Provides: bundled(npm(postcss-reporter)) = 6.0.1 +Provides: bundled(npm(prettier)) = 2.0.5 +Provides: bundled(npm(prismjs)) = 1.21.0 +Provides: bundled(npm(prop-types)) = 15.7.2 +Provides: bundled(npm(rc-cascader)) = 1.0.1 +Provides: bundled(npm(re-resizable)) = 6.2.0 +Provides: bundled(npm(react)) = 16.13.1 +Provides: bundled(npm(react-beautiful-dnd)) = 13.0.0 +Provides: bundled(npm(react-dom)) = 17.0.1 +Provides: bundled(npm(react-grid-layout)) = 1.2.0 +Provides: bundled(npm(react-highlight-words)) = 0.16.0 +Provides: bundled(npm(react-hot-loader)) = 4.8.0 +Provides: bundled(npm(react-loadable)) = 5.5.0 +Provides: bundled(npm(react-popper)) = 2.2.4 +Provides: bundled(npm(react-redux)) = 7.2.0 +Provides: bundled(npm(react-reverse-portal)) = 2.0.1 +Provides: bundled(npm(react-select-event)) = 5.1.0 +Provides: bundled(npm(react-sizeme)) = 2.6.12 +Provides: bundled(npm(react-split-pane)) = 0.1.89 +Provides: bundled(npm(react-test-renderer)) = 16.10.2 +Provides: bundled(npm(react-transition-group)) = 4.3.0 +Provides: bundled(npm(react-use)) = 13.27.0 +Provides: bundled(npm(react-virtualized-auto-sizer)) = 1.0.2 +Provides: bundled(npm(react-window)) = 1.8.5 +Provides: bundled(npm(redux)) = 3.7.2 +Provides: bundled(npm(redux-logger)) = 3.0.6 +Provides: bundled(npm(redux-mock-store)) = 1.5.4 +Provides: bundled(npm(redux-thunk)) = 2.3.0 +Provides: bundled(npm(regenerator-runtime)) = 0.11.1 +Provides: bundled(npm(regexp-replace-loader)) = 1.0.1 +Provides: bundled(npm(reselect)) = 4.0.0 +Provides: bundled(npm(rimraf)) = 2.6.3 +Provides: bundled(npm(rst2html)) = 1.0.4 +Provides: bundled(npm(rxjs)) = 6.5.5 +Provides: bundled(npm(rxjs-spy)) = 7.5.1 +Provides: bundled(npm(sass)) = 1.27.0 +Provides: bundled(npm(sass-lint)) = 1.12.1 +Provides: bundled(npm(sass-loader)) = 8.0.2 +Provides: bundled(npm(search-query-parser)) = 1.5.4 +Provides: bundled(npm(sinon)) = 8.1.1 +Provides: bundled(npm(slate)) = 0.47.8 +Provides: bundled(npm(slate-plain-serializer)) = 0.7.10 +Provides: bundled(npm(style-loader)) = 1.1.3 +Provides: bundled(npm(terser-webpack-plugin)) = 1.4.5 +Provides: bundled(npm(tether)) = 1.4.7 +Provides: bundled(npm(tether-drop)) = 1.5.0 +Provides: bundled(npm(tinycolor2)) = 1.4.1 +Provides: bundled(npm(ts-jest)) = 26.4.4 +Provides: bundled(npm(ts-node)) = 9.0.0 +Provides: bundled(npm(tslib)) = 1.10.0 +Provides: bundled(npm(tti-polyfill)) = 0.2.2 +Provides: bundled(npm(typescript)) = 3.9.7 +Provides: bundled(npm(uuid)) = 3.3.3 +Provides: bundled(npm(visjs-network)) = 4.25.0 +Provides: bundled(npm(webpack)) = 4.41.5 +Provides: bundled(npm(webpack-bundle-analyzer)) = 3.6.0 +Provides: bundled(npm(webpack-cleanup-plugin)) = 0.5.1 +Provides: bundled(npm(webpack-cli)) = 3.3.10 +Provides: bundled(npm(webpack-dev-server)) = 3.11.1 +Provides: bundled(npm(webpack-merge)) = 4.2.2 +Provides: bundled(npm(whatwg-fetch)) = 3.0.0 +Provides: bundled(npm(zone.js)) = 0.7.8 + + +%description +Grafana is an open source, feature rich metrics dashboard and graph editor for +Graphite, InfluxDB & OpenTSDB. + + +%prep +%setup -q -T -D -b 0 +%setup -q -T -D -b 1 +%if %{compile_frontend} == 0 +# remove bundled plugins source, otherwise they'll get merged +# with the compiled bundled plugins when extracting the webpack +rm -r plugins-bundled +%setup -q -T -D -b 2 +%endif + +%patch1 -p1 +%patch2 -p1 +%patch3 -p1 +%ifarch s390x +%patch4 -p1 +%endif +%patch5 -p1 +%patch6 -p1 +%patch8 -p1 +%patch9 -p1 +%if %{enable_fips_mode} +%patch10 -p1 +%endif +%patch11 -p1 +%patch12 -p1 + +# Set up build subdirs and links +mkdir -p %{_builddir}/src/github.com/grafana +ln -s %{_builddir}/%{name}-%{version} \ + %{_builddir}/src/github.com/grafana/grafana + + +%build +# Build the frontend +%if %{compile_frontend} +%{SOURCE5} +%endif + +# Build the backend +cd %{_builddir}/src/github.com/grafana/grafana +export GOPATH=%{_builddir} + +# see grafana-X.X.X/build.go +export LDFLAGS="-X main.version=%{version} -X main.buildstamp=${SOURCE_DATE_EPOCH}" +for cmd in grafana-cli grafana-server; do + %gobuild -o %{_builddir}/bin/${cmd} ./pkg/cmd/${cmd} +done + + +%install +# dirs, shared files, public html, webpack +install -d %{buildroot}%{_sbindir} +install -d %{buildroot}%{_datadir}/%{name} +install -d %{buildroot}%{_libexecdir}/%{name} +cp -a conf public plugins-bundled %{buildroot}%{_datadir}/%{name} + +# wrappers +install -p -m 755 packaging/wrappers/grafana-cli %{buildroot}%{_sbindir}/%{name}-cli + +# binaries +install -p -m 755 %{_builddir}/bin/%{name}-server %{buildroot}%{_sbindir} +install -p -m 755 %{_builddir}/bin/%{name}-cli %{buildroot}%{_libexecdir}/%{name} + +# man pages +install -d %{buildroot}%{_mandir}/man1 +install -p -m 644 docs/man/man1/* %{buildroot}%{_mandir}/man1 + +# config dirs +install -d %{buildroot}%{_sysconfdir}/%{name} +install -d %{buildroot}%{_sysconfdir}/%{name}/provisioning +install -d %{buildroot}%{_sysconfdir}/%{name}/provisioning/dashboards +install -d %{buildroot}%{_sysconfdir}/%{name}/provisioning/datasources +install -d %{buildroot}%{_sysconfdir}/%{name}/provisioning/notifiers +install -d %{buildroot}%{_sysconfdir}/%{name}/provisioning/plugins +install -d %{buildroot}%{_sysconfdir}/sysconfig + +# config defaults +install -p -m 640 %{SOURCE3} %{buildroot}%{_sysconfdir}/%{name}/grafana.ini +install -p -m 640 conf/ldap.toml %{buildroot}%{_sysconfdir}/%{name}/ldap.toml +install -p -m 644 %{SOURCE3} %{buildroot}%{_datadir}/%{name}/conf/defaults.ini +install -p -m 644 packaging/rpm/sysconfig/grafana-server \ + %{buildroot}%{_sysconfdir}/sysconfig/grafana-server + +# config database directory and plugins +install -d -m 750 %{buildroot}%{_sharedstatedir}/%{name} +install -d -m 755 %{buildroot}%{_sharedstatedir}/%{name}/plugins + +# log directory +install -d %{buildroot}%{_localstatedir}/log/%{name} + +# systemd service files +install -d %{buildroot}%{_unitdir} # only needed for manual rpmbuilds +install -p -m 644 packaging/rpm/systemd/grafana-server.service \ + %{buildroot}%{_unitdir} + +# daemon run pid file config for using tmpfs +install -d %{buildroot}%{_tmpfilesdir} +echo "d %{_rundir}/%{name} 0755 %{GRAFANA_USER} %{GRAFANA_GROUP} -" \ + > %{buildroot}%{_tmpfilesdir}/%{name}.conf + +%pre +getent group %{GRAFANA_GROUP} >/dev/null || groupadd -r %{GRAFANA_GROUP} +getent passwd %{GRAFANA_USER} >/dev/null || \ + useradd -r -g %{GRAFANA_GROUP} -d %{GRAFANA_HOME} -s /sbin/nologin \ + -c "%{GRAFANA_USER} user account" %{GRAFANA_USER} +exit 0 + +%preun +%systemd_preun grafana-server.service + +%post +%systemd_post grafana-server.service +# create grafana.db with secure permissions on new installations +# otherwise grafana-server is creating grafana.db on first start +# with world-readable permissions, which may leak encrypted datasource +# passwords to all users (if the secret_key in grafana.ini was not changed) + +# https://bugzilla.redhat.com/show_bug.cgi?id=1805472 +if [ "$1" = 1 ] && [ ! -f %{_sharedstatedir}/%{name}/grafana.db ]; then + touch %{_sharedstatedir}/%{name}/grafana.db +fi + +# apply secure permissions to grafana.db if it exists +# (may not exist on upgrades, because users can choose between sqlite/mysql/postgres) +if [ -f %{_sharedstatedir}/%{name}/grafana.db ]; then + chown %{GRAFANA_USER}:%{GRAFANA_GROUP} %{_sharedstatedir}/%{name}/grafana.db + chmod 640 %{_sharedstatedir}/%{name}/grafana.db +fi + +# required for upgrades +chmod 640 %{_sysconfdir}/%{name}/grafana.ini +chmod 640 %{_sysconfdir}/%{name}/ldap.toml + +%postun +%systemd_postun_with_restart grafana-server.service + + +%check +# Test frontend +%if %{compile_frontend} +node_modules/.bin/jest +%endif + +# Test backend +cd %{_builddir}/src/github.com/grafana/grafana +export GOPATH=%{_builddir} + +# in setting_test.go there is a unit test which checks if 10 days are 240 hours +# which is usually true except if the dayligt saving time change falls into the last 10 days, then it's either 239 or 241 hours... +# let's set the time zone to a time zone without daylight saving time +export TZ=GMT + +# GO111MODULE=on automatically skips vendored macaron sources in pkg/macaron +# GO111MODULE=off doesn't skip them, and fails with an error due to the canoncial import path +rm -r pkg/macaron + +%gotest ./pkg/... + +%if %{enable_fips_mode} +OPENSSL_FORCE_FIPS_MODE=1 GOLANG_FIPS=1 go test -v ./pkg/util -run TestEncryption +%endif + +%files +# binaries and wrappers +%{_sbindir}/%{name}-server +%{_sbindir}/%{name}-cli +%{_libexecdir}/%{name} + +# config files +%config(noreplace) %{_sysconfdir}/sysconfig/grafana-server +%dir %{_sysconfdir}/%{name} +%attr(0755, root, %{GRAFANA_GROUP}) %dir %{_sysconfdir}/%{name}/provisioning +%attr(0755, root, %{GRAFANA_GROUP}) %dir %{_sysconfdir}/%{name}/provisioning/dashboards +%attr(0750, root, %{GRAFANA_GROUP}) %dir %{_sysconfdir}/%{name}/provisioning/datasources +%attr(0755, root, %{GRAFANA_GROUP}) %dir %{_sysconfdir}/%{name}/provisioning/notifiers +%attr(0755, root, %{GRAFANA_GROUP}) %dir %{_sysconfdir}/%{name}/provisioning/plugins +%attr(0640, root, %{GRAFANA_GROUP}) %config(noreplace) %{_sysconfdir}/%{name}/grafana.ini +%attr(0640, root, %{GRAFANA_GROUP}) %config(noreplace) %{_sysconfdir}/%{name}/ldap.toml + +# config database directory and plugins +%attr(0750, %{GRAFANA_USER}, %{GRAFANA_GROUP}) %dir %{_sharedstatedir}/%{name} +%attr(-, %{GRAFANA_USER}, %{GRAFANA_GROUP}) %dir %{_sharedstatedir}/%{name}/plugins + +# shared directory and all files therein +%{_datadir}/%{name} +%attr(-, root, %{GRAFANA_GROUP}) %{_datadir}/%{name}/conf/* + +# systemd service file +%{_unitdir}/grafana-server.service + +# Grafana configuration to dynamically create /run/grafana/grafana.pid on tmpfs +%{_tmpfilesdir}/%{name}.conf + +# log directory - grafana.log is created by grafana-server, and it does it's own log rotation +%attr(0755, %{GRAFANA_USER}, %{GRAFANA_GROUP}) %dir %{_localstatedir}/log/%{name} + +# man pages for grafana binaries +%{_mandir}/man1/%{name}-server.1* +%{_mandir}/man1/%{name}-cli.1* + +# other docs and license +%license LICENSE +%doc CHANGELOG.md CODE_OF_CONDUCT.md CONTRIBUTING.md GOVERNANCE.md ISSUE_TRIAGE.md MAINTAINERS.md NOTICE.md +%doc PLUGIN_DEV.md README.md ROADMAP.md SECURITY.md SUPPORT.md UPGRADING_DEPENDENCIES.md WORKFLOW.md + + +%changelog +* Fri Mar 18 2022 Andreas Gerstmayr <agerstmayr@redhat.com> 7.5.11-4 +- resolves rhbz#1975396 + +* Tue Jan 18 2022 Andreas Gerstmayr <agerstmayr@redhat.com> 7.5.11-3 +- use HMAC-SHA-256 instead of SHA-1 to generate password reset tokens +- update FIPS tests in check phase + +* Thu Dec 16 2021 Andreas Gerstmayr <agerstmayr@redhat.com> 7.5.11-2 +- resolve CVE-2021-44716 golang: net/http: limit growth of header canonicalization cache +- resolve CVE-2021-43813 grafana: directory traversal vulnerability for *.md files + +* Mon Oct 11 2021 Andreas Gerstmayr <agerstmayr@redhat.com> 7.5.11-1 +- update to 7.5.11 tagged upstream community sources, see CHANGELOG +- resolve CVE-2021-39226 + +* Thu Sep 30 2021 Andreas Gerstmayr <agerstmayr@redhat.com> 7.5.10-1 +- update to 7.5.10 tagged upstream community sources, see CHANGELOG + +* Mon Aug 09 2021 Mohan Boddu <mboddu@redhat.com> - 7.5.9-3 +- Rebuilt for IMA sigs, glibc 2.34, aarch64 flags + Related: rhbz#1991688 + +* Thu Jul 08 2021 Andreas Gerstmayr <agerstmayr@redhat.com> 7.5.9-2 +- remove unused dependency property-information +- always include FIPS patch in SRPM + +* Fri Jun 25 2021 Andreas Gerstmayr <agerstmayr@redhat.com> 7.5.9-1 +- update to 7.5.9 tagged upstream community sources, see CHANGELOG + +* Tue Jun 22 2021 Mohan Boddu <mboddu@redhat.com> - 7.5.8-2 +- Rebuilt for RHEL 9 BETA for openssl 3.0 + Related: rhbz#1971065 + +* Mon Jun 21 2021 Andreas Gerstmayr <agerstmayr@redhat.com> 7.5.8-1 +- update to 7.5.8 tagged upstream community sources, see CHANGELOG +- remove unused dependencies selfsigned, http-signature and gofpdf + +* Fri Jun 11 2021 Andreas Gerstmayr <agerstmayr@redhat.com> 7.5.7-2 +- remove unused cryptographic implementations +- use cryptographic functions from OpenSSL if FIPS mode is enabled + +* Tue May 25 2021 Andreas Gerstmayr <agerstmayr@redhat.com> 7.5.7-1 +- update to 7.5.7 tagged upstream community sources, see CHANGELOG + +* Thu Apr 15 2021 Mohan Boddu <mboddu@redhat.com> - 7.3.6-4 +- Rebuilt for RHEL 9 BETA on Apr 15th 2021. Related: rhbz#1947937 + +* Tue Jan 26 2021 Fedora Release Engineering <releng@fedoraproject.org> - 7.3.6-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild + +* Fri Jan 22 2021 Andreas Gerstmayr <agerstmayr@redhat.com> 7.3.6-2 +- change working dir to $GRAFANA_HOME in grafana-cli wrapper (fixes Red Hat BZ #1916083) +- add pcp-redis-datasource to allow_loading_unsigned_plugins config option + +* Mon Dec 21 2020 Andreas Gerstmayr <agerstmayr@redhat.com> 7.3.6-1 +- update to 7.3.6 tagged upstream community sources, see CHANGELOG +- remove dependency on SAML (not supported in the open source version of Grafana) + +* Wed Nov 25 2020 Andreas Gerstmayr <agerstmayr@redhat.com> 7.3.4-1 +- update to 7.3.4 tagged upstream community sources, see CHANGELOG + +* Tue Nov 10 2020 Andreas Gerstmayr <agerstmayr@redhat.com> 7.3.1-1 +- update to 7.3.1 tagged upstream community sources, see CHANGELOG +- optionally bundle node.js dependencies and build and test frontend as part of the specfile +- change default provisioning path to /etc/grafana/provisioning (changed in version 7.1.1-1) +- resolve https://bugzilla.redhat.com/show_bug.cgi?id=1843170 + +* Sat Aug 01 2020 Fedora Release Engineering <releng@fedoraproject.org> - 7.1.1-2 +- Second attempt - Rebuilt for + https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild + +* Thu Jul 30 2020 Andreas Gerstmayr <agerstmayr@redhat.com> 7.1.1-1 +- update to 7.1.1 tagged upstream community sources, see CHANGELOG +- merge all datasources into main grafana package +- bundle golang dependencies + +* Tue Jul 28 2020 Fedora Release Engineering <releng@fedoraproject.org> - 6.7.4-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild + +* Fri Jun 05 2020 Andreas Gerstmayr <agerstmayr@redhat.com> 6.7.4-1 +- update to 6.7.4 tagged upstream community sources, see CHANGELOG +- security fix for CVE-2020-13379 + +* Tue Apr 28 2020 Andreas Gerstmayr <agerstmayr@redhat.com> 6.7.3-1 +- update to 6.7.3 tagged upstream community sources, see CHANGELOG +- add scripts to list Go dependencies and bundled npmjs dependencies +- set Grafana version in Grafana UI and grafana-cli --version +- declare README.md as documentation of datasource plugins +- create grafana.db on first installation (fixes RH BZ #1805472) +- change permissions of /var/lib/grafana to 750 (CVE-2020-12458) +- change permissions of /var/lib/grafana/grafana.db to 640 and + user/group grafana:grafana (CVE-2020-12458) +- change permissions of grafana.ini and ldap.toml to 640 (CVE-2020-12459) + +* Wed Feb 26 2020 Mark Goodwin <mgoodwin@redhat.com> 6.6.2-1 +- added patch0 to set the version string correctly +- removed patch 004-xerrors.patch, it's now upstream +- added several patches for golang vendored vrs build dep differences +- added patch to move grafana-cli binary to libexec dir +- update to 6.6.2 tagged upstream community sources, see CHANGELOG + +* Wed Nov 20 2019 Mark Goodwin <mgoodwin@redhat.com> 6.3.6-1 +- add weak depenency on grafana-pcp +- add patch to mute shellcheck SC1090 for grafana-cli +- update to 6.3.6 upstream community sources, see CHANGELOG + +* Thu Sep 05 2019 Mark Goodwin <mgoodwin@redhat.com> 6.3.5-1 +- drop uaparser patch now it's upstream +- add xerrors patch, see https://github.com/golang/go/issues/32246 +- use vendor sources on rawhide until modules are fully supported +- update to latest upstream community sources, see CHANGELOG + +* Fri Aug 30 2019 Mark Goodwin <mgoodwin@redhat.com> 6.3.4-1 +- include fix for CVE-2019-15043 +- add patch for uaparser on 32bit systems +- update to latest upstream community sources, see CHANGELOG + +* Wed Jul 31 2019 Mark Goodwin <mgoodwin@redhat.com> 6.2.5-1 +- update to latest upstream community sources, see CHANGELOG + +* Thu Jul 25 2019 Fedora Release Engineering <releng@fedoraproject.org> - 6.2.2-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild + +* Fri Jun 07 2019 Mark Goodwin <mgoodwin@redhat.com> 6.2.2-1 +- split out some datasource plugins to sub-packages +- update to latest upstream community sources, see CHANGELOG + +* Wed Jun 05 2019 Mark Goodwin <mgoodwin@redhat.com> 6.2.1-1 +- update to latest upstream community sources, see CHANGELOG + +* Fri May 24 2019 Mark Goodwin <mgoodwin@redhat.com> 6.2.0-1 +- update to latest upstream community sources +- drop a couple of patches + +* Wed May 08 2019 Mark Goodwin <mgoodwin@redhat.com> 6.1.6-2 +- add conditional unbundle_vendor_sources macro + +* Tue Apr 30 2019 Mark Goodwin <mgoodwin@redhat.com> 6.1.6-1 +- update to latest upstream stable release 6.1.6, see CHANGELOG +- includes jQuery 3.4.0 security update + +* Wed Apr 24 2019 Mark Goodwin <mgoodwin@redhat.com> 6.1.4-1 +- update to latest upstream stable release 6.1.4, see CHANGELOG +- use gobuild and gochecks macros, eliminate arch symlinks +- re-enable grafana-debugsource package +- fix GRAFANA_GROUP typo +- fix more modes for brp-mangle-shebangs +- vendor source unbundling now done in prep after patches +- remove all rhel and fedora conditional guff + +* Tue Apr 16 2019 Mark Goodwin <mgoodwin@redhat.com> 6.1.3-1 +- update to latest upstream stable release 6.1.3, see CHANGELOG +- unbundle all vendor sources, replace with BuildRequires, see + the long list of blocker BZs linked to BZ#1670656 +- BuildRequires go-plugin >= v1.0.0 for grpc_broker (thanks eclipseo) +- tweak make_webpack to no longer use grunt, switch to prod build +- add ExclusiveArch lua script (thanks quantum.analyst) +- move db directory and plugins to /var/lib/grafana +- split out into 6 patches, ready for upstream PRs +- add check to run go tests for gating checks + +* Thu Apr 04 2019 Mark Goodwin <mgoodwin@redhat.com> 6.1.0-1 +- update to latest upstream stable release 6.1.0, see CHANGELOG + +* Thu Mar 21 2019 Mark Goodwin <mgoodwin@redhat.com> 6.0.2-1 +- bump to latest upstream stable release 6.0.2-1 +- unbundle almost all remaining vendor code, see linked blockers in BZ#1670656 + +* Fri Mar 15 2019 Mark Goodwin <mgoodwin@redhat.com> 6.0.1-3 +- bump to latest upstream stable release 6.0.1-1 + +* Thu Mar 14 2019 Mark Goodwin <mgoodwin@redhat.com> 6.0.1-2 +- unbundle and add BuildRequires for golang-github-rainycape-unidecode-devel + +* Thu Mar 07 2019 Mark Goodwin <mgoodwin@redhat.com> 6.0.1-1 +- update to v6.0.1 upstream sources, tweak distro config, re-do patch +- simplify make_webpack.sh script (Elliott Sales de Andrade) +- vendor/github.com/go-ldap is now gone, so don't unbundle it + +* Thu Mar 07 2019 Mark Goodwin <mgoodwin@redhat.com> 5.4.3-11 +- tweak after latest feedback, bump to 5.4.3-11 (BZ 1670656) +- build debuginfo package again +- unbundle BuildRequires for golang-github-hashicorp-version-devel +- remove some unneeded development files +- remove macros from changelog and other rpmlint tweaks + +* Fri Feb 22 2019 Mark Goodwin <mgoodwin@redhat.com> 5.4.3-10 +- tweak spec for available and unavailable (bundled) golang packages + +* Wed Feb 20 2019 Xavier Bachelot <xavier@bachelot.org> 5.4.3-9 +- Remove extraneous slash (cosmetic) +- Create directories just before moving stuff in them +- Truncate long lines +- Group all golang stuff +- Simplify BuildRequires/bundled Provides +- Sort BuildRequires/bundled Provides +- Fix bundled go packages Provides + +* Fri Feb 15 2019 Mark Goodwin <mgoodwin@redhat.com> 5.4.3-8 +- add BuildRequires (and unbundle) vendor sources available in Fedora +- declare Provides for remaining (bundled) vendor go sources +- do not attempt to unbundle anything on RHEL < 7 or Fedora < 28 + +* Thu Feb 07 2019 Mark Goodwin <mgoodwin@redhat.com> 5.4.3-7 +- further refinement for spec doc section from Xavier Bachelot +- disable debug_package to avoid empty debugsourcefiles.list + +* Wed Feb 06 2019 Mark Goodwin <mgoodwin@redhat.com> 5.4.3-6 +- further refinement following review by Xavier Bachelot + +* Tue Feb 05 2019 Mark Goodwin <mgoodwin@redhat.com> 5.4.3-5 +- further refinement following review by Xavier Bachelot + +* Fri Feb 01 2019 Mark Goodwin <mgoodwin@redhat.com> 5.4.3-4 +- further spec updates after packaging review +- reworked post-install scriplets + +* Thu Jan 31 2019 Mark Goodwin <mgoodwin@redhat.com> 5.4.3-3 +- tweak FHS patch, update spec after packaging review + +* Wed Jan 30 2019 Mark Goodwin <mgoodwin@redhat.com> 5.4.3-2 +- add patch to be standard FHS compliant, remove phantomjs +- update to v5.4.3 upstream community sources + +* Wed Jan 09 2019 Mark Goodwin <mgoodwin@redhat.com> 5.4.2-1 +- update to v5.4.2 upstream community sources + +* Thu Oct 18 2018 Mark Goodwin <mgoodwin@redhat.com> 5.3.1-1 +- update to v5.3.1 upstream community sources + +* Tue Oct 02 2018 Mark Goodwin <mgoodwin@redhat.com> 5.2.5-1 +- native RPM spec build with current tagged v5.2.5 sources