mirror of
https://github.com/empayre/fleet.git
synced 2024-11-06 17:05:18 +00:00
170 lines
4.8 KiB
Go
170 lines
4.8 KiB
Go
package kolide
|
|
|
|
import (
|
|
"database/sql/driver"
|
|
"encoding/json"
|
|
"fmt"
|
|
"strings"
|
|
|
|
"golang.org/x/net/context"
|
|
)
|
|
|
|
// OptionStore interface describes methods to access datastore
|
|
type OptionStore interface {
|
|
// SaveOptions transactional write of options to storage. If one or more
|
|
// values fails validation none of the writes will succeed. Note only option
|
|
// values are written. Other option fields are created in migration and do
|
|
// not change. Attempting to write ReadOnly options will cause an error.
|
|
SaveOptions(opts []Option) error
|
|
// Options returns all options
|
|
ListOptions() ([]Option, error)
|
|
// Option return an option by ID
|
|
Option(id uint) (*Option, error)
|
|
// OptionByName returns an option uniquely identified by name
|
|
OptionByName(name string) (*Option, error)
|
|
// GetOsqueryConfigOptions returns options in a format that will be the options
|
|
// section of osquery configuration
|
|
GetOsqueryConfigOptions() (map[string]interface{}, error)
|
|
}
|
|
|
|
// OptionService interface describes methods that operate on osquery options
|
|
type OptionService interface {
|
|
// GetOptions retrieves all options
|
|
GetOptions(ctx context.Context) ([]Option, error)
|
|
// ModifyOptions will change values of the options in OptionRequest. Note
|
|
// passing ReadOnly options will cause an error.
|
|
ModifyOptions(ctx context.Context, req OptionRequest) ([]Option, error)
|
|
}
|
|
|
|
const (
|
|
ReadOnly = true
|
|
NotReadOnly = !ReadOnly
|
|
)
|
|
|
|
// OptionType defines the type of the value assigned to an option
|
|
type OptionType int
|
|
|
|
const (
|
|
OptionTypeString OptionType = iota
|
|
OptionTypeInt
|
|
OptionTypeBool
|
|
)
|
|
|
|
// String values that map from JSON to OptionType
|
|
const (
|
|
optionTypeString = "string"
|
|
optionTypeInt = "int"
|
|
optionTypeBool = "bool"
|
|
)
|
|
|
|
// MarshalJSON marshals option type to strings
|
|
func (ot OptionType) MarshalJSON() ([]byte, error) {
|
|
return []byte(fmt.Sprintf(`"%s"`, ot)), nil
|
|
}
|
|
|
|
// UnmarshalJSON converts json to OptionType
|
|
func (ot *OptionType) UnmarshalJSON(b []byte) error {
|
|
switch typ := string(b); strings.Trim(typ, `"`) {
|
|
case optionTypeString:
|
|
*ot = OptionTypeString
|
|
case optionTypeBool:
|
|
*ot = OptionTypeBool
|
|
case optionTypeInt:
|
|
*ot = OptionTypeInt
|
|
default:
|
|
return fmt.Errorf("unsupported option type '%s'", typ)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// String is used to marshal OptionType to human readable strings used in JSON payloads
|
|
func (ot OptionType) String() string {
|
|
switch ot {
|
|
case OptionTypeString:
|
|
return optionTypeString
|
|
case OptionTypeInt:
|
|
return optionTypeInt
|
|
case OptionTypeBool:
|
|
return optionTypeBool
|
|
default:
|
|
panic("stringer not implemented for OptionType")
|
|
}
|
|
}
|
|
|
|
// OptionValue supports Valuer and Scan interfaces for reading and writing
|
|
// to the database, and also JSON marshaling
|
|
type OptionValue struct {
|
|
Val interface{}
|
|
}
|
|
|
|
// Value is called by the DB driver. Note that we store data as JSON
|
|
// types, so we can use the JSON marshaller to assign the appropriate
|
|
// type when we fetch it from the db
|
|
func (ov OptionValue) Value() (dv driver.Value, err error) {
|
|
return json.Marshal(ov.Val)
|
|
}
|
|
|
|
// Scan takes db string and turns it into an option type
|
|
func (ov *OptionValue) Scan(src interface{}) error {
|
|
return json.Unmarshal(src.([]byte), &ov.Val)
|
|
}
|
|
|
|
// MarshalJSON implements the json.Marshaler interface
|
|
func (ov OptionValue) MarshalJSON() ([]byte, error) {
|
|
return json.Marshal(ov.Val)
|
|
}
|
|
|
|
// UnmarshalJSON implements the json.Unmarshaler interface
|
|
func (ov *OptionValue) UnmarshalJSON(b []byte) error {
|
|
return json.Unmarshal(b, &ov.Val)
|
|
}
|
|
|
|
// Option represents a possible osquery confguration option
|
|
// See https://osquery.readthedocs.io/en/stable/deployment/configuration/
|
|
type Option struct {
|
|
// ID unique identifier for option assigned by the dbms
|
|
ID uint `json:"id"`
|
|
// Name of the option which must be unique
|
|
Name string `json:"name"`
|
|
// Type of value for the option
|
|
Type OptionType `json:"type"`
|
|
// Value of the option which may be nil, bool, int, or string.
|
|
Value OptionValue `json:"value"`
|
|
// ReadOnly if true, this option is required for Kolide to function
|
|
// properly and cannot be modified by the end user
|
|
ReadOnly bool `json:"read_only" db:"read_only"`
|
|
}
|
|
|
|
// SetValue sets the value associated with the option
|
|
func (opt *Option) SetValue(v interface{}) {
|
|
opt.Value.Val = v
|
|
}
|
|
|
|
func (opt *Option) SameType(compare interface{}) bool {
|
|
switch compare.(type) {
|
|
case float64:
|
|
return opt.Type == OptionTypeInt
|
|
case string:
|
|
return opt.Type == OptionTypeString
|
|
case bool:
|
|
return opt.Type == OptionTypeBool
|
|
default:
|
|
return false
|
|
}
|
|
}
|
|
|
|
// OptionSet returns true if the option has a value assigned to it
|
|
func (opt *Option) OptionSet() bool {
|
|
return opt.Value.Val != nil
|
|
}
|
|
|
|
// GetValue returns the value associated with the option
|
|
func (opt Option) GetValue() interface{} {
|
|
return opt.Value.Val
|
|
}
|
|
|
|
// OptionRequest contains options that are passed to modify options requests.
|
|
type OptionRequest struct {
|
|
Options []Option `json:"options"`
|
|
}
|