Event Forwarder
Event Forwarder can be used to store events related to DNS filtering in Elasticsearch/Opensearch. These can then be retrieved/searched by the Report API.
An Event Forwarder is capable of processing protobuf messages from dstoredist for 2 processing pipelines:
- Individual messages associated with a filtering event for a subscriber are processed and stored in Elasticsearch/Opensearch
- Sampled messages associated with any event for a subscriber are processed and stored in Elasticsearch/Opensearch
For each of the above usecases, a dstoredist destination type is available to make configuration straightforward. These destination types are as follows:
type: eventforwarderfor the individual messages associated to filtering eventstype: eventforwarderqcfor the sampled data,qcbeing an abbreviation ofQuery Count
Configuration Reference
Instance Sets
Instances of Event Forwarder can be defined under the root node eventForwarders. Each instance set should be a key-value pair, with:
- key: Name of the instance set
- value: Dictionary holding the configuration of the instance set
In a minimal configuration you will need to have at least the elasticsearch backend configured and filter_tags:
eventForwarders:
myevforwarder:
elasticsearch:
addr: https://elasticsearch.example.local:9200/
index: "some-index-name"
filter_tags:
blocklist:
- "rule:user-blocklist"
Above configuration will ensure Event Forwarder has a backend to store the output and it has 1 tag defined by which it will match subscriber traffic to determine if this was a filtering event.
Parameters which can be used to configure Event Forwarder are shown in the below table.
| Parameter | Type | Default | Description |
|---|---|---|---|
affinity |
k8s:Affinity |
pod affinity (Kubernetes docs: Affinity and anti-affinity). If unset, a default anti-affinity is applied using antiAffinityPreset to spread pods across nodes |
|
agentLogLevel |
string |
"info" |
Verbosity of logging for the agent container. Available options: "debug" "info" "warn" "error" |
agentLogFormat |
string |
"text" |
Format of logging for the agent container. Available options: "text" "json" |
agentResources |
k8s:Resources |
|
Resources allocated to the agent container if resourceDefaults (global) is true |
antiAffinityPreset |
string |
"preferred" |
pod anti affinity preset. Available options: "preferred" "required" |
containerSecurityContext |
k8s:SecurityContext |
|
SecurityContext applied to each container |
elasticsearch |
Elasticsearch | {} |
Configuration of Elasticsearch / Opensearch backend |
filter_count |
Filter Count | Configuration of Event Forwarder's storing of global counts | |
filter_tags |
Filter Tags | {} |
Filter tags to be applied to inbound event to determine if they are related to filtering events |
hostNetwork |
boolean |
false |
Use host networking for pods |
logLevel |
string |
"info" |
Level of logging. Available options: "debug" "info" "warn" "error" |
max_concurrent |
integer |
(calculated: # cpu cores) |
Number of concurrent senders |
nodeSelector |
k8s:NodeSelector |
{} |
Kubernetes pod nodeSelector |
podAnnotations |
k8s:Annotations |
{} |
Annotations to be added to each pod |
podDisruptionBudget |
k8s:PodDisruptionBudgetSpec |
{} |
Spec of PodDisruptionBudget to be applied to deployment |
podLabels |
k8s:Labels |
{} |
Labels to be added to each pod |
podPreemptionPolicy |
string |
Policy for preempting pods with lower priority | |
podPriorityClassName |
string |
Name of PriorityClass to be assigned to each pod | |
podRuntimeClassName |
string |
Name of RuntimeClass to be assigned to each pod | |
podSchedulerName |
string |
Name of scheduler responsible for dispatching pods | |
podSecurityContext |
k8s:PodSecurityContext |
|
SecurityContext applied to each pod |
podTerminationGracePeriodSeconds |
integer |
Duration after which terminating pods are stopped immediately if they do not exit gracefully | |
qcConfig |
Query Count | Configuration for the Query Count feature | |
qcService |
Service | |
Service configuration for the Query Count endpoint |
readyInterval |
integer |
5 |
How often readiness of the Event Forwarder should be calculated in seconds |
replicas |
integer |
2 |
Default number of replicas in a Deployment |
resources |
k8s:Resources |
|
Resources allocated to the event forwarder container if resourceDefaults (global) is true |
service |
Service | |
Service configuration |
serviceLabels |
k8s:Labels |
{} |
Labels to be added to each service |
tls |
Inbound TLS | |
TLS configuration for inbound traffic |
tolerations |
List of k8s:Tolerations |
[] |
Kubernetes pod Tolerations |
topologySpreadConstraints |
List of k8s:TopologySpreadConstraint |
[] |
Kubernetes pod topology spread constraints |
Elasticsearch
Configuration of the Elasticsearch/Opensearch backend, for example:
eventForwarders:
myevforwarder:
elasticsearch:
addr: https://elasticsearch.example.local:9200/
index: "some-index-name"
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
add_date_to_index |
boolean |
false |
If true, append the date to the index name when sending events, e.g. indexname-2006-12-23 |
|
addr |
string |
URL of Elasticsearch instance. Mutually exclusive with addresses |
||
addresses |
List of string |
List of URLs of Elasticsearch instances. Can be used to specify multiple nodes (requests will be sent in a round-robin fashion and node health is tracked). Mutually exclusive with addr |
||
credentialsSecretName |
string |
Name of a pre-existing Kubernetes Secret containing a username & password for authentication with Elasticsearch | ||
credentialsSecretPasswordKey |
string |
"username" |
If credentialsSecretName is specified: name of the item inside the Secret which holds the username |
|
credentialsSecretUsernameKey |
string |
"password" |
If credentialsSecretName is specified: name of the item inside the Secret which holds the password |
|
connect_timeout |
go:DurationString |
10s |
How long to wait before timing out connection attempts | |
idle_conn_timeout |
go:DurationString |
90s |
Maximum amount of time an idle (keep-alive) connection will remain idle before closing itself | |
index |
string |
yes |
"" |
Name of the Elasticsearch index to send events to |
password |
string |
Password to use for authentication | ||
query_timeout |
go:DurationString |
10s |
Query timeout duration | |
readiness_interval |
go:DurationString |
5s |
How often to check the Elasticsearch connection for readiness | |
startup_retries |
integer |
100 |
On startup, how many times to retry connecting to Elasticsearch | |
tlsconfig |
Elasticsearch TLS | TLS configuration for connection towards Elasticsearch | ||
use_create_action |
boolean |
false |
If true, use the create action instead of index action in the bulk API. This is required when using Elasticsearch Data Streams |
|
user |
string |
Username to use for authentication | ||
wait_interval |
go:DurationString |
500ms |
On startup, how long to wait for an Elasticsearch connection to succeed before giving up |
Elasticsearch TLS Config
Parameters to configure TLS options, these should be child attributes of the tlsconfig node. For example:
eventForwarders:
myevforwarder:
elasticsearch:
addr: https://elasticsearch.example.local:9200/
index: "some-index-name"
tlsconfig:
insecure_skip_verify: true
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
ca |
string |
CA in PEM format to use for validation | ||
caSecretName |
string |
Name of a pre-existing Kubernetes Secret with a data item named ca.crt containing the CA in PEM format to use for validation |
||
insecure_skip_verify |
boolean |
false |
Skip validation of the storage backend's certificate chain and hostname |
Filter Count
Filter count configuration is used to configure how global counts about filtering are stored. Parameters which can be modified to configure this:
| Parameter | Type | Default | Description |
|---|---|---|---|
num_shards |
integer |
8 |
How many shards to use for that map that holds global filter counts |
query_interval |
go:DurationString |
1h |
How often to send query counts to Elasticsearch for each user |
send_interval |
go:DurationString |
5m |
How often to check for updated query data |
Filter Tags
Filter tags are used to identify which events are related to filtering. These should match the tags generated by the filtering engine's policies.
For example, to identify events filtered by a rule named user-blocklist:
Tags can be configured for the following identifiable categories:
| Parameter | Type | Default | Description |
|---|---|---|---|
blocklist |
List of string |
[] |
A list of tags that indicate the event is filtered because the user added the domain to their personal blocklist |
botnet |
List of string |
[] |
A list of tags that indicate the event is filtered for the purposes of preventing botnet command and control connections |
contentfilter |
List of string |
[] |
A list of tags that indicate the event is filtered because the user asked that category of content to be filtered |
malware |
List of string |
[] |
A list of tags that indicate the event is filtered for the purposes of preventing malware |
phishing |
List of string |
[] |
A list of tags that indicate the event is filtered for the purposes of preventing phishing |
Inbound TLS
Parameters to configure TLS for inbound traffic. An example:
In the above example the certificate present in Secret my-eventforwarder-certificate will be attempted to be used to start a TLS-enabled listener.
| Parameter | Type | Default | Description |
|---|---|---|---|
certSecretName |
string |
Name of a Secret object containing a certificate (must contain the tls.key, tls.crt items) |
|
certManager |
boolean |
false |
Toggle to have a request created for Certmanager to provision a certificate. By default, this will request for a Certificate covering the following: - eventforwarder-[Name of instance set]- eventforwarder-[Name of instance set].[Namespace]- eventforwarder-[Name of instance set].[Namespace].svcAdditional entries can be configured using extraDNSNames |
enabled |
boolean |
false |
Toggle to enable TLS If set to true, a certSecretName must be set or certManager must be set to true to ensure a valid certificate is available |
extraDNSNames |
List of string |
[] |
List of additional entries to be added to the Certificate requested from Certmanager |
issuerGroup |
string |
"cert-manager.io" |
Group to which issuer specified under issuerKind belongsDefault value is inherited from the global certManager configuration |
issuerKind |
string |
"ClusterIssuer" |
Type of Certmanager issuer to request a Certificate from Default value is inherited from the global certManager configuration |
issuerName |
string |
"" |
Name of the issuer from which to request a Certificate Default value is inherited from the global certManager configuration |
certSpecExtra |
CertificateSpec | {} |
Extra configuration to be injected into the Certmanager Certificate object's spec field.Disallowed options: "secretName" "commonName" "dnsNames" "issuerRef" (These are configured automatically and/or via other options) |
certLabels |
k8s:Labels |
{} |
Extra labels for the Certmanager Certificate object |
certAnnotations |
k8s:Annotations |
{} |
Extra annotations for the Certmanager Certificate object |
Query Count Configuration
Configuration of the Query Count feature:
| Parameter | Type | Default | Description |
|---|---|---|---|
max_concurrent |
integer |
(calculated: # cpu cores) |
Number of concurrent senders |
num_shards |
integer |
32 |
How many shards to use for the map that holds query counts |
query_interval |
go:DurationString |
1h |
How often to send query counts to Elasticsearch for each user |
sample_rate |
integer |
1 |
Indicates the sample rate that was applied to messages before sending to event forwarder, thus the multiplication factor that will be used when storing query counts in Elasticsearch |
send_interval |
go:DurationString |
5m |
How often to check for updated query data |
tls |
Inbound TLS | TLS configuration for inbound traffic on the Query Count endpoint |
Query Count TLS Config
Parameters to configure TLS for inbound traffic. An example:
eventForwarders:
myevforwarder:
qcConfig:
tls:
enabled: true
certSecretName: my-eventforwarder-qc-certificate
In the above example the certificate present in Secret my-eventforwarder-qc-certificate will be attempted to be used to start a TLS-enabled listener for the Query Count endpoint.
| Parameter | Type | Default | Description |
|---|---|---|---|
certSecretName |
string |
Name of a Secret object containing a certificate (must contain the tls.key, tls.crt items) |
|
certManager |
boolean |
false |
Toggle to have a request created for Certmanager to provision a certificate. By default, this will request for a Certificate covering the following: - eventforwarder-[Name of instance set]-querycount- eventforwarder-[Name of instance set]-querycount.[Namespace]- eventforwarder-[Name of instance set]-querycount.[Namespace].svcAdditional entries can be configured using extraDNSNames |
enabled |
boolean |
false |
Toggle to enable TLS If set to true, a certSecretName must be set or certManager must be set to true to ensure a valid certificate is available |
extraDNSNames |
List of string |
[] |
List of additional entries to be added to the Certificate requested from Certmanager |
issuerGroup |
string |
"cert-manager.io" |
Group to which issuer specified under issuerKind belongsDefault value is inherited from the global certManager configuration |
issuerKind |
string |
"ClusterIssuer" |
Type of Certmanager issuer to request a Certificate from Default value is inherited from the global certManager configuration |
issuerName |
string |
"" |
Name of the issuer from which to request a Certificate Default value is inherited from the global certManager configuration |
certSpecExtra |
CertificateSpec | {} |
Extra configuration to be injected into the Certmanager Certificate object's spec field.Disallowed options: "secretName" "commonName" "dnsNames" "issuerRef" (These are configured automatically and/or via other options) |
certLabels |
k8s:Labels |
{} |
Extra labels for the Certmanager Certificate object |
certAnnotations |
k8s:Annotations |
{} |
Extra annotations for the Certmanager Certificate object |
Service Configuration
Parameters to configure the service object for this deployment. For example:
eventForwarders:
myevforwarder:
service:
type: LoadBalancer
annotations:
metallb.universe.tf/address-pool: name_of_pool
| Parameter | Type | Default | Description |
|---|---|---|---|
allocateLoadBalancerNodePorts |
boolean |
true |
If true, services with type LoadBalancer automatically assign NodePorts. Can be set to false if the LoadBalancer provider does not rely on NodePorts |
annotations |
k8s:Annotations |
{} |
Annotations for the service |
clusterIP |
string |
Static cluster IP, must be in the cluster's range of cluster IPs and not in use. Randomly assigned when not specified. | |
clusterIPs |
List of string |
List of static cluster IPs, must be in the cluster's range of cluster IPs and not in use. | |
externalIPs |
List of string |
List of IP addresses for which nodes in the cluster will also accept traffic for this service. These IPs are not managed by Kubernetes and must be user-defined on the cluster's nodes | |
externalTrafficPolicy |
string |
Cluster |
Can be set to Local to let nodes distribute traffic received on one of the externally-facing addresses (NodePort and LoadBalancer) solely to endpoints on the node itself |
healthCheckNodePort |
integer |
For services with type LoadBalancer and externalTrafficPolicy Local you can configure this value to choose a static port for the NodePort which external systems (LoadBalancer provider mainly) can use to determine which node holds endpoints for this service |
|
internalTrafficPolicy |
string |
Cluster |
Can be set to Local to let nodes distribute traffic received on the ClusterIP solely to endpoints on the node itself |
ipv4 |
boolean |
false |
If true, force the Service to include support for IPv4, ignoring globally configured IP Family settings and/or cluster defaults. If ipv4 is set to true and ipv6 remains false, the result will be an ipv4-only SingleStack Service. If both are false, global settings and/or cluster defaults are used. If both are true, a PreferDualStack Service is created |
ipv6 |
boolean |
false |
If true, force the Service to include support for IPv6, ignoring globally configured IP Family settings and/or cluster defaults. If ipv6 is set to true and ipv4 remains false, the result will be an ipv6-only SingleStack Service. If both are false, global settings and/or cluster defaults are used. If both are true, a PreferDualStack Service is created |
labels |
k8s:Labels |
{} |
Labels to be added to the service |
loadBalancerIP |
string |
Deprecated Kubernetes feature, available for backwards compatibility: IP address to attempt to claim for use by this LoadBalancer. Replaced by annotations specific to each LoadBalancer provider |
|
loadBalancerSourceRanges |
List of string |
If supported by the LoadBalancer provider, restrict traffic to this LoadBalancer to these ranges | |
loadBalancerClass |
string |
Used to select a non-default type of LoadBalancer class to ensure the appropriate LoadBalancer provisioner attempt to manage this LoadBalancer service | |
publishNotReadyAddresses |
boolean |
false |
Service is populated with endpoints regardless of readiness state |
sessionAffinity |
string |
None |
Can be set to ClientIP to attempt to maintain session affinity. |
sessionAffinityConfig |
k8s:SessionAffinityConfig |
{} |
Configuration of session affinity |
type |
string |
ClusterIP |
Type of service. Available options: "ClusterIP" "LoadBalancer" "NodePort" |