mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Encryption: Add Prometheus metrics (#48603)
This commit is contained in:
parent
0e1dffc655
commit
9826a694a8
@ -12,7 +12,6 @@ import (
|
||||
const ExporterName = "grafana"
|
||||
|
||||
var (
|
||||
|
||||
// MInstanceStart is a metric counter for started instances
|
||||
MInstanceStart prometheus.Counter
|
||||
|
||||
@ -191,6 +190,9 @@ var (
|
||||
|
||||
// StatsTotalLibraryVariables is a metric of total number of library variables stored in Grafana.
|
||||
StatsTotalLibraryVariables prometheus.Gauge
|
||||
|
||||
// StatsTotalDataKeys is a metric of total number of data keys stored in Grafana.
|
||||
StatsTotalDataKeys prometheus.Gauge
|
||||
)
|
||||
|
||||
func init() {
|
||||
@ -565,6 +567,12 @@ func init() {
|
||||
Help: "total amount of library variables in the database",
|
||||
Namespace: ExporterName,
|
||||
})
|
||||
|
||||
StatsTotalDataKeys = prometheus.NewGauge(prometheus.GaugeOpts{
|
||||
Name: "stat_totals_data_keys",
|
||||
Help: "total amount of data keys in the database",
|
||||
Namespace: ExporterName,
|
||||
})
|
||||
}
|
||||
|
||||
// SetBuildInformation sets the build information for this binary
|
||||
@ -660,6 +668,7 @@ func initMetricVars() {
|
||||
MAccessEvaluationCount,
|
||||
StatsTotalLibraryPanels,
|
||||
StatsTotalLibraryVariables,
|
||||
StatsTotalDataKeys,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -138,6 +138,7 @@ func (s *Service) collect(ctx context.Context) (map[string]interface{}, error) {
|
||||
m["stats.folders_viewers_can_edit.count"] = statsQuery.Result.FoldersViewersCanEdit
|
||||
m["stats.folders_viewers_can_admin.count"] = statsQuery.Result.FoldersViewersCanAdmin
|
||||
m["stats.api_keys.count"] = statsQuery.Result.APIKeys
|
||||
m["stats.data_keys.count"] = statsQuery.Result.DataKeys
|
||||
|
||||
ossEditionCount := 1
|
||||
enterpriseEditionCount := 0
|
||||
@ -326,6 +327,7 @@ func (s *Service) updateTotalStats(ctx context.Context) bool {
|
||||
metrics.StatsTotalAlertRules.Set(float64(statsQuery.Result.AlertRules))
|
||||
metrics.StatsTotalLibraryPanels.Set(float64(statsQuery.Result.LibraryPanels))
|
||||
metrics.StatsTotalLibraryVariables.Set(float64(statsQuery.Result.LibraryVariables))
|
||||
metrics.StatsTotalDataKeys.Set(float64(statsQuery.Result.DataKeys))
|
||||
|
||||
dsStats := models.GetDataSourceStatsQuery{}
|
||||
if err := s.sqlstore.GetDataSourceStats(ctx, &dsStats); err != nil {
|
||||
|
@ -8,18 +8,17 @@ import (
|
||||
"time"
|
||||
|
||||
sdkhttpclient "github.com/grafana/grafana-plugin-sdk-go/backend/httpclient"
|
||||
"github.com/grafana/grafana/pkg/registry"
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/httpclient"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/infra/httpclient"
|
||||
"github.com/grafana/grafana/pkg/infra/usagestats"
|
||||
"github.com/grafana/grafana/pkg/login/social"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/plugins"
|
||||
"github.com/grafana/grafana/pkg/registry"
|
||||
"github.com/grafana/grafana/pkg/services/datasources"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore"
|
||||
@ -281,6 +280,8 @@ func TestCollectingUsageStats(t *testing.T) {
|
||||
assert.EqualValues(t, 1, metrics["stats.packaging.deb.count"])
|
||||
assert.EqualValues(t, 1, metrics["stats.distributor.hosted-grafana.count"])
|
||||
|
||||
assert.EqualValues(t, 11, metrics["stats.data_keys.count"])
|
||||
|
||||
assert.InDelta(t, int64(65), metrics["stats.uptime"], 6)
|
||||
}
|
||||
|
||||
@ -323,6 +324,7 @@ func mockSystemStats(sqlStore *mockstore.SQLStoreMock) {
|
||||
FoldersViewersCanAdmin: 1,
|
||||
FoldersViewersCanEdit: 5,
|
||||
APIKeys: 2,
|
||||
DataKeys: 11,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -39,6 +39,7 @@ type SystemStats struct {
|
||||
DailyActiveEditors int64
|
||||
DailyActiveViewers int64
|
||||
DailyActiveSessions int64
|
||||
DataKeys int64
|
||||
}
|
||||
|
||||
type DataSourceStats struct {
|
||||
|
@ -1,8 +1,11 @@
|
||||
package manager
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -36,6 +39,11 @@ func (c *dataKeyCache) get(id string) ([]byte, bool) {
|
||||
defer c.RUnlock()
|
||||
|
||||
entry, exists := c.entries[id]
|
||||
|
||||
cacheReadsCounter.With(prometheus.Labels{
|
||||
"hit": strconv.FormatBool(exists),
|
||||
}).Inc()
|
||||
|
||||
if !exists || entry.expired() {
|
||||
return nil, false
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ import (
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
@ -16,6 +17,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/kmsproviders"
|
||||
"github.com/grafana/grafana/pkg/services/secrets"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"golang.org/x/sync/errgroup"
|
||||
"xorm.io/xorm"
|
||||
)
|
||||
@ -130,11 +132,20 @@ func (s *SecretsService) EncryptWithDBSession(ctx context.Context, payload []byt
|
||||
return s.enc.Encrypt(ctx, payload, setting.SecretKey)
|
||||
}
|
||||
|
||||
var err error
|
||||
defer func() {
|
||||
opsCounter.With(prometheus.Labels{
|
||||
"success": strconv.FormatBool(err == nil),
|
||||
"operation": OpEncrypt,
|
||||
}).Inc()
|
||||
}()
|
||||
|
||||
// If encryption featuremgmt.FlagEnvelopeEncryption toggle is on, use envelope encryption
|
||||
scope := opt()
|
||||
keyName := s.keyName(scope)
|
||||
|
||||
dataKey, err := s.dataKey(ctx, keyName)
|
||||
var dataKey []byte
|
||||
dataKey, err = s.dataKey(ctx, keyName)
|
||||
if err != nil {
|
||||
if errors.Is(err, secrets.ErrDataKeyNotFound) {
|
||||
dataKey, err = s.newDataKey(ctx, keyName, scope, sess)
|
||||
@ -146,7 +157,8 @@ func (s *SecretsService) EncryptWithDBSession(ctx context.Context, payload []byt
|
||||
}
|
||||
}
|
||||
|
||||
encrypted, err := s.enc.Encrypt(ctx, payload, string(dataKey))
|
||||
var encrypted []byte
|
||||
encrypted, err = s.enc.Encrypt(ctx, payload, string(dataKey))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -174,8 +186,17 @@ func (s *SecretsService) Decrypt(ctx context.Context, payload []byte) ([]byte, e
|
||||
}
|
||||
|
||||
// If encryption featuremgmt.FlagEnvelopeEncryption toggle is on, use envelope encryption
|
||||
var err error
|
||||
defer func() {
|
||||
opsCounter.With(prometheus.Labels{
|
||||
"success": strconv.FormatBool(err == nil),
|
||||
"operation": OpDecrypt,
|
||||
}).Inc()
|
||||
}()
|
||||
|
||||
if len(payload) == 0 {
|
||||
return nil, fmt.Errorf("unable to decrypt empty payload")
|
||||
err = fmt.Errorf("unable to decrypt empty payload")
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var dataKey []byte
|
||||
@ -187,12 +208,13 @@ func (s *SecretsService) Decrypt(ctx context.Context, payload []byte) ([]byte, e
|
||||
payload = payload[1:]
|
||||
endOfKey := bytes.Index(payload, []byte{'#'})
|
||||
if endOfKey == -1 {
|
||||
return nil, fmt.Errorf("could not find valid key in encrypted payload")
|
||||
err = fmt.Errorf("could not find valid key in encrypted payload")
|
||||
return nil, err
|
||||
}
|
||||
b64Key := payload[:endOfKey]
|
||||
payload = payload[endOfKey+1:]
|
||||
key := make([]byte, b64.DecodedLen(len(b64Key)))
|
||||
_, err := b64.Decode(key, b64Key)
|
||||
_, err = b64.Decode(key, b64Key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -204,7 +226,10 @@ func (s *SecretsService) Decrypt(ctx context.Context, payload []byte) ([]byte, e
|
||||
}
|
||||
}
|
||||
|
||||
return s.enc.Decrypt(ctx, payload, string(dataKey))
|
||||
var decrypted []byte
|
||||
decrypted, err = s.enc.Decrypt(ctx, payload, string(dataKey))
|
||||
|
||||
return decrypted, err
|
||||
}
|
||||
|
||||
func (s *SecretsService) EncryptJsonData(ctx context.Context, kv map[string]string, opt secrets.EncryptionOptions) (map[string][]byte, error) {
|
||||
|
37
pkg/services/secrets/manager/metrics.go
Normal file
37
pkg/services/secrets/manager/metrics.go
Normal file
@ -0,0 +1,37 @@
|
||||
package manager
|
||||
|
||||
import (
|
||||
"github.com/grafana/grafana/pkg/infra/metrics"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
const (
|
||||
OpEncrypt = "encrypt"
|
||||
OpDecrypt = "decrypt"
|
||||
)
|
||||
|
||||
var (
|
||||
opsCounter = prometheus.NewCounterVec(
|
||||
prometheus.CounterOpts{
|
||||
Namespace: metrics.ExporterName,
|
||||
Name: "encryption_ops_total",
|
||||
Help: "A counter for encryption operations",
|
||||
},
|
||||
[]string{"success", "operation"},
|
||||
)
|
||||
cacheReadsCounter = prometheus.NewCounterVec(
|
||||
prometheus.CounterOpts{
|
||||
Namespace: metrics.ExporterName,
|
||||
Name: "encryption_cache_reads_total",
|
||||
Help: "A counter for encryption cache reads",
|
||||
},
|
||||
[]string{"hit"},
|
||||
)
|
||||
)
|
||||
|
||||
func init() {
|
||||
prometheus.MustRegister(
|
||||
opsCounter,
|
||||
cacheReadsCounter,
|
||||
)
|
||||
}
|
@ -102,6 +102,7 @@ func (ss *SQLStore) GetSystemStats(ctx context.Context, query *models.GetSystemS
|
||||
sb.Write(`(SELECT COUNT(id) FROM ` + dialect.Quote("api_key") + `WHERE service_account_id IS NULL) AS api_keys,`)
|
||||
sb.Write(`(SELECT COUNT(id) FROM `+dialect.Quote("library_element")+` WHERE kind = ?) AS library_panels,`, models.PanelElement)
|
||||
sb.Write(`(SELECT COUNT(id) FROM `+dialect.Quote("library_element")+` WHERE kind = ?) AS library_variables,`, models.VariableElement)
|
||||
sb.Write(`(SELECT COUNT(*) FROM ` + dialect.Quote("data_keys") + `) AS data_keys,`)
|
||||
|
||||
sb.Write(ss.roleCounterSQL(ctx))
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user