mirror of
https://github.com/SigNoz/signoz.git
synced 2026-04-02 18:30:25 +01:00
* feat(audit): handler-level AuditDef and response-capturing wrapper Add declarative audit instrumentation to the handler package. Routes declare an AuditDef alongside OpenAPIDef; the handler automatically captures the response status/body and emits an audit event via auditor.Audit() after every request. * refactor(audit): move audit logic to middleware, merge with logging Move audit event emission from handler to middleware layer. The handler package keeps only the AuditDef struct and AuditDefProvider interface. The logging middleware now handles both request logging and audit event emission using a single response capture, avoiding double-wrapping. Rename badResponseLoggingWriter to responseCapture with body capture on all 4xx/5xx responses (previously only 400 and 5xx). * refactor(audit): rename Logging middleware to Audit, merge into single file Delete logging.go and merge its contents into audit.go. Rename Logging/NewLogging to Audit/NewAudit. The response.go file with responseCapture is unchanged. * refactor(audit): extract NewAuditEventFromHTTPRequest factory into audittypes Move event construction to audittypes.NewAuditEventFromHTTPRequest with an AuditEventContext struct for caller-provided fields. The audittypes layer reads only transport fields from *http.Request and has no mux, authtypes, or context dependencies. The middleware pre-extracts principal, trace, error, and route fields before calling the factory. * refactor(audit): move error parsing to render.ErrorFromBody and render.ErrorTypeFromStatusCode Add render.ErrorFromBody to extract errors.JSON from a JSON-encoded ErrorResponse body, and render.ErrorTypeFromStatusCode to reverse-map HTTP status codes to error type strings. The middleware now uses these instead of local duplicates. * refactor(audit): move AuditDef onto Handler interface, consolidate files Move AuditDef() onto the Handler interface directly. All Handler implementations now carry it: handler returns the configured def, healthOpenAPIHandler returns nil. Delete the separate AuditDefProvider interface and audit.go handler file. Move excludedRoutes check before audit emission so excluded routes skip both logging and audit. * feat(audit): add option.go with AuditDef, Option, and WithAuditDef * refactor(audit): decompose AuditEvent into attribute sub-structs, add tests Decompose flat AuditEvent fields into typed sub-structs (AuditEventAuditAttributes, PrincipalAttributes, ResourceAttributes, ErrorAttributes, TransportAttributes) each with a constructor and Put(pcommon.Map) method. Simplify NewAuditEventFromHTTPRequest to accept authtypes.Claims and oteltrace IDs directly. Simplify the middleware caller accordingly. Add unit tests for the factory, outcome boundary, and principal type derivation. * refactor(audit): shorten attribute struct names, drop error message Rename AuditEventAuditAttributes to AuditAttributes, AuditEventPrincipalAttributes to PrincipalAttributes, and likewise for Resource, Error, and Transport. The package prefix already disambiguates. Remove ErrorMessage from ErrorAttributes to avoid leaking sensitive or PII data into audit logs. Error type and code are sufficient for filtering; investigators can correlate via trace ID. * fix(audit): update auditorserver test and otlphttp provider for new struct layout Update newTestEvent in server_test.go to use nested AuditAttributes and ResourceAttributes. Update otlphttpauditor provider to access PrincipalOrgID via PrincipalAttributes. Fix godot lint on attribute section comments. * fix(audit): fix gjson path in ErrorCodeFromBody, add tests Fix ErrorCodeFromBody gjson path from "errors.code" to "error.code" to match the ErrorResponse JSON structure. Add unit tests for valid error response and invalid JSON cases. * fix(audit): add CodeUnset, use ErrorCodeFromBody in middleware Add errors.CodeUnset for responses missing an error code. Update the audit middleware to use render.ErrorCodeFromBody instead of the removed render.ErrorFromBody. * test(audit): add unit tests for responseCapture Test the four meaningful behaviors: success responses don't capture body, error responses capture body, large error bodies truncate at 4096 bytes, and 204 No Content suppresses writes entirely. * fix(audit): check rw.Write return values in response_test.go * style(audit): rename want prefix to expected in test fields * refactor(audit): replace Sprintf with strings.Builder in newBody Handle edge cases where principal email, ID, or resource ID may be empty. The builder conditionally includes each segment, avoiding empty parentheses or leading spaces in the audit body. Add test cases covering all meaningful combinations: success/failure with full/partial/empty principal, resource ID, and error details. * chore: fix formatting * chore: remove json tags * fix: rebase with main
55 lines
1.4 KiB
Go
55 lines
1.4 KiB
Go
package errors
|
|
|
|
import (
|
|
"regexp"
|
|
)
|
|
|
|
var (
|
|
CodeInvalidInput Code = Code{"invalid_input"}
|
|
CodeInternal = Code{"internal"}
|
|
CodeUnsupported = Code{"unsupported"}
|
|
CodeNotFound = Code{"not_found"}
|
|
CodeMethodNotAllowed = Code{"method_not_allowed"}
|
|
CodeAlreadyExists = Code{"already_exists"}
|
|
CodeUnauthenticated = Code{"unauthenticated"}
|
|
CodeForbidden = Code{"forbidden"}
|
|
CodeCanceled = Code{"canceled"}
|
|
CodeTimeout = Code{"timeout"}
|
|
CodeUnknown = Code{"unknown"}
|
|
CodeFatal = Code{"fatal"}
|
|
CodeLicenseUnavailable = Code{"license_unavailable"}
|
|
)
|
|
|
|
var (
|
|
// Used when reverse engineering an error from a response that doesn't have a code.
|
|
// This should never be used in the codebase, and if it is, it's a bug that should be fixed by using proper error handling and including error codes in responses.
|
|
CodeUnset = Code{"unset"}
|
|
)
|
|
|
|
var (
|
|
codeRegex = regexp.MustCompile(`^[a-z_]+$`)
|
|
)
|
|
|
|
type Code struct{ s string }
|
|
|
|
func NewCode(s string) (Code, error) {
|
|
if !codeRegex.MatchString(s) {
|
|
return Code{}, NewInvalidInputf(CodeInvalidInput, "invalid code: %v", s)
|
|
}
|
|
|
|
return Code{s: s}, nil
|
|
}
|
|
|
|
func MustNewCode(s string) Code {
|
|
code, err := NewCode(s)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
return code
|
|
}
|
|
|
|
func (c Code) String() string {
|
|
return c.s
|
|
}
|