Encryption: Add Prometheus metrics (#48603)

This commit is contained in:
Joan López de la Franca Beltran 2022-05-06 10:21:55 +02:00 committed by GitHub
parent 0e1dffc655
commit 9826a694a8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 95 additions and 10 deletions

View File

@ -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,
)
}

View File

@ -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 {

View File

@ -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,
}
}

View File

@ -39,6 +39,7 @@ type SystemStats struct {
DailyActiveEditors int64
DailyActiveViewers int64
DailyActiveSessions int64
DataKeys int64
}
type DataSourceStats struct {

View File

@ -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
}

View File

@ -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) {

View 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,
)
}

View File

@ -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))