Resolves: RHEL-161792

Resolves: RHEL-166318
Resolves: RHEL-166490
Resolves: RHEL-167360
Resolves: RHEL-167516
This commit is contained in:
Sam Feifer 2026-04-21 18:32:21 -04:00
parent 5eef98b225
commit 9a3fdcbeb9
3 changed files with 203 additions and 1 deletions

View File

@ -0,0 +1,123 @@
diff --git a/pkg/api/frontendsettings.go b/pkg/api/frontendsettings.go
index 215714b6f83..36949e126b9 100644
--- a/pkg/api/frontendsettings.go
+++ b/pkg/api/frontendsettings.go
@@ -1,6 +1,7 @@
package api
import (
+ "bytes"
"context"
"fmt"
"net/http"
@@ -18,6 +19,7 @@ import (
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginsettings"
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginstore"
"github.com/grafana/grafana/pkg/services/secrets/kvstore"
+ dashboardkind "github.com/grafana/grafana/pkg/services/store/kind/dashboard"
"github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/tsdb/grafanads"
"github.com/grafana/grafana/pkg/util"
@@ -297,7 +299,12 @@ func (hs *HTTPServer) getFSDataSources(c *contextmodel.ReqContext, availablePlug
if c.IsPublicDashboardView() {
// If RBAC is enabled, it will filter out all datasources for a public user, so we need to skip it
- orgDataSources = dataSources
+ // But we can filter to only include datasources actually used by the dashboard
+ filtered, err := hs.publicDashFilterUsedDataSources(c, dataSources)
+ if err != nil {
+ return nil, err
+ }
+ orgDataSources = filtered
} else {
filtered, err := hs.dsGuardian.New(c.SignedInUser.OrgID, c.SignedInUser).FilterDatasourcesByQueryPermissions(dataSources)
if err != nil {
@@ -633,3 +640,36 @@ func (hs *HTTPServer) getEnabledOAuthProviders() map[string]any {
}
return providers
}
+
+func (hs *HTTPServer) publicDashFilterUsedDataSources(c *contextmodel.ReqContext, allDataSources []*datasources.DataSource) ([]*datasources.DataSource, error) {
+ _, dash, err := hs.PublicDashboardsApi.PublicDashboardService.FindPublicDashboardAndDashboardByAccessToken(c.Req.Context(), c.PublicDashboardAccessToken)
+ if err != nil {
+ return nil, err
+ }
+
+ payload, err := dash.Data.Encode()
+ if err != nil {
+ return nil, fmt.Errorf("failed to encode dashboard data: %w", err)
+ }
+
+ lookup := dashboardkind.CreateDatasourceLookup([]*dashboardkind.DatasourceQueryResult{})
+
+ usedDSRefs, err := dashboardkind.ReadDashboard(bytes.NewReader(payload), lookup)
+ if err != nil {
+ return nil, fmt.Errorf("failed to parse dashboard: %w", err)
+ }
+
+ usedUIDs := make(map[string]struct{}, len(usedDSRefs))
+ for _, ds := range usedDSRefs {
+ usedUIDs[ds.UID] = struct{}{}
+ }
+
+ filtered := make([]*datasources.DataSource, 0)
+ for _, ds := range allDataSources {
+ if _, ok := usedUIDs[ds.UID]; ok {
+ filtered = append(filtered, ds)
+ }
+ }
+
+ return filtered, nil
+}
diff --git a/pkg/services/store/kind/dashboard/dashboard.go b/pkg/services/store/kind/dashboard/dashboard.go
index b325acd8c57..054dcafe8ca 100644
--- a/pkg/services/store/kind/dashboard/dashboard.go
+++ b/pkg/services/store/kind/dashboard/dashboard.go
@@ -112,8 +112,17 @@ func newDatasourceVariableLookup(dsLookup DatasourceLookup) *datasourceVariableL
}
}
+// ReadDashboard parses dashboard JSON and returns the data sources used in the dashboard.
+func ReadDashboard(stream io.Reader, lookup DatasourceLookup) ([]DataSourceRef, error) {
+ info, err := readDashboard(stream, lookup)
+ if err != nil {
+ return nil, err
+ }
+ return info.Datasource, nil
+}
+
// nolint:gocyclo
-// ReadDashboard will take a byte stream and return dashboard info
+// readDashboard will take a byte stream and return dashboard info
func readDashboard(stream io.Reader, lookup DatasourceLookup) (*dashboardInfo, error) {
dash := &dashboardInfo{}
diff --git a/pkg/services/store/kind/dashboard/ds_lookup.go b/pkg/services/store/kind/dashboard/ds_lookup.go
index 5d132d569be..7330e598409 100644
--- a/pkg/services/store/kind/dashboard/ds_lookup.go
+++ b/pkg/services/store/kind/dashboard/ds_lookup.go
@@ -100,6 +100,9 @@ func (d *DsLookup) ByRef(ref *DataSourceRef) *DataSourceRef {
if ref == nil {
return d.defaultDS
}
+ if ref.UID == "default" && ref.Type == "" {
+ return d.defaultDS
+ }
key := ""
if ref.UID != "" {
@@ -117,7 +120,13 @@ func (d *DsLookup) ByRef(ref *DataSourceRef) *DataSourceRef {
return ds
}
- return d.byName[key]
+ ds, ok = d.byName[key]
+ if ok {
+ return ds
+ }
+
+ // With nothing was found (or configured), use the original reference
+ return ref
}
func (d *DsLookup) ByType(dsType string) []DataSourceRef {

70
CLAUDE.md Normal file
View File

@ -0,0 +1,70 @@
# Grafana CentOS Packaging Workflow
This file documents the standard workflow for working with the grafana centpkg repository. Claude Code will follow these steps autonomously.
## Workflow Steps
1. Fork the repository:
```
centpkg fork
```
2. Fetch all remotes:
```
git fetch --all
```
3. Create a new branch named after the Jira ticket, branching off the appropriate version branch.
Ask the user which version (c8s, c9s, c10s) and which Jira ticket before running this step.
The branch name is the ticket number lowercased with an `r` prefix (e.g. RHEL-161792 → r161792).
```
git checkout -b r<ticket-number> origin/<version>
```
4. Bump the release number in `grafana.spec` (the `Release:` field) by 1.
5. Add a new changelog entry at the top of `%changelog` in `grafana.spec` following this format:
```
* <Day> <Mon> <DD> <YYYY> <name> <<email>> <version>-<new-release>
- Resolves <TICKET>: <CVE>
- Resolves <TICKET>: <CVE>
...
```
Ask the user for:
- The primary Jira ticket (used for the branch name)
- Any additional Jira tickets being fixed in this build (there may be multiple)
- Their Atlassian account email (or check if it is stored in an environment variable)
- Their Atlassian API token variable name (or check if it is stored in an environment variable)
Fetch the CVE for each ticket from Jira simultaneously:
```
curl -s -H "Authorization: Basic $(echo -n "<email>:$<atlassian_token_var>" | base64 -w 0)" \
"https://redhat.atlassian.net/rest/api/2/issue/<TICKET>?fields=summary"
```
Extract the CVE identifier (e.g. `CVE-XXXX-XXXXX`) from the `summary` field of each response.
Add one `- Resolves` line per ticket.
6. Build the source RPM:
```
centpkg srpm
```
7. Stage all modified and new files:
```
git add grafana.spec CLAUDE.md <any new patch files>
```
8. Commit using `centpkg commit -m` with each ticket on its own line:
```
centpkg commit -m "$(cat <<'EOF'
Resolves: RHEL-XXXXXX
Resolves: RHEL-XXXXXX
EOF
)"
```
9. Push the branch to the fork. The fork remote name can be found by running `git remote -v`
and identifying the remote that points to the user's personal fork (not `origin`).
```
git push <fork-remote> <branch-name>
```

View File

@ -26,7 +26,7 @@ end}
Name: grafana
Version: 10.2.6
Release: 25%{?dist}
Release: 26%{?dist}
Summary: Metrics dashboard and graph editor
License: AGPL-3.0-only
URL: https://grafana.org
@ -81,6 +81,7 @@ Patch11: 0011-fix-dompurify-CVE.patch
Patch12: 0012-fix-jwt-CVE.patch
Patch13: 0013-fix-CVE-2025-4123.patch
Patch14: 0014-Fix-CVE-2026-21721.patch
Patch15: 0015-Fix-CVE-2026-27877.patch
# Patches affecting the vendor tarball
Patch1001: 1001-vendor-patch-removed-backend-crypto.patch
@ -775,6 +776,7 @@ rm -r plugins-bundled
%patch -P 12 -p1
%patch -P 13 -p1
%patch -P 14 -p1
%patch -P 15 -p1
%patch -P 1001 -p1
%if %{enable_fips_mode}
@ -1019,6 +1021,13 @@ done
%ghost %verify(not md5 size mode mtime) %{_sharedstatedir}/selinux/*/active/modules/200/grafana
%changelog
* Tue Apr 21 2026 Sam Feifer <sfeifer@redhat.com> 10.2.6-26
- Resolves RHEL-161792: CVE-2026-27877
- Resolves RHEL-166318: CVE-2026-33810
- Resolves RHEL-166490: CVE-2026-32282
- Resolves RHEL-167360: CVE-2026-32280
- Resolves RHEL-167516: CVE-2026-32283
* Wed Apr 1 2026 Sam Feifer <sfeifer@redhat.com> 10.2.6-25
- Resolves RHEL-156596: CVE-2026-25679