2021-06-06 22:07:29 +00:00
|
|
|
// Package service holds the implementation of the fleet interface and HTTP
|
|
|
|
// endpoints for the API
|
2016-09-26 18:48:55 +00:00
|
|
|
package service
|
2016-08-28 03:59:17 +00:00
|
|
|
|
2016-09-01 04:51:38 +00:00
|
|
|
import (
|
2019-08-02 21:08:42 +00:00
|
|
|
"html/template"
|
|
|
|
"strings"
|
2021-04-12 23:22:22 +00:00
|
|
|
"sync"
|
2016-09-04 05:13:42 +00:00
|
|
|
|
2016-09-21 03:08:11 +00:00
|
|
|
"github.com/WatchBeam/clock"
|
2021-06-03 23:24:15 +00:00
|
|
|
"github.com/fleetdm/fleet/server/authz"
|
2020-11-11 17:59:12 +00:00
|
|
|
"github.com/fleetdm/fleet/server/config"
|
2021-06-06 22:07:29 +00:00
|
|
|
"github.com/fleetdm/fleet/server/fleet"
|
2020-11-11 17:59:12 +00:00
|
|
|
"github.com/fleetdm/fleet/server/logging"
|
|
|
|
"github.com/fleetdm/fleet/server/sso"
|
2020-12-16 17:16:55 +00:00
|
|
|
kitlog "github.com/go-kit/kit/log"
|
2019-08-02 21:08:42 +00:00
|
|
|
"github.com/kolide/kit/version"
|
2019-04-08 18:47:15 +00:00
|
|
|
"github.com/pkg/errors"
|
2016-09-01 04:51:38 +00:00
|
|
|
)
|
2016-08-28 03:59:17 +00:00
|
|
|
|
2021-06-06 22:07:29 +00:00
|
|
|
// Service is the struct implementing fleet.Service. Create a new one with NewService.
|
2021-06-01 00:07:51 +00:00
|
|
|
type Service struct {
|
2021-06-06 22:07:29 +00:00
|
|
|
ds fleet.Datastore
|
|
|
|
carveStore fleet.CarveStore
|
|
|
|
resultStore fleet.QueryResultStore
|
|
|
|
liveQueryStore fleet.LiveQueryStore
|
2021-06-01 00:07:51 +00:00
|
|
|
logger kitlog.Logger
|
2021-06-06 22:07:29 +00:00
|
|
|
config config.FleetConfig
|
2021-06-01 00:07:51 +00:00
|
|
|
clock clock.Clock
|
2021-06-06 22:07:29 +00:00
|
|
|
license fleet.LicenseInfo
|
2021-06-01 00:07:51 +00:00
|
|
|
|
|
|
|
osqueryLogWriter *logging.OsqueryLogger
|
|
|
|
|
2021-06-06 22:07:29 +00:00
|
|
|
mailService fleet.MailService
|
2021-06-01 00:07:51 +00:00
|
|
|
ssoSessionStore sso.SessionStore
|
|
|
|
|
|
|
|
seenHostSet *seenHostSet
|
2021-06-03 23:24:15 +00:00
|
|
|
|
|
|
|
authz *authz.Authorizer
|
2021-06-01 00:07:51 +00:00
|
|
|
}
|
|
|
|
|
2016-09-01 04:51:38 +00:00
|
|
|
// NewService creates a new service from the config struct
|
2021-06-06 22:07:29 +00:00
|
|
|
func NewService(ds fleet.Datastore, resultStore fleet.QueryResultStore,
|
|
|
|
logger kitlog.Logger, config config.FleetConfig, mailService fleet.MailService,
|
|
|
|
c clock.Clock, sso sso.SessionStore, lq fleet.LiveQueryStore, carveStore fleet.CarveStore,
|
|
|
|
license fleet.LicenseInfo) (fleet.Service, error) {
|
|
|
|
var svc fleet.Service
|
2019-04-08 18:47:15 +00:00
|
|
|
|
|
|
|
osqueryLogger, err := logging.New(config, logger)
|
2017-04-03 21:48:50 +00:00
|
|
|
if err != nil {
|
2019-04-08 18:47:15 +00:00
|
|
|
return nil, errors.Wrap(err, "initializing osquery logging")
|
2017-04-03 21:48:50 +00:00
|
|
|
}
|
2016-09-04 05:13:42 +00:00
|
|
|
|
2021-06-03 23:24:15 +00:00
|
|
|
authorizer, err := authz.NewAuthorizer()
|
|
|
|
if err != nil {
|
|
|
|
return nil, errors.Wrap(err, "new authorizer")
|
|
|
|
}
|
|
|
|
|
2021-06-01 00:07:51 +00:00
|
|
|
svc = &Service{
|
2019-04-08 18:47:15 +00:00
|
|
|
ds: ds,
|
2020-12-16 17:16:55 +00:00
|
|
|
carveStore: carveStore,
|
2019-04-08 18:47:15 +00:00
|
|
|
resultStore: resultStore,
|
2020-03-23 01:33:04 +00:00
|
|
|
liveQueryStore: lq,
|
2019-04-08 18:47:15 +00:00
|
|
|
logger: logger,
|
|
|
|
config: config,
|
|
|
|
clock: c,
|
|
|
|
osqueryLogWriter: osqueryLogger,
|
|
|
|
mailService: mailService,
|
|
|
|
ssoSessionStore: sso,
|
2021-04-12 23:22:22 +00:00
|
|
|
seenHostSet: newSeenHostSet(),
|
2021-06-01 00:07:51 +00:00
|
|
|
license: license,
|
2021-06-03 23:24:15 +00:00
|
|
|
authz: authorizer,
|
2016-08-28 03:59:17 +00:00
|
|
|
}
|
2017-05-09 00:43:48 +00:00
|
|
|
svc = validationMiddleware{svc, ds, sso}
|
2016-08-28 03:59:17 +00:00
|
|
|
return svc, nil
|
|
|
|
}
|
|
|
|
|
2021-06-06 22:07:29 +00:00
|
|
|
func (s Service) SendEmail(mail fleet.Email) error {
|
2016-12-20 21:54:30 +00:00
|
|
|
return s.mailService.SendEmail(mail)
|
|
|
|
}
|
2017-01-04 21:16:17 +00:00
|
|
|
|
2017-05-09 00:43:48 +00:00
|
|
|
type validationMiddleware struct {
|
2021-06-06 22:07:29 +00:00
|
|
|
fleet.Service
|
|
|
|
ds fleet.Datastore
|
2017-05-09 00:43:48 +00:00
|
|
|
ssoSessionStore sso.SessionStore
|
|
|
|
}
|
2019-08-02 21:08:42 +00:00
|
|
|
|
|
|
|
// getAssetURL gets the URL prefix used for retrieving assets from Github. This
|
|
|
|
// function will determine the appropriate version to use, and create a URL
|
|
|
|
// prefix for retrieving assets from that tag.
|
|
|
|
func getAssetURL() template.URL {
|
|
|
|
v := version.Version().Version
|
|
|
|
tag := strings.Split(v, "-")[0]
|
|
|
|
if tag == "unknown" {
|
2021-06-15 18:29:20 +00:00
|
|
|
tag = "main"
|
2019-08-02 21:08:42 +00:00
|
|
|
}
|
|
|
|
|
2020-11-11 17:59:12 +00:00
|
|
|
return template.URL("https://github.com/fleetdm/fleet/blob/" + tag)
|
2019-08-02 21:08:42 +00:00
|
|
|
}
|
2021-04-12 23:22:22 +00:00
|
|
|
|
|
|
|
// seenHostSet implements synchronized storage for the set of seen hosts.
|
|
|
|
type seenHostSet struct {
|
|
|
|
mutex sync.Mutex
|
|
|
|
hostIDs map[uint]bool
|
|
|
|
}
|
|
|
|
|
|
|
|
func newSeenHostSet() *seenHostSet {
|
|
|
|
return &seenHostSet{
|
|
|
|
mutex: sync.Mutex{},
|
|
|
|
hostIDs: make(map[uint]bool),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// addHostID adds the host identified by ID to the set
|
|
|
|
func (m *seenHostSet) addHostID(id uint) {
|
|
|
|
m.mutex.Lock()
|
|
|
|
defer m.mutex.Unlock()
|
|
|
|
m.hostIDs[id] = true
|
|
|
|
}
|
|
|
|
|
|
|
|
// getAndClearHostIDs gets the list of unique host IDs from the set and empties
|
|
|
|
// the set.
|
|
|
|
func (m *seenHostSet) getAndClearHostIDs() []uint {
|
|
|
|
m.mutex.Lock()
|
|
|
|
defer m.mutex.Unlock()
|
|
|
|
var ids []uint
|
2021-05-17 17:29:50 +00:00
|
|
|
for id := range m.hostIDs {
|
2021-04-12 23:22:22 +00:00
|
|
|
ids = append(ids, id)
|
|
|
|
}
|
|
|
|
m.hostIDs = make(map[uint]bool)
|
|
|
|
return ids
|
|
|
|
}
|