x-pack/osquerybeat/ext/osquery-extension/cmd/gentables/README.md
This tool generates Go code and documentation from YAML specifications for osquery tables and views.
Tables and views are now defined using a unified YAML format in a single directory, differentiated by the type field:
type: table - Defines an osquery tabletype: view - Defines an osquery viewThis simplifies organization and allows both tables and views to be processed in a single pass.
This tool has its own go.mod to isolate its dependencies from the main osquerybeat module. This keeps the pingcap SQL parser as a build-time-only dependency without adding it to the production code.
From the cmd/gentables directory:
go run . -spec-dir <specs_dir> -out-dir <tables_output> -views-out-dir <views_output> -verbose
Or via go generate from the osquery-extension directory:
go generate ./...
gopkg.in/yaml.v3 - YAML parsinggithub.com/pingcap/parser - SQL parser for view validation (isolated from main module)embedgo_type: time.Time for proper timestamp handlingFor types that need to be consistent across multiple tables (e.g., UserProfile, LnkMetadata),
create a shared types spec in your specs directory:
# shared_types.yaml
type: shared_types
group: my_group
types:
- name: UserProfile
description: Windows user profile information
pointer: true
columns:
- name: username
type: TEXT
description: The username
- name: sid
type: TEXT
description: The Windows Security Identifier
- name: LnkMetadata
description: Windows LNK file metadata
pointer: true
columns:
- name: local_path
type: TEXT
description: Target local path
- name: file_size
type: INTEGER
description: Target file size
Then reference these shared types in your table specs:
# sample_jumplists.yaml
type: table
name: sample_jumplists
shared_types:
- UserProfile
- LnkMetadata
columns:
- name: UserProfile
type: EMBEDDED
embedded_type: UserProfile
# ...
# sample_recent_files.yaml
type: table
name: sample_recent_files
shared_types:
- UserProfile # Same type definition as jumplists
- LnkMetadata # Same type definition as jumplists
columns:
- name: UserProfile
type: EMBEDDED
embedded_type: UserProfile
# ...
This ensures both tables have identical column definitions for shared fields.
See examples/tables/shared_types.yaml, examples/tables/sample_jumplists.yaml, and
examples/tables/sample_recent_files.yaml for complete examples.
You may define multiple type: shared_types spec files. Each shared types file
must set a group, and type names must be unique within that group. Specs that
use shared_types must also set the same group.
Shared types are generated under the tables output directory:
<tables_out_dir>/<group>/types.go with package name derived from the group.
Templates are stored under cmd/gentables/templates/ and embedded into the
binary via embed. The generator loads them from the embedded filesystem at
runtime, so you do not need to ship template files separately.
Each table/view is generated into its own package:
pkg/tables/
├── registry.go # STATIC - metadata registry for all tables
└── generated/
└── sample_custom_table/ # Directory (descriptive)
└── sample_custom_table.go # package samplecustomtable (idiomatic)
pkg/views/
├── registry.go # STATIC - metadata registry for all views
└── generated/
└── sample_combined_resources/ # Directory (descriptive)
└── sample_combined_resources.go # package samplecombinedresources (idiomatic)
Package Naming:
sample_custom_table)samplecustomtable)Grouped Specs:
If a spec includes group: my_group, generated code is placed under:
pkg/tables/generated/my_group/<table_name>/pkg/views/generated/my_group/<view_name>/
Shared types for that group are generated at:
pkg/tables/generated/my_group/types.go.Generated Code:
// Each package includes:
type Result struct { ... } // Typed result struct with osquery tags
func Columns() []table.ColumnDefinition { ... } // For tables
func View() *hooks.View { ... } // For views
const TableName = "..." // For tables
See the examples/ directory for usage examples and detailed documentation.