Access control: Pass access control metadata for api keys (#48445)

* Move ApiKeyDTO to dtos package

* Add access control filter to api keys

* pass user in GetApiKeysQuery

* Add api key metadata to DTO

* Remove scope all requirement from get api keys endpoint

* Handle api key access control metadata in frondend
This commit is contained in:
Karl Persson
2022-04-29 15:30:24 +02:00
committed by GitHub
parent e9a2a06651
commit 6c6137f45a
13 changed files with 123 additions and 39 deletions

View File

@@ -9,6 +9,7 @@ import (
)
var sqlIDAcceptList = map[string]struct{}{
"id": {},
"org_user.user_id": {},
"role.id": {},
"t.id": {},

View File

@@ -7,6 +7,8 @@ import (
"xorm.io/xorm"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/accesscontrol"
"github.com/grafana/grafana/pkg/services/featuremgmt"
)
// GetAPIKeys queries the database based
@@ -27,6 +29,14 @@ func (ss *SQLStore) GetAPIKeys(ctx context.Context, query *models.GetApiKeysQuer
sess = sess.Where("service_account_id IS NULL")
if ss.Cfg.IsFeatureToggleEnabled(featuremgmt.FlagAccesscontrol) {
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)
})

View File

@@ -5,10 +5,14 @@ package sqlstore
import (
"context"
"fmt"
"testing"
"time"
"github.com/stretchr/testify/require"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/featuremgmt"
"github.com/stretchr/testify/assert"
)
@@ -149,3 +153,60 @@ func TestApiKeyErrors(t *testing.T) {
})
})
}
type getApiKeysTestCase struct {
desc string
user *models.SignedInUser
expectedNumKeys int
}
func TestSQLStore_GetAPIKeys(t *testing.T) {
tests := []getApiKeysTestCase{
{
desc: "expect all keys for wildcard scope",
user: &models.SignedInUser{OrgId: 1, Permissions: map[int64]map[string][]string{
1: {"apikeys:read": {"apikeys:*"}},
}},
expectedNumKeys: 10,
},
{
desc: "expect only api keys that user have scopes for",
user: &models.SignedInUser{OrgId: 1, Permissions: map[int64]map[string][]string{
1: {"apikeys:read": {"apikeys:id:1", "apikeys:id:3"}},
}},
expectedNumKeys: 2,
},
{
desc: "expect no keys when user have no scopes",
user: &models.SignedInUser{OrgId: 1, Permissions: map[int64]map[string][]string{
1: {"apikeys:read": {}},
}},
expectedNumKeys: 0,
},
}
for _, tt := range tests {
t.Run(tt.desc, func(t *testing.T) {
store := InitTestDB(t, InitTestDBOpt{FeatureFlags: []string{featuremgmt.FlagAccesscontrol}})
seedApiKeys(t, store, 10)
query := &models.GetApiKeysQuery{OrgId: 1, User: tt.user}
err := store.GetAPIKeys(context.Background(), query)
require.NoError(t, err)
assert.Len(t, query.Result, tt.expectedNumKeys)
})
}
}
func seedApiKeys(t *testing.T, store *SQLStore, num int) {
t.Helper()
for i := 0; i < num; i++ {
err := store.AddAPIKey(context.Background(), &models.AddApiKeyCommand{
Name: fmt.Sprintf("key:%d", i),
Key: fmt.Sprintf("key:%d", i),
OrgId: 1,
})
require.NoError(t, err)
}
}