grafana/pkg/services/thumbs/crawler_auth.go
idafurjes 6afad51761
Move SignedInUser to user service and RoleType and Roles to org (#53445)
* Move SignedInUser to user service and RoleType and Roles to org

* Use go naming convention for roles

* Fix some imports and leftovers

* Fix ldap debug test

* Fix lint

* Fix lint 2

* Fix lint 3

* Fix type and not needed conversion

* Clean up messages in api tests

* Clean up api tests 2
2022-08-10 11:56:48 +02:00

140 lines
4.3 KiB
Go

package thumbs
import (
"context"
"errors"
"strconv"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/org"
"github.com/grafana/grafana/pkg/services/serviceaccounts"
"github.com/grafana/grafana/pkg/services/serviceaccounts/database"
"github.com/grafana/grafana/pkg/services/sqlstore"
)
type CrawlerAuthSetupService interface {
Setup(ctx context.Context) (CrawlerAuth, error)
}
func ProvideCrawlerAuthSetupService(serviceAccounts serviceaccounts.Service, serviceAccountsStore serviceaccounts.Store, sqlStore *sqlstore.SQLStore) *OSSCrawlerAuthSetupService {
return &OSSCrawlerAuthSetupService{
serviceAccountNamePrefix: "dashboard-previews-crawler-org-",
serviceAccounts: serviceAccounts,
log: log.New("oss_crawler_account_setup_service"),
sqlStore: sqlStore,
serviceAccountsStore: serviceAccountsStore,
}
}
type OSSCrawlerAuthSetupService struct {
log log.Logger
serviceAccountNamePrefix string
serviceAccounts serviceaccounts.Service
serviceAccountsStore serviceaccounts.Store
sqlStore *sqlstore.SQLStore
}
type CrawlerAuth interface {
GetUserId(orgId int64) int64
GetLogin(orgId int64) string
GetOrgRole() org.RoleType
}
func (o *OSSCrawlerAuthSetupService) findAllOrgIds(ctx context.Context) ([]int64, error) {
searchAllOrgsQuery := &models.SearchOrgsQuery{}
if err := o.sqlStore.SearchOrgs(ctx, searchAllOrgsQuery); err != nil {
o.log.Error("Error when searching for orgs", "err", err)
return nil, err
}
orgIds := make([]int64, 0)
for i := range searchAllOrgsQuery.Result {
orgIds = append(orgIds, searchAllOrgsQuery.Result[i].Id)
}
return orgIds, nil
}
type crawlerAuth struct {
accountIdByOrgId map[int64]int64
loginByOrgId map[int64]string
orgRole org.RoleType
}
func (o *crawlerAuth) GetOrgRole() org.RoleType {
return o.orgRole
}
func (o *crawlerAuth) GetUserId(orgId int64) int64 {
return o.accountIdByOrgId[orgId]
}
func (o *crawlerAuth) GetLogin(orgId int64) string {
return o.loginByOrgId[orgId]
}
func (o *OSSCrawlerAuthSetupService) Setup(ctx context.Context) (CrawlerAuth, error) {
orgIds, err := o.findAllOrgIds(ctx)
if err != nil {
return nil, err
}
// userId:0 and RoleAdmin grants the crawler process permissions to view all dashboards in all folders & orgs
// the process doesn't and shouldn't actually need to edit/modify any resources from the UI
orgRole := org.RoleAdmin
accountIdByOrgId := make(map[int64]int64)
loginByOrgId := make(map[int64]string)
for _, orgId := range orgIds {
o.log.Info("Creating account for org", "orgId", orgId)
serviceAccountNameOrg := o.serviceAccountNamePrefix + strconv.FormatInt(orgId, 10)
saForm := serviceaccounts.CreateServiceAccountForm{
Name: serviceAccountNameOrg,
Role: &orgRole,
}
serviceAccount, err := o.serviceAccounts.CreateServiceAccount(ctx, orgId, &saForm)
accountAlreadyExists := errors.Is(err, database.ErrServiceAccountAlreadyExists)
if !accountAlreadyExists && err != nil {
o.log.Error("Failed to create the service account", "err", err, "accountName", serviceAccountNameOrg, "orgId", orgId)
return nil, err
}
var serviceAccountLogin string
var serviceAccountId int64
if accountAlreadyExists {
id, err := o.serviceAccounts.RetrieveServiceAccountIdByName(ctx, orgId, serviceAccountNameOrg)
if err != nil {
o.log.Error("Failed to retrieve service account", "err", err, "accountName", serviceAccountNameOrg)
return nil, err
}
// update org_role to make sure everything works properly if someone has changed the role since SA's original creation
dto, err := o.serviceAccountsStore.UpdateServiceAccount(ctx, orgId, id, &serviceaccounts.UpdateServiceAccountForm{
Name: &serviceAccountNameOrg,
Role: &orgRole,
})
if err != nil {
o.log.Error("Failed to update service account's role", "err", err, "accountName", serviceAccountNameOrg)
return nil, err
}
serviceAccountLogin = dto.Login
serviceAccountId = id
} else {
serviceAccountLogin = serviceAccount.Login
serviceAccountId = serviceAccount.Id
}
accountIdByOrgId[orgId] = serviceAccountId
loginByOrgId[orgId] = serviceAccountLogin
}
return &crawlerAuth{accountIdByOrgId: accountIdByOrgId, loginByOrgId: loginByOrgId, orgRole: orgRole}, nil
}