2016-09-29 04:21:39 +00:00
|
|
|
package service
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"encoding/json"
|
|
|
|
|
|
|
|
|
|
"github.com/go-kit/kit/endpoint"
|
|
|
|
|
"github.com/kolide/kolide-ose/server/kolide"
|
|
|
|
|
"golang.org/x/net/context"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
// Enroll Agent
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
type enrollAgentRequest struct {
|
|
|
|
|
EnrollSecret string `json:"enroll_secret"`
|
|
|
|
|
HostIdentifier string `json:"host_identifier"`
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type enrollAgentResponse struct {
|
|
|
|
|
NodeKey string `json:"node_key,omitempty"`
|
|
|
|
|
Err error `json:"error,omitempty"`
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (r enrollAgentResponse) error() error { return r.Err }
|
|
|
|
|
|
|
|
|
|
func makeEnrollAgentEndpoint(svc kolide.Service) endpoint.Endpoint {
|
|
|
|
|
return func(ctx context.Context, request interface{}) (interface{}, error) {
|
|
|
|
|
req := request.(enrollAgentRequest)
|
|
|
|
|
nodeKey, err := svc.EnrollAgent(ctx, req.EnrollSecret, req.HostIdentifier)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return enrollAgentResponse{Err: err}, nil
|
|
|
|
|
}
|
|
|
|
|
return enrollAgentResponse{NodeKey: nodeKey}, nil
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
// Get Client Config
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
type getClientConfigRequest struct {
|
|
|
|
|
NodeKey string `json:"node_key"`
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type getClientConfigResponse struct {
|
2017-01-10 22:27:52 +00:00
|
|
|
kolide.OsqueryConfig
|
|
|
|
|
Err error `json:"error,omitempty"`
|
2016-09-29 04:21:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (r getClientConfigResponse) error() error { return r.Err }
|
|
|
|
|
|
|
|
|
|
func makeGetClientConfigEndpoint(svc kolide.Service) endpoint.Endpoint {
|
|
|
|
|
return func(ctx context.Context, request interface{}) (interface{}, error) {
|
|
|
|
|
config, err := svc.GetClientConfig(ctx)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return getClientConfigResponse{Err: err}, nil
|
|
|
|
|
}
|
2017-01-10 22:27:52 +00:00
|
|
|
return getClientConfigResponse{OsqueryConfig: *config}, nil
|
2016-09-29 04:21:39 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
// Get Distributed Queries
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
type getDistributedQueriesRequest struct {
|
|
|
|
|
NodeKey string `json:"node_key"`
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type getDistributedQueriesResponse struct {
|
|
|
|
|
Queries map[string]string `json:"queries"`
|
|
|
|
|
Err error `json:"error,omitempty"`
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (r getDistributedQueriesResponse) error() error { return r.Err }
|
|
|
|
|
|
|
|
|
|
func makeGetDistributedQueriesEndpoint(svc kolide.Service) endpoint.Endpoint {
|
|
|
|
|
return func(ctx context.Context, request interface{}) (interface{}, error) {
|
|
|
|
|
queries, err := svc.GetDistributedQueries(ctx)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return getDistributedQueriesResponse{Err: err}, nil
|
|
|
|
|
}
|
|
|
|
|
return getDistributedQueriesResponse{Queries: queries}, nil
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
// Write Distributed Query Results
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
type submitDistributedQueryResultsRequest struct {
|
Push distributed query errors over results websocket (#878)
As of recently, osquery will report when a distributed query fails. We now
expose errors over the results websocket. When a query errored on the host, the
`error` key in the result will be non-null. Note that osquery currently doesn't
provide any details so the error string will always be "failed". I anticipate
that we will fix this and the string is included for future-proofing.
Successful result:
```
{
"type": "result",
"data": {
"distributed_query_execution_id": 15,
"host": {
... omitted ...
},
"rows": [
{
"hour": "1"
}
],
"error": null
}
}
```
Failed result:
```
{
"type": "result",
"data": {
"distributed_query_execution_id": 14,
"host": {
... omitted ...
},
"rows": [
],
"error": "failed"
}
}
```
2017-01-11 03:34:32 +00:00
|
|
|
NodeKey string `json:"node_key"`
|
|
|
|
|
Results kolide.OsqueryDistributedQueryResults `json:"queries"`
|
|
|
|
|
Statuses map[string]string `json:"statuses"`
|
2016-09-29 04:21:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type submitDistributedQueryResultsResponse struct {
|
|
|
|
|
Err error `json:"error,omitempty"`
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (r submitDistributedQueryResultsResponse) error() error { return r.Err }
|
|
|
|
|
|
|
|
|
|
func makeSubmitDistributedQueryResultsEndpoint(svc kolide.Service) endpoint.Endpoint {
|
|
|
|
|
return func(ctx context.Context, request interface{}) (interface{}, error) {
|
|
|
|
|
req := request.(submitDistributedQueryResultsRequest)
|
Push distributed query errors over results websocket (#878)
As of recently, osquery will report when a distributed query fails. We now
expose errors over the results websocket. When a query errored on the host, the
`error` key in the result will be non-null. Note that osquery currently doesn't
provide any details so the error string will always be "failed". I anticipate
that we will fix this and the string is included for future-proofing.
Successful result:
```
{
"type": "result",
"data": {
"distributed_query_execution_id": 15,
"host": {
... omitted ...
},
"rows": [
{
"hour": "1"
}
],
"error": null
}
}
```
Failed result:
```
{
"type": "result",
"data": {
"distributed_query_execution_id": 14,
"host": {
... omitted ...
},
"rows": [
],
"error": "failed"
}
}
```
2017-01-11 03:34:32 +00:00
|
|
|
err := svc.SubmitDistributedQueryResults(ctx, req.Results, req.Statuses)
|
2016-09-29 04:21:39 +00:00
|
|
|
if err != nil {
|
|
|
|
|
return submitDistributedQueryResultsResponse{Err: err}, nil
|
|
|
|
|
}
|
|
|
|
|
return submitDistributedQueryResultsResponse{}, nil
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
// Submit Logs
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
type submitLogsRequest struct {
|
2016-10-01 02:18:27 +00:00
|
|
|
NodeKey string `json:"node_key"`
|
|
|
|
|
LogType string `json:"log_type"`
|
|
|
|
|
Data json.RawMessage `json:"data"`
|
2016-09-29 04:21:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type submitLogsResponse struct {
|
|
|
|
|
Err error `json:"error,omitempty"`
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (r submitLogsResponse) error() error { return r.Err }
|
|
|
|
|
|
|
|
|
|
func makeSubmitLogsEndpoint(svc kolide.Service) endpoint.Endpoint {
|
|
|
|
|
return func(ctx context.Context, request interface{}) (interface{}, error) {
|
|
|
|
|
req := request.(submitLogsRequest)
|
2016-10-01 02:18:27 +00:00
|
|
|
|
|
|
|
|
var err error
|
|
|
|
|
switch req.LogType {
|
|
|
|
|
case "status":
|
|
|
|
|
var statuses []kolide.OsqueryStatusLog
|
|
|
|
|
if err := json.Unmarshal(req.Data, &statuses); err != nil {
|
|
|
|
|
err = osqueryError{message: "unmarshalling status logs: " + err.Error()}
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
err = svc.SubmitStatusLogs(ctx, statuses)
|
|
|
|
|
if err != nil {
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case "result":
|
|
|
|
|
var results []kolide.OsqueryResultLog
|
|
|
|
|
if err := json.Unmarshal(req.Data, &results); err != nil {
|
|
|
|
|
err = osqueryError{message: "unmarshalling result logs: " + err.Error()}
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
err = svc.SubmitResultLogs(ctx, results)
|
|
|
|
|
if err != nil {
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
err = osqueryError{message: "unknown log type: " + req.LogType}
|
2016-09-29 04:21:39 +00:00
|
|
|
}
|
2016-10-01 02:18:27 +00:00
|
|
|
|
|
|
|
|
return submitLogsResponse{Err: err}, nil
|
2016-09-29 04:21:39 +00:00
|
|
|
}
|
|
|
|
|
}
|