From 9c11040c3e99558754e8d496f39f2997b197c7d7 Mon Sep 17 00:00:00 2001 From: Eric Leijonmarck Date: Tue, 23 Nov 2021 23:06:40 +0000 Subject: [PATCH] Serviceaccounts: Filtering service accounts from user queries (#41410) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add extra fields to OSS types to support enterprise * WIP service accounts * Update public/app/features/api-keys/ApiKeysForm.tsx Co-authored-by: Hugo Häggmark * Create a service account at the same time as the API key * Use service account credentials when accessing API with APIkey * Throw better error * Use Boolean for "create service account button" * Add GetRole to service, merge RoleDTO and Role structs This patch merges the identical OSS and Enterprise data structures, which improves the code for two reasons: 1. Makes switching between OSS and Enterprise easier 2. Reduces the chance of incompatibilities developing between the same functions in OSS and Enterprise * Start work cloning permissions onto service account * If API key is not linked to a service account, continue login as usual * Fallback to old auth if no service account linked to key * Commented * Add CloneUserToServiceAccount * Update mock.go * Put graphical bits behind a feature toggle * Start adding LinkAPIKeyToServiceAccount * Update pkg/models/user.go Co-authored-by: Eric Leijonmarck * Update pkg/api/apikey.go Co-authored-by: Eric Leijonmarck * Update pkg/api/apikey.go Co-authored-by: Eric Leijonmarck * Finish LinkAPIKeyToServiceAccount * Update comment * Handle api key link error * Update pkg/services/sqlstore/apikey.go Co-authored-by: Emil Tullstedt * Feature toggle * Update pkg/services/accesscontrol/accesscontrol.go Co-authored-by: Ieva * Not needed (yet) * Better error messages for OSS accesscontrol * Set an invalid user id as default * ServiceAccountId should be string * Re-arrange field names * ServiceAccountId is integer * Update ossaccesscontrol.go * Linter * Remove fronend edits * Remove console log * Update ApiKeysForm.tsx * feat: add serviceaccount deletion * feat: make sure we do not accidently delete serviceaccount * feat: ServiceAccount Type * refactor: userDeletions function * refactor: serviceaccount deletions\ * refactor: error name and removed attribute for userDeletecommand * refactor:: remove serviceaccount type for now * WIP * add mocked function * Remove unnecessary db query, move to right place * Update pkg/services/accesscontrol/mock/mock.go Co-authored-by: Gabriel MABILLE * Update pkg/services/accesscontrol/mock/mock.go Co-authored-by: Gabriel MABILLE * Update pkg/services/accesscontrol/mock/mock.go Co-authored-by: Gabriel MABILLE * Better error messages * Better and correcter error messages * add mocked function * refactor: move function call, add error msg * add IsServiceAccount and fix table * add service accounts package * WIP * WIP * working serviceaccountsapi registration * WIP tests * test * test working * test running for service * moved the error out of the models package * fixed own review * linting errors * Update pkg/services/serviceaccounts/database/database.go Co-authored-by: Jeremy Price * tests running for api * WIP * WIP * removed unused secrets background svc * removed background svc for serviceaccount infavor or wire.go * serviceaccounts manager tests * wip * Filtering service accounts from the user queries in frontend * clean up * Update pkg/services/sqlstore/org_test.go * methods on same type should have same receiver * _ unused variable and comment * add additional join for results query * remove unused code * remove error fmt * refactor: change to only have false * no new variable to the left hand side * refactor: create serviceaccount cmd * dialect fix Co-authored-by: Jeremy Price Co-authored-by: Hugo Häggmark Co-authored-by: Emil Tullstedt Co-authored-by: Ieva Co-authored-by: Gabriel MABILLE --- pkg/services/serviceaccounts/manager/service.go | 8 ++++---- pkg/services/sqlstore/org_test.go | 4 ++++ pkg/services/sqlstore/org_users.go | 11 ++++++++++- pkg/services/sqlstore/user.go | 4 ++++ 4 files changed, 22 insertions(+), 5 deletions(-) diff --git a/pkg/services/serviceaccounts/manager/service.go b/pkg/services/serviceaccounts/manager/service.go index a7e41de2cb8..c2ec6a0977b 100644 --- a/pkg/services/serviceaccounts/manager/service.go +++ b/pkg/services/serviceaccounts/manager/service.go @@ -42,10 +42,10 @@ func ProvideServiceAccountsService( return s, nil } -func (s *ServiceAccountsService) DeleteServiceAccount(ctx context.Context, orgID, serviceAccountID int64) error { - if !s.cfg.FeatureToggles["service-accounts"] { - s.log.Debug(ServiceAccountFeatureToggleNotFound) +func (sa *ServiceAccountsService) DeleteServiceAccount(ctx context.Context, orgID, serviceAccountID int64) error { + if !sa.cfg.FeatureToggles["service-accounts"] { + sa.log.Debug(ServiceAccountFeatureToggleNotFound) return nil } - return s.store.DeleteServiceAccount(ctx, orgID, serviceAccountID) + return sa.store.DeleteServiceAccount(ctx, orgID, serviceAccountID) } diff --git a/pkg/services/sqlstore/org_test.go b/pkg/services/sqlstore/org_test.go index 376fad7be68..bce5d2352ee 100644 --- a/pkg/services/sqlstore/org_test.go +++ b/pkg/services/sqlstore/org_test.go @@ -141,11 +141,15 @@ func TestAccountDataAccess(t *testing.T) { ac1cmd := models.CreateUserCommand{Login: "ac1", Email: "ac1@test.com", Name: "ac1 name"} ac2cmd := models.CreateUserCommand{Login: "ac2", Email: "ac2@test.com", Name: "ac2 name", IsAdmin: true} + serviceaccountcmd := models.CreateUserCommand{Login: "serviceaccount", Email: "service@test.com", Name: "serviceaccount name", IsAdmin: true, IsServiceAccount: true} ac1, err := sqlStore.CreateUser(context.Background(), ac1cmd) require.NoError(t, err) ac2, err := sqlStore.CreateUser(context.Background(), ac2cmd) require.NoError(t, err) + // user only used for making sure we filter out the service accounts + _, err = sqlStore.CreateUser(context.Background(), serviceaccountcmd) + require.NoError(t, err) t.Run("Should be able to read user info projection", func(t *testing.T) { query := models.GetUserProfileQuery{UserId: ac1.Id} diff --git a/pkg/services/sqlstore/org_users.go b/pkg/services/sqlstore/org_users.go index adadc20025c..e825667f5f5 100644 --- a/pkg/services/sqlstore/org_users.go +++ b/pkg/services/sqlstore/org_users.go @@ -107,6 +107,10 @@ func (ss *SQLStore) GetOrgUsers(ctx context.Context, query *models.GetOrgUsersQu whereConditions = append(whereConditions, "org_user.org_id = ?") whereParams = append(whereParams, query.OrgId) + // TODO: add to chore, for cleaning up after we have created + // service accounts table in the modelling + whereConditions = append(whereConditions, fmt.Sprintf("%s.is_service_account = false", x.Dialect().Quote("user"))) + if query.Query != "" { queryWithWildcards := "%" + query.Query + "%" whereConditions = append(whereConditions, "(email "+dialect.LikeStr()+" ? OR name "+dialect.LikeStr()+" ? OR login "+dialect.LikeStr()+" ?)") @@ -157,6 +161,10 @@ func (ss *SQLStore) SearchOrgUsers(ctx context.Context, query *models.SearchOrgU whereConditions = append(whereConditions, "org_user.org_id = ?") whereParams = append(whereParams, query.OrgID) + // TODO: add to chore, for cleaning up after we have created + // service accounts table in the modelling + whereConditions = append(whereConditions, fmt.Sprintf("%s.is_service_account = false", x.Dialect().Quote("user"))) + if query.Query != "" { queryWithWildcards := "%" + query.Query + "%" whereConditions = append(whereConditions, "(email "+dialect.LikeStr()+" ? OR name "+dialect.LikeStr()+" ? OR login "+dialect.LikeStr()+" ?)") @@ -189,7 +197,8 @@ func (ss *SQLStore) SearchOrgUsers(ctx context.Context, query *models.SearchOrgU // get total count orgUser := models.OrgUser{} - countSess := x.Table("org_user") + countSess := x.Table("org_user"). + Join("INNER", x.Dialect().Quote("user"), fmt.Sprintf("org_user.user_id=%s.id", x.Dialect().Quote("user"))) if len(whereConditions) > 0 { countSess.Where(strings.Join(whereConditions, " AND "), whereParams...) diff --git a/pkg/services/sqlstore/user.go b/pkg/services/sqlstore/user.go index 0cc36a5746c..f3c5ffea65e 100644 --- a/pkg/services/sqlstore/user.go +++ b/pkg/services/sqlstore/user.go @@ -609,6 +609,10 @@ func SearchUsers(ctx context.Context, query *models.SearchUsersQuery) error { whereParams := make([]interface{}, 0) sess := x.Table("user").Alias("u") + // TODO: add to chore, for cleaning up after we have created + // service accounts table in the modelling + whereConditions = append(whereConditions, "u.is_service_account = false") + // Join with only most recent auth module joinCondition := `( SELECT id from user_auth