Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
f4f3334
eapol_status: add macOS 802.1X/EAPOL supplicant state table
robbiet480 Jun 5, 2026
fbe964e
CI: gate darwin binary builds behind macOS host platform check
robbiet480 Jun 6, 2026
7281095
CI: gate mac binary cquery in bazel_to_builddir.sh behind macOS host …
robbiet480 Jun 6, 2026
e5898f1
CI: scope `make test` to only go_test targets, not all targets
robbiet480 Jun 6, 2026
d7bbdfe
CI: exclude eapolstatus from go-test-coverage on Linux
robbiet480 Jun 6, 2026
e2ca4d1
eapol_status: add Windows backend using wlanapi.dll
robbiet480 Jun 6, 2026
6628f2c
docs: update README eapol_status entry for Windows support
robbiet480 Jun 6, 2026
7230e49
eapol_status: add Windows unit tests and mock tests
robbiet480 Jun 6, 2026
463bf1c
Merge branch 'main' into add-eapol-status
robbiet480 Jun 6, 2026
b5e89b2
coverage: narrow eapolstatus exclusion to platform-specific files only
robbiet480 Jun 6, 2026
7fd7b48
CI: broaden make test query and harden bazel_to_builddir.sh
robbiet480 Jun 6, 2026
34aa32c
eapol_status: add macOS mock-backend tests
robbiet480 Jun 6, 2026
e0612d9
Rename eapol_status table to dot1x
robbiet480 Jun 6, 2026
c11ba8e
Address Copilot review: neutral backend-unavailable sentinel, robust …
robbiet480 Jun 6, 2026
cf97ff7
dot1x: strip all whitespace from TrustedRootCA hex, not just spaces
robbiet480 Jun 7, 2026
7189887
dot1x: reset SupplicantState for non-802.1X Wi-Fi networks
robbiet480 Jun 7, 2026
59f2378
dot1x: use syscall.Errno for Win32 errors, windows.UTF16PtrToString, …
robbiet480 Jun 7, 2026
1de369b
dot1x: pass opcodeValueType out-param to WlanQueryInterface, capture …
robbiet480 Jun 7, 2026
2971348
dot1x: skip live tests on ErrBackendUnavailable, clarify cgo comments
robbiet480 Jun 7, 2026
07ff06f
Address Copilot review: cover Linux backend, distinguish cquery failures
robbiet480 Jun 10, 2026
811d82c
dot1x(windows): reuse WLAN handle + parse profile XML via encoding/xml
robbiet480 Jun 10, 2026
207f740
dot1x(windows): skip on query failure, gate live tests, rebind loop var
robbiet480 Jun 10, 2026
ed45470
Address Copilot review: portable mktemp, dup interface keys, bounded …
robbiet480 Jun 10, 2026
5023bad
Address Copilot review: cp -- , validate TrustedRootCA hex, guard for…
robbiet480 Jun 10, 2026
c3afda4
Address Copilot review: portable cp option-guard, well-formed namespa…
robbiet480 Jun 10, 2026
68c6478
Address Copilot review: empty-vs-nil defaults, dlerror detail, robust…
robbiet480 Jun 10, 2026
fcb3142
dot1x(windows): harden syscall error paths; move WLAN XML parsing to …
robbiet480 Jun 10, 2026
cfe7a1d
dot1x: error on NULL status (darwin), wrap underlying enum error (win…
robbiet480 Jun 10, 2026
7e1e2a2
dot1x tests: use context.Background(); BUILD: tag mac cgo binaries ma…
robbiet480 Jun 10, 2026
7e63e2d
dot1x: accurate Dot1XBackend doc; de-dup constraintFor test helper
robbiet480 Jun 10, 2026
d70376d
dot1x(windows): system DLL load, separate trusted-root-CA column, sin…
robbiet480 Jun 10, 2026
6891d45
dot1x(windows): report specific init failure; Makefile: robust uname …
robbiet480 Jun 10, 2026
3dfd943
dot1x: make TestInterfacesToQuery deterministic via interfaceLister stub
robbiet480 Jun 10, 2026
da811c5
dot1x: fix double-enum in interfacesToQuery; parse WLAN profile in on…
robbiet480 Jun 10, 2026
e968c8e
dot1x/build: robust EapMethod scan, right-sized hex buf, trap temp-fi…
robbiet480 Jun 10, 2026
c47befc
bazel_to_builddir.sh: scope temp-file cleanup to a subshell EXIT trap
robbiet480 Jun 10, 2026
f9087b9
bazel_to_builddir.sh: tolerate missing uname; BUILD: fix stale gating…
robbiet480 Jun 10, 2026
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
4 changes: 4 additions & 0 deletions .testcoverage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@ exclude:
- tables/puppet/puppet_logs.go
- tables/puppet/puppet_state.go
- tables/puppet/yaml.go
# darwin/windows backends are build-tagged out of the Linux coverage run;
# the active !darwin && !windows path (dot1x_other.go) stays covered.
- tables/dot1x/dot1x_darwin.go
- tables/dot1x/dot1x_windows.go
# - \.pb\.go$ # excludes all protobuf generated files
# - ^pkg/bar # exclude package `pkg/bar`

Expand Down
22 changes: 22 additions & 0 deletions BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ go_library(
"//tables/authdb",
"//tables/chromeuserprofiles",
"//tables/crowdstrike_falcon",
"//tables/dot1x",
"//tables/energyimpact",
"//tables/fileline",
"//tables/filevaultusers",
Expand All @@ -62,19 +63,40 @@ go_library(
],
)

# The dot1x table (and any future cgo tables) need cgo + Apple CC
# toolchain on darwin. These are darwin-only binaries (goos = "darwin"),
# so cgo=True does not affect Linux/Windows builds. The apple_support
# toolchain in WORKSPACE satisfies the CC requirement on macOS.
#
# These targets require a darwin C++ toolchain (only available on macOS
# hosts), so they are tagged "manual" to keep them out of `//...` / `:all`
# wildcard expansion. That way `bazel build //...` / `bazel test //...` on a
# Linux/Windows host won't try to analyze them and fail; they still build when
# named explicitly (the Makefile and tools/bazel_to_builddir.sh do so, gated on
# the host OS via `ifeq ($(UNAME_S),Darwin)` and `[ "$host_os" = "Darwin" ]`).
#
# target_compatible_with is not used here: the goos="darwin" platform
# transition makes the resolved target platform macOS, so a macos constraint
# would always be satisfied and would never skip the target on a Linux host.
go_binary(
name = "osquery-extension-mac-arm",
cgo = True,
embed = [":osquery-extension_lib"],
goarch = "arm64",
goos = "darwin",
pure = "off",
tags = ["manual"],
visibility = ["//visibility:public"],
)
Comment thread
robbiet480 marked this conversation as resolved.

go_binary(
name = "osquery-extension-mac-amd",
cgo = True,
embed = [":osquery-extension_lib"],
goarch = "amd64",
goos = "darwin",
pure = "off",
tags = ["manual"],
visibility = ["//visibility:public"],
)
Comment thread
robbiet480 marked this conversation as resolved.

Expand Down
20 changes: 19 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ current_dir = $(shell pwd)

SHELL = /bin/sh

# Computed once, with a safe empty default if `uname` is unavailable (some
# Windows shells / CI images). Used to gate the darwin-only binary builds.
UNAME_S := $(shell uname -s 2>/dev/null)

BAZEL_OUTPUT_PATH := $(shell bazel info output_path)

APP_NAME = macadmins_extension
Expand Down Expand Up @@ -50,11 +54,25 @@ update-repos:
bazel run //:gazelle-update-repos -- -from_file=go.mod

test:
bazel test --test_output=errors //...
# Query only test targets (any *_test kind) rather than `bazel test //...`,
# which would also analyze the darwin go_binary targets (pure="off",
# cgo=True in root BUILD.bazel) and fail on Linux CI where no darwin
# C++ toolchain exists.
# Matching all *_test kinds (not just go_test) keeps non-Go tests
# (sh_test, py_test, etc.) in scope if any are added later. The target
# list is passed via --target_pattern_file rather than expanded onto the
# command line, so a growing test set can't hit argv length limits.
@set -e; \
targets="$$(mktemp "$${TMPDIR:-/tmp}/dot1x-test-targets.XXXXXX")"; \
trap 'rm -f "$$targets"' EXIT; \
bazel query 'kind(".*_test", //...)' > "$$targets"; \
bazel test --test_output=errors --target_pattern_file="$$targets"

build: .pre-build
ifeq ($(UNAME_S),Darwin)
bazel build --verbose_failures //:osquery-extension-mac-amd
bazel build --verbose_failures //:osquery-extension-mac-arm
endif
bazel build --verbose_failures //:osquery-extension-linux-amd
bazel build --verbose_failures //:osquery-extension-linux-arm
bazel build --verbose_failures //:osquery-extension-win-amd
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ For production deployment, you should refer to the [osquery documentation](https
| `alt_system_info` | Alternative system_info table | macOS | This table is an alternative to the built-in system_info table in osquery, which triggers an `Allow "osquery" to find devices on local networks?` prompt on macOS 15.0. On versions other than 15.0, this table falls back to the built-in system_info table. Note: this table returns an empty `cpu_subtype` field. See [#58](https://github.com/macadmins/osquery-extension/pull/58) for more details. |
| `authdb` | macOS Authorization database | macOS | Use the constraint `name` to specify a right name to query, otherwise all rights will be returned. |
| `crowdstrike_falcon` | Provides basic information about the currently installed Falcon sensor. | Linux / macOS | Requires Falcon to be installed. |
| `dot1x` | Per-interface 802.1X / EAPOL supplicant state and authentication status | macOS / Windows | Exposes state, supplicant state, EAP method, authenticator MAC, auth mode, and unique identifier. macOS additionally provides TLS certificate chain, trust status, cipher, protocol version, and timestamp via EAP8021X.framework. Windows queries wlanapi.dll and parses WLAN profile XML. Use `WHERE interface = 'en0'` (macOS) or `WHERE interface = 'Adapter Name'` (Windows). No root required. |
| `energy_impact` | Process energy impact data from `powermetrics` | macOS | Use the `interval` constraint to specify sampling duration in milliseconds (default: 1000). |
| `file_lines` | Read an arbitrary file | Linux / macOS / Windows | Use the constraint `path` and `last` to specify the file to read lines from |
| `filevault_users` | Information on the users able to unlock the current boot volume when encrypted with Filevault | macOS | |
Expand Down
52 changes: 52 additions & 0 deletions WORKSPACE
Original file line number Diff line number Diff line change
@@ -1,5 +1,57 @@
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")

# --- Apple C/C++ toolchain for cgo on macOS -------------------------------
# The dot1x table calls EAP8021X.framework (CoreFoundation) via cgo,
# so the macOS go_binary targets are built with cgo enabled (see
# root BUILD.bazel go_binary targets: cgo = True, pure = "off"). That requires an Apple CC toolchain,
# which apple_support provides. This block must precede rules_go so its CC
# toolchain is registered for the Apple cc actions cgo uses.
Comment thread
robbiet480 marked this conversation as resolved.
#
# NOTE: In WORKSPACE mode (no bzlmod), these http_archive + load calls are
# unconditional — they are fetched on every platform even though only darwin
# builds consume them. The alternative (platform-gating with a load/condition)
# adds complexity without meaningful savings, since Bazel lazy-fetches archives
# and the WORKSPACE is already ~200 lines of unconditional deps. On bzlmod the
# toolchain is registered via MODULE.bazel, not this file.
#
# Pinned to 1.24.5: the last apple_support release that supports WORKSPACE mode
# (2.0.0 dropped it), and >= 1.19.0 so wrapped_clang is built WITHOUT the
# -Wl,-no_uuid workaround that recent macOS / dyld versions reject with
# "missing LC_UUID load command" (apple_support PR #373; bazelbuild/bazel#27026).
http_archive(
name = "build_bazel_apple_support",
sha256 = "1ae6fcf983cff3edab717636f91ad0efff2e5ba75607fdddddfd6ad0dbdfaf10",
url = "https://github.com/bazelbuild/apple_support/releases/download/1.24.5/apple_support.1.24.5.tar.gz",
)
Comment thread
robbiet480 marked this conversation as resolved.

load(
"@build_bazel_apple_support//lib:repositories.bzl",
"apple_support_dependencies",
)

apple_support_dependencies()

# bazel_features (pulled in by apple_support_dependencies) deps.
load("@bazel_features//:deps.bzl", "bazel_features_deps")

bazel_features_deps()

# rules_cc (pulled in by apple_support_dependencies) deps + toolchains, plus the
# WORKSPACE-mode compatibility proxy repo (cc_compatibility_proxy) that the
# rules_cc 0.2.x APIs resolve through. In bzlmod this repo is created by a module
# extension; in WORKSPACE mode it must be created explicitly here.
load("@rules_cc//cc:repositories.bzl", "rules_cc_dependencies", "rules_cc_toolchains")

rules_cc_dependencies()

rules_cc_toolchains()
Comment thread
robbiet480 marked this conversation as resolved.

load("@rules_cc//cc:extensions.bzl", "compatibility_proxy_repo")

compatibility_proxy_repo()

# --------------------------------------------------------------------------

http_archive(
name = "io_bazel_rules_go",
sha256 = "68af54cb97fbdee5e5e8fe8d210d15a518f9d62abfd71620c3eaff3b26a5ff86",
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ require (
github.com/pkg/errors v0.9.1
github.com/stretchr/testify v1.11.1
golang.org/x/sync v0.17.0
golang.org/x/sys v0.36.0
gopkg.in/yaml.v3 v3.0.1
)

Expand All @@ -24,5 +25,4 @@ require (
go.opentelemetry.io/otel v1.41.0 // indirect
go.opentelemetry.io/otel/metric v1.41.0 // indirect
go.opentelemetry.io/otel/trace v1.41.0 // indirect
golang.org/x/sys v0.36.0 // indirect
)
10 changes: 7 additions & 3 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"github.com/macadmins/osquery-extension/tables/alt_system_info"
"github.com/macadmins/osquery-extension/tables/chromeuserprofiles"
"github.com/macadmins/osquery-extension/tables/crowdstrike_falcon"
"github.com/macadmins/osquery-extension/tables/dot1x"
"github.com/macadmins/osquery-extension/tables/energyimpact"
"github.com/macadmins/osquery-extension/tables/fileline"
"github.com/macadmins/osquery-extension/tables/filevaultusers"
Expand Down Expand Up @@ -77,9 +78,12 @@ func main() {
}

// Platform specific tables
// if runtime.GOOS == "windows" {
// If there were windows only tables, they would go here
// }
if runtime.GOOS == "darwin" || runtime.GOOS == "windows" {
dot1xPlugins := []osquery.OsqueryPlugin{
table.NewPlugin("dot1x", dot1x.Dot1XStatusColumns(), dot1x.Dot1XStatusGenerate),
}
plugins = append(plugins, dot1xPlugins...)
}

if runtime.GOOS == "linux" || runtime.GOOS == "darwin" {
linuxPlugins := []osquery.OsqueryPlugin{
Expand Down
55 changes: 55 additions & 0 deletions tables/dot1x/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")

go_library(
name = "dot1x",
srcs = [
"dot1x.go",
"dot1x_darwin.go",
"dot1x_other.go",
"dot1x_wlanprofile.go",
"dot1x_windows.go",
],
# cgo is only needed on darwin: dot1x_darwin.go (//go:build darwin) calls
# EAP8021X.framework (via dlopen/dlsym) + CoreFoundation via cgo.
# The darwin build constraint does NOT include ios, so only darwin gets
# the cgo + framework links; linux/windows stay pure Go.
cgo = select({
"@io_bazel_rules_go//go/platform:darwin": True,
"//conditions:default": False,
}),
clinkopts = select({
"@io_bazel_rules_go//go/platform:darwin": [
"-framework",
"CoreFoundation",
],
"//conditions:default": [],
}),
Comment thread
robbiet480 marked this conversation as resolved.
Comment thread
robbiet480 marked this conversation as resolved.
Comment thread
robbiet480 marked this conversation as resolved.
importpath = "github.com/macadmins/osquery-extension/tables/dot1x",
visibility = ["//visibility:public"],
deps = [
"@com_github_osquery_osquery_go//plugin/table",
] + select({
"@io_bazel_rules_go//go/platform:windows": [
"@org_golang_x_sys//windows",
],
"//conditions:default": [],
}),
)

go_test(
name = "dot1x_test",
srcs = [
"dot1x_test.go",
"dot1x_darwin_test.go",
"dot1x_helpers_test.go",
"dot1x_other_test.go",
"dot1x_wlanprofile_test.go",
"dot1x_windows_test.go",
],
embed = [":dot1x"],
deps = [
"@com_github_osquery_osquery_go//plugin/table",
"@com_github_stretchr_testify//assert",
"@com_github_stretchr_testify//require",
],
)
Comment thread
robbiet480 marked this conversation as resolved.
Loading