Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
33d374ec7b | ||
|
|
848c99ad0c | ||
|
|
1f1c5b7468 | ||
|
|
1327403277 | ||
|
|
beee65fb83 | ||
|
|
12135fa1d4 | ||
|
|
7f5e5e904d | ||
|
|
f01252c56b |
32
.drone.yml
32
.drone.yml
@@ -629,7 +629,7 @@ steps:
|
||||
name: identify-runner
|
||||
- commands:
|
||||
- mkdir -p bin
|
||||
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.1.1/grabpl
|
||||
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.1.2/grabpl
|
||||
- chmod +x bin/grabpl
|
||||
image: byrnedo/alpine-curl:0.1.8
|
||||
name: grabpl
|
||||
@@ -696,6 +696,9 @@ steps:
|
||||
token:
|
||||
from_secret: drone_token
|
||||
- commands:
|
||||
- docker run --privileged --rm tonistiigi/binfmt:qemu-v7.0.0-28 --version
|
||||
- docker run --privileged --rm tonistiigi/binfmt:qemu-v7.0.0-28 --uninstall 'qemu-*'
|
||||
- docker run --privileged --rm tonistiigi/binfmt:qemu-v7.0.0-28 --install all
|
||||
- /src/grafana-build artifacts -a targz:grafana:linux/amd64 -a targz:grafana:linux/arm64
|
||||
-a targz:grafana:linux/arm/v7 --go-version=1.22.11 --yarn-cache=$$YARN_CACHE_FOLDER
|
||||
--build-id=$$DRONE_BUILD_NUMBER --grafana-dir=$$PWD > packages.txt
|
||||
@@ -937,7 +940,9 @@ steps:
|
||||
image: grafana/docker-puppeteer:1.1.0
|
||||
name: test-a11y-frontend
|
||||
- commands:
|
||||
- docker run --privileged --rm tonistiigi/binfmt --install all
|
||||
- docker run --privileged --rm tonistiigi/binfmt:qemu-v7.0.0-28 --version
|
||||
- docker run --privileged --rm tonistiigi/binfmt:qemu-v7.0.0-28 --uninstall 'qemu-*'
|
||||
- docker run --privileged --rm tonistiigi/binfmt:qemu-v7.0.0-28 --install all
|
||||
- /src/grafana-build artifacts -a docker:grafana:linux/amd64 -a docker:grafana:linux/amd64:ubuntu
|
||||
-a docker:grafana:linux/arm64 -a docker:grafana:linux/arm64:ubuntu -a docker:grafana:linux/arm/v7
|
||||
-a docker:grafana:linux/arm/v7:ubuntu --yarn-cache=$$YARN_CACHE_FOLDER --build-id=$$DRONE_BUILD_NUMBER
|
||||
@@ -1095,7 +1100,7 @@ steps:
|
||||
path: /github-app
|
||||
- commands:
|
||||
- mkdir -p bin
|
||||
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.1.1/grabpl
|
||||
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.1.2/grabpl
|
||||
- chmod +x bin/grabpl
|
||||
image: byrnedo/alpine-curl:0.1.8
|
||||
name: grabpl
|
||||
@@ -2098,7 +2103,7 @@ steps:
|
||||
name: identify-runner
|
||||
- commands:
|
||||
- mkdir -p bin
|
||||
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.1.1/grabpl
|
||||
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.1.2/grabpl
|
||||
- chmod +x bin/grabpl
|
||||
image: byrnedo/alpine-curl:0.1.8
|
||||
name: grabpl
|
||||
@@ -2164,6 +2169,9 @@ steps:
|
||||
image: node:20.9.0-alpine
|
||||
name: build-frontend-packages
|
||||
- commands:
|
||||
- docker run --privileged --rm tonistiigi/binfmt:qemu-v7.0.0-28 --version
|
||||
- docker run --privileged --rm tonistiigi/binfmt:qemu-v7.0.0-28 --uninstall 'qemu-*'
|
||||
- docker run --privileged --rm tonistiigi/binfmt:qemu-v7.0.0-28 --install all
|
||||
- /src/grafana-build artifacts -a targz:grafana:linux/amd64 -a targz:grafana:linux/arm64
|
||||
-a targz:grafana:linux/arm/v7 --go-version=1.22.11 --yarn-cache=$$YARN_CACHE_FOLDER
|
||||
--build-id=$$DRONE_BUILD_NUMBER --grafana-dir=$$PWD > packages.txt
|
||||
@@ -2441,7 +2449,9 @@ steps:
|
||||
repo:
|
||||
- grafana/grafana
|
||||
- commands:
|
||||
- docker run --privileged --rm tonistiigi/binfmt --install all
|
||||
- docker run --privileged --rm tonistiigi/binfmt:qemu-v7.0.0-28 --version
|
||||
- docker run --privileged --rm tonistiigi/binfmt:qemu-v7.0.0-28 --uninstall 'qemu-*'
|
||||
- docker run --privileged --rm tonistiigi/binfmt:qemu-v7.0.0-28 --install all
|
||||
- /src/grafana-build artifacts -a docker:grafana:linux/amd64 -a docker:grafana:linux/amd64:ubuntu
|
||||
-a docker:grafana:linux/arm64 -a docker:grafana:linux/arm64:ubuntu -a docker:grafana:linux/arm/v7
|
||||
-a docker:grafana:linux/arm/v7:ubuntu --yarn-cache=$$YARN_CACHE_FOLDER --build-id=$$DRONE_BUILD_NUMBER
|
||||
@@ -2644,7 +2654,7 @@ services:
|
||||
steps:
|
||||
- commands:
|
||||
- mkdir -p bin
|
||||
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.1.1/grabpl
|
||||
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.1.2/grabpl
|
||||
- chmod +x bin/grabpl
|
||||
image: byrnedo/alpine-curl:0.1.8
|
||||
name: grabpl
|
||||
@@ -3228,7 +3238,7 @@ services:
|
||||
steps:
|
||||
- commands:
|
||||
- mkdir -p bin
|
||||
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.1.1/grabpl
|
||||
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.1.2/grabpl
|
||||
- chmod +x bin/grabpl
|
||||
image: byrnedo/alpine-curl:0.1.8
|
||||
name: grabpl
|
||||
@@ -3473,7 +3483,7 @@ steps:
|
||||
name: identify-runner
|
||||
- commands:
|
||||
- mkdir -p bin
|
||||
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.1.1/grabpl
|
||||
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.1.2/grabpl
|
||||
- chmod +x bin/grabpl
|
||||
image: byrnedo/alpine-curl:0.1.8
|
||||
name: grabpl
|
||||
@@ -3605,7 +3615,7 @@ steps:
|
||||
name: identify-runner
|
||||
- commands:
|
||||
- mkdir -p bin
|
||||
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.1.1/grabpl
|
||||
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.1.2/grabpl
|
||||
- chmod +x bin/grabpl
|
||||
image: byrnedo/alpine-curl:0.1.8
|
||||
name: grabpl
|
||||
@@ -4936,7 +4946,7 @@ services:
|
||||
steps:
|
||||
- commands:
|
||||
- mkdir -p bin
|
||||
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.1.1/grabpl
|
||||
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.1.2/grabpl
|
||||
- chmod +x bin/grabpl
|
||||
image: byrnedo/alpine-curl:0.1.8
|
||||
name: grabpl
|
||||
@@ -5695,6 +5705,6 @@ kind: secret
|
||||
name: gcr_credentials
|
||||
---
|
||||
kind: signature
|
||||
hmac: 812a2ddecbf18b9e10cc4953a157c4d613b5bab169f4cfe72431295e3ce68b2e
|
||||
hmac: a812aa5256b686f7422b378d66f25eb0d096afbbf2ce8cc200c7984e01601876
|
||||
|
||||
...
|
||||
|
||||
@@ -11,6 +11,7 @@ on:
|
||||
branches:
|
||||
- "main"
|
||||
- "v*.*.*"
|
||||
- "release-*.*.*"
|
||||
|
||||
# This is run before the pull request has been merged, so we'll run against the src branch
|
||||
jobs:
|
||||
|
||||
@@ -151,7 +151,8 @@ RUN if grep -i -q alpine /etc/issue && [ `arch` = "x86_64" ]; then \
|
||||
usr/glibc-compat/lib/libdl.so.2 \
|
||||
usr/glibc-compat/lib/libm.so.6 \
|
||||
usr/glibc-compat/lib/libpthread.so.0 \
|
||||
usr/glibc-compat/lib/librt.so.1 && \
|
||||
usr/glibc-compat/lib/librt.so.1 \
|
||||
usr/glibc-compat/lib/libresolv.so.2 && \
|
||||
mkdir /lib64 && \
|
||||
ln -s /usr/glibc-compat/lib/ld-linux-x86-64.so.2 /lib64; \
|
||||
fi
|
||||
|
||||
@@ -272,6 +272,10 @@ Path to the certificate file (if `protocol` is set to `https` or `h2`).
|
||||
|
||||
Path to the certificate key file (if `protocol` is set to `https` or `h2`).
|
||||
|
||||
### cert_pass
|
||||
|
||||
Optional. Password to decrypt encrypted certificates.
|
||||
|
||||
### certs_watch_interval
|
||||
|
||||
Controls whether `cert_key` and `cert_file` are periodically watched for changes.
|
||||
|
||||
@@ -244,6 +244,8 @@ To configure Grafana HTTPS and restart Grafana, complete the following steps.
|
||||
|
||||
> **Note**: The standard port for SSL traffic is 443, which you can use instead of Grafana's default port 3000. This change might require additional operating system privileges or configuration to bind to lower-numbered privileged ports.
|
||||
|
||||
1. Optional. From Grafana v11.2, edit the `cert_pass` configuration option with the decryption password if you are using encrypted certificates.
|
||||
|
||||
1. [Restart the Grafana server]({{< relref "./start-restart-grafana#linux" >}}) using `systemd`, `init.d`, or the binary as appropriate for your environment.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
@@ -26,12 +26,13 @@ func (lw *logWrapper) Println(v ...any) {
|
||||
lw.logger.Info("graphite metric bridge", v...)
|
||||
}
|
||||
|
||||
func ProvideService(cfg *setting.Cfg, reg prometheus.Registerer) (*InternalMetricsService, error) {
|
||||
func ProvideService(cfg *setting.Cfg, reg prometheus.Registerer, gatherer prometheus.Gatherer) (*InternalMetricsService, error) {
|
||||
initMetricVars(reg)
|
||||
initFrontendMetrics(reg)
|
||||
|
||||
s := &InternalMetricsService{
|
||||
Cfg: cfg,
|
||||
Cfg: cfg,
|
||||
gatherer: gatherer,
|
||||
}
|
||||
return s, s.readSettings()
|
||||
}
|
||||
@@ -41,6 +42,7 @@ type InternalMetricsService struct {
|
||||
|
||||
intervalSeconds int64
|
||||
graphiteCfg *graphitebridge.Config
|
||||
gatherer prometheus.Gatherer
|
||||
}
|
||||
|
||||
func (im *InternalMetricsService) Run(ctx context.Context) error {
|
||||
|
||||
@@ -5,8 +5,6 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/metrics/graphitebridge"
|
||||
)
|
||||
|
||||
@@ -40,7 +38,7 @@ func (im *InternalMetricsService) parseGraphiteSettings() error {
|
||||
URL: address,
|
||||
Prefix: graphiteSection.Key("prefix").MustString("prod.grafana.%(instance_name)s"),
|
||||
CountersAsDelta: true,
|
||||
Gatherer: prometheus.DefaultGatherer,
|
||||
Gatherer: im.gatherer,
|
||||
Interval: time.Duration(im.intervalSeconds) * time.Second,
|
||||
Timeout: 10 * time.Second,
|
||||
Logger: &logWrapper{logger: metricsLogger},
|
||||
|
||||
@@ -78,10 +78,17 @@ type keySetJWKS struct {
|
||||
}
|
||||
|
||||
func NewAzureADProvider(info *social.OAuthInfo, cfg *setting.Cfg, orgRoleMapper *OrgRoleMapper, ssoSettings ssosettings.Service, features featuremgmt.FeatureToggles, cache remotecache.CacheStorage) *SocialAzureAD {
|
||||
s := newSocialBase(social.AzureADProviderName, orgRoleMapper, info, features, cfg)
|
||||
|
||||
allowedOrganizations, err := util.SplitStringWithError(info.Extra[allowedOrganizationsKey])
|
||||
if err != nil {
|
||||
s.log.Error("Invalid auth configuration setting", "config", allowedOrganizationsKey, "provider", social.AzureADProviderName, "error", err)
|
||||
}
|
||||
|
||||
provider := &SocialAzureAD{
|
||||
SocialBase: newSocialBase(social.AzureADProviderName, orgRoleMapper, info, features, cfg),
|
||||
SocialBase: s,
|
||||
cache: cache,
|
||||
allowedOrganizations: util.SplitString(info.Extra[allowedOrganizationsKey]),
|
||||
allowedOrganizations: allowedOrganizations,
|
||||
forceUseGraphAPI: MustBool(info.Extra[forceUseGraphAPIKey], ExtraAzureADSettingKeys[forceUseGraphAPIKey].DefaultValue.(bool)),
|
||||
}
|
||||
|
||||
@@ -169,7 +176,7 @@ func (s *SocialAzureAD) UserInfo(ctx context.Context, client *http.Client, token
|
||||
}
|
||||
|
||||
func (s *SocialAzureAD) Reload(ctx context.Context, settings ssoModels.SSOSettings) error {
|
||||
newInfo, err := CreateOAuthInfoFromKeyValues(settings.Settings)
|
||||
newInfo, err := CreateOAuthInfoFromKeyValuesWithLogging(s.log, social.AzureADProviderName, settings.Settings)
|
||||
if err != nil {
|
||||
return ssosettings.ErrInvalidSettings.Errorf("SSO settings map cannot be converted to OAuthInfo: %v", err)
|
||||
}
|
||||
@@ -183,7 +190,12 @@ func (s *SocialAzureAD) Reload(ctx context.Context, settings ssoModels.SSOSettin
|
||||
appendUniqueScope(s.Config, social.OfflineAccessScope)
|
||||
}
|
||||
|
||||
s.allowedOrganizations = util.SplitString(newInfo.Extra[allowedOrganizationsKey])
|
||||
allowedOrganizations, err := util.SplitStringWithError(newInfo.Extra[allowedOrganizationsKey])
|
||||
if err != nil {
|
||||
s.log.Error("Invalid auth configuration setting", "config", allowedOrganizationsKey, "provider", social.AzureADProviderName, "error", err)
|
||||
}
|
||||
|
||||
s.allowedOrganizations = allowedOrganizations
|
||||
s.forceUseGraphAPI = MustBool(newInfo.Extra[forceUseGraphAPIKey], false)
|
||||
|
||||
return nil
|
||||
|
||||
@@ -2,6 +2,7 @@ package connectors
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
@@ -13,6 +14,7 @@ import (
|
||||
"github.com/mitchellh/mapstructure"
|
||||
"golang.org/x/oauth2"
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/login/social"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
@@ -155,9 +157,25 @@ func MustBool(value any, defaultValue bool) bool {
|
||||
return result
|
||||
}
|
||||
|
||||
// CreateOAuthInfoFromKeyValuesWithLogging creates an OAuthInfo struct from a map[string]any using mapstructure
|
||||
// it puts all extra key values into OAuthInfo's Extra map.
|
||||
// It logs as errors any parsing errors that are not critical
|
||||
func CreateOAuthInfoFromKeyValuesWithLogging(l log.Logger, provider string, settingsKV map[string]any) (*social.OAuthInfo, error) {
|
||||
parsingWarns := []error{}
|
||||
info, err := createOAuthInfoFromKeyValues(settingsKV, &parsingWarns)
|
||||
if len(parsingWarns) > 0 {
|
||||
l.Error("Invalid auth configuration setting", "error", errors.Join(parsingWarns...), "provider", provider)
|
||||
}
|
||||
return info, err
|
||||
}
|
||||
|
||||
// CreateOAuthInfoFromKeyValues creates an OAuthInfo struct from a map[string]any using mapstructure
|
||||
// it puts all extra key values into OAuthInfo's Extra map
|
||||
func CreateOAuthInfoFromKeyValues(settingsKV map[string]any) (*social.OAuthInfo, error) {
|
||||
return createOAuthInfoFromKeyValues(settingsKV, nil)
|
||||
}
|
||||
|
||||
func createOAuthInfoFromKeyValues(settingsKV map[string]any, parsingWarns *[]error) (*social.OAuthInfo, error) {
|
||||
emptyStrToSliceDecodeHook := func(from reflect.Type, to reflect.Type, data any) (any, error) {
|
||||
if from.Kind() == reflect.String && to.Kind() == reflect.Slice {
|
||||
strData, ok := data.(string)
|
||||
@@ -168,7 +186,12 @@ func CreateOAuthInfoFromKeyValues(settingsKV map[string]any) (*social.OAuthInfo,
|
||||
if strData == "" {
|
||||
return []string{}, nil
|
||||
}
|
||||
return util.SplitString(strData), nil
|
||||
|
||||
splitStr, err := util.SplitStringWithError(strData)
|
||||
if err != nil && parsingWarns != nil {
|
||||
*parsingWarns = append(*parsingWarns, err)
|
||||
}
|
||||
return splitStr, nil
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
||||
@@ -53,6 +53,18 @@ type SocialGenericOAuth struct {
|
||||
}
|
||||
|
||||
func NewGenericOAuthProvider(info *social.OAuthInfo, cfg *setting.Cfg, orgRoleMapper *OrgRoleMapper, ssoSettings ssosettings.Service, features featuremgmt.FeatureToggles) *SocialGenericOAuth {
|
||||
s := newSocialBase(social.GenericOAuthProviderName, orgRoleMapper, info, features, cfg)
|
||||
|
||||
teamIds, err := util.SplitStringWithError(info.Extra[teamIdsKey])
|
||||
if err != nil {
|
||||
s.log.Error("Invalid auth configuration setting", "config", teamIdsKey, "provider", social.GenericOAuthProviderName, "error", err)
|
||||
}
|
||||
|
||||
allowedOrganizations, err := util.SplitStringWithError(info.Extra[allowedOrganizationsKey])
|
||||
if err != nil {
|
||||
s.log.Error("Invalid auth configuration setting", "config", allowedOrganizationsKey, "provider", social.GenericOAuthProviderName, "error", err)
|
||||
}
|
||||
|
||||
provider := &SocialGenericOAuth{
|
||||
SocialBase: newSocialBase(social.GenericOAuthProviderName, orgRoleMapper, info, features, cfg),
|
||||
teamsUrl: info.TeamsUrl,
|
||||
@@ -63,8 +75,8 @@ func NewGenericOAuthProvider(info *social.OAuthInfo, cfg *setting.Cfg, orgRoleMa
|
||||
loginAttributePath: info.Extra[loginAttributePathKey],
|
||||
idTokenAttributeName: info.Extra[idTokenAttributeNameKey],
|
||||
teamIdsAttributePath: info.TeamIdsAttributePath,
|
||||
teamIds: util.SplitString(info.Extra[teamIdsKey]),
|
||||
allowedOrganizations: util.SplitString(info.Extra[allowedOrganizationsKey]),
|
||||
teamIds: teamIds,
|
||||
allowedOrganizations: allowedOrganizations,
|
||||
}
|
||||
|
||||
if features.IsEnabledGlobally(featuremgmt.FlagSsoSettingsApi) {
|
||||
@@ -118,7 +130,7 @@ func validateTeamsUrlWhenNotEmpty(info *social.OAuthInfo, requester identity.Req
|
||||
}
|
||||
|
||||
func (s *SocialGenericOAuth) Reload(ctx context.Context, settings ssoModels.SSOSettings) error {
|
||||
newInfo, err := CreateOAuthInfoFromKeyValues(settings.Settings)
|
||||
newInfo, err := CreateOAuthInfoFromKeyValuesWithLogging(s.log, social.GenericOAuthProviderName, settings.Settings)
|
||||
if err != nil {
|
||||
return ssosettings.ErrInvalidSettings.Errorf("SSO settings map cannot be converted to OAuthInfo: %v", err)
|
||||
}
|
||||
@@ -128,6 +140,15 @@ func (s *SocialGenericOAuth) Reload(ctx context.Context, settings ssoModels.SSOS
|
||||
|
||||
s.updateInfo(ctx, social.GenericOAuthProviderName, newInfo)
|
||||
|
||||
teamIds, err := util.SplitStringWithError(newInfo.Extra[teamIdsKey])
|
||||
if err != nil {
|
||||
s.log.Error("Invalid auth configuration setting", "config", teamIdsKey, "provider", social.GenericOAuthProviderName, "error", err)
|
||||
}
|
||||
allowedOrganizations, err := util.SplitStringWithError(newInfo.Extra[allowedOrganizationsKey])
|
||||
if err != nil {
|
||||
s.log.Error("Invalid auth configuration setting", "config", allowedOrganizationsKey, "provider", social.GenericOAuthProviderName, "error", err)
|
||||
}
|
||||
|
||||
s.teamsUrl = newInfo.TeamsUrl
|
||||
s.emailAttributeName = newInfo.EmailAttributeName
|
||||
s.emailAttributePath = newInfo.EmailAttributePath
|
||||
@@ -136,8 +157,8 @@ func (s *SocialGenericOAuth) Reload(ctx context.Context, settings ssoModels.SSOS
|
||||
s.loginAttributePath = newInfo.Extra[loginAttributePathKey]
|
||||
s.idTokenAttributeName = newInfo.Extra[idTokenAttributeNameKey]
|
||||
s.teamIdsAttributePath = newInfo.TeamIdsAttributePath
|
||||
s.teamIds = util.SplitString(newInfo.Extra[teamIdsKey])
|
||||
s.allowedOrganizations = util.SplitString(newInfo.Extra[allowedOrganizationsKey])
|
||||
s.teamIds = teamIds
|
||||
s.allowedOrganizations = allowedOrganizations
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -62,13 +62,23 @@ var (
|
||||
)
|
||||
|
||||
func NewGitHubProvider(info *social.OAuthInfo, cfg *setting.Cfg, orgRoleMapper *OrgRoleMapper, ssoSettings ssosettings.Service, features featuremgmt.FeatureToggles) *SocialGithub {
|
||||
teamIdsSplitted := util.SplitString(info.Extra[teamIdsKey])
|
||||
s := newSocialBase(social.GitHubProviderName, orgRoleMapper, info, features, cfg)
|
||||
|
||||
teamIdsSplitted, err := util.SplitStringWithError(info.Extra[teamIdsKey])
|
||||
if err != nil {
|
||||
s.log.Error("Invalid auth configuration setting", "config", teamIdsKey, "provider", social.GitHubProviderName, "error", err)
|
||||
}
|
||||
teamIds := mustInts(teamIdsSplitted)
|
||||
|
||||
allowedOrganizations, err := util.SplitStringWithError(info.Extra[allowedOrganizationsKey])
|
||||
if err != nil {
|
||||
s.log.Error("Invalid auth configuration setting", "config", allowedOrganizationsKey, "provider", social.GitHubProviderName, "error", err)
|
||||
}
|
||||
|
||||
provider := &SocialGithub{
|
||||
SocialBase: newSocialBase(social.GitHubProviderName, orgRoleMapper, info, features, cfg),
|
||||
SocialBase: s,
|
||||
teamIds: teamIds,
|
||||
allowedOrganizations: util.SplitString(info.Extra[allowedOrganizationsKey]),
|
||||
allowedOrganizations: allowedOrganizations,
|
||||
}
|
||||
|
||||
if len(teamIdsSplitted) != len(teamIds) {
|
||||
@@ -117,14 +127,22 @@ func teamIdsNumbersValidator(info *social.OAuthInfo, requester identity.Requeste
|
||||
}
|
||||
|
||||
func (s *SocialGithub) Reload(ctx context.Context, settings ssoModels.SSOSettings) error {
|
||||
newInfo, err := CreateOAuthInfoFromKeyValues(settings.Settings)
|
||||
newInfo, err := CreateOAuthInfoFromKeyValuesWithLogging(s.log, social.GitHubProviderName, settings.Settings)
|
||||
if err != nil {
|
||||
return ssosettings.ErrInvalidSettings.Errorf("SSO settings map cannot be converted to OAuthInfo: %v", err)
|
||||
}
|
||||
|
||||
teamIdsSplitted := util.SplitString(newInfo.Extra[teamIdsKey])
|
||||
teamIdsSplitted, err := util.SplitStringWithError(newInfo.Extra[teamIdsKey])
|
||||
if err != nil {
|
||||
s.log.Error("Invalid auth configuration setting", "config", teamIdsKey, "provider", social.GitHubProviderName, "error", err)
|
||||
}
|
||||
teamIds := mustInts(teamIdsSplitted)
|
||||
|
||||
allowedOrganizations, err := util.SplitStringWithError(newInfo.Extra[allowedOrganizationsKey])
|
||||
if err != nil {
|
||||
s.log.Error("Invalid auth configuration setting", "config", allowedOrganizationsKey, "provider", social.GitHubProviderName, "error", err)
|
||||
}
|
||||
|
||||
if len(teamIdsSplitted) != len(teamIds) {
|
||||
s.log.Warn("Failed to parse team ids. Team ids must be a list of numbers.", "teamIds", teamIdsSplitted)
|
||||
}
|
||||
@@ -135,7 +153,7 @@ func (s *SocialGithub) Reload(ctx context.Context, settings ssoModels.SSOSetting
|
||||
s.updateInfo(ctx, social.GitHubProviderName, newInfo)
|
||||
|
||||
s.teamIds = teamIds
|
||||
s.allowedOrganizations = util.SplitString(newInfo.Extra[allowedOrganizationsKey])
|
||||
s.allowedOrganizations = allowedOrganizations
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -87,7 +87,7 @@ func (s *SocialGitlab) Validate(ctx context.Context, newSettings ssoModels.SSOSe
|
||||
}
|
||||
|
||||
func (s *SocialGitlab) Reload(ctx context.Context, settings ssoModels.SSOSettings) error {
|
||||
newInfo, err := CreateOAuthInfoFromKeyValues(settings.Settings)
|
||||
newInfo, err := CreateOAuthInfoFromKeyValuesWithLogging(s.log, social.GitlabProviderName, settings.Settings)
|
||||
if err != nil {
|
||||
return ssosettings.ErrInvalidSettings.Errorf("SSO settings map cannot be converted to OAuthInfo: %v", err)
|
||||
}
|
||||
|
||||
@@ -87,7 +87,7 @@ func (s *SocialGoogle) Validate(ctx context.Context, newSettings ssoModels.SSOSe
|
||||
}
|
||||
|
||||
func (s *SocialGoogle) Reload(ctx context.Context, settings ssoModels.SSOSettings) error {
|
||||
newInfo, err := CreateOAuthInfoFromKeyValues(settings.Settings)
|
||||
newInfo, err := CreateOAuthInfoFromKeyValuesWithLogging(s.log, social.GoogleProviderName, settings.Settings)
|
||||
if err != nil {
|
||||
return ssosettings.ErrInvalidSettings.Errorf("SSO settings map cannot be converted to OAuthInfo: %v", err)
|
||||
}
|
||||
|
||||
@@ -36,15 +36,22 @@ type OrgRecord struct {
|
||||
}
|
||||
|
||||
func NewGrafanaComProvider(info *social.OAuthInfo, cfg *setting.Cfg, orgRoleMapper *OrgRoleMapper, ssoSettings ssosettings.Service, features featuremgmt.FeatureToggles) *SocialGrafanaCom {
|
||||
s := newSocialBase(social.GrafanaComProviderName, orgRoleMapper, info, features, cfg)
|
||||
|
||||
// Override necessary settings
|
||||
info.AuthUrl = cfg.GrafanaComURL + "/oauth2/authorize"
|
||||
info.TokenUrl = cfg.GrafanaComURL + "/api/oauth2/token"
|
||||
info.AuthStyle = "inheader"
|
||||
|
||||
allowedOrganizations, err := util.SplitStringWithError(info.Extra[allowedOrganizationsKey])
|
||||
if err != nil {
|
||||
s.log.Error("Invalid auth configuration setting", "config", allowedOrganizationsKey, "provider", social.GrafanaComProviderName, "error", err)
|
||||
}
|
||||
|
||||
provider := &SocialGrafanaCom{
|
||||
SocialBase: newSocialBase(social.GrafanaComProviderName, orgRoleMapper, info, features, cfg),
|
||||
SocialBase: s,
|
||||
url: cfg.GrafanaComURL,
|
||||
allowedOrganizations: util.SplitString(info.Extra[allowedOrganizationsKey]),
|
||||
allowedOrganizations: allowedOrganizations,
|
||||
}
|
||||
|
||||
if features.IsEnabledGlobally(featuremgmt.FlagSsoSettingsApi) {
|
||||
@@ -77,11 +84,16 @@ func (s *SocialGrafanaCom) Validate(ctx context.Context, newSettings ssoModels.S
|
||||
}
|
||||
|
||||
func (s *SocialGrafanaCom) Reload(ctx context.Context, settings ssoModels.SSOSettings) error {
|
||||
newInfo, err := CreateOAuthInfoFromKeyValues(settings.Settings)
|
||||
newInfo, err := CreateOAuthInfoFromKeyValuesWithLogging(s.log, social.GrafanaComProviderName, settings.Settings)
|
||||
if err != nil {
|
||||
return ssosettings.ErrInvalidSettings.Errorf("SSO settings map cannot be converted to OAuthInfo: %v", err)
|
||||
}
|
||||
|
||||
allowedOrganizations, err := util.SplitStringWithError(newInfo.Extra[allowedOrganizationsKey])
|
||||
if err != nil {
|
||||
s.log.Error("Invalid auth configuration setting", "config", allowedOrganizationsKey, "provider", social.GrafanaComProviderName, "error", err)
|
||||
}
|
||||
|
||||
// Override necessary settings
|
||||
newInfo.AuthUrl = s.cfg.GrafanaComURL + "/oauth2/authorize"
|
||||
newInfo.TokenUrl = s.cfg.GrafanaComURL + "/api/oauth2/token"
|
||||
@@ -93,7 +105,7 @@ func (s *SocialGrafanaCom) Reload(ctx context.Context, settings ssoModels.SSOSet
|
||||
s.updateInfo(ctx, social.GrafanaComProviderName, newInfo)
|
||||
|
||||
s.url = s.cfg.GrafanaComURL
|
||||
s.allowedOrganizations = util.SplitString(newInfo.Extra[allowedOrganizationsKey])
|
||||
s.allowedOrganizations = allowedOrganizations
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -84,7 +84,7 @@ func (s *SocialOkta) Validate(ctx context.Context, newSettings ssoModels.SSOSett
|
||||
}
|
||||
|
||||
func (s *SocialOkta) Reload(ctx context.Context, settings ssoModels.SSOSettings) error {
|
||||
newInfo, err := CreateOAuthInfoFromKeyValues(settings.Settings)
|
||||
newInfo, err := CreateOAuthInfoFromKeyValuesWithLogging(s.log, social.OktaProviderName, settings.Settings)
|
||||
if err != nil {
|
||||
return ssosettings.ErrInvalidSettings.Errorf("SSO settings map cannot be converted to OAuthInfo: %v", err)
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ func ProvideService(cfg *setting.Cfg,
|
||||
continue
|
||||
}
|
||||
|
||||
info, err := connectors.CreateOAuthInfoFromKeyValues(ssoSetting.Settings)
|
||||
info, err := connectors.CreateOAuthInfoFromKeyValuesWithLogging(ss.log, ssoSetting.Provider, ssoSetting.Settings)
|
||||
if err != nil {
|
||||
ss.log.Error("Failed to create OAuthInfo for provider", "error", err, "provider", ssoSetting.Provider)
|
||||
continue
|
||||
@@ -85,7 +85,7 @@ func ProvideService(cfg *setting.Cfg,
|
||||
|
||||
settingsKVs := convertIniSectionToMap(sec)
|
||||
|
||||
info, err := connectors.CreateOAuthInfoFromKeyValues(settingsKVs)
|
||||
info, err := connectors.CreateOAuthInfoFromKeyValuesWithLogging(ss.log, name, settingsKVs)
|
||||
if err != nil {
|
||||
ss.log.Error("Failed to create OAuthInfo for provider", "error", err, "provider", name)
|
||||
continue
|
||||
|
||||
@@ -47,6 +47,11 @@ var (
|
||||
StatusCode: 400,
|
||||
Status: "empty-name",
|
||||
}
|
||||
ErrDashboardTitleTooLong = DashboardErr{
|
||||
Reason: "Dashboard title cannot contain more than 5 000 characters",
|
||||
StatusCode: 400,
|
||||
Status: "title-too-long",
|
||||
}
|
||||
ErrDashboardFolderCannotHaveParent = DashboardErr{
|
||||
Reason: "A Dashboard Folder cannot be added to another folder",
|
||||
StatusCode: 400,
|
||||
|
||||
@@ -113,6 +113,10 @@ func (dr *DashboardServiceImpl) BuildSaveDashboardCommand(ctx context.Context, d
|
||||
return nil, dashboards.ErrDashboardTitleEmpty
|
||||
}
|
||||
|
||||
if len(dash.Title) > 5000 {
|
||||
return nil, dashboards.ErrDashboardTitleTooLong
|
||||
}
|
||||
|
||||
metrics.MFolderIDsServiceCount.WithLabelValues(metrics.Dashboard).Inc()
|
||||
// nolint:staticcheck
|
||||
if dash.IsFolder && dash.FolderID > 0 {
|
||||
|
||||
@@ -33,9 +33,18 @@ func stringsFallback(vals ...string) string {
|
||||
|
||||
// SplitString splits a string and returns a list of strings. It supports JSON list syntax and strings separated by commas or spaces.
|
||||
// It supports quoted strings with spaces, e.g. "foo bar", "baz".
|
||||
// It will return an empty list if it fails to parse the string.
|
||||
func SplitString(str string) []string {
|
||||
result, _ := SplitStringWithError(str)
|
||||
return result
|
||||
}
|
||||
|
||||
// SplitStringWithError splits a string and returns a list of strings. It supports JSON list syntax and strings separated by commas or spaces.
|
||||
// It supports quoted strings with spaces, e.g. "foo bar", "baz".
|
||||
// It returns an error if it cannot parse the string.
|
||||
func SplitStringWithError(str string) ([]string, error) {
|
||||
if len(str) == 0 {
|
||||
return []string{}
|
||||
return []string{}, nil
|
||||
}
|
||||
|
||||
// JSON list syntax support
|
||||
@@ -43,9 +52,9 @@ func SplitString(str string) []string {
|
||||
var res []string
|
||||
err := json.Unmarshal([]byte(str), &res)
|
||||
if err != nil {
|
||||
return []string{}
|
||||
return []string{}, fmt.Errorf("incorrect format: %s", str)
|
||||
}
|
||||
return res
|
||||
return res, nil
|
||||
}
|
||||
|
||||
matches := stringListItemMatcher.FindAllString(str, -1)
|
||||
@@ -55,7 +64,7 @@ func SplitString(str string) []string {
|
||||
result[i] = strings.Trim(match, "\"")
|
||||
}
|
||||
|
||||
return result
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// GetAgeString returns a string representing certain time from years to minutes.
|
||||
|
||||
@@ -53,7 +53,10 @@ const strToValue = (val: string | string[]): SelectableValue[] => {
|
||||
}
|
||||
// Stored as JSON Array
|
||||
if (val.startsWith('[') && val.endsWith(']')) {
|
||||
return JSON.parse(val).map((v: string) => ({ label: v, value: v }));
|
||||
// Fallback to parsing it like a non-json string if it is not valid json, instead of crashing.
|
||||
try {
|
||||
return JSON.parse(val).map((v: string) => ({ label: v, value: v }));
|
||||
} catch {}
|
||||
}
|
||||
|
||||
return val.split(/[\s,]/).map((s) => ({ label: s, value: s }));
|
||||
|
||||
@@ -34,6 +34,9 @@ def rgm_artifacts_step(name = "rgm-package", artifacts = ["targz:grafana:linux/a
|
||||
"_EXPERIMENTAL_DAGGER_CLOUD_TOKEN": from_secret(rgm_dagger_token),
|
||||
},
|
||||
"commands": [
|
||||
"docker run --privileged --rm tonistiigi/binfmt:qemu-v7.0.0-28 --version",
|
||||
"docker run --privileged --rm tonistiigi/binfmt:qemu-v7.0.0-28 --uninstall 'qemu-*'",
|
||||
"docker run --privileged --rm tonistiigi/binfmt:qemu-v7.0.0-28 --install all",
|
||||
cmd +
|
||||
"--go-version={} ".format(golang_version) +
|
||||
"--yarn-cache=$$YARN_CACHE_FOLDER " +
|
||||
@@ -58,7 +61,9 @@ def rgm_build_docker_step(ubuntu, alpine, depends_on = ["yarn-install"], file =
|
||||
"_EXPERIMENTAL_DAGGER_CLOUD_TOKEN": from_secret(rgm_dagger_token),
|
||||
},
|
||||
"commands": [
|
||||
"docker run --privileged --rm tonistiigi/binfmt --install all",
|
||||
"docker run --privileged --rm tonistiigi/binfmt:qemu-v7.0.0-28 --version",
|
||||
"docker run --privileged --rm tonistiigi/binfmt:qemu-v7.0.0-28 --uninstall 'qemu-*'",
|
||||
"docker run --privileged --rm tonistiigi/binfmt:qemu-v7.0.0-28 --install all",
|
||||
"/src/grafana-build artifacts " +
|
||||
"-a docker:grafana:linux/amd64 " +
|
||||
"-a docker:grafana:linux/amd64:ubuntu " +
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
global variables
|
||||
"""
|
||||
|
||||
grabpl_version = "v3.1.1"
|
||||
grabpl_version = "v3.1.2"
|
||||
golang_version = "1.22.11"
|
||||
|
||||
# nodejs_version should match what's in ".nvmrc", but without the v prefix.
|
||||
|
||||
Reference in New Issue
Block a user