-
Notifications
You must be signed in to change notification settings - Fork 465
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add access logging support #10506
Add access logging support #10506
Conversation
any chance we can do something like https://github.com/solo-io/gloo/blob/main/projects/gloo/pkg/plugins/als/converter.go#L56-L64 to validate the contents of the access logging itself? |
I'm hesitant to include those initially for a couple of reasons:
Most of the validation should be happening as part of the kubebuilder validation lines. I'm not sure we want to validate on the content of access logs, just the configuration. |
7bf1610
to
9827e53
Compare
8714c83
to
d521feb
Compare
install/helm/kgateway/crds/gateway.kgateway.dev_httplistenerpolicies.yaml
Show resolved
Hide resolved
projects/gateway2/extensions2/plugins/listenerpolicy/listener_plugin.go
Outdated
Show resolved
Hide resolved
723c703
to
8a7ba90
Compare
8204da6
to
29699ff
Compare
"github.com/kgateway-dev/kgateway/v2/internal/kgateway/utils/krtutil" | ||
) | ||
|
||
type httpListenerOptsPlugin struct { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is this an accurate name? the plugin suffix is throwing me off, seems like this is closer to httpListenerOptsPolicy
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's matching what we do in the listener plugin:
kgateway/internal/kgateway/extensions2/plugins/listenerpolicy/listener_policy_plugin.go
Line 23 in d68bd4d
type listenerOptsPlugin struct { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes I think we should rename, wdyt @yuval-k ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great!
left some small comments
internal/kgateway/extensions2/plugins/httplistenerpolicy/httplistener_plugin.go
Show resolved
Hide resolved
internal/kgateway/extensions2/plugins/httplistenerpolicy/access_logging_converter.go
Outdated
Show resolved
Hide resolved
internal/kgateway/extensions2/plugins/httplistenerpolicy/access_logging_converter.go
Outdated
Show resolved
Hide resolved
internal/kgateway/extensions2/plugins/httplistenerpolicy/access_logging_converter.go
Outdated
Show resolved
Hide resolved
internal/kgateway/extensions2/plugins/httplistenerpolicy/access_logging_converter.go
Outdated
Show resolved
Hide resolved
internal/kgateway/extensions2/plugins/httplistenerpolicy/access_logging_converter.go
Show resolved
Hide resolved
if !ok { | ||
return false | ||
} | ||
return d.spec == d2.spec | ||
} | ||
|
||
type routeOptsPluginGwPass struct { | ||
type routeOptsPolicyGwPass struct { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this struct should still be named routeOptsPluginGwPass
.
My point was just the initial struct, which is now routeOptsPolicy
, is not specific to an instance of a plugin, i.e. a plugin doesn't have a created time or a policy Spec, but the policy does.
However the routeOptsPluginGwPass
is accurate -- it represents a translation pass of a given plugin, in this case the route options plugin
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🚀
Description
Adds support for HTTP access logging: #10507
API changes
Introduces access logging support on the HCM for kgateway. This is based on the Gloo access logging APIs:
Before Gloo would configure both the listener, tcp and HttpConnectionManager (HCM) access logging in one plugin.
The new kgateway configuration is on the HTTPListenerPolicy which only configures the access logging on the HCM to make it clear what specific access logging is being configured. Listener and TCP access logging can be supported in the future, but will live on a separate resource.
How does it work?
The
HTTPListenerPolicy
selects a Gateway via a targetRef:The user must configure where the access logs are sent by either setting:
Optionally, the user can also configure the
filter
field to filter access logs based on some criteria. We support a variety of envoy's filtering config:- runtime (Filter that uses a runtime feature key to check if the log should be written)Code changes
http_listener_policy_types.go
httplistener_plugin.go
ApplyHCM
plugins are run incomputeNetworkFilters
to apply the HCM config before the HCM typedConfig is serializedCI changes
NONE
Docs changes
Docs changes will need to be added in a follow up. Should be based on scenarios covered in https://docs.solo.io/gateway/latest/security/access-logging/ and include CEL.
Context
A common use case for the API gateway is to produce an access log (sometimes referred to as an audit log). The entries of an access log represent traffic through the proxy. The access log entries can be customized to include data from the request, the routing destination, and the response.
Access logs in Envoy can be written to a file, the stdout stream of the gateway proxy container, or exported to a gRPC server for custom handling.
Envoy also supports configuring the format of the access logs. See: https://www.envoyproxy.io/docs/envoy/v1.10.0/configuration/access_log#format-dictionaries In kgateway, istead of outputting strings, the file sink access logger can be configured to log structured json instead. When configuring structured json, the Envoy fields are referenced in the same way as in the string format, however a mapping to json keys is defined:
More than one access log can be configured for a single Envoy listener. For example, the following configuration includes four different access log outputs: a default string-formatted access log to standard out on the Envoy container, a default string-formatted access log to a file in the Envoy container, a json-formatted access log to a different file in the Envoy container, and an access log to standard out a separate
access_log_cluster
container.In addition to the output, users can apply different filters on their access logs to reduce and optimize the number of logs that are stored. kgateway supports filtering access logs based on request headers, HTTP response codes, gRPC status codes, request duration, health check status, tracing parameters, response flags, and custom CEL expressions.
HTTP response header filter example:
CEL filter example:
It is also possible to combine multiple filters, and perform AND and OR operations on filter results.
Interesting decisions
The HTTP header match API for the access logging filter is based on the K8s Gateway API. This is the same header filtering supported on the HTTPRoutes for reusability.
Some of the kubebuilder validation oneOf logic was too complex to be evaulated:
To keep the oneOf behavior, the plugin accesslog conversion does the validation instead.
Testing steps
Added new tests for:
Manually testing steps:
I used httpbin in the default namespace along with this config to setup basic access logging with a file sink:
Port-forward the gateway:
Send a request:
Look at the access logs in the gateway, you should see the json access log:
Checklist: