feat: add template version ID to re-emitted boundary logs (#21636)

Adds template_version_id to re-emitted boundary audit logs to allow
filtering and analysis by specific template versions iin addition to the
existing template_id field. Since boundary policies are defined in the
template, the template version is critical to figuring out which policy
was responsible for boundaries decision in a workspace.

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Zach
2026-01-22 15:06:02 -07:00
committed by GitHub
co-authored by Claude Opus 4.5
parent e1282b6904
commit 6c49938fca
5 changed files with 38 additions and 28 deletions
+7 -3
View File
@@ -79,10 +79,12 @@ func TestBoundaryLogs_EndToEnd(t *testing.T) {
logger := slog.Make(sink)
workspaceID := uuid.New()
templateID := uuid.New()
templateVersionID := uuid.New()
reporter := &agentapi.BoundaryLogsAPI{
Log: logger,
WorkspaceID: workspaceID,
TemplateID: templateID,
Log: logger,
WorkspaceID: workspaceID,
TemplateID: templateID,
TemplateVersionID: templateVersionID,
}
ctx, cancel := context.WithCancel(context.Background())
@@ -126,6 +128,7 @@ func TestBoundaryLogs_EndToEnd(t *testing.T) {
require.Equal(t, "allow", getField(entry.Fields, "decision"))
require.Equal(t, workspaceID.String(), getField(entry.Fields, "workspace_id"))
require.Equal(t, templateID.String(), getField(entry.Fields, "template_id"))
require.Equal(t, templateVersionID.String(), getField(entry.Fields, "template_version_id"))
require.Equal(t, "GET", getField(entry.Fields, "http_method"))
require.Equal(t, "https://example.com/allowed", getField(entry.Fields, "http_url"))
require.Equal(t, "*.example.com", getField(entry.Fields, "matched_rule"))
@@ -159,6 +162,7 @@ func TestBoundaryLogs_EndToEnd(t *testing.T) {
require.Equal(t, "deny", getField(entry.Fields, "decision"))
require.Equal(t, workspaceID.String(), getField(entry.Fields, "workspace_id"))
require.Equal(t, templateID.String(), getField(entry.Fields, "template_id"))
require.Equal(t, templateVersionID.String(), getField(entry.Fields, "template_version_id"))
require.Equal(t, "POST", getField(entry.Fields, "http_method"))
require.Equal(t, "https://blocked.com/denied", getField(entry.Fields, "http_url"))
require.Equal(t, nil, getField(entry.Fields, "matched_rule"))
+9 -7
View File
@@ -65,10 +65,11 @@ type API struct {
var _ agentproto.DRPCAgentServer = &API{}
type Options struct {
AgentID uuid.UUID
OwnerID uuid.UUID
WorkspaceID uuid.UUID
OrganizationID uuid.UUID
AgentID uuid.UUID
OwnerID uuid.UUID
WorkspaceID uuid.UUID
OrganizationID uuid.UUID
TemplateVersionID uuid.UUID
AuthenticatedCtx context.Context
Log slog.Logger
@@ -221,9 +222,10 @@ func New(opts Options, workspace database.Workspace) *API {
}
api.BoundaryLogsAPI = &BoundaryLogsAPI{
Log: opts.Log,
WorkspaceID: opts.WorkspaceID,
TemplateID: workspace.TemplateID,
Log: opts.Log,
WorkspaceID: opts.WorkspaceID,
TemplateID: workspace.TemplateID,
TemplateVersionID: opts.TemplateVersionID,
}
// Start background cache refresh loop to handle workspace changes
+5 -3
View File
@@ -11,9 +11,10 @@ import (
)
type BoundaryLogsAPI struct {
Log slog.Logger
WorkspaceID uuid.UUID
TemplateID uuid.UUID
Log slog.Logger
WorkspaceID uuid.UUID
TemplateID uuid.UUID
TemplateVersionID uuid.UUID
}
func (a *BoundaryLogsAPI) ReportBoundaryLogs(ctx context.Context, req *agentproto.ReportBoundaryLogsRequest) (*agentproto.ReportBoundaryLogsResponse, error) {
@@ -35,6 +36,7 @@ func (a *BoundaryLogsAPI) ReportBoundaryLogs(ctx context.Context, req *agentprot
slog.F("decision", allowBoolToString(l.Allowed)),
slog.F("workspace_id", a.WorkspaceID.String()),
slog.F("template_id", a.TemplateID.String()),
slog.F("template_version_id", a.TemplateVersionID.String()),
slog.F("http_method", r.HttpRequest.Method),
slog.F("http_url", r.HttpRequest.Url),
slog.F("event_time", logTime.Format(time.RFC3339Nano)),
+5 -4
View File
@@ -127,10 +127,11 @@ func (api *API) workspaceAgentRPC(rw http.ResponseWriter, r *http.Request) {
defer monitor.close()
agentAPI := agentapi.New(agentapi.Options{
AgentID: workspaceAgent.ID,
OwnerID: workspace.OwnerID,
WorkspaceID: workspace.ID,
OrganizationID: workspace.OrganizationID,
AgentID: workspaceAgent.ID,
OwnerID: workspace.OwnerID,
WorkspaceID: workspace.ID,
OrganizationID: workspace.OrganizationID,
TemplateVersionID: build.TemplateVersionID,
AuthenticatedCtx: ctx,
Log: logger,
+12 -11
View File
@@ -127,17 +127,18 @@ commands run with `boundary-run`.
Each boundary audit log entry includes:
| Field | Description |
|------------------|-----------------------------------------------------------------------------------------|
| `decision` | Whether the request was allowed (`allow`) or blocked (`deny`) |
| `workspace_id` | The UUID of the workspace where the request originated |
| `workspace_name` | The name of the workspace where the request originated |
| `owner` | The owner of the workspace where the request originated |
| `template_id` | The UUID of the template that the workspace was created from |
| `http_method` | The HTTP method used (GET, POST, PUT, DELETE, etc.) |
| `http_url` | The fully qualified URL that was requested |
| `event_time` | Timestamp when boundary processed the request (RFC3339 format) |
| `matched_rule` | The allowlist rule that permitted the request (only present when `decision` is `allow`) |
| Field | Description |
|-----------------------|-----------------------------------------------------------------------------------------|
| `decision` | Whether the request was allowed (`allow`) or blocked (`deny`) |
| `workspace_id` | The UUID of the workspace where the request originated |
| `workspace_name` | The name of the workspace where the request originated |
| `owner` | The owner of the workspace where the request originated |
| `template_id` | The UUID of the template that the workspace was created from |
| `template_version_id` | The UUID of the template version used by the current workspace build |
| `http_method` | The HTTP method used (GET, POST, PUT, DELETE, etc.) |
| `http_url` | The fully qualified URL that was requested |
| `event_time` | Timestamp when boundary processed the request (RFC3339 format) |
| `matched_rule` | The allowlist rule that permitted the request (only present when `decision` is `allow`) |
### Viewing Audit Logs