2016-09-26 18:48:55 +00:00
|
|
|
package service
|
2016-08-28 03:59:17 +00:00
|
|
|
|
|
|
|
import (
|
2017-03-15 15:55:30 +00:00
|
|
|
"context"
|
2016-08-28 03:59:17 +00:00
|
|
|
"net/http"
|
2017-01-12 00:40:58 +00:00
|
|
|
"strings"
|
2021-02-10 20:13:11 +00:00
|
|
|
"time"
|
2016-08-28 03:59:17 +00:00
|
|
|
|
2020-11-13 03:06:56 +00:00
|
|
|
"github.com/fleetdm/fleet/server/config"
|
|
|
|
"github.com/fleetdm/fleet/server/kolide"
|
2021-03-26 18:23:29 +00:00
|
|
|
"github.com/fleetdm/fleet/server/service/middleware/ratelimit"
|
2016-09-26 17:14:39 +00:00
|
|
|
"github.com/go-kit/kit/endpoint"
|
2016-08-28 03:59:17 +00:00
|
|
|
kitlog "github.com/go-kit/kit/log"
|
2021-02-10 20:13:11 +00:00
|
|
|
"github.com/go-kit/kit/log/level"
|
2016-08-28 03:59:17 +00:00
|
|
|
kithttp "github.com/go-kit/kit/transport/http"
|
|
|
|
"github.com/gorilla/mux"
|
2021-02-10 20:13:11 +00:00
|
|
|
"github.com/pkg/errors"
|
2016-12-22 17:39:44 +00:00
|
|
|
"github.com/prometheus/client_golang/prometheus"
|
2021-03-26 18:23:29 +00:00
|
|
|
"github.com/throttled/throttled/v2"
|
2016-08-28 03:59:17 +00:00
|
|
|
)
|
|
|
|
|
2016-09-26 17:14:39 +00:00
|
|
|
// KolideEndpoints is a collection of RPC endpoints implemented by the Kolide API.
|
|
|
|
type KolideEndpoints struct {
|
2018-05-17 22:54:34 +00:00
|
|
|
Login endpoint.Endpoint
|
|
|
|
Logout endpoint.Endpoint
|
|
|
|
ForgotPassword endpoint.Endpoint
|
|
|
|
ResetPassword endpoint.Endpoint
|
|
|
|
Me endpoint.Endpoint
|
|
|
|
ChangePassword endpoint.Endpoint
|
2020-11-05 01:06:55 +00:00
|
|
|
CreateUserWithInvite endpoint.Endpoint
|
2018-05-17 22:54:34 +00:00
|
|
|
CreateUser endpoint.Endpoint
|
|
|
|
GetUser endpoint.Endpoint
|
|
|
|
ListUsers endpoint.Endpoint
|
|
|
|
ModifyUser endpoint.Endpoint
|
2021-04-08 23:53:33 +00:00
|
|
|
DeleteUser endpoint.Endpoint
|
2018-05-17 22:54:34 +00:00
|
|
|
AdminUser endpoint.Endpoint
|
|
|
|
RequirePasswordReset endpoint.Endpoint
|
|
|
|
PerformRequiredPasswordReset endpoint.Endpoint
|
|
|
|
GetSessionsForUserInfo endpoint.Endpoint
|
|
|
|
DeleteSessionsForUser endpoint.Endpoint
|
|
|
|
GetSessionInfo endpoint.Endpoint
|
|
|
|
DeleteSession endpoint.Endpoint
|
|
|
|
GetAppConfig endpoint.Endpoint
|
|
|
|
ModifyAppConfig endpoint.Endpoint
|
2020-05-29 16:12:39 +00:00
|
|
|
ApplyEnrollSecretSpec endpoint.Endpoint
|
|
|
|
GetEnrollSecretSpec endpoint.Endpoint
|
2018-05-17 22:54:34 +00:00
|
|
|
CreateInvite endpoint.Endpoint
|
|
|
|
ListInvites endpoint.Endpoint
|
|
|
|
DeleteInvite endpoint.Endpoint
|
|
|
|
VerifyInvite endpoint.Endpoint
|
|
|
|
GetQuery endpoint.Endpoint
|
|
|
|
ListQueries endpoint.Endpoint
|
|
|
|
CreateQuery endpoint.Endpoint
|
|
|
|
ModifyQuery endpoint.Endpoint
|
|
|
|
DeleteQuery endpoint.Endpoint
|
2018-06-15 14:13:11 +00:00
|
|
|
DeleteQueryByID endpoint.Endpoint
|
2018-05-17 22:54:34 +00:00
|
|
|
DeleteQueries endpoint.Endpoint
|
|
|
|
ApplyQuerySpecs endpoint.Endpoint
|
|
|
|
GetQuerySpecs endpoint.Endpoint
|
|
|
|
GetQuerySpec endpoint.Endpoint
|
|
|
|
CreateDistributedQueryCampaign endpoint.Endpoint
|
|
|
|
CreateDistributedQueryCampaignByNames endpoint.Endpoint
|
2018-06-15 14:13:11 +00:00
|
|
|
CreatePack endpoint.Endpoint
|
|
|
|
ModifyPack endpoint.Endpoint
|
2018-05-17 22:54:34 +00:00
|
|
|
GetPack endpoint.Endpoint
|
|
|
|
ListPacks endpoint.Endpoint
|
|
|
|
DeletePack endpoint.Endpoint
|
2018-06-15 14:13:11 +00:00
|
|
|
DeletePackByID endpoint.Endpoint
|
2018-05-17 22:54:34 +00:00
|
|
|
GetScheduledQueriesInPack endpoint.Endpoint
|
2018-06-15 14:13:11 +00:00
|
|
|
ScheduleQuery endpoint.Endpoint
|
|
|
|
GetScheduledQuery endpoint.Endpoint
|
|
|
|
ModifyScheduledQuery endpoint.Endpoint
|
|
|
|
DeleteScheduledQuery endpoint.Endpoint
|
2018-05-17 22:54:34 +00:00
|
|
|
ApplyPackSpecs endpoint.Endpoint
|
|
|
|
GetPackSpecs endpoint.Endpoint
|
|
|
|
GetPackSpec endpoint.Endpoint
|
|
|
|
EnrollAgent endpoint.Endpoint
|
|
|
|
GetClientConfig endpoint.Endpoint
|
|
|
|
GetDistributedQueries endpoint.Endpoint
|
|
|
|
SubmitDistributedQueryResults endpoint.Endpoint
|
|
|
|
SubmitLogs endpoint.Endpoint
|
2020-11-05 04:45:16 +00:00
|
|
|
CarveBegin endpoint.Endpoint
|
|
|
|
CarveBlock endpoint.Endpoint
|
2018-06-18 17:09:08 +00:00
|
|
|
CreateLabel endpoint.Endpoint
|
|
|
|
ModifyLabel endpoint.Endpoint
|
2018-05-17 22:54:34 +00:00
|
|
|
GetLabel endpoint.Endpoint
|
|
|
|
ListLabels endpoint.Endpoint
|
2020-03-30 02:19:54 +00:00
|
|
|
ListHostsInLabel endpoint.Endpoint
|
2018-05-17 22:54:34 +00:00
|
|
|
DeleteLabel endpoint.Endpoint
|
2018-06-25 20:56:59 +00:00
|
|
|
DeleteLabelByID endpoint.Endpoint
|
2018-05-17 22:54:34 +00:00
|
|
|
ApplyLabelSpecs endpoint.Endpoint
|
|
|
|
GetLabelSpecs endpoint.Endpoint
|
|
|
|
GetLabelSpec endpoint.Endpoint
|
|
|
|
GetHost endpoint.Endpoint
|
2020-04-22 20:54:32 +00:00
|
|
|
HostByIdentifier endpoint.Endpoint
|
2018-05-17 22:54:34 +00:00
|
|
|
DeleteHost endpoint.Endpoint
|
|
|
|
ListHosts endpoint.Endpoint
|
|
|
|
GetHostSummary endpoint.Endpoint
|
|
|
|
SearchTargets endpoint.Endpoint
|
|
|
|
ApplyOsqueryOptionsSpec endpoint.Endpoint
|
|
|
|
GetOsqueryOptionsSpec endpoint.Endpoint
|
|
|
|
GetCertificate endpoint.Endpoint
|
|
|
|
ChangeEmail endpoint.Endpoint
|
|
|
|
InitiateSSO endpoint.Endpoint
|
|
|
|
CallbackSSO endpoint.Endpoint
|
|
|
|
SSOSettings endpoint.Endpoint
|
2019-08-13 16:42:58 +00:00
|
|
|
StatusResultStore endpoint.Endpoint
|
2020-01-14 00:53:04 +00:00
|
|
|
StatusLiveQuery endpoint.Endpoint
|
2020-11-05 04:45:16 +00:00
|
|
|
ListCarves endpoint.Endpoint
|
2020-11-13 03:06:56 +00:00
|
|
|
GetCarve endpoint.Endpoint
|
2020-11-05 04:45:16 +00:00
|
|
|
GetCarveBlock endpoint.Endpoint
|
2021-03-27 01:03:31 +00:00
|
|
|
Version endpoint.Endpoint
|
2021-03-18 04:59:00 +00:00
|
|
|
CreateTeam endpoint.Endpoint
|
|
|
|
ModifyTeam endpoint.Endpoint
|
2021-04-06 18:40:14 +00:00
|
|
|
ListTeams endpoint.Endpoint
|
2016-09-26 17:14:39 +00:00
|
|
|
}
|
2016-09-04 05:13:42 +00:00
|
|
|
|
2016-09-26 17:14:39 +00:00
|
|
|
// MakeKolideServerEndpoints creates the Kolide API endpoints.
|
2021-03-26 18:23:29 +00:00
|
|
|
func MakeKolideServerEndpoints(svc kolide.Service, jwtKey, urlPrefix string, limitStore throttled.GCRAStore) KolideEndpoints {
|
|
|
|
limiter := ratelimit.NewMiddleware(limitStore)
|
|
|
|
|
2016-09-26 17:14:39 +00:00
|
|
|
return KolideEndpoints{
|
2021-03-26 18:23:29 +00:00
|
|
|
Login: limiter.Limit(throttled.RateQuota{MaxRate: throttled.PerMin(10), MaxBurst: 9})(
|
|
|
|
makeLoginEndpoint(svc),
|
|
|
|
),
|
|
|
|
Logout: makeLogoutEndpoint(svc),
|
|
|
|
ForgotPassword: limiter.Limit(
|
|
|
|
throttled.RateQuota{MaxRate: throttled.PerHour(10), MaxBurst: 9})(
|
|
|
|
makeForgotPasswordEndpoint(svc),
|
|
|
|
),
|
2020-11-05 01:06:55 +00:00
|
|
|
ResetPassword: makeResetPasswordEndpoint(svc),
|
|
|
|
CreateUserWithInvite: makeCreateUserWithInviteEndpoint(svc),
|
|
|
|
VerifyInvite: makeVerifyInviteEndpoint(svc),
|
|
|
|
InitiateSSO: makeInitiateSSOEndpoint(svc),
|
|
|
|
CallbackSSO: makeCallbackSSOEndpoint(svc, urlPrefix),
|
|
|
|
SSOSettings: makeSSOSettingsEndpoint(svc),
|
2016-09-29 04:21:39 +00:00
|
|
|
|
|
|
|
// Authenticated user endpoints
|
2016-12-13 16:57:49 +00:00
|
|
|
// Each of these endpoints should have exactly one
|
|
|
|
// authorization check around the make.*Endpoint method. At a
|
|
|
|
// minimum, canPerformActions. Some endpoints use
|
|
|
|
// stricter/different checks and should NOT also use
|
|
|
|
// canPerformActions (these other checks should also call
|
|
|
|
// canPerformActions if that is appropriate).
|
2017-01-10 04:42:50 +00:00
|
|
|
Me: authenticatedUser(jwtKey, svc, canPerformActions(makeGetSessionUserEndpoint(svc))),
|
|
|
|
ChangePassword: authenticatedUser(jwtKey, svc, canPerformActions(makeChangePasswordEndpoint(svc))),
|
|
|
|
GetUser: authenticatedUser(jwtKey, svc, canReadUser(makeGetUserEndpoint(svc))),
|
|
|
|
ListUsers: authenticatedUser(jwtKey, svc, canPerformActions(makeListUsersEndpoint(svc))),
|
2018-09-13 17:41:30 +00:00
|
|
|
ModifyUser: authenticatedUser(jwtKey, svc, canModifyUser(makeModifyUserEndpoint(svc))),
|
2021-04-08 23:53:33 +00:00
|
|
|
DeleteUser: authenticatedUser(jwtKey, svc, canModifyUser(makeDeleteUserEndpoint(svc))),
|
2017-01-17 16:43:59 +00:00
|
|
|
AdminUser: authenticatedUser(jwtKey, svc, mustBeAdmin(makeAdminUserEndpoint(svc))),
|
2017-01-10 04:42:50 +00:00
|
|
|
RequirePasswordReset: authenticatedUser(jwtKey, svc, mustBeAdmin(makeRequirePasswordResetEndpoint(svc))),
|
2020-11-05 01:06:55 +00:00
|
|
|
CreateUser: authenticatedUser(jwtKey, svc, mustBeAdmin(makeCreateUserEndpoint(svc))),
|
2017-01-10 04:42:50 +00:00
|
|
|
// PerformRequiredPasswordReset needs only to authenticate the
|
|
|
|
// logged in user
|
2018-09-13 20:59:53 +00:00
|
|
|
PerformRequiredPasswordReset: authenticatedUser(jwtKey, svc, canPerformPasswordReset(makePerformRequiredPasswordResetEndpoint(svc))),
|
2018-05-17 22:54:34 +00:00
|
|
|
GetSessionsForUserInfo: authenticatedUser(jwtKey, svc, canReadUser(makeGetInfoAboutSessionsForUserEndpoint(svc))),
|
|
|
|
DeleteSessionsForUser: authenticatedUser(jwtKey, svc, canModifyUser(makeDeleteSessionsForUserEndpoint(svc))),
|
|
|
|
GetSessionInfo: authenticatedUser(jwtKey, svc, mustBeAdmin(makeGetInfoAboutSessionEndpoint(svc))),
|
|
|
|
DeleteSession: authenticatedUser(jwtKey, svc, mustBeAdmin(makeDeleteSessionEndpoint(svc))),
|
|
|
|
GetAppConfig: authenticatedUser(jwtKey, svc, canPerformActions(makeGetAppConfigEndpoint(svc))),
|
|
|
|
ModifyAppConfig: authenticatedUser(jwtKey, svc, mustBeAdmin(makeModifyAppConfigEndpoint(svc))),
|
2020-05-29 16:12:39 +00:00
|
|
|
ApplyEnrollSecretSpec: authenticatedUser(jwtKey, svc, mustBeAdmin(makeApplyEnrollSecretSpecEndpoint(svc))),
|
|
|
|
GetEnrollSecretSpec: authenticatedUser(jwtKey, svc, canPerformActions(makeGetEnrollSecretSpecEndpoint(svc))),
|
2018-05-17 22:54:34 +00:00
|
|
|
CreateInvite: authenticatedUser(jwtKey, svc, mustBeAdmin(makeCreateInviteEndpoint(svc))),
|
|
|
|
ListInvites: authenticatedUser(jwtKey, svc, mustBeAdmin(makeListInvitesEndpoint(svc))),
|
|
|
|
DeleteInvite: authenticatedUser(jwtKey, svc, mustBeAdmin(makeDeleteInviteEndpoint(svc))),
|
|
|
|
GetQuery: authenticatedUser(jwtKey, svc, makeGetQueryEndpoint(svc)),
|
|
|
|
ListQueries: authenticatedUser(jwtKey, svc, makeListQueriesEndpoint(svc)),
|
|
|
|
CreateQuery: authenticatedUser(jwtKey, svc, makeCreateQueryEndpoint(svc)),
|
|
|
|
ModifyQuery: authenticatedUser(jwtKey, svc, makeModifyQueryEndpoint(svc)),
|
|
|
|
DeleteQuery: authenticatedUser(jwtKey, svc, makeDeleteQueryEndpoint(svc)),
|
2018-06-15 14:13:11 +00:00
|
|
|
DeleteQueryByID: authenticatedUser(jwtKey, svc, makeDeleteQueryByIDEndpoint(svc)),
|
2018-05-17 22:54:34 +00:00
|
|
|
DeleteQueries: authenticatedUser(jwtKey, svc, makeDeleteQueriesEndpoint(svc)),
|
|
|
|
ApplyQuerySpecs: authenticatedUser(jwtKey, svc, makeApplyQuerySpecsEndpoint(svc)),
|
|
|
|
GetQuerySpecs: authenticatedUser(jwtKey, svc, makeGetQuerySpecsEndpoint(svc)),
|
|
|
|
GetQuerySpec: authenticatedUser(jwtKey, svc, makeGetQuerySpecEndpoint(svc)),
|
|
|
|
CreateDistributedQueryCampaign: authenticatedUser(jwtKey, svc, makeCreateDistributedQueryCampaignEndpoint(svc)),
|
|
|
|
CreateDistributedQueryCampaignByNames: authenticatedUser(jwtKey, svc, makeCreateDistributedQueryCampaignByNamesEndpoint(svc)),
|
2018-06-15 14:13:11 +00:00
|
|
|
CreatePack: authenticatedUser(jwtKey, svc, makeCreatePackEndpoint(svc)),
|
|
|
|
ModifyPack: authenticatedUser(jwtKey, svc, makeModifyPackEndpoint(svc)),
|
|
|
|
GetPack: authenticatedUser(jwtKey, svc, makeGetPackEndpoint(svc)),
|
|
|
|
ListPacks: authenticatedUser(jwtKey, svc, makeListPacksEndpoint(svc)),
|
|
|
|
DeletePack: authenticatedUser(jwtKey, svc, makeDeletePackEndpoint(svc)),
|
|
|
|
DeletePackByID: authenticatedUser(jwtKey, svc, makeDeletePackByIDEndpoint(svc)),
|
|
|
|
GetScheduledQueriesInPack: authenticatedUser(jwtKey, svc, makeGetScheduledQueriesInPackEndpoint(svc)),
|
|
|
|
ScheduleQuery: authenticatedUser(jwtKey, svc, makeScheduleQueryEndpoint(svc)),
|
|
|
|
GetScheduledQuery: authenticatedUser(jwtKey, svc, makeGetScheduledQueryEndpoint(svc)),
|
|
|
|
ModifyScheduledQuery: authenticatedUser(jwtKey, svc, makeModifyScheduledQueryEndpoint(svc)),
|
|
|
|
DeleteScheduledQuery: authenticatedUser(jwtKey, svc, makeDeleteScheduledQueryEndpoint(svc)),
|
|
|
|
ApplyPackSpecs: authenticatedUser(jwtKey, svc, makeApplyPackSpecsEndpoint(svc)),
|
|
|
|
GetPackSpecs: authenticatedUser(jwtKey, svc, makeGetPackSpecsEndpoint(svc)),
|
|
|
|
GetPackSpec: authenticatedUser(jwtKey, svc, makeGetPackSpecEndpoint(svc)),
|
|
|
|
GetHost: authenticatedUser(jwtKey, svc, makeGetHostEndpoint(svc)),
|
2020-04-22 20:54:32 +00:00
|
|
|
HostByIdentifier: authenticatedUser(jwtKey, svc, makeHostByIdentifierEndpoint(svc)),
|
2018-06-15 14:13:11 +00:00
|
|
|
ListHosts: authenticatedUser(jwtKey, svc, makeListHostsEndpoint(svc)),
|
|
|
|
GetHostSummary: authenticatedUser(jwtKey, svc, makeGetHostSummaryEndpoint(svc)),
|
|
|
|
DeleteHost: authenticatedUser(jwtKey, svc, makeDeleteHostEndpoint(svc)),
|
2018-06-18 17:09:08 +00:00
|
|
|
CreateLabel: authenticatedUser(jwtKey, svc, makeCreateLabelEndpoint(svc)),
|
|
|
|
ModifyLabel: authenticatedUser(jwtKey, svc, makeModifyLabelEndpoint(svc)),
|
2018-06-15 14:13:11 +00:00
|
|
|
GetLabel: authenticatedUser(jwtKey, svc, makeGetLabelEndpoint(svc)),
|
|
|
|
ListLabels: authenticatedUser(jwtKey, svc, makeListLabelsEndpoint(svc)),
|
2020-03-30 02:19:54 +00:00
|
|
|
ListHostsInLabel: authenticatedUser(jwtKey, svc, makeListHostsInLabelEndpoint(svc)),
|
2018-06-15 14:13:11 +00:00
|
|
|
DeleteLabel: authenticatedUser(jwtKey, svc, makeDeleteLabelEndpoint(svc)),
|
2018-06-25 20:56:59 +00:00
|
|
|
DeleteLabelByID: authenticatedUser(jwtKey, svc, makeDeleteLabelByIDEndpoint(svc)),
|
2018-06-15 14:13:11 +00:00
|
|
|
ApplyLabelSpecs: authenticatedUser(jwtKey, svc, makeApplyLabelSpecsEndpoint(svc)),
|
|
|
|
GetLabelSpecs: authenticatedUser(jwtKey, svc, makeGetLabelSpecsEndpoint(svc)),
|
|
|
|
GetLabelSpec: authenticatedUser(jwtKey, svc, makeGetLabelSpecEndpoint(svc)),
|
|
|
|
SearchTargets: authenticatedUser(jwtKey, svc, makeSearchTargetsEndpoint(svc)),
|
|
|
|
ApplyOsqueryOptionsSpec: authenticatedUser(jwtKey, svc, makeApplyOsqueryOptionsSpecEndpoint(svc)),
|
|
|
|
GetOsqueryOptionsSpec: authenticatedUser(jwtKey, svc, makeGetOsqueryOptionsSpecEndpoint(svc)),
|
|
|
|
GetCertificate: authenticatedUser(jwtKey, svc, makeCertificateEndpoint(svc)),
|
|
|
|
ChangeEmail: authenticatedUser(jwtKey, svc, makeChangeEmailEndpoint(svc)),
|
2020-11-05 04:45:16 +00:00
|
|
|
ListCarves: authenticatedUser(jwtKey, svc, makeListCarvesEndpoint(svc)),
|
2020-11-13 03:06:56 +00:00
|
|
|
GetCarve: authenticatedUser(jwtKey, svc, makeGetCarveEndpoint(svc)),
|
2020-11-05 04:45:16 +00:00
|
|
|
GetCarveBlock: authenticatedUser(jwtKey, svc, makeGetCarveBlockEndpoint(svc)),
|
2021-03-27 01:03:31 +00:00
|
|
|
Version: authenticatedUser(jwtKey, svc, makeVersionEndpoint(svc)),
|
2021-04-06 18:40:14 +00:00
|
|
|
// TODO permissions for teams endpoints
|
|
|
|
CreateTeam: authenticatedUser(jwtKey, svc, makeCreateTeamEndpoint(svc)),
|
|
|
|
ModifyTeam: authenticatedUser(jwtKey, svc, makeModifyTeamEndpoint(svc)),
|
|
|
|
ListTeams: authenticatedUser(jwtKey, svc, makeListTeamsEndpoint(svc)),
|
2016-09-29 04:21:39 +00:00
|
|
|
|
2019-08-13 16:42:58 +00:00
|
|
|
// Authenticated status endpoints
|
|
|
|
StatusResultStore: authenticatedUser(jwtKey, svc, makeStatusResultStoreEndpoint(svc)),
|
2020-01-14 00:53:04 +00:00
|
|
|
StatusLiveQuery: authenticatedUser(jwtKey, svc, makeStatusLiveQueryEndpoint(svc)),
|
2019-08-13 16:42:58 +00:00
|
|
|
|
2016-09-29 04:21:39 +00:00
|
|
|
// Osquery endpoints
|
|
|
|
EnrollAgent: makeEnrollAgentEndpoint(svc),
|
|
|
|
GetClientConfig: authenticatedHost(svc, makeGetClientConfigEndpoint(svc)),
|
|
|
|
GetDistributedQueries: authenticatedHost(svc, makeGetDistributedQueriesEndpoint(svc)),
|
|
|
|
SubmitDistributedQueryResults: authenticatedHost(svc, makeSubmitDistributedQueryResultsEndpoint(svc)),
|
|
|
|
SubmitLogs: authenticatedHost(svc, makeSubmitLogsEndpoint(svc)),
|
2020-11-05 04:45:16 +00:00
|
|
|
CarveBegin: authenticatedHost(svc, makeCarveBeginEndpoint(svc)),
|
|
|
|
// For some reason osquery does not provide a node key with the block
|
|
|
|
// data. Instead the carve session ID should be verified in the service
|
|
|
|
// method.
|
|
|
|
CarveBlock: makeCarveBlockEndpoint(svc),
|
2016-09-26 17:14:39 +00:00
|
|
|
}
|
|
|
|
}
|
2016-09-04 05:13:42 +00:00
|
|
|
|
2016-09-26 17:14:39 +00:00
|
|
|
type kolideHandlers struct {
|
2018-05-17 22:54:34 +00:00
|
|
|
Login http.Handler
|
|
|
|
Logout http.Handler
|
|
|
|
ForgotPassword http.Handler
|
|
|
|
ResetPassword http.Handler
|
|
|
|
Me http.Handler
|
|
|
|
ChangePassword http.Handler
|
2020-11-05 01:06:55 +00:00
|
|
|
CreateUserWithInvite http.Handler
|
2018-05-17 22:54:34 +00:00
|
|
|
CreateUser http.Handler
|
|
|
|
GetUser http.Handler
|
|
|
|
ListUsers http.Handler
|
|
|
|
ModifyUser http.Handler
|
2021-04-08 23:53:33 +00:00
|
|
|
DeleteUser http.Handler
|
2018-05-17 22:54:34 +00:00
|
|
|
AdminUser http.Handler
|
|
|
|
RequirePasswordReset http.Handler
|
|
|
|
PerformRequiredPasswordReset http.Handler
|
|
|
|
GetSessionsForUserInfo http.Handler
|
|
|
|
DeleteSessionsForUser http.Handler
|
|
|
|
GetSessionInfo http.Handler
|
|
|
|
DeleteSession http.Handler
|
|
|
|
GetAppConfig http.Handler
|
|
|
|
ModifyAppConfig http.Handler
|
2020-05-29 16:12:39 +00:00
|
|
|
ApplyEnrollSecretSpec http.Handler
|
|
|
|
GetEnrollSecretSpec http.Handler
|
2018-05-17 22:54:34 +00:00
|
|
|
CreateInvite http.Handler
|
|
|
|
ListInvites http.Handler
|
|
|
|
DeleteInvite http.Handler
|
|
|
|
VerifyInvite http.Handler
|
|
|
|
GetQuery http.Handler
|
|
|
|
ListQueries http.Handler
|
|
|
|
CreateQuery http.Handler
|
|
|
|
ModifyQuery http.Handler
|
|
|
|
DeleteQuery http.Handler
|
2018-06-15 14:13:11 +00:00
|
|
|
DeleteQueryByID http.Handler
|
2018-05-17 22:54:34 +00:00
|
|
|
DeleteQueries http.Handler
|
|
|
|
ApplyQuerySpecs http.Handler
|
|
|
|
GetQuerySpecs http.Handler
|
|
|
|
GetQuerySpec http.Handler
|
|
|
|
CreateDistributedQueryCampaign http.Handler
|
|
|
|
CreateDistributedQueryCampaignByNames http.Handler
|
2018-06-15 14:13:11 +00:00
|
|
|
CreatePack http.Handler
|
|
|
|
ModifyPack http.Handler
|
2018-05-17 22:54:34 +00:00
|
|
|
GetPack http.Handler
|
|
|
|
ListPacks http.Handler
|
|
|
|
DeletePack http.Handler
|
2018-06-15 14:13:11 +00:00
|
|
|
DeletePackByID http.Handler
|
2018-05-17 22:54:34 +00:00
|
|
|
GetScheduledQueriesInPack http.Handler
|
2018-06-15 14:13:11 +00:00
|
|
|
ScheduleQuery http.Handler
|
|
|
|
GetScheduledQuery http.Handler
|
|
|
|
ModifyScheduledQuery http.Handler
|
|
|
|
DeleteScheduledQuery http.Handler
|
2018-05-17 22:54:34 +00:00
|
|
|
ApplyPackSpecs http.Handler
|
|
|
|
GetPackSpecs http.Handler
|
|
|
|
GetPackSpec http.Handler
|
|
|
|
EnrollAgent http.Handler
|
|
|
|
GetClientConfig http.Handler
|
|
|
|
GetDistributedQueries http.Handler
|
|
|
|
SubmitDistributedQueryResults http.Handler
|
|
|
|
SubmitLogs http.Handler
|
2020-11-05 04:45:16 +00:00
|
|
|
CarveBegin http.Handler
|
|
|
|
CarveBlock http.Handler
|
2018-06-18 17:09:08 +00:00
|
|
|
CreateLabel http.Handler
|
|
|
|
ModifyLabel http.Handler
|
2018-05-17 22:54:34 +00:00
|
|
|
GetLabel http.Handler
|
|
|
|
ListLabels http.Handler
|
2020-03-30 02:19:54 +00:00
|
|
|
ListHostsInLabel http.Handler
|
2018-05-17 22:54:34 +00:00
|
|
|
DeleteLabel http.Handler
|
2018-06-25 20:56:59 +00:00
|
|
|
DeleteLabelByID http.Handler
|
2018-05-17 22:54:34 +00:00
|
|
|
ApplyLabelSpecs http.Handler
|
|
|
|
GetLabelSpecs http.Handler
|
|
|
|
GetLabelSpec http.Handler
|
|
|
|
GetHost http.Handler
|
2020-04-22 20:54:32 +00:00
|
|
|
HostByIdentifier http.Handler
|
2018-05-17 22:54:34 +00:00
|
|
|
DeleteHost http.Handler
|
|
|
|
ListHosts http.Handler
|
|
|
|
GetHostSummary http.Handler
|
|
|
|
SearchTargets http.Handler
|
|
|
|
ApplyOsqueryOptionsSpec http.Handler
|
|
|
|
GetOsqueryOptionsSpec http.Handler
|
|
|
|
GetCertificate http.Handler
|
|
|
|
ChangeEmail http.Handler
|
|
|
|
InitiateSSO http.Handler
|
|
|
|
CallbackSSO http.Handler
|
|
|
|
SettingsSSO http.Handler
|
2019-08-13 16:42:58 +00:00
|
|
|
StatusResultStore http.Handler
|
2020-01-14 00:53:04 +00:00
|
|
|
StatusLiveQuery http.Handler
|
2020-11-05 04:45:16 +00:00
|
|
|
ListCarves http.Handler
|
2020-11-13 03:06:56 +00:00
|
|
|
GetCarve http.Handler
|
2020-11-05 04:45:16 +00:00
|
|
|
GetCarveBlock http.Handler
|
2021-03-27 01:03:31 +00:00
|
|
|
Version http.Handler
|
2021-03-18 04:59:00 +00:00
|
|
|
CreateTeam http.Handler
|
|
|
|
ModifyTeam http.Handler
|
2021-04-06 18:40:14 +00:00
|
|
|
ListTeams http.Handler
|
2016-09-26 17:14:39 +00:00
|
|
|
}
|
2016-09-04 05:13:42 +00:00
|
|
|
|
2017-03-15 15:55:30 +00:00
|
|
|
func makeKolideKitHandlers(e KolideEndpoints, opts []kithttp.ServerOption) *kolideHandlers {
|
2016-12-22 17:39:44 +00:00
|
|
|
newServer := func(e endpoint.Endpoint, decodeFn kithttp.DecodeRequestFunc) http.Handler {
|
2017-03-15 15:55:30 +00:00
|
|
|
return kithttp.NewServer(e, decodeFn, encodeResponse, opts...)
|
2016-09-26 17:14:39 +00:00
|
|
|
}
|
2016-12-22 17:39:44 +00:00
|
|
|
return &kolideHandlers{
|
2018-05-17 22:54:34 +00:00
|
|
|
Login: newServer(e.Login, decodeLoginRequest),
|
|
|
|
Logout: newServer(e.Logout, decodeNoParamsRequest),
|
|
|
|
ForgotPassword: newServer(e.ForgotPassword, decodeForgotPasswordRequest),
|
|
|
|
ResetPassword: newServer(e.ResetPassword, decodeResetPasswordRequest),
|
|
|
|
Me: newServer(e.Me, decodeNoParamsRequest),
|
|
|
|
ChangePassword: newServer(e.ChangePassword, decodeChangePasswordRequest),
|
2020-11-05 01:06:55 +00:00
|
|
|
CreateUserWithInvite: newServer(e.CreateUserWithInvite, decodeCreateUserRequest),
|
2018-05-17 22:54:34 +00:00
|
|
|
CreateUser: newServer(e.CreateUser, decodeCreateUserRequest),
|
|
|
|
GetUser: newServer(e.GetUser, decodeGetUserRequest),
|
|
|
|
ListUsers: newServer(e.ListUsers, decodeListUsersRequest),
|
|
|
|
ModifyUser: newServer(e.ModifyUser, decodeModifyUserRequest),
|
2021-04-08 23:53:33 +00:00
|
|
|
DeleteUser: newServer(e.DeleteUser, decodeDeleteUserRequest),
|
2018-05-17 22:54:34 +00:00
|
|
|
RequirePasswordReset: newServer(e.RequirePasswordReset, decodeRequirePasswordResetRequest),
|
|
|
|
PerformRequiredPasswordReset: newServer(e.PerformRequiredPasswordReset, decodePerformRequiredPasswordResetRequest),
|
|
|
|
AdminUser: newServer(e.AdminUser, decodeAdminUserRequest),
|
|
|
|
GetSessionsForUserInfo: newServer(e.GetSessionsForUserInfo, decodeGetInfoAboutSessionsForUserRequest),
|
|
|
|
DeleteSessionsForUser: newServer(e.DeleteSessionsForUser, decodeDeleteSessionsForUserRequest),
|
|
|
|
GetSessionInfo: newServer(e.GetSessionInfo, decodeGetInfoAboutSessionRequest),
|
|
|
|
DeleteSession: newServer(e.DeleteSession, decodeDeleteSessionRequest),
|
|
|
|
GetAppConfig: newServer(e.GetAppConfig, decodeNoParamsRequest),
|
|
|
|
ModifyAppConfig: newServer(e.ModifyAppConfig, decodeModifyAppConfigRequest),
|
2020-05-29 16:12:39 +00:00
|
|
|
ApplyEnrollSecretSpec: newServer(e.ApplyEnrollSecretSpec, decodeApplyEnrollSecretSpecRequest),
|
|
|
|
GetEnrollSecretSpec: newServer(e.GetEnrollSecretSpec, decodeNoParamsRequest),
|
2018-05-17 22:54:34 +00:00
|
|
|
CreateInvite: newServer(e.CreateInvite, decodeCreateInviteRequest),
|
|
|
|
ListInvites: newServer(e.ListInvites, decodeListInvitesRequest),
|
|
|
|
DeleteInvite: newServer(e.DeleteInvite, decodeDeleteInviteRequest),
|
|
|
|
VerifyInvite: newServer(e.VerifyInvite, decodeVerifyInviteRequest),
|
|
|
|
GetQuery: newServer(e.GetQuery, decodeGetQueryRequest),
|
|
|
|
ListQueries: newServer(e.ListQueries, decodeListQueriesRequest),
|
|
|
|
CreateQuery: newServer(e.CreateQuery, decodeCreateQueryRequest),
|
|
|
|
ModifyQuery: newServer(e.ModifyQuery, decodeModifyQueryRequest),
|
|
|
|
DeleteQuery: newServer(e.DeleteQuery, decodeDeleteQueryRequest),
|
2018-06-15 14:13:11 +00:00
|
|
|
DeleteQueryByID: newServer(e.DeleteQueryByID, decodeDeleteQueryByIDRequest),
|
2018-05-17 22:54:34 +00:00
|
|
|
DeleteQueries: newServer(e.DeleteQueries, decodeDeleteQueriesRequest),
|
|
|
|
ApplyQuerySpecs: newServer(e.ApplyQuerySpecs, decodeApplyQuerySpecsRequest),
|
|
|
|
GetQuerySpecs: newServer(e.GetQuerySpecs, decodeNoParamsRequest),
|
|
|
|
GetQuerySpec: newServer(e.GetQuerySpec, decodeGetGenericSpecRequest),
|
|
|
|
CreateDistributedQueryCampaign: newServer(e.CreateDistributedQueryCampaign, decodeCreateDistributedQueryCampaignRequest),
|
|
|
|
CreateDistributedQueryCampaignByNames: newServer(e.CreateDistributedQueryCampaignByNames, decodeCreateDistributedQueryCampaignByNamesRequest),
|
2018-06-15 14:13:11 +00:00
|
|
|
CreatePack: newServer(e.CreatePack, decodeCreatePackRequest),
|
|
|
|
ModifyPack: newServer(e.ModifyPack, decodeModifyPackRequest),
|
|
|
|
GetPack: newServer(e.GetPack, decodeGetPackRequest),
|
|
|
|
ListPacks: newServer(e.ListPacks, decodeListPacksRequest),
|
|
|
|
DeletePack: newServer(e.DeletePack, decodeDeletePackRequest),
|
|
|
|
DeletePackByID: newServer(e.DeletePackByID, decodeDeletePackByIDRequest),
|
|
|
|
GetScheduledQueriesInPack: newServer(e.GetScheduledQueriesInPack, decodeGetScheduledQueriesInPackRequest),
|
|
|
|
ScheduleQuery: newServer(e.ScheduleQuery, decodeScheduleQueryRequest),
|
|
|
|
GetScheduledQuery: newServer(e.GetScheduledQuery, decodeGetScheduledQueryRequest),
|
|
|
|
ModifyScheduledQuery: newServer(e.ModifyScheduledQuery, decodeModifyScheduledQueryRequest),
|
|
|
|
DeleteScheduledQuery: newServer(e.DeleteScheduledQuery, decodeDeleteScheduledQueryRequest),
|
|
|
|
ApplyPackSpecs: newServer(e.ApplyPackSpecs, decodeApplyPackSpecsRequest),
|
|
|
|
GetPackSpecs: newServer(e.GetPackSpecs, decodeNoParamsRequest),
|
|
|
|
GetPackSpec: newServer(e.GetPackSpec, decodeGetGenericSpecRequest),
|
|
|
|
EnrollAgent: newServer(e.EnrollAgent, decodeEnrollAgentRequest),
|
|
|
|
GetClientConfig: newServer(e.GetClientConfig, decodeGetClientConfigRequest),
|
|
|
|
GetDistributedQueries: newServer(e.GetDistributedQueries, decodeGetDistributedQueriesRequest),
|
|
|
|
SubmitDistributedQueryResults: newServer(e.SubmitDistributedQueryResults, decodeSubmitDistributedQueryResultsRequest),
|
|
|
|
SubmitLogs: newServer(e.SubmitLogs, decodeSubmitLogsRequest),
|
2020-11-05 04:45:16 +00:00
|
|
|
CarveBegin: newServer(e.CarveBegin, decodeCarveBeginRequest),
|
|
|
|
CarveBlock: newServer(e.CarveBlock, decodeCarveBlockRequest),
|
2018-06-18 17:09:08 +00:00
|
|
|
CreateLabel: newServer(e.CreateLabel, decodeCreateLabelRequest),
|
|
|
|
ModifyLabel: newServer(e.ModifyLabel, decodeModifyLabelRequest),
|
2018-06-15 14:13:11 +00:00
|
|
|
GetLabel: newServer(e.GetLabel, decodeGetLabelRequest),
|
|
|
|
ListLabels: newServer(e.ListLabels, decodeListLabelsRequest),
|
2020-03-30 02:19:54 +00:00
|
|
|
ListHostsInLabel: newServer(e.ListHostsInLabel, decodeListHostsInLabelRequest),
|
2018-06-15 14:13:11 +00:00
|
|
|
DeleteLabel: newServer(e.DeleteLabel, decodeDeleteLabelRequest),
|
2018-06-25 20:56:59 +00:00
|
|
|
DeleteLabelByID: newServer(e.DeleteLabelByID, decodeDeleteLabelByIDRequest),
|
2018-06-15 14:13:11 +00:00
|
|
|
ApplyLabelSpecs: newServer(e.ApplyLabelSpecs, decodeApplyLabelSpecsRequest),
|
|
|
|
GetLabelSpecs: newServer(e.GetLabelSpecs, decodeNoParamsRequest),
|
|
|
|
GetLabelSpec: newServer(e.GetLabelSpec, decodeGetGenericSpecRequest),
|
|
|
|
GetHost: newServer(e.GetHost, decodeGetHostRequest),
|
2020-04-22 20:54:32 +00:00
|
|
|
HostByIdentifier: newServer(e.HostByIdentifier, decodeHostByIdentifierRequest),
|
2018-06-15 14:13:11 +00:00
|
|
|
DeleteHost: newServer(e.DeleteHost, decodeDeleteHostRequest),
|
|
|
|
ListHosts: newServer(e.ListHosts, decodeListHostsRequest),
|
|
|
|
GetHostSummary: newServer(e.GetHostSummary, decodeNoParamsRequest),
|
|
|
|
SearchTargets: newServer(e.SearchTargets, decodeSearchTargetsRequest),
|
|
|
|
ApplyOsqueryOptionsSpec: newServer(e.ApplyOsqueryOptionsSpec, decodeApplyOsqueryOptionsSpecRequest),
|
|
|
|
GetOsqueryOptionsSpec: newServer(e.GetOsqueryOptionsSpec, decodeNoParamsRequest),
|
|
|
|
GetCertificate: newServer(e.GetCertificate, decodeNoParamsRequest),
|
|
|
|
ChangeEmail: newServer(e.ChangeEmail, decodeChangeEmailRequest),
|
|
|
|
InitiateSSO: newServer(e.InitiateSSO, decodeInitiateSSORequest),
|
|
|
|
CallbackSSO: newServer(e.CallbackSSO, decodeCallbackSSORequest),
|
|
|
|
SettingsSSO: newServer(e.SSOSettings, decodeNoParamsRequest),
|
2019-08-13 16:42:58 +00:00
|
|
|
StatusResultStore: newServer(e.StatusResultStore, decodeNoParamsRequest),
|
2020-01-14 00:53:04 +00:00
|
|
|
StatusLiveQuery: newServer(e.StatusLiveQuery, decodeNoParamsRequest),
|
2020-11-05 04:45:16 +00:00
|
|
|
ListCarves: newServer(e.ListCarves, decodeListCarvesRequest),
|
2020-11-13 03:06:56 +00:00
|
|
|
GetCarve: newServer(e.GetCarve, decodeGetCarveRequest),
|
|
|
|
GetCarveBlock: newServer(e.GetCarveBlock, decodeGetCarveBlockRequest),
|
2021-03-27 01:03:31 +00:00
|
|
|
Version: newServer(e.Version, decodeNoParamsRequest),
|
2021-03-18 04:59:00 +00:00
|
|
|
CreateTeam: newServer(e.CreateTeam, decodeCreateTeamRequest),
|
|
|
|
ModifyTeam: newServer(e.ModifyTeam, decodeModifyTeamRequest),
|
2021-04-06 18:40:14 +00:00
|
|
|
ListTeams: newServer(e.ListTeams, decodeListTeamsRequest),
|
2016-09-26 17:14:39 +00:00
|
|
|
}
|
2016-09-04 19:43:12 +00:00
|
|
|
}
|
2016-09-01 04:51:38 +00:00
|
|
|
|
2021-03-26 18:23:29 +00:00
|
|
|
type errorHandler struct {
|
|
|
|
logger kitlog.Logger
|
|
|
|
}
|
|
|
|
|
|
|
|
func (h *errorHandler) Handle(ctx context.Context, err error) {
|
|
|
|
// get the request path
|
|
|
|
path, _ := ctx.Value(kithttp.ContextKeyRequestPath).(string)
|
|
|
|
logger := level.Info(kitlog.With(h.logger, "path", path))
|
|
|
|
|
|
|
|
switch e := err.(type) {
|
|
|
|
case ratelimit.Error:
|
|
|
|
res := e.Result()
|
|
|
|
logger.Log("err", "limit exceeded", "retry_after", res.RetryAfter)
|
|
|
|
|
|
|
|
default:
|
|
|
|
logger.Log("err", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-01-24 17:39:32 +00:00
|
|
|
// MakeHandler creates an HTTP handler for the Fleet server endpoints.
|
2021-03-26 18:23:29 +00:00
|
|
|
func MakeHandler(svc kolide.Service, config config.KolideConfig, logger kitlog.Logger, limitStore throttled.GCRAStore) http.Handler {
|
2016-09-26 17:14:39 +00:00
|
|
|
kolideAPIOptions := []kithttp.ServerOption{
|
2016-09-04 19:43:12 +00:00
|
|
|
kithttp.ServerBefore(
|
2017-12-01 00:52:23 +00:00
|
|
|
kithttp.PopulateRequestContext, // populate the request context with common fields
|
2019-10-16 23:40:45 +00:00
|
|
|
setRequestsContexts(svc, config.Auth.JwtKey),
|
2016-09-04 19:43:12 +00:00
|
|
|
),
|
2021-03-26 18:23:29 +00:00
|
|
|
//kithttp.ServerErrorLogger(logger),
|
|
|
|
kithttp.ServerErrorHandler(&errorHandler{logger}),
|
2016-09-23 02:41:58 +00:00
|
|
|
kithttp.ServerErrorEncoder(encodeError),
|
2016-09-04 19:43:12 +00:00
|
|
|
kithttp.ServerAfter(
|
|
|
|
kithttp.SetContentType("application/json; charset=utf-8"),
|
|
|
|
),
|
|
|
|
}
|
2016-08-28 03:59:17 +00:00
|
|
|
|
2021-03-26 18:23:29 +00:00
|
|
|
kolideEndpoints := MakeKolideServerEndpoints(svc, config.Auth.JwtKey, config.Server.URLPrefix, limitStore)
|
2017-03-15 15:55:30 +00:00
|
|
|
kolideHandlers := makeKolideKitHandlers(kolideEndpoints, kolideAPIOptions)
|
2016-09-26 17:14:39 +00:00
|
|
|
|
2016-09-04 19:43:12 +00:00
|
|
|
r := mux.NewRouter()
|
2021-02-10 20:13:11 +00:00
|
|
|
|
2016-09-26 17:14:39 +00:00
|
|
|
attachKolideAPIRoutes(r, kolideHandlers)
|
2021-02-10 20:13:11 +00:00
|
|
|
|
|
|
|
// TODO #42 remove the shims
|
|
|
|
shimRoutes(r, logger)
|
|
|
|
|
2020-11-13 03:06:56 +00:00
|
|
|
// Results endpoint is handled different due to websockets use
|
2021-02-10 20:13:11 +00:00
|
|
|
r.PathPrefix("/api/v1/fleet/results/").
|
|
|
|
Handler(makeStreamDistributedQueryCampaignResultsHandler(svc, config.Auth.JwtKey, logger)).
|
|
|
|
Name("distributed_query_results")
|
|
|
|
r.PathPrefix("/api/v1/fleet/results/").
|
2019-10-16 23:40:45 +00:00
|
|
|
Handler(makeStreamDistributedQueryCampaignResultsHandler(svc, config.Auth.JwtKey, logger)).
|
2017-03-01 21:14:26 +00:00
|
|
|
Name("distributed_query_results")
|
|
|
|
|
2020-11-13 03:06:56 +00:00
|
|
|
addMetrics(r)
|
|
|
|
|
2016-08-28 03:59:17 +00:00
|
|
|
return r
|
|
|
|
}
|
2016-09-26 17:14:39 +00:00
|
|
|
|
2016-12-22 17:39:44 +00:00
|
|
|
// addMetrics decorates each hander with prometheus instrumentation
|
|
|
|
func addMetrics(r *mux.Router) {
|
|
|
|
walkFn := func(route *mux.Route, router *mux.Router, ancestors []*mux.Route) error {
|
|
|
|
route.Handler(prometheus.InstrumentHandler(route.GetName(), route.GetHandler()))
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
r.Walk(walkFn)
|
|
|
|
}
|
|
|
|
|
2021-03-08 18:59:39 +00:00
|
|
|
func shimRoutes(r *mux.Router, logger kitlog.Logger) {
|
2021-02-10 20:13:11 +00:00
|
|
|
if err := r.Walk(func(route *mux.Route, router *mux.Router, ancestors []*mux.Route) error {
|
|
|
|
path, err := route.GetPathTemplate()
|
|
|
|
if err != nil {
|
|
|
|
return errors.Wrap(err, "get path template")
|
|
|
|
}
|
|
|
|
|
|
|
|
if !strings.HasPrefix(path, "/api/v1/fleet") {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
methods, err := route.GetMethods()
|
|
|
|
if err != nil {
|
|
|
|
methods = []string{}
|
|
|
|
}
|
|
|
|
|
|
|
|
path = strings.Replace(path, "fleet", "kolide", 1)
|
|
|
|
router.Handle(path, route.GetHandler()).Methods(methods...).Name(route.GetName())
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}); err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Shim the routes to allow them to be referred as /api/v1/fleet or
|
|
|
|
// /api/v1/kolide.
|
|
|
|
var lastShimLogTime time.Time
|
|
|
|
r.Use(func(next http.Handler) http.Handler {
|
|
|
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
if time.Now().After(lastShimLogTime.Add(1 * time.Hour)) {
|
|
|
|
if strings.HasPrefix(r.URL.Path, "/api/v1/kolide") {
|
|
|
|
// There's a race condition with this timestamp but it's not
|
|
|
|
// a big deal if we accidentally log this message more than
|
|
|
|
// once. The point is to not overwhelm the logs with these
|
|
|
|
// messages and this code will be killed soon anyway.
|
|
|
|
lastShimLogTime = time.Now()
|
|
|
|
level.Info(logger).Log(
|
|
|
|
"msg", "client used deprecated route",
|
|
|
|
"deprecated", r.URL.Path,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
next.ServeHTTP(w, r)
|
|
|
|
})
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2016-12-22 17:39:44 +00:00
|
|
|
func attachKolideAPIRoutes(r *mux.Router, h *kolideHandlers) {
|
2021-02-10 20:13:11 +00:00
|
|
|
r.Handle("/api/v1/fleet/login", h.Login).Methods("POST").Name("login")
|
|
|
|
r.Handle("/api/v1/fleet/logout", h.Logout).Methods("POST").Name("logout")
|
|
|
|
r.Handle("/api/v1/fleet/forgot_password", h.ForgotPassword).Methods("POST").Name("forgot_password")
|
|
|
|
r.Handle("/api/v1/fleet/reset_password", h.ResetPassword).Methods("POST").Name("reset_password")
|
|
|
|
r.Handle("/api/v1/fleet/me", h.Me).Methods("GET").Name("me")
|
|
|
|
r.Handle("/api/v1/fleet/change_password", h.ChangePassword).Methods("POST").Name("change_password")
|
|
|
|
r.Handle("/api/v1/fleet/perform_required_password_reset", h.PerformRequiredPasswordReset).Methods("POST").Name("perform_required_password_reset")
|
|
|
|
r.Handle("/api/v1/fleet/sso", h.InitiateSSO).Methods("POST").Name("intiate_sso")
|
|
|
|
r.Handle("/api/v1/fleet/sso", h.SettingsSSO).Methods("GET").Name("sso_config")
|
|
|
|
r.Handle("/api/v1/fleet/sso/callback", h.CallbackSSO).Methods("POST").Name("callback_sso")
|
|
|
|
r.Handle("/api/v1/fleet/users", h.ListUsers).Methods("GET").Name("list_users")
|
|
|
|
r.Handle("/api/v1/fleet/users", h.CreateUserWithInvite).Methods("POST").Name("create_user_with_invite")
|
|
|
|
r.Handle("/api/v1/fleet/users/admin", h.CreateUser).Methods("POST").Name("create_user")
|
|
|
|
r.Handle("/api/v1/fleet/users/{id}", h.GetUser).Methods("GET").Name("get_user")
|
|
|
|
r.Handle("/api/v1/fleet/users/{id}", h.ModifyUser).Methods("PATCH").Name("modify_user")
|
2021-04-08 23:53:33 +00:00
|
|
|
r.Handle("/api/v1/fleet/users/{id}", h.DeleteUser).Methods("DELETE").Name("delete_user")
|
2021-02-10 20:13:11 +00:00
|
|
|
r.Handle("/api/v1/fleet/users/{id}/admin", h.AdminUser).Methods("POST").Name("admin_user")
|
|
|
|
r.Handle("/api/v1/fleet/users/{id}/require_password_reset", h.RequirePasswordReset).Methods("POST").Name("require_password_reset")
|
|
|
|
r.Handle("/api/v1/fleet/users/{id}/sessions", h.GetSessionsForUserInfo).Methods("GET").Name("get_session_for_user")
|
|
|
|
r.Handle("/api/v1/fleet/users/{id}/sessions", h.DeleteSessionsForUser).Methods("DELETE").Name("delete_session_for_user")
|
|
|
|
|
|
|
|
r.Handle("/api/v1/fleet/sessions/{id}", h.GetSessionInfo).Methods("GET").Name("get_session_info")
|
|
|
|
r.Handle("/api/v1/fleet/sessions/{id}", h.DeleteSession).Methods("DELETE").Name("delete_session")
|
|
|
|
|
|
|
|
r.Handle("/api/v1/fleet/config/certificate", h.GetCertificate).Methods("GET").Name("get_certificate")
|
|
|
|
r.Handle("/api/v1/fleet/config", h.GetAppConfig).Methods("GET").Name("get_app_config")
|
|
|
|
r.Handle("/api/v1/fleet/config", h.ModifyAppConfig).Methods("PATCH").Name("modify_app_config")
|
|
|
|
r.Handle("/api/v1/fleet/spec/enroll_secret", h.ApplyEnrollSecretSpec).Methods("POST").Name("apply_enroll_secret_spec")
|
|
|
|
r.Handle("/api/v1/fleet/spec/enroll_secret", h.GetEnrollSecretSpec).Methods("GET").Name("get_enroll_secret_spec")
|
|
|
|
r.Handle("/api/v1/fleet/invites", h.CreateInvite).Methods("POST").Name("create_invite")
|
|
|
|
r.Handle("/api/v1/fleet/invites", h.ListInvites).Methods("GET").Name("list_invites")
|
|
|
|
r.Handle("/api/v1/fleet/invites/{id}", h.DeleteInvite).Methods("DELETE").Name("delete_invite")
|
|
|
|
r.Handle("/api/v1/fleet/invites/{token}", h.VerifyInvite).Methods("GET").Name("verify_invite")
|
|
|
|
|
|
|
|
r.Handle("/api/v1/fleet/email/change/{token}", h.ChangeEmail).Methods("GET").Name("change_email")
|
|
|
|
|
|
|
|
r.Handle("/api/v1/fleet/queries/{id}", h.GetQuery).Methods("GET").Name("get_query")
|
|
|
|
r.Handle("/api/v1/fleet/queries", h.ListQueries).Methods("GET").Name("list_queries")
|
|
|
|
r.Handle("/api/v1/fleet/queries", h.CreateQuery).Methods("POST").Name("create_query")
|
|
|
|
r.Handle("/api/v1/fleet/queries/{id}", h.ModifyQuery).Methods("PATCH").Name("modify_query")
|
|
|
|
r.Handle("/api/v1/fleet/queries/{name}", h.DeleteQuery).Methods("DELETE").Name("delete_query")
|
|
|
|
r.Handle("/api/v1/fleet/queries/id/{id}", h.DeleteQueryByID).Methods("DELETE").Name("delete_query_by_id")
|
|
|
|
r.Handle("/api/v1/fleet/queries/delete", h.DeleteQueries).Methods("POST").Name("delete_queries")
|
|
|
|
r.Handle("/api/v1/fleet/spec/queries", h.ApplyQuerySpecs).Methods("POST").Name("apply_query_specs")
|
|
|
|
r.Handle("/api/v1/fleet/spec/queries", h.GetQuerySpecs).Methods("GET").Name("get_query_specs")
|
|
|
|
r.Handle("/api/v1/fleet/spec/queries/{name}", h.GetQuerySpec).Methods("GET").Name("get_query_spec")
|
|
|
|
r.Handle("/api/v1/fleet/queries/run", h.CreateDistributedQueryCampaign).Methods("POST").Name("create_distributed_query_campaign")
|
|
|
|
r.Handle("/api/v1/fleet/queries/run_by_names", h.CreateDistributedQueryCampaignByNames).Methods("POST").Name("create_distributed_query_campaign_by_names")
|
|
|
|
|
|
|
|
r.Handle("/api/v1/fleet/packs", h.CreatePack).Methods("POST").Name("create_pack")
|
|
|
|
r.Handle("/api/v1/fleet/packs/{id}", h.ModifyPack).Methods("PATCH").Name("modify_pack")
|
|
|
|
r.Handle("/api/v1/fleet/packs/{id}", h.GetPack).Methods("GET").Name("get_pack")
|
|
|
|
r.Handle("/api/v1/fleet/packs", h.ListPacks).Methods("GET").Name("list_packs")
|
|
|
|
r.Handle("/api/v1/fleet/packs/{name}", h.DeletePack).Methods("DELETE").Name("delete_pack")
|
|
|
|
r.Handle("/api/v1/fleet/packs/id/{id}", h.DeletePackByID).Methods("DELETE").Name("delete_pack_by_id")
|
|
|
|
r.Handle("/api/v1/fleet/packs/{id}/scheduled", h.GetScheduledQueriesInPack).Methods("GET").Name("get_scheduled_queries_in_pack")
|
|
|
|
r.Handle("/api/v1/fleet/schedule", h.ScheduleQuery).Methods("POST").Name("schedule_query")
|
|
|
|
r.Handle("/api/v1/fleet/schedule/{id}", h.GetScheduledQuery).Methods("GET").Name("get_scheduled_query")
|
|
|
|
r.Handle("/api/v1/fleet/schedule/{id}", h.ModifyScheduledQuery).Methods("PATCH").Name("modify_scheduled_query")
|
|
|
|
r.Handle("/api/v1/fleet/schedule/{id}", h.DeleteScheduledQuery).Methods("DELETE").Name("delete_scheduled_query")
|
|
|
|
r.Handle("/api/v1/fleet/spec/packs", h.ApplyPackSpecs).Methods("POST").Name("apply_pack_specs")
|
|
|
|
r.Handle("/api/v1/fleet/spec/packs", h.GetPackSpecs).Methods("GET").Name("get_pack_specs")
|
|
|
|
r.Handle("/api/v1/fleet/spec/packs/{name}", h.GetPackSpec).Methods("GET").Name("get_pack_spec")
|
|
|
|
|
|
|
|
r.Handle("/api/v1/fleet/labels", h.CreateLabel).Methods("POST").Name("create_label")
|
|
|
|
r.Handle("/api/v1/fleet/labels/{id}", h.ModifyLabel).Methods("PATCH").Name("modify_label")
|
|
|
|
r.Handle("/api/v1/fleet/labels/{id}", h.GetLabel).Methods("GET").Name("get_label")
|
|
|
|
r.Handle("/api/v1/fleet/labels", h.ListLabels).Methods("GET").Name("list_labels")
|
|
|
|
r.Handle("/api/v1/fleet/labels/{id}/hosts", h.ListHostsInLabel).Methods("GET").Name("list_hosts_in_label")
|
|
|
|
r.Handle("/api/v1/fleet/labels/{name}", h.DeleteLabel).Methods("DELETE").Name("delete_label")
|
|
|
|
r.Handle("/api/v1/fleet/labels/id/{id}", h.DeleteLabelByID).Methods("DELETE").Name("delete_label_by_id")
|
|
|
|
r.Handle("/api/v1/fleet/spec/labels", h.ApplyLabelSpecs).Methods("POST").Name("apply_label_specs")
|
|
|
|
r.Handle("/api/v1/fleet/spec/labels", h.GetLabelSpecs).Methods("GET").Name("get_label_specs")
|
|
|
|
r.Handle("/api/v1/fleet/spec/labels/{name}", h.GetLabelSpec).Methods("GET").Name("get_label_spec")
|
|
|
|
|
|
|
|
r.Handle("/api/v1/fleet/hosts", h.ListHosts).Methods("GET").Name("list_hosts")
|
|
|
|
r.Handle("/api/v1/fleet/host_summary", h.GetHostSummary).Methods("GET").Name("get_host_summary")
|
|
|
|
r.Handle("/api/v1/fleet/hosts/{id}", h.GetHost).Methods("GET").Name("get_host")
|
|
|
|
r.Handle("/api/v1/fleet/hosts/identifier/{identifier}", h.HostByIdentifier).Methods("GET").Name("host_by_identifier")
|
|
|
|
r.Handle("/api/v1/fleet/hosts/{id}", h.DeleteHost).Methods("DELETE").Name("delete_host")
|
|
|
|
|
|
|
|
r.Handle("/api/v1/fleet/spec/osquery_options", h.ApplyOsqueryOptionsSpec).Methods("POST").Name("apply_osquery_options_spec")
|
|
|
|
r.Handle("/api/v1/fleet/spec/osquery_options", h.GetOsqueryOptionsSpec).Methods("GET").Name("get_osquery_options_spec")
|
|
|
|
|
|
|
|
r.Handle("/api/v1/fleet/targets", h.SearchTargets).Methods("POST").Name("search_targets")
|
|
|
|
|
2021-03-27 01:03:31 +00:00
|
|
|
r.Handle("/api/v1/fleet/version", h.Version).Methods("GET").Name("version")
|
|
|
|
|
2021-02-10 20:13:11 +00:00
|
|
|
r.Handle("/api/v1/fleet/status/result_store", h.StatusResultStore).Methods("GET").Name("status_result_store")
|
|
|
|
r.Handle("/api/v1/fleet/status/live_query", h.StatusLiveQuery).Methods("GET").Name("status_live_query")
|
|
|
|
|
|
|
|
r.Handle("/api/v1/fleet/carves", h.ListCarves).Methods("GET").Name("list_carves")
|
|
|
|
r.Handle("/api/v1/fleet/carves/{id}", h.GetCarve).Methods("GET").Name("get_carve")
|
|
|
|
r.Handle("/api/v1/fleet/carves/{id}/block/{block_id}", h.GetCarveBlock).Methods("GET").Name("get_carve_block")
|
2020-11-05 04:45:16 +00:00
|
|
|
|
2021-03-18 04:59:00 +00:00
|
|
|
r.Handle("/api/v1/fleet/teams", h.CreateTeam).Methods("POST").Name("create_team")
|
2021-04-06 18:40:14 +00:00
|
|
|
r.Handle("/api/v1/fleet/teams", h.ListTeams).Methods("GET").Name("list_teams")
|
2021-03-18 04:59:00 +00:00
|
|
|
r.Handle("/api/v1/fleet/teams/{id}", h.ModifyTeam).Methods("PATCH").Name("modify_team")
|
|
|
|
|
2016-12-22 17:39:44 +00:00
|
|
|
r.Handle("/api/v1/osquery/enroll", h.EnrollAgent).Methods("POST").Name("enroll_agent")
|
|
|
|
r.Handle("/api/v1/osquery/config", h.GetClientConfig).Methods("POST").Name("get_client_config")
|
|
|
|
r.Handle("/api/v1/osquery/distributed/read", h.GetDistributedQueries).Methods("POST").Name("get_distributed_queries")
|
|
|
|
r.Handle("/api/v1/osquery/distributed/write", h.SubmitDistributedQueryResults).Methods("POST").Name("submit_distributed_query_results")
|
|
|
|
r.Handle("/api/v1/osquery/log", h.SubmitLogs).Methods("POST").Name("submit_logs")
|
2020-11-05 04:45:16 +00:00
|
|
|
r.Handle("/api/v1/osquery/carve/begin", h.CarveBegin).Methods("POST").Name("carve_begin")
|
|
|
|
r.Handle("/api/v1/osquery/carve/block", h.CarveBlock).Methods("POST").Name("carve_block")
|
2016-09-26 17:14:39 +00:00
|
|
|
}
|
2016-11-09 17:19:07 +00:00
|
|
|
|
2020-11-18 19:10:55 +00:00
|
|
|
// WithSetup is an http middleware that checks if setup procedures have been completed.
|
2017-02-09 18:43:45 +00:00
|
|
|
// If setup hasn't been completed it serves the API with a setup middleware.
|
2016-11-09 17:19:07 +00:00
|
|
|
// If the server is already configured, the default API handler is exposed.
|
2016-12-02 18:46:31 +00:00
|
|
|
func WithSetup(svc kolide.Service, logger kitlog.Logger, next http.Handler) http.HandlerFunc {
|
|
|
|
return func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
configRouter := http.NewServeMux()
|
|
|
|
configRouter.Handle("/api/v1/setup", kithttp.NewServer(
|
|
|
|
makeSetupEndpoint(svc),
|
|
|
|
decodeSetupRequest,
|
|
|
|
encodeResponse,
|
|
|
|
))
|
2017-01-12 00:40:58 +00:00
|
|
|
// whitelist osqueryd endpoints
|
|
|
|
if strings.HasPrefix(r.URL.Path, "/api/v1/osquery") {
|
|
|
|
next.ServeHTTP(w, r)
|
|
|
|
return
|
|
|
|
}
|
2017-02-09 18:43:45 +00:00
|
|
|
requireSetup, err := RequireSetup(svc)
|
|
|
|
if err != nil {
|
|
|
|
logger.Log("msg", "fetching setup info from db", "err", err)
|
|
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
if requireSetup {
|
2016-12-02 18:46:31 +00:00
|
|
|
configRouter.ServeHTTP(w, r)
|
2017-02-09 18:43:45 +00:00
|
|
|
return
|
2016-12-02 18:46:31 +00:00
|
|
|
}
|
2017-02-09 18:43:45 +00:00
|
|
|
next.ServeHTTP(w, r)
|
2016-11-09 17:19:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-12-29 23:36:36 +00:00
|
|
|
// RedirectLoginToSetup detects if the setup endpoint should be used. If setup is required it redirect all
|
|
|
|
// frontend urls to /setup, otherwise the frontend router is used.
|
2019-10-16 23:40:45 +00:00
|
|
|
func RedirectLoginToSetup(svc kolide.Service, logger kitlog.Logger, next http.Handler, urlPrefix string) http.HandlerFunc {
|
2016-12-29 23:36:36 +00:00
|
|
|
return func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
redirect := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
2017-09-01 16:42:46 +00:00
|
|
|
if r.URL.Path == "/setup" {
|
2016-12-29 23:36:36 +00:00
|
|
|
next.ServeHTTP(w, r)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
newURL := r.URL
|
2019-10-16 23:40:45 +00:00
|
|
|
newURL.Path = urlPrefix + "/setup"
|
2016-12-29 23:36:36 +00:00
|
|
|
http.Redirect(w, r, newURL.String(), http.StatusTemporaryRedirect)
|
|
|
|
})
|
2017-02-09 18:43:45 +00:00
|
|
|
|
|
|
|
setupRequired, err := RequireSetup(svc)
|
|
|
|
if err != nil {
|
2017-09-01 16:42:46 +00:00
|
|
|
logger.Log("msg", "fetching setupinfo from db", "err", err)
|
2017-02-09 18:43:45 +00:00
|
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
if setupRequired {
|
2016-12-29 23:36:36 +00:00
|
|
|
redirect.ServeHTTP(w, r)
|
2017-02-09 18:43:45 +00:00
|
|
|
return
|
2016-12-29 23:36:36 +00:00
|
|
|
}
|
2019-10-16 23:40:45 +00:00
|
|
|
RedirectSetupToLogin(svc, logger, next, urlPrefix).ServeHTTP(w, r)
|
2016-11-09 17:19:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-09-01 16:42:46 +00:00
|
|
|
// RequireSetup checks to see if the service has been setup.
|
2017-02-09 18:43:45 +00:00
|
|
|
func RequireSetup(svc kolide.Service) (bool, error) {
|
|
|
|
ctx := context.Background()
|
|
|
|
users, err := svc.ListUsers(ctx, kolide.ListOptions{Page: 0, PerPage: 1})
|
2016-11-09 17:19:07 +00:00
|
|
|
if err != nil {
|
2017-02-09 18:43:45 +00:00
|
|
|
return false, err
|
2016-11-09 17:19:07 +00:00
|
|
|
}
|
2017-02-09 18:43:45 +00:00
|
|
|
if len(users) == 0 {
|
|
|
|
return true, nil
|
|
|
|
}
|
|
|
|
return false, nil
|
2016-11-09 17:19:07 +00:00
|
|
|
}
|
2017-01-11 19:05:07 +00:00
|
|
|
|
2017-09-01 16:42:46 +00:00
|
|
|
// RedirectSetupToLogin forces the /setup path to be redirected to login. This middleware is used after
|
2017-01-11 19:05:07 +00:00
|
|
|
// the app has been setup.
|
2019-10-16 23:40:45 +00:00
|
|
|
func RedirectSetupToLogin(svc kolide.Service, logger kitlog.Logger, next http.Handler, urlPrefix string) http.HandlerFunc {
|
2017-01-11 19:05:07 +00:00
|
|
|
return func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
if r.URL.Path == "/setup" {
|
|
|
|
newURL := r.URL
|
2019-10-16 23:40:45 +00:00
|
|
|
newURL.Path = urlPrefix + "/login"
|
2017-01-11 19:05:07 +00:00
|
|
|
http.Redirect(w, r, newURL.String(), http.StatusTemporaryRedirect)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
next.ServeHTTP(w, r)
|
|
|
|
}
|
|
|
|
}
|