Skip to content

Commit 6038a45

Browse files
committed
feat: introduce osQuery ATC generator
1 parent 65878cc commit 6038a45

File tree

3 files changed

+140
-0
lines changed

3 files changed

+140
-0
lines changed

lib/osquery/atc.ts

+64
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
export type OsQueryAutoTableConstrRecord = {
2+
readonly query: string;
3+
readonly path: string;
4+
readonly columns: string[];
5+
readonly platform?: string;
6+
};
7+
8+
export type OsQueryAutoTableConstrConfig = {
9+
readonly auto_table_construction: Record<
10+
string,
11+
OsQueryAutoTableConstrRecord
12+
>;
13+
};
14+
15+
/**
16+
* Create an osQuery Automatic Table Construction (ATC) configuration file
17+
* content from a series of tables.
18+
* See: https://osquery.readthedocs.io/en/stable/deployment/configuration/#automatic-table-construction
19+
* and: https://www.kolide.com/blog/how-to-build-custom-osquery-tables-using-atc
20+
* @param tables the list of tables that should be included in the ATC configuration
21+
* @returns a function which, when called, will produce an ATC configuratin object
22+
*/
23+
export function osQueryATCConfigSupplier(
24+
tables: Generator<{
25+
readonly tableName: string;
26+
readonly columns: Array<{ readonly columnName: string }>;
27+
readonly query?: string;
28+
}>,
29+
) {
30+
const osQueryATCPartials: Record<
31+
string,
32+
Omit<OsQueryAutoTableConstrRecord, "path">
33+
> = {};
34+
35+
for (const table of tables) {
36+
const columns = table.columns.map((c) => c.columnName);
37+
const query = table.query ??
38+
`select ${columns.join(", ")} from ${table.tableName}`;
39+
osQueryATCPartials[table.tableName] = { query, columns };
40+
}
41+
42+
return (
43+
atcRecConfig: (
44+
suggested: string,
45+
atcPartial: Omit<OsQueryAutoTableConstrRecord, "path">,
46+
) => {
47+
readonly osQueryTableName: string;
48+
readonly atcRec: OsQueryAutoTableConstrRecord;
49+
},
50+
): OsQueryAutoTableConstrConfig => {
51+
const ATC: Record<string, OsQueryAutoTableConstrRecord> = {};
52+
for (const atcPartialEntry of Object.entries(osQueryATCPartials)) {
53+
const [suggestedTableName, atcPartialRec] = atcPartialEntry;
54+
const { osQueryTableName, atcRec } = atcRecConfig(
55+
suggestedTableName,
56+
atcPartialRec,
57+
);
58+
ATC[osQueryTableName] = atcRec;
59+
}
60+
return {
61+
auto_table_construction: ATC,
62+
};
63+
};
64+
}

lib/osquery/atc_test.ts

+75
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import { testingAsserts as ta } from "../../deps-test.ts";
2+
import * as mod from "./atc.ts";
3+
4+
Deno.test("osQueryATCConfigSupplier with auto-generated queries", () => {
5+
function* tables() {
6+
yield {
7+
tableName: "test_table",
8+
columns: [{ columnName: "column1" }, { columnName: "column2" }],
9+
};
10+
yield {
11+
tableName: "test_table2",
12+
columns: [{ columnName: "column2_1" }, { columnName: "column2_2" }],
13+
};
14+
}
15+
const configSupplier = mod.osQueryATCConfigSupplier(tables());
16+
17+
ta.assertEquals(
18+
configSupplier((
19+
suggested: string,
20+
atcPartial: Omit<mod.OsQueryAutoTableConstrRecord, "path">,
21+
) => ({
22+
osQueryTableName: suggested,
23+
atcRec: { ...atcPartial, path: "./sqlite-src.db" },
24+
})),
25+
{
26+
auto_table_construction: {
27+
test_table: {
28+
query: "select column1, column2 from test_table",
29+
columns: ["column1", "column2"],
30+
path: "./sqlite-src.db",
31+
},
32+
test_table2: {
33+
query: "select column2_1, column2_2 from test_table2",
34+
columns: ["column2_1", "column2_2"],
35+
path: "./sqlite-src.db",
36+
},
37+
},
38+
},
39+
);
40+
});
41+
42+
Deno.test("osQueryATCConfigSupplier with custom query", () => {
43+
function* tables() {
44+
yield {
45+
tableName: "test_table",
46+
columns: [{ columnName: "column1" }, { columnName: "column2" }],
47+
query:
48+
"select column1 as 'special1', column2 as 'special2' from test_table",
49+
};
50+
}
51+
52+
const atcRecConfig = (
53+
suggested: string,
54+
atcPartial: Omit<mod.OsQueryAutoTableConstrRecord, "path">,
55+
) => ({
56+
osQueryTableName: suggested,
57+
atcRec: { ...atcPartial, path: "./sqlite-src.db" },
58+
});
59+
60+
const configSupplier = mod.osQueryATCConfigSupplier(tables());
61+
const config: mod.OsQueryAutoTableConstrConfig = configSupplier(atcRecConfig);
62+
63+
const expected: mod.OsQueryAutoTableConstrConfig = {
64+
auto_table_construction: {
65+
test_table: {
66+
query:
67+
"select column1 as 'special1', column2 as 'special2' from test_table",
68+
columns: ["column1", "column2"],
69+
path: "./sqlite-src.db",
70+
},
71+
},
72+
};
73+
74+
ta.assertEquals(config, expected);
75+
});

lib/osquery/mod.ts

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from "./atc.ts";

0 commit comments

Comments
 (0)