Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for column options #77

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
155 changes: 123 additions & 32 deletions plugin/table/table.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ func (t *Plugin) Routes() osquery.ExtensionPluginResponse {
"id": "column",
"name": col.Name,
"type": string(col.Type),
"op": "0",
"op": strconv.FormatUint(uint64(col.Options), 10),
})
}
return routes
Expand Down Expand Up @@ -107,55 +107,146 @@ func (t *Plugin) Shutdown() {}
// plugin. Both values are mandatory. Prefer using the *Column helpers to
// create ColumnDefinition structs.
type ColumnDefinition struct {
Name string
Type ColumnType
Name string
Type ColumnType
Options columnOptions // bitmask
Description string
}

// TextColumn is a helper for defining columns containing strings.
func TextColumn(name string) ColumnDefinition {
return ColumnDefinition{
// NewColumn returns a ColumnDefinition for the specified column. It
// defaults to a TEXT column, and accepts functional args to change
// settings.
func NewColumn(name string, opts ...ColumnOpt) ColumnDefinition {
cd := ColumnDefinition{
Name: name,
Type: ColumnTypeText,
Type: ColumnTypeText, // Default to TEXT, and not UNKNOWN
}
}

// IntegerColumn is a helper for defining columns containing integers.
func IntegerColumn(name string) ColumnDefinition {
return ColumnDefinition{
Name: name,
Type: ColumnTypeInteger,
for _, opt := range opts {
opt(&cd)
}

return cd

}

// BigIntColumn is a helper for defining columns containing big integers.
func BigIntColumn(name string) ColumnDefinition {
return ColumnDefinition{
Name: name,
Type: ColumnTypeBigInt,
}
// ColumnType is a strongly typed representation of the data type string for a
// column definition. The named constants should be used.
type ColumnType string

// The following column types are defined in osquery tables.h and column.cpp
const (
ColumnTypeUnknown ColumnType = "UNKNOWN"
ColumnTypeText = "TEXT"
ColumnTypeInteger = "INTEGER"
ColumnTypeBigInt = "BIGINT"
ColumnTypeUnsignedBigInt = "UNSIGNED BIGINT"
ColumnTypeDouble = "DOUBLE"
ColumnTypeBlob = "BLOB"
)

// TextColumn is a DEPRECATED helper for defining columns containing strings.
func TextColumn(name string, opts ...ColumnOpt) ColumnDefinition {
return NewColumn(name, append(opts, IsText())...)
}

// IntegerColumn is a DEPRECATED helper for defining columns containing integers.
func IntegerColumn(name string, opts ...ColumnOpt) ColumnDefinition {
return NewColumn(name, append(opts, IsInteger())...)
}

// DoubleColumn is a helper for defining columns containing floating point
// BigIntColumn is a DEPRECATED helper for defining columns containing big integers.
func BigIntColumn(name string, opts ...ColumnOpt) ColumnDefinition {
return NewColumn(name, append(opts, IsBigInt())...)
}

// DoubleColumn is a DEPRECATED helper for defining columns containing floating point
// values.
func DoubleColumn(name string) ColumnDefinition {
return ColumnDefinition{
Name: name,
Type: ColumnTypeDouble,
func DoubleColumn(name string, opts ...ColumnOpt) ColumnDefinition {
return NewColumn(name, append(opts, IsDouble())...)
}

// setColumnType is an internal function to set column type
func setColumnType(ctype ColumnType) ColumnOpt {
return func(cd *ColumnDefinition) {
cd.Type = ctype
}
}

// ColumnType is a strongly typed representation of the data type string for a
// column definition. The named constants should be used.
type ColumnType string
// IsUnknown is a functional argument that defines this as an unknown column
func IsUnknown() ColumnOpt { return setColumnType(ColumnTypeUnknown) }

// IsText is a functional argument that defines this as a text column
func IsText() ColumnOpt { return setColumnType(ColumnTypeText) }

// IsInteger is a functional argument that defines this as a text column
func IsInteger() ColumnOpt { return setColumnType(ColumnTypeInteger) }

// IseBigInt is a functional argument that defines this as a text column
func IsBigInt() ColumnOpt { return setColumnType(ColumnTypeBigInt) }

// IsUnsignedBigInt is a functional argument that defines this as a text column
func IsUnsignedBigInt() ColumnOpt { return setColumnType(ColumnTypeUnsignedBigInt) }

// IsDouble is a functional argument that defines this as a text column
func IsDouble() ColumnOpt { return setColumnType(ColumnTypeDouble) }

// The following column types are defined in osquery tables.h.
// IsTypeBlob is a functional argument that defines this as a text column
func IsTypeBlob() ColumnOpt { return setColumnType(ColumnTypeBlob) }

// ColumnOption are the osquery column options. These are represented by a bitmask
type columnOptions uint8

// From https://github.com/osquery/osquery/blob/master/osquery/core/sql/column.h#L37
const (
ColumnTypeText ColumnType = "TEXT"
ColumnTypeInteger = "INTEGER"
ColumnTypeBigInt = "BIGINT"
ColumnTypeDouble = "DOUBLE"
columnOptionDefault columnOptions = 0
columnOptionIndex = 1
columnOptionRequired = 2
columnOptionAdditional = 4
columnOptionOptimized = 8
columnOptionHidden = 16
)

// setColumnOption is an internal function that applies the column options.
func setColumnOption(flag columnOptions) ColumnOpt {
return func(cd *ColumnDefinition) {
cd.Options = cd.Options | flag
}
}

// IndexColumn is a functional argument to declare this as an indexed
// column. Depending on impmelentation, this can significantly change
// performance. See osquery source code for more information.
func IndexColumn() ColumnOpt { return setColumnOption(columnOptionIndex) }

// RequiredColumn is a functional argument that sets this as a
// required column. sqlite will not process queries, if a required
// column is missing. See osquery source code for more information.
func RequiredColumn() ColumnOpt { return setColumnOption(columnOptionRequired) }

// AdditionalColumn is a functional argument that sets this as an
// additional column. See osquery source code for more information.
func AdditionalColumn() ColumnOpt { return setColumnOption(columnOptionAdditional) }

// OptimizedColumn is a functional argument that sets this as an
// optimized column. See osquery source code for more information.
func OptimizedColumn() ColumnOpt { return setColumnOption(columnOptionOptimized) }

// HiddenColumn is a functional argument that sets this as an
// hidden column. This omits it from `select *` queries. See osquery source code for more information.
func HiddenColumn() ColumnOpt { return setColumnOption(columnOptionHidden) }

// ColumnDescription sets the column description. This is not
// currently part of the underlying osquery api, it is here for human
// consumption. It may become part of osquery spec generation.
func ColumnDescription(d string) ColumnOpt {
return func(cd *ColumnDefinition) {
cd.Description = d
}
}

type ColumnOpt func(*ColumnDefinition)

// QueryContext contains the constraints from the WHERE clause of the query,
// that can optionally be used to optimize the table generation. Note that the
// osquery SQLite engine will perform the filtering with these constraints, so
Expand Down