From d8c2957c84841cb4fa461d9525bc82ad4e3df0bb Mon Sep 17 00:00:00 2001 From: jkoberg Date: Fri, 11 Aug 2023 14:10:10 +0200 Subject: [PATCH] use service accounts for search Signed-off-by: jkoberg --- services/search/pkg/config/config.go | 8 ++++- .../pkg/config/defaults/defaultconfig.go | 9 +++--- services/search/pkg/config/parser/parse.go | 4 --- services/search/pkg/search/search.go | 24 ++------------- services/search/pkg/search/service.go | 29 ++++++++----------- 5 files changed, 25 insertions(+), 49 deletions(-) diff --git a/services/search/pkg/config/config.go b/services/search/pkg/config/config.go index 9b66cd808..6b2399959 100644 --- a/services/search/pkg/config/config.go +++ b/services/search/pkg/config/config.go @@ -29,7 +29,13 @@ type Config struct { Extractor Extractor `yaml:"extractor"` ContentExtractionSizeLimit uint64 `yaml:"content_extraction_size_limit" env:"SEARCH_CONTENT_EXTRACTION_SIZE_LIMIT" desc:"Maximum file size in bytes that is allowed for content extraction."` - MachineAuthAPIKey string `yaml:"machine_auth_api_key" env:"OCIS_MACHINE_AUTH_API_KEY;SEARCH_MACHINE_AUTH_API_KEY" desc:"Machine auth API key used to validate internal requests necessary for the access to resources from other services."` + ServiceAccount ServiceAccount `yaml:"service_account"` Context context.Context `yaml:"-"` } + +// ServiceAccount is the configuration for the used service account +type ServiceAccount struct { + ServiceAccountID string `yaml:"service_account_id" env:"OCIS_SERVICE_ACCOUNT_ID;SEARCH_SERVICE_ACCOUNT_ID" desc:"The ID of the service account the service should use. See the 'auth-service' service description for more details."` + ServiceAccountSecret string `yaml:"service_account_secret" env:"OCIS_SERVICE_ACCOUNT_SECRET;SEARCH_SERVICE_ACCOUNT_SECRET" desc:"The service account secret."` +} diff --git a/services/search/pkg/config/defaults/defaultconfig.go b/services/search/pkg/config/defaults/defaultconfig.go index 50fe01b12..04c8d0a24 100644 --- a/services/search/pkg/config/defaults/defaultconfig.go +++ b/services/search/pkg/config/defaults/defaultconfig.go @@ -54,7 +54,10 @@ func DefaultConfig() *config.Config { EnableTLS: false, }, ContentExtractionSizeLimit: 20 * 1024 * 1024, // Limit content extraction to <20MB files by default - MachineAuthAPIKey: "", + ServiceAccount: config.ServiceAccount{ + ServiceAccountID: "service-user-id", + ServiceAccountSecret: "secret-string", + }, } } @@ -91,10 +94,6 @@ func EnsureDefaults(cfg *config.Config) { cfg.TokenManager = &config.TokenManager{} } - if cfg.MachineAuthAPIKey == "" && cfg.Commons != nil && cfg.Commons.MachineAuthAPIKey != "" { - cfg.MachineAuthAPIKey = cfg.Commons.MachineAuthAPIKey - } - if cfg.Reva == nil && cfg.Commons != nil { cfg.Reva = structs.CopyOrZeroValue(cfg.Commons.Reva) } diff --git a/services/search/pkg/config/parser/parse.go b/services/search/pkg/config/parser/parse.go index fafad8f84..9b3c124ae 100644 --- a/services/search/pkg/config/parser/parse.go +++ b/services/search/pkg/config/parser/parse.go @@ -4,7 +4,6 @@ import ( "errors" ociscfg "github.com/owncloud/ocis/v2/ocis-pkg/config" - "github.com/owncloud/ocis/v2/ocis-pkg/shared" "github.com/owncloud/ocis/v2/services/search/pkg/config" "github.com/owncloud/ocis/v2/services/search/pkg/config/defaults" @@ -34,8 +33,5 @@ func ParseConfig(cfg *config.Config) error { } func Validate(cfg *config.Config) error { - if cfg.MachineAuthAPIKey == "" { - return shared.MissingMachineAuthApiKeyError(cfg.Service.Name) - } return nil } diff --git a/services/search/pkg/search/search.go b/services/search/pkg/search/search.go index d8d595ea8..26213790a 100644 --- a/services/search/pkg/search/search.go +++ b/services/search/pkg/search/search.go @@ -8,18 +8,14 @@ import ( "strings" gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1" - user "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1" provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" - ctxpkg "github.com/cs3org/reva/v2/pkg/ctx" - "github.com/cs3org/reva/v2/pkg/errtypes" "github.com/cs3org/reva/v2/pkg/rgrpc/todo/pool" "github.com/cs3org/reva/v2/pkg/storagespace" "github.com/cs3org/reva/v2/pkg/utils" "github.com/owncloud/ocis/v2/ocis-pkg/log" searchmsg "github.com/owncloud/ocis/v2/protogen/gen/ocis/messages/search/v0" "github.com/owncloud/ocis/v2/services/search/pkg/engine" - "google.golang.org/grpc/metadata" ) var scopeRegex = regexp.MustCompile(`scope:\s*([^" "\n\r]*)`) @@ -71,30 +67,14 @@ func logDocCount(engine engine.Engine, logger log.Logger) { logger.Debug().Interface("count", c).Msg("new document count") } -func getAuthContext(owner *user.User, gatewaySelector pool.Selectable[gateway.GatewayAPIClient], secret string, logger log.Logger) (context.Context, error) { +func getAuthContext(serviceAccountID string, gatewaySelector pool.Selectable[gateway.GatewayAPIClient], secret string, logger log.Logger) (context.Context, error) { gatewayClient, err := gatewaySelector.Next() if err != nil { logger.Error().Err(err).Msg("could not get reva gatewayClient") return nil, err } - ownerCtx := ctxpkg.ContextSetUser(context.Background(), owner) - authRes, err := gatewayClient.Authenticate(ownerCtx, &gateway.AuthenticateRequest{ - Type: "machine", - ClientId: "userid:" + owner.GetId().GetOpaqueId(), - ClientSecret: secret, - }) - - if err == nil && authRes.GetStatus().GetCode() != rpc.Code_CODE_OK { - err = errtypes.NewErrtypeFromStatus(authRes.Status) - } - - if err != nil { - logger.Error().Err(err).Interface("owner", owner).Interface("authRes", authRes).Msg("error using machine auth") - return nil, err - } - - return metadata.AppendToOutgoingContext(ownerCtx, ctxpkg.TokenHeader, authRes.Token), nil + return utils.GetServiceUserContext(serviceAccountID, gatewayClient, secret) } func statResource(ctx context.Context, ref *provider.Reference, gatewaySelector pool.Selectable[gateway.GatewayAPIClient], logger log.Logger) (*provider.StatResponse, error) { diff --git a/services/search/pkg/search/service.go b/services/search/pkg/search/service.go index 43707a07f..1ce6a9c32 100644 --- a/services/search/pkg/search/service.go +++ b/services/search/pkg/search/service.go @@ -57,7 +57,9 @@ type Service struct { gatewaySelector pool.Selectable[gateway.GatewayAPIClient] engine engine.Engine extractor content.Extractor - secret string + + serviceAccountID string + serviceAccountSecret string } var errSkipSpace error @@ -67,9 +69,11 @@ func NewService(gatewaySelector pool.Selectable[gateway.GatewayAPIClient], eng e var s = &Service{ gatewaySelector: gatewaySelector, engine: eng, - secret: cfg.MachineAuthAPIKey, logger: logger, extractor: extractor, + + serviceAccountID: cfg.ServiceAccount.ServiceAccountID, + serviceAccountSecret: cfg.ServiceAccount.ServiceAccountSecret, } return s @@ -291,21 +295,12 @@ func (s *Service) searchIndex(ctx context.Context, req *searchsvc.SearchRequest, return nil, err } - var ownerCtx context.Context - if space.Owner.Id.Type == user.UserType_USER_TYPE_SPACE_OWNER { - // We can't impersonate SPACE_OWNER users and have to fall back to using the user auth instead, - // which will not resolve the absolute path of the share in the space but only the part the user - // is allowed to see. - // In the future this problem can be solved using service accounts. - ownerCtx = ctx - } else { - ownerCtx, err = getAuthContext(&user.User{Id: space.Owner.Id}, s.gatewaySelector, s.secret, s.logger) - if err != nil { - return nil, err - } + serviceCtx, err := getAuthContext(s.serviceAccountID, s.gatewaySelector, s.serviceAccountSecret, s.logger) + if err != nil { + return nil, err } - gpRes, err := gatewayClient.GetPath(ownerCtx, &provider.GetPathRequest{ + gpRes, err := gatewayClient.GetPath(serviceCtx, &provider.GetPathRequest{ ResourceId: space.Root, }) if err != nil { @@ -380,7 +375,7 @@ func (s *Service) searchIndex(ctx context.Context, req *searchsvc.SearchRequest, // IndexSpace (re)indexes all resources of a given space. func (s *Service) IndexSpace(spaceID *provider.StorageSpaceId, uID *user.UserId) error { - ownerCtx, err := getAuthContext(&user.User{Id: uID}, s.gatewaySelector, s.secret, s.logger) + ownerCtx, err := getAuthContext(s.serviceAccountID, s.gatewaySelector, s.serviceAccountSecret, s.logger) if err != nil { return err } @@ -510,7 +505,7 @@ func (s *Service) MoveItem(ref *provider.Reference, uID *user.UserId) { } func (s *Service) resInfo(uID *user.UserId, ref *provider.Reference) (context.Context, *provider.StatResponse, string) { - ownerCtx, err := getAuthContext(&user.User{Id: uID}, s.gatewaySelector, s.secret, s.logger) + ownerCtx, err := getAuthContext(s.serviceAccountID, s.gatewaySelector, s.serviceAccountSecret, s.logger) if err != nil { return nil, nil, "" }