grafana/pkg/services/sqlstore/apikey.go
Ieva a5672758d8
Access control: further reduce access control feature toggle checks (#48171)
* reduce the usage of access control flag further by removing it from SQL store methods

* fixing tests

* fix another test

* linting

* remove AC feature toggle use from API keys

* remove unneeded function
2022-05-05 17:31:14 +02:00

147 lines
3.9 KiB
Go

package sqlstore
import (
"context"
"time"
"xorm.io/xorm"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/accesscontrol"
)
// GetAPIKeys queries the database based
// on input on GetApiKeysQuery
func (ss *SQLStore) GetAPIKeys(ctx context.Context, query *models.GetApiKeysQuery) error {
return ss.WithDbSession(ctx, func(dbSession *DBSession) error {
var sess *xorm.Session
if query.IncludeExpired {
sess = dbSession.Limit(100, 0).
Where("org_id=?", query.OrgId).
Asc("name")
} else {
sess = dbSession.Limit(100, 0).
Where("org_id=? and ( expires IS NULL or expires >= ?)", query.OrgId, timeNow().Unix()).
Asc("name")
}
sess = sess.Where("service_account_id IS NULL")
if !accesscontrol.IsDisabled(ss.Cfg) {
filter, err := accesscontrol.Filter(query.User, "id", "apikeys:id:", accesscontrol.ActionAPIKeyRead)
if err != nil {
return err
}
sess.And(filter.Where, filter.Args...)
}
query.Result = make([]*models.ApiKey, 0)
return sess.Find(&query.Result)
})
}
// GetAllOrgsAPIKeys queries the database for valid non SA APIKeys across all orgs
func (ss *SQLStore) GetAllOrgsAPIKeys(ctx context.Context) []*models.ApiKey {
result := make([]*models.ApiKey, 0)
err := ss.WithDbSession(ctx, func(dbSession *DBSession) error {
sess := dbSession. //CHECK how many API keys do our clients have? Can we load them all?
Where("(expires IS NULL OR expires >= ?) AND service_account_id IS NULL", timeNow().Unix()).Asc("name")
return sess.Find(&result)
})
if err != nil {
ss.log.Warn("API key not loaded", "err", err)
}
return result
}
func (ss *SQLStore) DeleteApiKey(ctx context.Context, cmd *models.DeleteApiKeyCommand) error {
return ss.WithDbSession(ctx, func(sess *DBSession) error {
return deleteAPIKey(sess, cmd.Id, cmd.OrgId)
})
}
func deleteAPIKey(sess *DBSession, id, orgID int64) error {
rawSQL := "DELETE FROM api_key WHERE id=? and org_id=? and service_account_id IS NULL"
result, err := sess.Exec(rawSQL, id, orgID)
if err != nil {
return err
}
n, err := result.RowsAffected()
if err != nil {
return err
} else if n == 0 {
return models.ErrApiKeyNotFound
}
return nil
}
// AddAPIKey adds the API key to the database.
func (ss *SQLStore) AddAPIKey(ctx context.Context, cmd *models.AddApiKeyCommand) error {
return ss.WithTransactionalDbSession(ctx, func(sess *DBSession) error {
key := models.ApiKey{OrgId: cmd.OrgId, Name: cmd.Name}
exists, _ := sess.Get(&key)
if exists {
return models.ErrDuplicateApiKey
}
updated := timeNow()
var expires *int64 = nil
if cmd.SecondsToLive > 0 {
v := updated.Add(time.Second * time.Duration(cmd.SecondsToLive)).Unix()
expires = &v
} else if cmd.SecondsToLive < 0 {
return models.ErrInvalidApiKeyExpiration
}
t := models.ApiKey{
OrgId: cmd.OrgId,
Name: cmd.Name,
Role: cmd.Role,
Key: cmd.Key,
Created: updated,
Updated: updated,
Expires: expires,
ServiceAccountId: nil,
}
if _, err := sess.Insert(&t); err != nil {
return err
}
cmd.Result = &t
return nil
})
}
func (ss *SQLStore) GetApiKeyById(ctx context.Context, query *models.GetApiKeyByIdQuery) error {
return ss.WithDbSession(ctx, func(sess *DBSession) error {
var apikey models.ApiKey
has, err := sess.ID(query.ApiKeyId).Get(&apikey)
if err != nil {
return err
} else if !has {
return models.ErrInvalidApiKey
}
query.Result = &apikey
return nil
})
}
func (ss *SQLStore) GetApiKeyByName(ctx context.Context, query *models.GetApiKeyByNameQuery) error {
return ss.WithDbSession(ctx, func(sess *DBSession) error {
var apikey models.ApiKey
has, err := sess.Where("org_id=? AND name=?", query.OrgId, query.KeyName).Get(&apikey)
if err != nil {
return err
} else if !has {
return models.ErrInvalidApiKey
}
query.Result = &apikey
return nil
})
}