From 14234aa87ecfcdd24e429910757475d28de8766a Mon Sep 17 00:00:00 2001 From: Guillaume Fournier <36961134+Gui774ume@users.noreply.github.com> Date: Tue, 6 Jun 2023 16:48:24 +0200 Subject: [PATCH 01/76] [CWS] reset events_stats to a PERCPU_ARRAY instead of a HASHMAP (#17473) --- pkg/security/ebpf/c/include/perf_ring.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/security/ebpf/c/include/perf_ring.h b/pkg/security/ebpf/c/include/perf_ring.h index c78fa8e955145..cf1da8e894218 100644 --- a/pkg/security/ebpf/c/include/perf_ring.h +++ b/pkg/security/ebpf/c/include/perf_ring.h @@ -17,7 +17,7 @@ struct ring_buffer_stats_t { }; BPF_PERF_EVENT_ARRAY_MAP(events, u32) -BPF_HASH_MAP(events_stats, u32, struct perf_map_stats_t, EVENT_MAX) +BPF_PERCPU_ARRAY_MAP(events_stats, u32, struct perf_map_stats_t, EVENT_MAX) #if USE_RING_BUFFER == 1 BPF_ARRAY_MAP(events_ringbuf_stats, u64, 1) From 37df2b8842f82cdbb51fecfcf86caa67efb3c5d8 Mon Sep 17 00:00:00 2001 From: Alexandre Menasria <47357713+amenasria@users.noreply.github.com> Date: Tue, 6 Jun 2023 14:49:14 -0400 Subject: [PATCH 02/76] Bump ncurses to 6.4 to fix CVE-2023-29491 (#17493) --- .../notes/bump-ncurses-6.4-62712eeadb4e0899.yaml | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 releasenotes/notes/bump-ncurses-6.4-62712eeadb4e0899.yaml diff --git a/releasenotes/notes/bump-ncurses-6.4-62712eeadb4e0899.yaml b/releasenotes/notes/bump-ncurses-6.4-62712eeadb4e0899.yaml new file mode 100644 index 0000000000000..322d3c7a9b6b5 --- /dev/null +++ b/releasenotes/notes/bump-ncurses-6.4-62712eeadb4e0899.yaml @@ -0,0 +1,11 @@ +# Each section from every release note are combined when the +# CHANGELOG.rst is rendered. So the text needs to be worded so that +# it does not depend on any information only available in another +# section. This may mean repeating some details, but each section +# must be readable independently of the other. +# +# Each section note must be formatted as reStructuredText. +--- +security: + - | + Bump ncurses to 6.4 in the Agent embedded environment. Fixes CVE-2023-29491. From 7be2f31e01071f2a0616b7045bb33b9250813743 Mon Sep 17 00:00:00 2001 From: Kacper <89013263+kacper-murzyn@users.noreply.github.com> Date: Tue, 6 Jun 2023 15:05:12 -0400 Subject: [PATCH 03/76] Kacper murzyn/7.45.0 changelog backport (#17489) * 7.45.0 changelog (#17394) * Release date updated --- CHANGELOG-DCA.rst | 33 +++++++ CHANGELOG.rst | 228 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 261 insertions(+) diff --git a/CHANGELOG-DCA.rst b/CHANGELOG-DCA.rst index 69944d19874fb..47293aa033fc8 100644 --- a/CHANGELOG-DCA.rst +++ b/CHANGELOG-DCA.rst @@ -2,6 +2,39 @@ Release Notes ============= +.. _Release Notes_7.45.0: + +7.45.0 / 6.45.0 +====== + +.. _Release Notes_7.45.0_Enhancement Notes: + +Enhancement Notes +----------------- + +- Add "active" tag on the telemetry datadog.cluster_agent.external_metrics.datadog_metrics tag. + The label active is true if DatadogMetrics CR is used, false otherwise. + +- Library injection via Admission Controller: Allow configuring the CPU and Memory requests/limits for library init containers. + +- Validate the orchestration config provided by the user. + + +.. _Release Notes_7.45.0_Bug Fixes: + +Bug Fixes +--------- + +- Fix the admission controller in socket mode for pods with init containers. + +- Fix resource requirements detection for containers without any request and + limit set. + +- The KSM core check now correctly handles labels and annotations with + uppercase letters defined in the "labels_as_tags" and "annotations_as_tags" + config attributes. + + .. _Release Notes_7.44.0: 7.44.0 / 6.44.0 diff --git a/CHANGELOG.rst b/CHANGELOG.rst index d10c8af360216..daaaf5cdba547 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -2,6 +2,234 @@ Release Notes ============= +.. _Release Notes_7.45.0: + +7.45.0 / 6.45.0 +====== + +.. _Release Notes_7.45.0_Prelude: + +Prelude +------- + +Release on: 2023-06-05 + +- Please refer to the `7.45.0 tag on integrations-core `_ for the list of changes on the Core Checks + + +.. _Release Notes_7.45.0_New Features: + +New Features +------------ + +- Add Topology data collection with CDP. + +- APM: Addition of configuration to add ``peer.service`` to trace stats exported by the Agent. + +- APM: Addition of configuration to compute trace stats on spans based on their ``span.kind`` value. + +- APM: Added a new endpoint in the trace-agent API `/symdb/v1/input` that acts as a reverse proxy forwarding requests to Datadog. The feature using this is currently in development. + +- Add support for confluent-kafka. + +- Add support for XCCDF benchmarks in CSPM. + A new configuration option, 'compliance_config.xccdf.enabled', + disabled by default, has been added for enabling XCCDF benchmarks. + +- Add arguments to module load events + +- Oracle DBM monitoring with activity sampling. The collected samples form the foundation for database load profiling. With Datadog GUI, samples can be aggregated and filtered to identify bottlenecks. + +- Add reporting of `container.{cpu|memory|io}.partial_stall` metrics based on PSI Some values when host is running with cgroupv2 enabled (Linux only). + This metric provides the wall time (in nanoseconds) during which at least one task in the container has been stalled on the given resource. + +- Adding a new option `secret_backend_remove_trailing_line_break` to remove trailing line breaks from secrets returned + by `secret_backend_command`. This makes it easier to use secret management tools that automatically add a line break when + exporting secrets through files. + + +.. _Release Notes_7.45.0_Enhancement Notes: + +Enhancement Notes +----------------- + +- Cluster Agent: User config, cluster Agent deployment and node Agent daemonset manifests are now added to the flare archive, when the Cluster Agent is deployed with Helm (version 3.23.0+). + +- Datadog Agent running as a systemd service can optionally read + environment variables from a text file `/etc/datadog-agent/environment` + containing newline-separated variable assignments. + See https://www.freedesktop.org/software/systemd/man/systemd.exec.html#Environment + +- Add ability to filter kubernetes containers based on autodiscovery annotation. Containers in a pod + can now be omitted by setting `ad.datadoghq.com/.exclude` as an annotation on the + pod. Logs can now be ommitted by setting `ad.datadoghq.com/.logs_exclude` as an + annotation on the pod. + +- Added support for custom resource definitions metrics: `crd.count` and `crd.condition`. + +- * Remove BadgerDB cache for Trivy. + * Add new custom LRU cache for Trivy backed by BoltDB and parametrized by: + * Periodically delete unused entries from the custom cache. + * Add telemetry metrics to monitor the cache: + - ``sbom.cached_keys``: Number of cache keys stored in memory + - ``sbom.cache_disk_size``: Total size, in bytes, of the database as reported by BoltDB. + - ``sbom.cached_objects_size``: Total size, in bytes, of cached SBOM objects on disk. Limited by sbom.custom_cache_max_disk_size. + - ``sbom.cache_hits_total``: Total number of cache hits. + - ``sbom.cache_misses_total``: Total number of cache misses. + - ``sbom.cache_evicts_total``: Total number of cache evicts. + +- Added `DD_ENV` to the SBOMPayload in the SBOM check. + +- Added `kubernetes_state.hpa.status_target_metric` and `kubernetes_state.deployment.replicas_ready` metrics part of the `kubernetes_state_core` check. + +- Add support for emitting resources on metrics from tags in the + format dd.internal.resource:type,name. + +- APM: Dynamic instrumentation logs and snapshots can now be shipped to multiple Datadog logs intakes. + +- Adds support for OpenTelemetry span links to the Trace Agent OTLP endpoint when converting OTLP spans (span links are added as metadata to the converted span). + +- Agents are now built with Go ``1.19.9``. + +- Make Podman DB path configurable for rootless environment. + Now we can set ``$HOME/.local/share/containers/storage/libpod/bolt_state.db``. + +- Add ownership information for containers to the container-lifecycle check. + +- Add Pod exit timestamp to container-lifecycle check. + +- The Agent now uses the `ec2_metadata_timeout` value when fetching EC2 instance tags with AWS SDK. The Agent fetches + instance tags when `collect_ec2_tags` is set to `true`. + +- Upgraded JMXFetch to ``0.47.8`` which has improvements aimed + to help large metric collections drop fewer payloads. + +- Kubernetes State Metrics Core: Adds collection of Kubernetes APIServices metrics + +- Add support for URLs with the `http|https` scheme in the `dd_url` or `logs_dd_url` parameters + when configuring endpoints. + Also automatically detects SSL needs, based on the scheme when it is present. + +- [pkg/netflow] Add NetFlow Exporter to NDM Metadata. + +- SUSE RPMs are now built with RPM 4.14.3 and have SHA256 digest headers. + +- ``observability_pipelines_worker`` can now be used in place of the ``vector`` + config options. + +- Add an option and an annotation to skip ``kube_service`` tags on Kubernetes pods. + + When the selector of a service matches a pod and that pod is ready, its metrics are decorated with a ``kube_service`` tag. + + When the readiness of a pod flips, so does the ``kube_service`` tag. This could create visual artifacts (spikes when the tag flips) on dashboards where the queries are missing ``.fill(null)``. + + If many services target a pod, the total number of tags attached to its metrics might exceed a limit that causes the whole metric to be discarded. + + In order to mitigate these two issues, it’s now possible to set the ``kubernetes_ad_tags_disabled`` parameter to ``kube_config`` to globally remove the ``kube_service`` tags on all pods:: + kubernetes_ad_tags_disabled + - kube_service + + It’s also possible to add a ``tags.datadoghq.com/disable: kube_service`` annotation on only the pods for which we want to remove the ``kube_service`` tag. + + Note that ``kube_service`` is the only tag that can be removed via this parameter and this annotation. + +- Support OTel semconv 1.17.0 in OTLP ingest endpoint. + +- When ``otlp_config.metrics.histograms.send_aggregation_metrics`` is set to ``true``, + the OTLP ingest pipeline will now send min and max metrics for delta OTLP Histograms + and OTLP Exponential Histograms when available, in addition to count and sum metrics. + + The deprecated option ``otlp_config.metrics.histograms.send_count_sum_metrics`` now + also sends min and max metrics when available. + +- OTLP: Use minimum and maximum values from cumulative OTLP Histograms. Values are used only when we can assume they are from the last time window or otherwise to clamp estimates. + +- The OTLP ingest endpoint now supports the same settings and protocol as the OpenTelemetry Collector OTLP receiver v0.75.0. + +- Secrets with `ENC[]` notation are now supported for proxy setting from environment variables. For more information + you can refer to our [Secrets Management](https://docs.datadoghq.com/agent/guide/secrets-management/) + and [Agent Proxy Configuration](https://docs.datadoghq.com/agent/proxy/) documentations. + +- [corechecks/snmp] Adds ability to send constant metrics in SNMP profiles. + +- [corechecks/snmp] Adds ability to map metric tag value to string in SNMP profiles. + +- [corechecks/snmp] Add support to format bytes into ip_address + + +.. _Release Notes_7.45.0_Deprecation Notes: + +Deprecation Notes +----------------- + +- APM OTLP: Field UsePreviewHostnameLogic is deprecated, and usage of this field has been removed. This is done in preparation to graduate the exporter.datadog.hostname.preview feature gate to stable. + +- The Windows Installer NPM feature option, used in ``ADDLOCAL=NPM`` and ``REMOVE=NPM``, no + longer controls the install state of NPM components. The NPM components are now always + installed, but will only run when enabled in the agent configuration. The Windows Installer + NPM feature option still exists for backwards compatability purposes, but has no effect. + +- Deprecate ``otlp_config.metrics.histograms.send_count_sum_metrics`` in favor of ``otlp_config.metrics.histograms.send_aggregation_metrics``. + +- Removed the `--info` flag in the Process Agent, which has been replaced by the `status` command since 7.35. + + +.. _Release Notes_7.45.0_Security Notes: + +Security Notes +-------------- + +- Handle the return value of Close() for writable files in ``pkg/forwarder`` + +- Fixes cwe 703. Handle the return value of Close() for writable files and forces writes to disks + in `system-probe` + + +.. _Release Notes_7.45.0_Bug Fixes: + +Bug Fixes +--------- + +- APM: Setting apm_config.receiver_port: 0 now allows enabling UNIX Socket or Windows Pipes listeners. + +- APM: OTLP: Ensure that container tags are set globally on the payload so that they can be picked up as primary tags in the app. + +- APM: Fixes a bug with how stats are calculated when using single span sampling + along with other sampling configurations. + +- APM: Fixed the issue where not all trace stats are flushed on trace-agent shutdown. + +- Fix an issue on the pod collection where the cluster name would not + be consistently RFC1123 compliant. + +- Make the agent able to detect it is running on ECS EC2, even with a host install, i.e. when the agent isn’t deployed as an ECS task. + +- Fix missing case-sensitive version of the ``device`` tag on the ``system.disk`` group of metrics. + +- The help output of the Agent command now correctly displays the executable name on Windows. + +- Fix resource requirements detection for containers without any request and + limit set. + +- The KSM core check now correctly handles labels and annotations with + uppercase letters defined in the "labels_as_tags" and "annotations_as_tags" + config attributes. + +- Fixes issue where trace data drops in OTLP ingest by adding batch processor for traces, and increases the grpc message limit + +- [pkg/netflow] Rename payload ``device.ip`` to ``exporter.ip`` + +- Fixes an issue in the process agent where in rare scenarios, negative CPU usage percentages would be reported for processes. + +- When a pod was annotated with ``prometheus.io/scrape: true``, the Agent used to schedule one ``openmetrics`` check per container in the pod unless a ``datadog.prometheusScrape.additionalConfigs[].autodiscovery.kubernetes_container_names`` list was defined, which restricted the potential container targets. + The Agent is now able to leverage the ``prometheus.io/port`` annotation to schedule an ``openmetrics`` check only on the container of the pod that declares that port in its spec. + +- Fixing an issue with Prometheus scrape feature when `service_endpoints` option is used where endpoint updates were missed by the Agent, causing checks to not be scheduled on endpoints created after Agent start. + +- On Windows, when using USM, fixes tracking of connections made via + localhost. + + .. _Release Notes_7.44.1: 7.44.1 / 6.44.1 From 8e96de893c96a2dde1938e421be9dec121d4c5ce Mon Sep 17 00:00:00 2001 From: Kacper <89013263+kacper-murzyn@users.noreply.github.com> Date: Tue, 6 Jun 2023 15:07:31 -0400 Subject: [PATCH 04/76] Update latest stable agent version to 7.45.0 (#17491) --- release.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/release.json b/release.json index 28983fc66f3f7..a139a855e1557 100644 --- a/release.json +++ b/release.json @@ -1,8 +1,8 @@ { "base_branch": "main", "last_stable": { - "6": "6.44.1", - "7": "7.44.1" + "6": "6.45.0", + "7": "7.45.0" }, "nightly": { "INTEGRATIONS_CORE_VERSION": "master", From 85c58dc04d25c008976f397490716f93c0043498 Mon Sep 17 00:00:00 2001 From: Paul Cacheux Date: Tue, 6 Jun 2023 17:28:41 -0400 Subject: [PATCH 05/76] fix subscriptionId fetching on azure (#17495) --- pkg/util/cloudproviders/azure/azure.go | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/pkg/util/cloudproviders/azure/azure.go b/pkg/util/cloudproviders/azure/azure.go index ac67b92033b27..0d3b453d33395 100644 --- a/pkg/util/cloudproviders/azure/azure.go +++ b/pkg/util/cloudproviders/azure/azure.go @@ -190,20 +190,21 @@ func GetPublicIPv4(ctx context.Context) (string, error) { return publicIPv4Fetcher.FetchString(ctx) } -var subscriptionIdFetcher = cachedfetch.Fetcher{ - Name: "Azure Subscription ID", - Attempt: func(ctx context.Context) (interface{}, error) { - subscriptionID, err := getResponse(ctx, - metadataURL+"/metadata/instance/compute/subscriptionId?api-version=2017-04-02&format=text") - if err != nil { - return "", fmt.Errorf("failed to get Azure Subscription ID: %s", err) - } - - return subscriptionID, nil - }, +type instanceMetadata struct { + SubscriptionID string `json:"subscriptionId"` } // GetSubscriptionID returns the subscription ID of the current Azure instance func GetSubscriptionID(ctx context.Context) (string, error) { - return subscriptionIdFetcher.FetchString(ctx) + body, err := instanceMetaFetcher.FetchString(ctx) + if err != nil { + return "", err + } + + var metadata instanceMetadata + if err := json.Unmarshal([]byte(body), &metadata); err != nil { + return "", err + } + + return metadata.SubscriptionID, nil } From baf054a4530ff64dd4de4da6c39831a8cb809085 Mon Sep 17 00:00:00 2001 From: AliDatadog <125997632+AliDatadog@users.noreply.github.com> Date: Wed, 7 Jun 2023 15:32:43 +0200 Subject: [PATCH 06/76] [SBOM] Remove `DeleteBlobs` from the sbom cache (#17465) * remove delete missing blobs * remove test * fix strconv * change from code review * fix typo --- pkg/util/trivy/cache.go | 5 +++-- pkg/util/trivy/cache_test.go | 35 ----------------------------------- 2 files changed, 3 insertions(+), 37 deletions(-) diff --git a/pkg/util/trivy/cache.go b/pkg/util/trivy/cache.go index 7f444e1e5bfec..fe4a7f418f82b 100644 --- a/pkg/util/trivy/cache.go +++ b/pkg/util/trivy/cache.go @@ -211,9 +211,10 @@ func (c *TrivyCache) PutBlob(blobID string, blobInfo types.BlobInfo) error { return trivyCachePut(c, blobID, blobInfo) } -// Implements cache.Cache#DeleteBlobs +// Implements cache.Cache#DeleteBlobs does nothing because the cache cleaning logic is +// managed by CacheCleaner func (c *TrivyCache) DeleteBlobs(blobIDs []string) error { - return c.Cache.Remove(blobIDs) + return nil } // Implements cache.Cache#Clear diff --git a/pkg/util/trivy/cache_test.go b/pkg/util/trivy/cache_test.go index 511fd81bf3cda..f317130b75ae5 100644 --- a/pkg/util/trivy/cache_test.go +++ b/pkg/util/trivy/cache_test.go @@ -10,7 +10,6 @@ package trivy import ( "context" "encoding/json" - "strconv" "strings" "testing" "time" @@ -67,40 +66,6 @@ func TestCustomBoltCache_Blobs(t *testing.T) { require.Equal(t, blobInfo, storedBlobInfo) } -func TestCustomBoltCache_DeleteBlobs(t *testing.T) { - cache, _, err := NewCustomBoltCache(t.TempDir(), defaultCacheSize, defaultDiskSize) - require.NoError(t, err) - defer func() { - require.NoError(t, cache.Close()) - }() - - // Store 3 blobs with IDs "0", "1", "2" - for blobID, osName := range []string{"3.15", "3.16", "3.17"} { - blobInfo := types.BlobInfo{ - SchemaVersion: 1, - OS: types.OS{ - Family: "alpine", - Name: osName, - }, - } - - err := cache.PutBlob(strconv.Itoa(blobID), blobInfo) - require.NoError(t, err) - } - - // Delete 2 blobs - err = cache.DeleteBlobs([]string{"0", "1"}) - require.NoError(t, err) - - // Check that the deleted blobs are no longer there, but the other one is - _, err = cache.GetBlob("0") - require.Error(t, err) - _, err = cache.GetBlob("1") - require.Error(t, err) - _, err = cache.GetBlob("2") - require.NoError(t, err) -} - func TestCustomBoltCache_MissingBlobs(t *testing.T) { cache, _, err := NewCustomBoltCache(t.TempDir(), defaultCacheSize, defaultDiskSize) require.NoError(t, err) From 3df6d831b4fec627db7fadbeaefc99946640c505 Mon Sep 17 00:00:00 2001 From: Paul Cacheux Date: Wed, 7 Jun 2023 09:47:07 -0400 Subject: [PATCH 07/76] [CWS] fix duration suffix parsing (#17476) --- pkg/security/secl/compiler/ast/secl.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/security/secl/compiler/ast/secl.go b/pkg/security/secl/compiler/ast/secl.go index 55534e9810559..3372a7149e314 100644 --- a/pkg/security/secl/compiler/ast/secl.go +++ b/pkg/security/secl/compiler/ast/secl.go @@ -27,7 +27,7 @@ Comment = ("#" | "//") { "\u0000"…"\uffff"-"\n" } . CIDR = IP "/" digit { digit } . IP = (ipv4 | ipv6) . Variable = "${" (alpha | "_") { "_" | alpha | digit | "." } "}" . -Duration = digit { digit } ("ms" | "s" | "m" | "h" | "d") . +Duration = digit { digit } ("m" | "s" | "m" | "h") { "s" } . Regexp = "r\"" { "\u0000"…"\uffff"-"\""-"\\" | "\\" any } "\"" . Ident = (alpha | "_") { "_" | alpha | digit | "." | "[" | "]" } . String = "\"" { "\u0000"…"\uffff"-"\""-"\\" | "\\" any } "\"" . From 3d3ca12f89816663f4d9c9b7d392d14184fd6b8c Mon Sep 17 00:00:00 2001 From: Paul Cacheux Date: Wed, 7 Jun 2023 09:47:20 -0400 Subject: [PATCH 08/76] convert remaining users of old `golang-lru` to new generics based version (#17467) * convert dogstatsd mapper cache to lru/v2 * convert network process cache to lru/v2 * convert network conntracker to lru/v2 * convert trivy cache to lru/v2 * convert network gateway lookup to lru/v2 * cleanup dependencies * fix licenses * fix conntracker tests * fix conntrack debug --- LICENSE-3rdparty.csv | 1 - comp/dogstatsd/mapper/mapper_cache.go | 8 ++++---- go.mod | 2 +- pkg/network/netlink/conntrack_debug.go | 12 ++---------- pkg/network/netlink/conntracker.go | 13 +++++-------- pkg/network/netlink/conntracker_test.go | 10 ++++------ pkg/network/tracer/gateway_lookup.go | 6 +++--- pkg/network/tracer/process_cache.go | 7 +++---- pkg/util/trivy/cache.go | 12 ++++++------ 9 files changed, 28 insertions(+), 43 deletions(-) diff --git a/LICENSE-3rdparty.csv b/LICENSE-3rdparty.csv index 27ca099576513..46ed6a7cbbeb9 100644 --- a/LICENSE-3rdparty.csv +++ b/LICENSE-3rdparty.csv @@ -981,7 +981,6 @@ core,github.com/hashicorp/go-multierror,MPL-2.0,"Copyright © 2014-2018 HashiCor core,github.com/hashicorp/go-retryablehttp,MPL-2.0,"Copyright © 2014-2018 HashiCorp, Inc" core,github.com/hashicorp/go-rootcerts,MPL-2.0,"Copyright © 2014-2018 HashiCorp, Inc" core,github.com/hashicorp/go-version,MPL-2.0,"Copyright © 2014-2018 HashiCorp, Inc" -core,github.com/hashicorp/golang-lru,MPL-2.0,"Copyright © 2014-2018 HashiCorp, Inc" core,github.com/hashicorp/golang-lru/simplelru,MPL-2.0,"Copyright © 2014-2018 HashiCorp, Inc" core,github.com/hashicorp/golang-lru/v2,MPL-2.0,"Copyright © 2014-2018 HashiCorp, Inc" core,github.com/hashicorp/golang-lru/v2/simplelru,MPL-2.0,"Copyright © 2014-2018 HashiCorp, Inc" diff --git a/comp/dogstatsd/mapper/mapper_cache.go b/comp/dogstatsd/mapper/mapper_cache.go index b915fff6f7a67..d5c2e1d7cafc0 100644 --- a/comp/dogstatsd/mapper/mapper_cache.go +++ b/comp/dogstatsd/mapper/mapper_cache.go @@ -6,16 +6,16 @@ package mapper import ( - lru "github.com/hashicorp/golang-lru" + lru "github.com/hashicorp/golang-lru/v2" ) type mapperCache struct { - cache *lru.Cache + cache *lru.Cache[string, *MapResult] } // newMapperCache creates a new mapperCache func newMapperCache(size int) (*mapperCache, error) { - cache, err := lru.New(size) + cache, err := lru.New[string, *MapResult](size) if err != nil { return &mapperCache{}, err } @@ -27,7 +27,7 @@ func newMapperCache(size int) (*mapperCache, error) { // - a boolean indicating if a match has been found func (m *mapperCache) get(metricName string) (*MapResult, bool) { if result, ok := m.cache.Get(metricName); ok { - return result.(*MapResult), true + return result, true } return nil, false } diff --git a/go.mod b/go.mod index 59caa3946e1db..b6b7ed39504ad 100644 --- a/go.mod +++ b/go.mod @@ -129,7 +129,6 @@ require ( github.com/h2non/filetype v1.1.3 github.com/hashicorp/consul/api v1.20.0 github.com/hashicorp/go-multierror v1.1.1 - github.com/hashicorp/golang-lru v0.5.4 github.com/hashicorp/golang-lru/v2 v2.0.2 github.com/hectane/go-acl v0.0.0-20190604041725-da78bae5fc95 github.com/iceber/iouring-go v0.0.0-20220609112130-b1dc8dd9fbfd @@ -385,6 +384,7 @@ require ( github.com/hashicorp/go-retryablehttp v0.7.2 // indirect github.com/hashicorp/go-rootcerts v1.0.2 // indirect github.com/hashicorp/go-version v1.6.0 // indirect + github.com/hashicorp/golang-lru v0.5.4 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/hashicorp/serf v0.10.1 // indirect github.com/huandu/xstrings v1.3.3 // indirect diff --git a/pkg/network/netlink/conntrack_debug.go b/pkg/network/netlink/conntrack_debug.go index accbc5b884bc1..83d8cf1ee5f78 100644 --- a/pkg/network/netlink/conntrack_debug.go +++ b/pkg/network/netlink/conntrack_debug.go @@ -47,20 +47,12 @@ func (ctr *realConntracker) DumpCachedTable(ctx context.Context) (map[uint32][]D ns := uint32(0) table[ns] = []DebugConntrackEntry{} - for _, k := range keys { + for _, ck := range keys { if ctx.Err() != nil { return nil, ctx.Err() } - ck, ok := k.(connKey) - if !ok { - continue - } - v, ok := ctr.cache.cache.Peek(ck) - if !ok { - continue - } - te, ok := v.(*translationEntry) + te, ok := ctr.cache.cache.Peek(ck) if !ok { continue } diff --git a/pkg/network/netlink/conntracker.go b/pkg/network/netlink/conntracker.go index 3042c8d2de51d..302ce7725f4ad 100644 --- a/pkg/network/netlink/conntracker.go +++ b/pkg/network/netlink/conntracker.go @@ -16,7 +16,7 @@ import ( "sync" "time" - "github.com/hashicorp/golang-lru/simplelru" + "github.com/hashicorp/golang-lru/v2/simplelru" "golang.org/x/sys/unix" "github.com/DataDog/datadog-agent/pkg/network" @@ -303,7 +303,7 @@ func (ctr *realConntracker) compact() { } type conntrackCache struct { - cache *simplelru.LRU + cache *simplelru.LRU[connKey, *translationEntry] orphans *list.List orphanTimeout time.Duration } @@ -314,8 +314,7 @@ func newConntrackCache(maxSize int, orphanTimeout time.Duration) *conntrackCache orphanTimeout: orphanTimeout, } - c.cache, _ = simplelru.NewLRU(maxSize, func(key, value interface{}) { - t := value.(*translationEntry) + c.cache, _ = simplelru.NewLRU(maxSize, func(_ connKey, t *translationEntry) { if t.orphan != nil { c.orphans.Remove(t.orphan) } @@ -325,12 +324,11 @@ func newConntrackCache(maxSize int, orphanTimeout time.Duration) *conntrackCache } func (cc *conntrackCache) Get(k connKey) (*translationEntry, bool) { - v, ok := cc.cache.Get(k) + t, ok := cc.cache.Get(k) if !ok { return nil, false } - t := v.(*translationEntry) if t.orphan != nil { cc.orphans.Remove(t.orphan) t.orphan = nil @@ -355,11 +353,10 @@ func (cc *conntrackCache) Add(c Con, orphan bool) (evicts int) { return } - if v, ok := cc.cache.Peek(key); ok { + if t, ok := cc.cache.Peek(key); ok { // value is going to get replaced // by the call to Add below, make // sure orphan is removed - t := v.(*translationEntry) if t.orphan != nil { cc.orphans.Remove(t.orphan) } diff --git a/pkg/network/netlink/conntracker_test.go b/pkg/network/netlink/conntracker_test.go index 8ecb9d1980f1e..66c9363f937a6 100644 --- a/pkg/network/netlink/conntracker_test.go +++ b/pkg/network/netlink/conntracker_test.go @@ -264,10 +264,9 @@ func TestConntrackCacheAdd(t *testing.T) { } for _, te := range tests { - v, ok := cache.cache.Get(te.k) + tr, ok := cache.cache.Get(te.k) require.True(t, ok, "translation entry not found for key %+v", te.k) - require.NotNil(t, v) - tr := v.(*translationEntry) + require.NotNil(t, tr) require.Equal(t, te.expectedReplSrcIP, tr.IPTranslation.ReplSrcIP.String()) require.Equal(t, te.expectedReplSrcPort, tr.IPTranslation.ReplSrcPort) require.NotNil(t, tr.orphan) @@ -346,9 +345,8 @@ func TestConntrackCacheAdd(t *testing.T) { } for _, te := range tests { - v, ok := cache.cache.Get(te.k) + tr, ok := cache.cache.Get(te.k) require.True(t, ok, "translation entry not found for key %+v", te.k) - tr := v.(*translationEntry) require.Equal(t, te.expectedReplSrcIP, tr.IPTranslation.ReplSrcIP.String()) require.Equal(t, te.expectedReplSrcPort, tr.IPTranslation.ReplSrcPort) require.NotNil(t, tr.orphan) @@ -422,7 +420,7 @@ func crossCheckCacheOrphans(t *testing.T, cc *conntrackCache) { o := l.Value.(*orphanEntry) v, ok := cc.cache.Get(o.key) require.True(t, ok) - require.Equal(t, l, v.(*translationEntry).orphan) + require.Equal(t, l, v.orphan) } } diff --git a/pkg/network/tracer/gateway_lookup.go b/pkg/network/tracer/gateway_lookup.go index cc9230a71f0fb..c68dfef0afe6f 100644 --- a/pkg/network/tracer/gateway_lookup.go +++ b/pkg/network/tracer/gateway_lookup.go @@ -13,7 +13,7 @@ import ( "net" "time" - "github.com/hashicorp/golang-lru/simplelru" + "github.com/hashicorp/golang-lru/v2/simplelru" "github.com/vishvananda/netns" ddconfig "github.com/DataDog/datadog-agent/pkg/config" @@ -50,7 +50,7 @@ type gatewayLookup struct { procRoot string rootNetNs netns.NsHandle routeCache network.RouteCache - subnetCache *simplelru.LRU // interface index to subnet cache + subnetCache *simplelru.LRU[int, interface{}] // interface index to subnet cache subnetForHwAddrFunc func(net.HardwareAddr) (network.Subnet, error) } @@ -99,7 +99,7 @@ func newGatewayLookup(config *config.Config) *gatewayLookup { log.Warnf("using truncated route cache size of %d instead of %d", routeCacheSize, config.MaxTrackedConnections) } - gl.subnetCache, _ = simplelru.NewLRU(maxSubnetCacheSize, nil) + gl.subnetCache, _ = simplelru.NewLRU[int, interface{}](maxSubnetCacheSize, nil) gl.routeCache = network.NewRouteCache(int(routeCacheSize), router) return gl } diff --git a/pkg/network/tracer/process_cache.go b/pkg/network/tracer/process_cache.go index 31b08f679ec24..bcfca951d4e2b 100644 --- a/pkg/network/tracer/process_cache.go +++ b/pkg/network/tracer/process_cache.go @@ -13,7 +13,7 @@ import ( "sync" "time" - lru "github.com/hashicorp/golang-lru" + lru "github.com/hashicorp/golang-lru/v2" smodel "github.com/DataDog/datadog-agent/pkg/security/secl/model" "github.com/DataDog/datadog-agent/pkg/telemetry" @@ -63,7 +63,7 @@ type processCache struct { // match to a connection's timestamp cacheByPid map[uint32]processList // lru cache; keyed by (pid, start time) - cache *lru.Cache + cache *lru.Cache[processCacheKey, *process] // filteredEnvs contains environment variable names // that a process in the cache must have; empty filteredEnvs // means no filter, and any process can be inserted the cache @@ -92,8 +92,7 @@ func newProcessCache(maxProcs int, filteredEnvs []string) (*processCache, error) } var err error - pc.cache, err = lru.NewWithEvict(maxProcs, func(key, value interface{}) { - p := value.(*process) + pc.cache, err = lru.NewWithEvict(maxProcs, func(_ processCacheKey, p *process) { pl, _ := pc.cacheByPid[p.Pid] if pl = pl.remove(p); len(pl) == 0 { delete(pc.cacheByPid, p.Pid) diff --git a/pkg/util/trivy/cache.go b/pkg/util/trivy/cache.go index fe4a7f418f82b..558c93cd0062f 100644 --- a/pkg/util/trivy/cache.go +++ b/pkg/util/trivy/cache.go @@ -21,7 +21,7 @@ import ( "github.com/aquasecurity/trivy/pkg/fanal/cache" "github.com/aquasecurity/trivy/pkg/fanal/types" "github.com/aquasecurity/trivy/pkg/utils" - "github.com/hashicorp/golang-lru/simplelru" + "github.com/hashicorp/golang-lru/v2/simplelru" ) // telemetryTick is the frequency at which the cache usage metrics are collected. @@ -239,7 +239,7 @@ func (c *TrivyCache) GetBlob(id string) (types.BlobInfo, error) { // PersistentCache is a cache that uses a persistent database for storage. type PersistentCache struct { - lruCache *simplelru.LRU + lruCache *simplelru.LRU[string, struct{}] db PersistentDB mutex sync.RWMutex currentCachedObjectTotalSize int @@ -260,8 +260,8 @@ func NewPersistentCache( maximumCachedObjectSize: maxCachedObjectSize, } - lruCache, err := simplelru.NewLRU(maxCacheSize, func(key interface{}, _ interface{}) { - persistentCache.lastEvicted = key.(string) + lruCache, err := simplelru.NewLRU(maxCacheSize, func(key string, _ struct{}) { + persistentCache.lastEvicted = key }) if err != nil { return nil, err @@ -312,7 +312,7 @@ func (c *PersistentCache) Keys() []string { defer c.mutex.RUnlock() keys := make([]string, c.lruCache.Len()) for i, key := range c.lruCache.Keys() { - keys[i] = key.(string) + keys[i] = key } return keys } @@ -495,7 +495,7 @@ func (c *PersistentCache) removeOldestKeyFromMemory() (string, bool) { if ok { telemetry.SBOMCacheEntries.Dec() } - return key.(string), ok + return key, ok } // GetCurrentCachedObjectTotalSize returns the current cached object total size. From f9477807311822bfa0ecebda43361b1cc89e927c Mon Sep 17 00:00:00 2001 From: Paul Cacheux Date: Wed, 7 Jun 2023 09:47:34 -0400 Subject: [PATCH 09/76] [CWS] pre-alloc msg tags (#17434) --- pkg/security/module/server.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pkg/security/module/server.go b/pkg/security/module/server.go index 7b996c3c115d1..b4f5a0d80cef4 100644 --- a/pkg/security/module/server.go +++ b/pkg/security/module/server.go @@ -471,17 +471,19 @@ func (a *APIServer) SendEvent(rule *rules.Rule, event Event, extTagsCb func() [] data = append(data, ruleEventJSON[1:]...) seclog.Tracef("Sending event message for rule `%s` to security-agent `%s`", rule.ID, string(data)) + eventTags := event.GetTags() msg := &pendingMsg{ ruleID: rule.Definition.ID, data: data, extTagsCb: extTagsCb, service: service, sendAfter: time.Now().Add(a.retention), + tags: make([]string, 0, 1+len(rule.Tags)+len(eventTags)+1), } msg.tags = append(msg.tags, "rule_id:"+rule.Definition.ID) msg.tags = append(msg.tags, rule.Tags...) - msg.tags = append(msg.tags, event.GetTags()...) + msg.tags = append(msg.tags, eventTags...) msg.tags = append(msg.tags, common.QueryAccountIdTag()) a.enqueue(msg) From 1ab475f5f308bae5c55368223ecae1f664e2f088 Mon Sep 17 00:00:00 2001 From: Paul Cacheux Date: Wed, 7 Jun 2023 09:48:00 -0400 Subject: [PATCH 10/76] silence error log about `DD_API_KEY` in internal profiler (#17371) --- pkg/util/profiling/profiling.go | 1 + 1 file changed, 1 insertion(+) diff --git a/pkg/util/profiling/profiling.go b/pkg/util/profiling/profiling.go index 95e9920c83cf6..c621fd7bae383 100644 --- a/pkg/util/profiling/profiling.go +++ b/pkg/util/profiling/profiling.go @@ -50,6 +50,7 @@ func Start(settings Settings) error { profiler.CPUDuration(settings.CPUDuration), profiler.WithDeltaProfiles(settings.WithDeltaProfiles), profiler.WithTags(settings.Tags...), + profiler.WithAPIKey(""), // to silence the error log about `DD_API_KEY` } // If block or mutex profiling was configured via runtime configuration, pass current From f81e4cd48685522a2a847e8f0047bfa533ed8c1e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 7 Jun 2023 15:48:29 +0200 Subject: [PATCH 11/76] Bump golang.org/x/sys from 0.3.0 to 0.8.0 in /pkg/gohai (#17106) Bumps [golang.org/x/sys](https://github.com/golang/sys) from 0.3.0 to 0.8.0. - [Commits](https://github.com/golang/sys/compare/v0.3.0...v0.8.0) --- updated-dependencies: - dependency-name: golang.org/x/sys dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkg/gohai/go.mod | 2 +- pkg/gohai/go.sum | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/pkg/gohai/go.mod b/pkg/gohai/go.mod index 595444be50f63..8d3ca07fc1f05 100644 --- a/pkg/gohai/go.mod +++ b/pkg/gohai/go.mod @@ -8,7 +8,7 @@ require ( github.com/cihub/seelog v0.0.0-20151216151435-d2c6e5aa9fbf github.com/shirou/gopsutil/v3 v3.22.12 github.com/stretchr/testify v1.8.2 - golang.org/x/sys v0.3.0 + golang.org/x/sys v0.8.0 ) require ( diff --git a/pkg/gohai/go.sum b/pkg/gohai/go.sum index e830771143e0b..a9e92a927efce 100644 --- a/pkg/gohai/go.sum +++ b/pkg/gohai/go.sum @@ -33,8 +33,9 @@ github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQ golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.3.0 h1:w8ZOecv6NaNa/zC8944JTU3vz4u6Lagfk4RPQxv92NQ= golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= From 2e9f9b0ba47252986ddf8b0b538d324633f0e566 Mon Sep 17 00:00:00 2001 From: Pierre Gimalac Date: Wed, 7 Jun 2023 15:49:03 +0200 Subject: [PATCH 12/76] [Gohai] Add common elements of the future new API (#17221) * chore(gohai): use go version 1.18 to have generics * feat(gohai): implement Value type * feat(gohai): implement AsJSON and Initialize * fix(gohai): fix lint warnings * docs(gohai): add copyright in new files * feat(gohai): add NewValueFrom method in Value * feat(gohai): display suffix field tag in AsJSON * Fix typo in pkg/gohai/utils/common.go Co-authored-by: Nicolas Guerguadj <35628945+Kaderinho@users.noreply.github.com> * fix(gohai): address review comments * feat(gohai): simplify common, remove Initialize * docs(gohai): address comments review feedback * feat(gohai): simplify AsJSON logic * feat(gohai): return warnings as list of strings in AsJSON * fix(gohai): fix common tests * docs(gohai): fix comments/naming related review feedback * test(gohai): simplify tests following pr review --------- Co-authored-by: Nicolas Guerguadj <35628945+Kaderinho@users.noreply.github.com> --- pkg/gohai/go.mod | 2 +- pkg/gohai/utils/common.go | 183 +++++++++++++++++++++++++ pkg/gohai/utils/common_test.go | 236 +++++++++++++++++++++++++++++++++ pkg/gohai/utils/value.go | 61 +++++++++ pkg/gohai/utils/value_test.go | 46 +++++++ 5 files changed, 527 insertions(+), 1 deletion(-) create mode 100644 pkg/gohai/utils/common.go create mode 100644 pkg/gohai/utils/common_test.go create mode 100644 pkg/gohai/utils/value.go create mode 100644 pkg/gohai/utils/value_test.go diff --git a/pkg/gohai/go.mod b/pkg/gohai/go.mod index 8d3ca07fc1f05..07a1fd5cf12ec 100644 --- a/pkg/gohai/go.mod +++ b/pkg/gohai/go.mod @@ -2,7 +2,7 @@ module github.com/DataDog/datadog-agent/pkg/gohai // we don't want to just use the agent's go version because gohai might be used outside of it // eg. opentelemetry -go 1.17 +go 1.18 require ( github.com/cihub/seelog v0.0.0-20151216151435-d2c6e5aa9fbf diff --git a/pkg/gohai/utils/common.go b/pkg/gohai/utils/common.go new file mode 100644 index 0000000000000..b95b4aed0e306 --- /dev/null +++ b/pkg/gohai/utils/common.go @@ -0,0 +1,183 @@ +// This file is licensed under the MIT License. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2014-present Datadog, Inc. + +package utils + +import ( + "errors" + "fmt" + "reflect" + "runtime" +) + +var ErrNoFieldCollected = errors.New("no field was collected") +var ErrArgNotStruct = errors.New("argument is not a struct") +var ErrNotCollectable = fmt.Errorf("cannot be collected on %s %s", runtime.GOOS, runtime.GOARCH) +var ErrNotExported = errors.New("field not exported by the struct") +var ErrCannotRender = errors.New("field inner type cannot be rendered") +var ErrNoValueMethod = errors.New("field doesn't have the expected Value method") +var ErrNoJSONTag = errors.New("field doesn't have a json tag") + +// reflectValueToString converts the given value to a string, and returns a boolean indicating +// whether it succeeded +// +// Supported types are int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, float32, float64, string +func reflectValueToString(value reflect.Value) (string, bool) { + var rendered string + switch value.Kind() { + // case reflect.Bool: + case reflect.Int: + rendered = fmt.Sprintf("%d", value.Interface().(int)) + case reflect.Int8: + rendered = fmt.Sprintf("%d", value.Interface().(int8)) + case reflect.Int16: + rendered = fmt.Sprintf("%d", value.Interface().(int16)) + case reflect.Int32: + rendered = fmt.Sprintf("%d", value.Interface().(int32)) + case reflect.Int64: + rendered = fmt.Sprintf("%d", value.Interface().(int64)) + case reflect.Uint: + rendered = fmt.Sprintf("%d", value.Interface().(uint)) + case reflect.Uint8: + rendered = fmt.Sprintf("%d", value.Interface().(uint8)) + case reflect.Uint16: + rendered = fmt.Sprintf("%d", value.Interface().(uint16)) + case reflect.Uint32: + rendered = fmt.Sprintf("%d", value.Interface().(uint32)) + case reflect.Uint64: + rendered = fmt.Sprintf("%d", value.Interface().(uint64)) + // case reflect.Uintptr: + case reflect.Float32: + rendered = fmt.Sprintf("%f", value.Interface().(float32)) + case reflect.Float64: + rendered = fmt.Sprintf("%f", value.Interface().(float64)) + // case reflect.Complex64: + // case reflect.Complex128: + // case reflect.Array: + // case reflect.Chan: + // case reflect.Func: + // case reflect.Interface: + // case reflect.Map: + // case reflect.Pointer: + // case reflect.Slice: + case reflect.String: + rendered = value.String() + // case reflect.Struct: + // case reflect.UnsafePointer: + default: + return "", false + } + + return rendered, true +} + +// getValueMethod returns whether the field has a Value function with the correct arguments and return types. +// +// Since we don't know the specific T, we can't cast to an interface, and reflect doesn't have any way to check +// a generic type as long as https://github.com/golang/go/issues/54393 is not implemented. +func getValueMethod(fieldTy reflect.StructField) (reflect.Method, bool) { + // check that a pointer to the field type has a Value method + // (Value is a method on *Value[T]) + valueMethod, ok := reflect.PtrTo(fieldTy.Type).MethodByName("Value") + if !ok || valueMethod.Type.NumIn() != 1 || valueMethod.Type.NumOut() != 2 { + return reflect.Method{}, false + } + + // check that the second return value is an error + reflErrorInterface := reflect.TypeOf((*error)(nil)).Elem() + secondRetType := valueMethod.Type.Out(1) + if !secondRetType.Implements(reflErrorInterface) { + return reflect.Method{}, false + } + + return valueMethod, true +} + +// AsJSON takes a structure and returns a marshal-able object representing the fields of the struct, +// the lists of errors for fields for which the collection failed, and an error if it failed. +// +// If useDefault is true, fields which failed to be collected will be included in the marshal-able object +// as their default value, otherwise they are ignored. +// +// Fields which are not exported, don't have a json tag or are not of type Value[T] for a T which can +// be rendered cause the function to return an error. +// +// The string list contain errors of fields which failed to be collected. Fields which are not +// collected on the platform are ignored. +// +// If the error is non-nil, the first two parameters are unspecified. +func AsJSON[T any](info *T, useDefault bool) (interface{}, []string, error) { + reflVal := reflect.ValueOf(info).Elem() + reflType := reflect.TypeOf(info).Elem() + + // info has to be a struct + if reflVal.Kind() != reflect.Struct { + return nil, nil, ErrArgNotStruct + } + + values := make(map[string]interface{}) + warns := []string{} + + for i := 0; i < reflVal.NumField(); i++ { + fieldTy := reflType.Field(i) + fieldName := fieldTy.Name + + // check if field is exported + if !fieldTy.IsExported() { + return nil, nil, fmt.Errorf("%s: %w", fieldName, ErrNotExported) + } + + // check if field has a json tag + jsonName, ok := fieldTy.Tag.Lookup("json") + if !ok { + return nil, nil, fmt.Errorf("%s: %w", fieldName, ErrNoJSONTag) + } + + // check that the field has the expected Value method + valueMethod, ok := getValueMethod(fieldTy) + if !ok { + return nil, nil, fmt.Errorf("%s: %w", fieldName, ErrNoValueMethod) + } + + ret := valueMethod.Func.Call([]reflect.Value{reflVal.Field(i).Addr()}) + retValue := ret[0] + if ret[1].Interface() != nil { + // get the error returned by Value + err := ret[1].Interface().(error) + + // we want errors for fields which failed to collect + // ErrNotCollectable means that the field is not implemented on the current platform + // ignore these errors + if !errors.Is(err, ErrNotCollectable) { + warns = append(warns, err.Error()) + } + + // if the field is an error and we don't want to print the default value, continue + if !useDefault { + continue + } + + // use the default value of the type + retValue = reflect.Zero(retValue.Type()) + } + + // try to render the value + renderedValue, ok := reflectValueToString(retValue) + if !ok { + return nil, nil, fmt.Errorf("%s: %w", fieldName, ErrCannotRender) + } + + // Get returns an empty string if the key does not exist so no need for particular error handling + unit := fieldTy.Tag.Get("unit") + + values[jsonName] = fmt.Sprintf("%s%s", renderedValue, unit) + } + + // return an error if no field was successfully collected + if len(values) == 0 { + return nil, warns, ErrNoFieldCollected + } + + return values, warns, nil +} diff --git a/pkg/gohai/utils/common_test.go b/pkg/gohai/utils/common_test.go new file mode 100644 index 0000000000000..aa50a4ee63ab2 --- /dev/null +++ b/pkg/gohai/utils/common_test.go @@ -0,0 +1,236 @@ +// This file is licensed under the MIT License. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2014-present Datadog, Inc. + +package utils + +import ( + "encoding/json" + "errors" + "fmt" + "testing" + + "github.com/stretchr/testify/require" +) + +// TestAsJSONTypes tests that each supported type can appear properly in the output +func TestAsJSONTypes(t *testing.T) { + info := &struct { + SomeInt Value[int] `json:"my_int"` + SomeInt8 Value[int8] `json:"my_int8"` + SomeInt16 Value[int16] `json:"my_int16"` + SomeInt32 Value[int32] `json:"my_int32"` + SomeInt64 Value[int64] `json:"my_int64"` + SomeUint Value[uint] `json:"my_uint"` + SomeUint8 Value[uint8] `json:"my_uint8"` + SomeUint16 Value[uint16] `json:"my_uint16"` + SomeUint32 Value[uint32] `json:"my_uint32"` + SomeUint64 Value[uint64] `json:"my_uint64"` + SomeFloat32 Value[float32] `json:"my_float32"` + SomeFloat64 Value[float64] `json:"my_float64"` + SomeString Value[string] `json:"my_string"` + }{ + SomeInt: NewValue(1), + SomeInt8: NewValue[int8](2), + SomeInt16: NewValue[int16](3), + SomeInt32: NewValue[int32](4), + SomeInt64: NewValue[int64](5), + SomeUint: NewValue[uint](6), + SomeUint8: NewValue[uint8](7), + SomeUint16: NewValue[uint16](8), + SomeUint32: NewValue[uint32](9), + SomeUint64: NewValue[uint64](10), + SomeFloat32: NewValue[float32](32.), + SomeFloat64: NewValue(64.), + SomeString: NewValue("mystr"), + } + + marshallable, warns, err := AsJSON(info, false) + require.NoError(t, err) + require.Empty(t, warns) + + marshalled, err := json.Marshal(marshallable) + require.NoError(t, err) + + // use format specifier for floats to make sure the formatting is the same + expected := fmt.Sprintf(`{ + "my_int": "1", + "my_int8": "2", + "my_int16": "3", + "my_int32": "4", + "my_int64": "5", + "my_uint": "6", + "my_uint8": "7", + "my_uint16": "8", + "my_uint32": "9", + "my_uint64": "10", + "my_float32": "%f", + "my_float64": "%f", + "my_string": "mystr" + }`, float32(32.), 64.) + require.JSONEq(t, expected, string(marshalled)) +} + +func TestAsJSONEmpty(t *testing.T) { + info := &struct{}{} + _, _, err := AsJSON(info, false) + require.ErrorIs(t, err, ErrNoFieldCollected) + + _, _, err = AsJSON(info, true) + require.ErrorIs(t, err, ErrNoFieldCollected) +} + +// TestAsJsonInvalidParam tests that using something other than struct returns an error +func TestAsJsonInvalidParam(t *testing.T) { + var err error + // slice + _, _, err = AsJSON(&[]int{1}, false) + require.ErrorIs(t, err, ErrArgNotStruct) + // array + _, _, err = AsJSON(&[1]int{1}, false) + require.ErrorIs(t, err, ErrArgNotStruct) + // pointer + p := &struct{}{} + _, _, err = AsJSON(&p, false) + require.ErrorIs(t, err, ErrArgNotStruct) +} + +// TestAsJsonFieldError checks that AsJSON returns an error when there is a field which cannot be exported +// - type is not Value +// - no json tag +// - not exported +// - Value inner type cannot be rendered (struct, ptr, ...) +func TestAsJsonFieldError(t *testing.T) { + infoNotValue := &struct { + NotValue int `json:"not_value"` + }{ + NotValue: 1, + } + + _, _, err := AsJSON(infoNotValue, false) + require.ErrorIs(t, err, ErrNoValueMethod) + + infoNoTag := &struct { + NoTag Value[int] + }{ + NoTag: NewValue(2), + } + _, _, err = AsJSON(infoNoTag, false) + require.ErrorIs(t, err, ErrNoJSONTag) + + infoNotExported := &struct { + // use a json tag to make sure the error is due to the field not being exported + // but govet doesn't like that + notExported Value[int] `json:"not_exported"` //nolint:govet + }{ + notExported: NewValue(3), + } + _, _, err = AsJSON(infoNotExported, false) + require.ErrorIs(t, err, ErrNotExported) + + infoValueStruct := &struct { + ValueStruct Value[struct{}] `json:"value_struct"` + }{ + ValueStruct: NewValue(struct{}{}), + } + _, _, err = AsJSON(infoValueStruct, false) + require.ErrorIs(t, err, ErrCannotRender) + + infoValuePtr := &struct { + ValuePtr Value[*int] `json:"value_ptr"` + }{ + ValuePtr: NewValue[*int](nil), + } + _, _, err = AsJSON(infoValuePtr, false) + require.ErrorIs(t, err, ErrCannotRender) +} + +func TestAsJsonWarns(t *testing.T) { + errs := []string{ + "this is the first error", + "this is the second error", + "this is the third error", + "this is the fourth error", + } + info := &struct { + FieldOne Value[int] `json:"field_one"` + FieldTwo Value[int] `json:"field_two"` + FieldThree Value[int] `json:"field_three"` + FieldFour Value[int] `json:"field_four"` + FieldFive Value[int] `json:"field_five"` + }{ + FieldOne: NewErrorValue[int](errors.New(errs[0])), + FieldTwo: NewErrorValue[int](errors.New(errs[1])), + FieldThree: NewErrorValue[int](errors.New(errs[2])), + FieldFour: NewErrorValue[int](errors.New(errs[3])), + FieldFive: NewValue(1), + } + + marshallable, warns, err := AsJSON(info, false) + require.NoError(t, err) + require.ElementsMatch(t, errs, warns) + + marshalled, err := json.Marshal(marshallable) + require.NoError(t, err) + + expected := `{ + "field_five": "1" + }` + require.JSONEq(t, expected, string(marshalled)) + + marshallable, warns, err = AsJSON(info, true) + require.NoError(t, err) + require.ElementsMatch(t, errs, warns) + + marshalled, err = json.Marshal(marshallable) + require.NoError(t, err) + + expected = `{ + "field_one": "0", + "field_two": "0", + "field_three": "0", + "field_four": "0", + "field_five": "1" + }` + require.JSONEq(t, expected, string(marshalled)) +} + +func TestAsJSONSuffix(t *testing.T) { + errs := []string{ + "this is the first error", + "this is the second error", + "this is the third error", + } + info := &struct { + FieldOne Value[int] `json:"field_one"` + FieldTwo Value[int] `json:"field_two" unit:""` + FieldThree Value[int] `json:"field_three" unit:"kb"` + FieldFour Value[int] `json:"field_four"` + FieldFive Value[int] `json:"field_five" unit:""` + FieldSix Value[int] `json:"field_six" unit:"M"` + }{ + FieldOne: NewValue(1), + FieldTwo: NewValue(2), + FieldThree: NewValue(3), + FieldFour: NewErrorValue[int](errors.New(errs[0])), + FieldFive: NewErrorValue[int](errors.New(errs[1])), + FieldSix: NewErrorValue[int](errors.New(errs[2])), + } + + marshallable, warns, err := AsJSON(info, true) + require.NoError(t, err) + require.ElementsMatch(t, errs, warns) + + marshalled, err := json.Marshal(marshallable) + require.NoError(t, err) + + expected := `{ + "field_one": "1", + "field_two": "2", + "field_three": "3kb", + "field_four": "0", + "field_five": "0", + "field_six": "0M" + }` + require.JSONEq(t, expected, string(marshalled)) +} diff --git a/pkg/gohai/utils/value.go b/pkg/gohai/utils/value.go new file mode 100644 index 0000000000000..ee5a8175e554e --- /dev/null +++ b/pkg/gohai/utils/value.go @@ -0,0 +1,61 @@ +// This file is licensed under the MIT License. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2014-present Datadog, Inc. + +package utils + +import ( + "errors" +) + +// Value represents either an error or an actual value of type T. +// +// The default value of the type is an error saying that the value was not initialized. +type Value[T any] struct { + value T + err error + initialized bool +} + +// NewValue initializes a Value[T] with the given value of type T and no error. +func NewValue[T any](value T) Value[T] { + return Value[T]{ + value: value, + initialized: true, + } +} + +// NewValueFrom returns a Value[T] from a value and an error. +// If the error is non-nil then it represents this error, otherwise it represents the value. +// +// This is a convenient function to get a Value from a function which returns a value and an error. +func NewValueFrom[T any](value T, err error) Value[T] { + if err != nil { + return NewErrorValue[T](err) + } + return NewValue(value) +} + +// NewErrorValue initializes a Value[T] with the given error. +// +// Note that if err is nil, the returned Value[T] is fundamentally equivalent to a Value[T] +// containing the default value of T and no error. +func NewErrorValue[T any](err error) Value[T] { + return Value[T]{ + err: err, + initialized: true, + } +} + +// Value returns the value and the error stored in the Value[T]. +// +// If the Value[T] represents an error, it returns the default value of type T +// and a non-nil error, otherwise the stored value of type T and a nil error. +func (value *Value[T]) Value() (T, error) { + if value.initialized { + return value.value, value.err + } else { + var def T + return def, errors.New("value not initialized") + } +} diff --git a/pkg/gohai/utils/value_test.go b/pkg/gohai/utils/value_test.go new file mode 100644 index 0000000000000..2daecf47b3fc3 --- /dev/null +++ b/pkg/gohai/utils/value_test.go @@ -0,0 +1,46 @@ +// This file is licensed under the MIT License. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2014-present Datadog, Inc. + +package utils + +import ( + "errors" + "fmt" + "testing" + + "github.com/stretchr/testify/require" +) + +func TestValueDefault(t *testing.T) { + value := Value[int]{} + _, err := value.Value() + require.Error(t, err) +} + +func TestNewValue(t *testing.T) { + value := NewValue(42) + v, err := value.Value() + require.NoError(t, err) + require.Equal(t, 42, v) +} + +func TestNewErrorValue(t *testing.T) { + myErr := errors.New("this is an error") + value := NewErrorValue[int](myErr) + result, err := value.Value() + require.ErrorIs(t, err, myErr) + require.Equal(t, 0, result) +} + +func TestNewValueFrom(t *testing.T) { + myerr := fmt.Errorf("yet another error") + value := NewValueFrom(42, myerr) + _, err := value.Value() + require.ErrorIs(t, err, myerr) + + value = NewValueFrom(42, nil) + val, err := value.Value() + require.NoError(t, err) + require.Equal(t, 42, val) +} From 6c439d8f0e0a085d4eab7f88dd56dac33c3b259a Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 7 Jun 2023 09:50:11 -0400 Subject: [PATCH 13/76] CWS: sync BTFhub constants (#17498) Co-authored-by: paulcacheux --- .../probe/constantfetch/btfhub/constants.json | 107 +++++++++++++++++- 1 file changed, 106 insertions(+), 1 deletion(-) diff --git a/pkg/security/probe/constantfetch/btfhub/constants.json b/pkg/security/probe/constantfetch/btfhub/constants.json index 16b26a6977689..0a4e1de7b00d0 100644 --- a/pkg/security/probe/constantfetch/btfhub/constants.json +++ b/pkg/security/probe/constantfetch/btfhub/constants.json @@ -1,5 +1,5 @@ { - "commit": "8cf236a3f30f50eb9460626ca07e1d5cd02e7dc4", + "commit": "836f43887cabdfc30549a1cd49c2ee2ca08e46f5", "constants": [ { "binprm_file_offset": 168, @@ -9184,6 +9184,13 @@ "uname_release": "3.10.0-1160.88.1.el7.x86_64", "cindex": 33 }, + { + "distrib": "centos", + "version": "7", + "arch": "x86_64", + "uname_release": "3.10.0-1160.90.1.el7.x86_64", + "cindex": 33 + }, { "distrib": "centos", "version": "7", @@ -9611,6 +9618,27 @@ "uname_release": "5.10.0-0.deb10.22-rt-arm64", "cindex": 46 }, + { + "distrib": "debian", + "version": "10", + "arch": "arm64", + "uname_release": "5.10.0-0.deb10.23-arm64", + "cindex": 45 + }, + { + "distrib": "debian", + "version": "10", + "arch": "arm64", + "uname_release": "5.10.0-0.deb10.23-cloud-arm64", + "cindex": 45 + }, + { + "distrib": "debian", + "version": "10", + "arch": "arm64", + "uname_release": "5.10.0-0.deb10.23-rt-arm64", + "cindex": 46 + }, { "distrib": "debian", "version": "10", @@ -9884,6 +9912,27 @@ "uname_release": "5.10.0-0.deb10.22-rt-amd64", "cindex": 52 }, + { + "distrib": "debian", + "version": "10", + "arch": "x86_64", + "uname_release": "5.10.0-0.deb10.23-amd64", + "cindex": 51 + }, + { + "distrib": "debian", + "version": "10", + "arch": "x86_64", + "uname_release": "5.10.0-0.deb10.23-cloud-amd64", + "cindex": 51 + }, + { + "distrib": "debian", + "version": "10", + "arch": "x86_64", + "uname_release": "5.10.0-0.deb10.23-rt-amd64", + "cindex": 52 + }, { "distrib": "debian", "version": "9", @@ -12068,6 +12117,13 @@ "uname_release": "4.14.35-2047.526.1.el7uek.aarch64", "cindex": 77 }, + { + "distrib": "ol", + "version": "7", + "arch": "arm64", + "uname_release": "4.14.35-2047.526.2.el7uek.aarch64", + "cindex": 77 + }, { "distrib": "ol", "version": "7", @@ -16828,6 +16884,13 @@ "uname_release": "4.14.35-2047.526.1.el7uek.x86_64", "cindex": 85 }, + { + "distrib": "ol", + "version": "7", + "arch": "x86_64", + "uname_release": "4.14.35-2047.526.2.el7uek.x86_64", + "cindex": 85 + }, { "distrib": "ol", "version": "7", @@ -25704,6 +25767,13 @@ "uname_release": "4.15.0-1156-aws", "cindex": 129 }, + { + "distrib": "ubuntu", + "version": "18.04", + "arch": "arm64", + "uname_release": "4.15.0-1157-aws", + "cindex": 129 + }, { "distrib": "ubuntu", "version": "18.04", @@ -26117,6 +26187,13 @@ "uname_release": "4.15.0-211-generic", "cindex": 129 }, + { + "distrib": "ubuntu", + "version": "18.04", + "arch": "arm64", + "uname_release": "4.15.0-212-generic", + "cindex": 129 + }, { "distrib": "ubuntu", "version": "18.04", @@ -29099,6 +29176,13 @@ "uname_release": "4.15.0-1151-azure", "cindex": 140 }, + { + "distrib": "ubuntu", + "version": "18.04", + "arch": "x86_64", + "uname_release": "4.15.0-1151-gcp", + "cindex": 115 + }, { "distrib": "ubuntu", "version": "18.04", @@ -29134,6 +29218,13 @@ "uname_release": "4.15.0-1156-aws", "cindex": 115 }, + { + "distrib": "ubuntu", + "version": "18.04", + "arch": "x86_64", + "uname_release": "4.15.0-1157-aws", + "cindex": 115 + }, { "distrib": "ubuntu", "version": "18.04", @@ -29190,6 +29281,13 @@ "uname_release": "4.15.0-1165-azure", "cindex": 140 }, + { + "distrib": "ubuntu", + "version": "18.04", + "arch": "x86_64", + "uname_release": "4.15.0-1166-azure", + "cindex": 140 + }, { "distrib": "ubuntu", "version": "18.04", @@ -29603,6 +29701,13 @@ "uname_release": "4.15.0-211-generic", "cindex": 115 }, + { + "distrib": "ubuntu", + "version": "18.04", + "arch": "x86_64", + "uname_release": "4.15.0-212-generic", + "cindex": 115 + }, { "distrib": "ubuntu", "version": "18.04", From ba710b2f51f7e9158d8c69339bc083b0dca7e67c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 7 Jun 2023 09:51:19 -0400 Subject: [PATCH 14/76] Bump golang.org/x/tools from 0.9.1 to 0.9.3 in /pkg/security/secl (#17479) * Bump golang.org/x/tools from 0.9.1 to 0.9.3 in /pkg/security/secl Bumps [golang.org/x/tools](https://github.com/golang/tools) from 0.9.1 to 0.9.3. - [Release notes](https://github.com/golang/tools/releases) - [Commits](https://github.com/golang/tools/compare/v0.9.1...v0.9.3) --- updated-dependencies: - dependency-name: golang.org/x/tools dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * Auto-generate go.sum and LICENSE-3rdparty.csv changes --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- pkg/security/secl/go.mod | 2 +- pkg/security/secl/go.sum | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index b6b7ed39504ad..9d213b29e1b86 100644 --- a/go.mod +++ b/go.mod @@ -217,7 +217,7 @@ require ( golang.org/x/sys v0.8.0 golang.org/x/text v0.9.0 golang.org/x/time v0.3.0 - golang.org/x/tools v0.9.1 + golang.org/x/tools v0.9.3 golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect google.golang.org/grpc v1.55.0 diff --git a/go.sum b/go.sum index d4783c455a2d9..f16e6ca58d789 100644 --- a/go.sum +++ b/go.sum @@ -2513,8 +2513,8 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k= golang.org/x/tools v0.4.0/go.mod h1:UE5sM2OK9E/d67R0ANs2xJizIymRP5gJU295PvKXxjQ= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.9.1 h1:8WMNJAz3zrtPmnYC7ISf5dEn3MT0gY7jBJfw27yrrLo= -golang.org/x/tools v0.9.1/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc= +golang.org/x/tools v0.9.3 h1:Gn1I8+64MsuTb/HpH+LmQtNas23LhUVr3rYZ0eKuaMM= +golang.org/x/tools v0.9.3/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/pkg/security/secl/go.mod b/pkg/security/secl/go.mod index 365a2c711df4c..d13793c200388 100644 --- a/pkg/security/secl/go.mod +++ b/pkg/security/secl/go.mod @@ -16,7 +16,7 @@ require ( github.com/stretchr/testify v1.8.3 golang.org/x/exp v0.0.0-20221114191408-850992195362 golang.org/x/sys v0.8.0 - golang.org/x/tools v0.9.1 + golang.org/x/tools v0.9.3 gopkg.in/yaml.v2 v2.4.0 gopkg.in/yaml.v3 v3.0.1 ) diff --git a/pkg/security/secl/go.sum b/pkg/security/secl/go.sum index 7f26045cddb5d..0de67ae6a2c3f 100644 --- a/pkg/security/secl/go.sum +++ b/pkg/security/secl/go.sum @@ -94,8 +94,8 @@ golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.9.1 h1:8WMNJAz3zrtPmnYC7ISf5dEn3MT0gY7jBJfw27yrrLo= -golang.org/x/tools v0.9.1/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc= +golang.org/x/tools v0.9.3 h1:Gn1I8+64MsuTb/HpH+LmQtNas23LhUVr3rYZ0eKuaMM= +golang.org/x/tools v0.9.3/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= From 9115720e5ad19eb315fe1548a5a79de02a5ad82e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 7 Jun 2023 09:52:11 -0400 Subject: [PATCH 15/76] Bump github.com/stretchr/testify from 1.8.3 to 1.8.4 in /pkg/security/secl (#17478) * Bump github.com/stretchr/testify in /pkg/security/secl Bumps [github.com/stretchr/testify](https://github.com/stretchr/testify) from 1.8.3 to 1.8.4. - [Release notes](https://github.com/stretchr/testify/releases) - [Commits](https://github.com/stretchr/testify/compare/v1.8.3...v1.8.4) --- updated-dependencies: - dependency-name: github.com/stretchr/testify dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * Auto-generate go.sum and LICENSE-3rdparty.csv changes --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- pkg/security/secl/go.mod | 2 +- pkg/security/secl/go.sum | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 9d213b29e1b86..1511231963940 100644 --- a/go.mod +++ b/go.mod @@ -177,7 +177,7 @@ require ( github.com/spf13/cobra v1.7.0 github.com/spf13/pflag v1.0.5 github.com/streadway/amqp v1.0.0 - github.com/stretchr/testify v1.8.3 + github.com/stretchr/testify v1.8.4 github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 github.com/tinylib/msgp v1.1.8 github.com/twmb/murmur3 v1.1.6 diff --git a/go.sum b/go.sum index f16e6ca58d789..2dd83291bccc6 100644 --- a/go.sum +++ b/go.sum @@ -1775,8 +1775,8 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= -github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stvp/go-udp-testing v0.0.0-20201019212854-469649b16807/go.mod h1:7jxmlfBCDBXRzr0eAQJ48XC1hBu1np4CS5+cHEYfwpc= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= diff --git a/pkg/security/secl/go.mod b/pkg/security/secl/go.mod index d13793c200388..b7f82101eaddd 100644 --- a/pkg/security/secl/go.mod +++ b/pkg/security/secl/go.mod @@ -13,7 +13,7 @@ require ( github.com/hashicorp/golang-lru/v2 v2.0.2 github.com/skydive-project/go-debouncer v1.0.0 github.com/spf13/cast v1.5.1 - github.com/stretchr/testify v1.8.3 + github.com/stretchr/testify v1.8.4 golang.org/x/exp v0.0.0-20221114191408-850992195362 golang.org/x/sys v0.8.0 golang.org/x/tools v0.9.3 diff --git a/pkg/security/secl/go.sum b/pkg/security/secl/go.sum index 0de67ae6a2c3f..9782751bbbb07 100644 --- a/pkg/security/secl/go.sum +++ b/pkg/security/secl/go.sum @@ -56,8 +56,8 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= -github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= From 50c85b695bfc21b689dd5890b0c5550c6b72c93d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 7 Jun 2023 09:52:34 -0400 Subject: [PATCH 16/76] Bump requests from 2.30.0 to 2.31.0 in /test/e2e/cws-tests (#17428) Bumps [requests](https://github.com/psf/requests) from 2.30.0 to 2.31.0. - [Release notes](https://github.com/psf/requests/releases) - [Changelog](https://github.com/psf/requests/blob/main/HISTORY.md) - [Commits](https://github.com/psf/requests/compare/v2.30.0...v2.31.0) --- updated-dependencies: - dependency-name: requests dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- test/e2e/cws-tests/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/e2e/cws-tests/requirements.txt b/test/e2e/cws-tests/requirements.txt index a931ee676a87b..16619af26582d 100644 --- a/test/e2e/cws-tests/requirements.txt +++ b/test/e2e/cws-tests/requirements.txt @@ -4,4 +4,4 @@ pyaml==23.5.9 docker==6.1.2 retry==0.9.2 emoji==2.2.0 -requests==2.30.0 +requests==2.31.0 From 37496bd05a55a96af8f17d726fe9acab0c54da4e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 7 Jun 2023 09:52:48 -0400 Subject: [PATCH 17/76] Bump docker from 6.1.2 to 6.1.3 in /test/e2e/cws-tests (#17427) Bumps [docker](https://github.com/docker/docker-py) from 6.1.2 to 6.1.3. - [Release notes](https://github.com/docker/docker-py/releases) - [Commits](https://github.com/docker/docker-py/compare/6.1.2...6.1.3) --- updated-dependencies: - dependency-name: docker dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- test/e2e/cws-tests/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/e2e/cws-tests/requirements.txt b/test/e2e/cws-tests/requirements.txt index 16619af26582d..7ac7b0c3cfab9 100644 --- a/test/e2e/cws-tests/requirements.txt +++ b/test/e2e/cws-tests/requirements.txt @@ -1,7 +1,7 @@ kubernetes==26.1.0 datadog-api-client==2.12.0 pyaml==23.5.9 -docker==6.1.2 +docker==6.1.3 retry==0.9.2 emoji==2.2.0 requests==2.31.0 From 9eb060263cab71fc44e3c37da8b7c642d0b53887 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 7 Jun 2023 09:53:33 -0400 Subject: [PATCH 18/76] Bump datadog-api-client from 2.12.0 to 2.13.1 in /test/e2e/cws-tests (#17429) Bumps [datadog-api-client](https://github.com/DataDog/datadog-api-client-python) from 2.12.0 to 2.13.1. - [Release notes](https://github.com/DataDog/datadog-api-client-python/releases) - [Changelog](https://github.com/DataDog/datadog-api-client-python/blob/master/CHANGELOG.md) - [Commits](https://github.com/DataDog/datadog-api-client-python/compare/2.12.0...2.13.1) --- updated-dependencies: - dependency-name: datadog-api-client dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- test/e2e/cws-tests/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/e2e/cws-tests/requirements.txt b/test/e2e/cws-tests/requirements.txt index 7ac7b0c3cfab9..0e6e90f5c1630 100644 --- a/test/e2e/cws-tests/requirements.txt +++ b/test/e2e/cws-tests/requirements.txt @@ -1,5 +1,5 @@ kubernetes==26.1.0 -datadog-api-client==2.12.0 +datadog-api-client==2.13.1 pyaml==23.5.9 docker==6.1.3 retry==0.9.2 From 27585c5de8d69bf67e3c92d3cd9069c473166ae8 Mon Sep 17 00:00:00 2001 From: Adam Karpowich Date: Wed, 7 Jun 2023 08:55:15 -0500 Subject: [PATCH 19/76] [system-probe] only increment unregisters metric if delete actually occurs (#17402) * only increment unregisters if delete actually occurs * measure time from start of delete function, only increment if no err --- pkg/network/tracer/connection/tracer.go | 1 - pkg/network/tracer/ebpf_conntracker.go | 7 ++++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pkg/network/tracer/connection/tracer.go b/pkg/network/tracer/connection/tracer.go index 1ba235f281239..947d3ecee3c35 100644 --- a/pkg/network/tracer/connection/tracer.go +++ b/pkg/network/tracer/connection/tracer.go @@ -75,7 +75,6 @@ type Tracer interface { const ( defaultClosedChannelSize = 500 - ProbeUID = "net" connTracerModuleName = "network_tracer__ebpf" ) diff --git a/pkg/network/tracer/ebpf_conntracker.go b/pkg/network/tracer/ebpf_conntracker.go index f841afe959840..c4907fa905656 100644 --- a/pkg/network/tracer/ebpf_conntracker.go +++ b/pkg/network/tracer/ebpf_conntracker.go @@ -299,17 +299,20 @@ func (e *ebpfConntracker) get(src *netebpf.ConntrackTuple) *netebpf.ConntrackTup } func (e *ebpfConntracker) delete(key *netebpf.ConntrackTuple) { + start := time.Now() if err := e.ctMap.Delete(unsafe.Pointer(key)); err != nil { if errors.Is(err, ebpf.ErrKeyNotExist) { log.Tracef("connection does not exist in ebpf conntrack map: %s", key) return } log.Warnf("unable to delete conntrack entry from eBPF map: %s", err) + } else { + conntrackerTelemetry.unregistersTotal.Inc() + conntrackerTelemetry.unregistersDuration.Observe(float64(time.Since(start).Nanoseconds())) } } func (e *ebpfConntracker) DeleteTranslation(stats network.ConnectionStats) { - start := time.Now() key := tuplePool.Get().(*netebpf.ConntrackTuple) defer tuplePool.Put(key) @@ -321,8 +324,6 @@ func (e *ebpfConntracker) DeleteTranslation(stats network.ConnectionStats) { e.delete(dst) tuplePool.Put(dst) } - conntrackerTelemetry.unregistersTotal.Inc() - conntrackerTelemetry.unregistersDuration.Observe(float64(time.Since(start).Nanoseconds())) } // Refreshes conntracker telemetry on a loop From 41fe3699ac7a24a9a90f61cb1b71aaff3a7228ad Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 7 Jun 2023 09:56:07 -0400 Subject: [PATCH 20/76] Bump github.com/prometheus/procfs from 0.10.0 to 0.10.1 (#17347) Bumps [github.com/prometheus/procfs](https://github.com/prometheus/procfs) from 0.10.0 to 0.10.1. - [Release notes](https://github.com/prometheus/procfs/releases) - [Commits](https://github.com/prometheus/procfs/compare/v0.10.0...v0.10.1) --- updated-dependencies: - dependency-name: github.com/prometheus/procfs dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 1511231963940..e76922fccce2d 100644 --- a/go.mod +++ b/go.mod @@ -161,7 +161,7 @@ require ( github.com/pkg/errors v0.9.1 github.com/prometheus/client_golang v1.15.1 github.com/prometheus/client_model v0.3.0 - github.com/prometheus/procfs v0.10.0 + github.com/prometheus/procfs v0.10.1 github.com/richardartoul/molecule v1.0.1-0.20221107223329-32cfee06a052 github.com/robfig/cron/v3 v3.0.1 github.com/samber/lo v1.38.1 diff --git a/go.sum b/go.sum index 2dd83291bccc6..34cff51977120 100644 --- a/go.sum +++ b/go.sum @@ -1616,8 +1616,8 @@ github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4O github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= -github.com/prometheus/procfs v0.10.0 h1:UkG7GPYkO4UZyLnyXjaWYcgOSONqwdBqFUT95ugmt6I= -github.com/prometheus/procfs v0.10.0/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM= +github.com/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+PymziUAg= +github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM= github.com/prometheus/statsd_exporter v0.22.7 h1:7Pji/i2GuhK6Lu7DHrtTkFmNBCudCPT1pX2CziuyQR0= github.com/prometheus/statsd_exporter v0.22.7/go.mod h1:N/TevpjkIh9ccs6nuzY3jQn9dFqnUakOjnEuMPJJJnI= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= From 04562ae11612ad4aa916c1ab1f7862ecbd8054d7 Mon Sep 17 00:00:00 2001 From: Bryce Kahle Date: Wed, 7 Jun 2023 06:57:54 -0700 Subject: [PATCH 21/76] Fix duplicate prebuilt module in use during tests (#17472) Because this is a global object, and the tests load prebuilt modules a bunch, you can end up with a long list of the same string. Example output: ``` &{{[] 0xc0013ada10} map[] map[closed_conn_dropped:0 conn_dropped:0 conns_bpf_map_size:18 conns_closed:1 kprobes_missed:0 kprobes_triggered:2] map[conntrack:{true 10 2032871} oomKill:{false 0 0} runtimeSecurity:{false 0 0} tcpQueueLength:{false 0 0} tracer:{true 10 3072361} usm:{true 10 2701840}] 2 map[tracer:1 usm:1] [offset-guess offset-guess offset-guess offset-guess offset-guess offset-guess offset-guess offset-guess offset-guess offset-guess offset-guess offset-guess offset-guess offset-guess tracer offset-guess dns tracer offset-guess dns tracer offset-guess dns tracer offset-guess dns tracer offset-guess dns tracer offset-guess dns tracer offset-guess dns tracer offset-guess dns tracer offset-guess dns tracer offset-guess dns tracer offset-guess dns tracer offset-guess dns tracer offset-guess dns tracer offset-guess dns tracer offset-guess dns tracer offset-guess dns tracer offset-guess dns tracer offset-guess dns usm tracer dns usm tracer offset-guess dns tracer offset-guess dns tracer offset-guess dns tracer offset-guess dns tracer offset-guess dns tracer offset-guess dns tracer offset-guess dns tracer offset-guess dns tracer offset-guess dns tracer offset-guess dns tracer offset-guess dns tracer offset-guess dns tracer offset-guess dns tracer offset-guess dns tracer offset-guess dns tracer offset-guess dns tracer offset-guess dns tracer offset-guess dns tracer offset-guess dns tracer offset-guess dns tracer offset-guess dns tracer offset-guess dns tracer offset-guess dns tracer offset-guess dns tracer offset-guess dns tracer offset-guess dns tracer offset-guess dns tracer offset-guess dns tracer offset-guess dns tracer offset-guess dns tracer offset-guess dns tracer offset-guess dns tracer offset-guess dns tracer offset-guess dns tracer offset-guess dns dns dns dns dns dns dns dns dns dns dns dns dns dns dns dns dns dns dns dns dns dns dns dns dns dns dns dns dns dns dns dns dns dns dns dns dns dns dns dns dns dns dns dns dns dns dns dns dns dns dns dns dns dns dns offset-guess dns offset-guess dns offset-guess dns offset-guess dns offset-guess dns offset-guess dns offset-guess dns offset-guess dns offset-guess dns offset-guess dns offset-guess dns offset-guess dns offset-guess dns offset-guess dns offset-guess dns offset-guess dns offset-guess dns offset-guess dns dns offset-guess dns offset-guess dns offset-guess dns offset-guess dns offset-guess dns offset-guess dns offset-guess dns offset-guess dns offset-guess dns offset-guess dns offset-guess dns offset-guess dns offset-guess dns offset-guess dns offset-guess dns offset-guess dns offset-guess dns offset-guess dns offset-guess dns offset-guess dns offset-guess dns offset-guess dns offset-guess dns offset-guess dns offset-guess dns offset-guess dns offset-guess dns offset-guess dns offset-guess dns offset-guess dns offset-guess dns offset-guess dns offset-guess dns offset-guess dns offset-guess dns tracer offset-guess dns usm tracer offset-guess dns usm tracer offset-guess dns usm tracer offset-guess dns usm tracer offset-guess dns usm tracer offset-guess dns usm tracer offset-guess dns usm tracer offset-guess dns usm tracer offset-guess dns usm tracer offset-guess dns usm tracer offset-guess dns usm tracer offset-guess dns usm tracer offset-guess dns usm tracer offset-guess dns usm tracer offset-guess dns usm tracer offset-guess dns usm tracer offset-guess dns dns dns dns dns dns dns dns dns dns dns dns dns dns dns dns dns] map[] map[] map[] map[]} ``` --- pkg/network/ebpf/bpf_module.go | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/pkg/network/ebpf/bpf_module.go b/pkg/network/ebpf/bpf_module.go index 22457c1d7770d..00bab7a26957e 100644 --- a/pkg/network/ebpf/bpf_module.go +++ b/pkg/network/ebpf/bpf_module.go @@ -11,12 +11,14 @@ import ( "fmt" "sync" + "golang.org/x/exp/maps" + "github.com/DataDog/datadog-agent/pkg/ebpf/bytecode" ) // prebuiltModulesInUse is a global object which is responsible for keeping a list of all the prebuilt ebpf assets in use. // This is used to report ebpf asset telemetry -var prebuiltModulesInUse = []string{} +var prebuiltModulesInUse = map[string]struct{}{} var telemetrymu sync.Mutex func ModuleFileName(moduleName string, debug bool) string { @@ -35,8 +37,7 @@ func readModule(bpfDir, moduleName string, debug bool) (bytecode.AssetReader, er telemetrymu.Lock() defer telemetrymu.Unlock() - prebuiltModulesInUse = append(prebuiltModulesInUse, moduleName) - + prebuiltModulesInUse[moduleName] = struct{}{} return ebpfReader, nil } @@ -83,7 +84,5 @@ func GetModulesInUse() []string { telemetrymu.Lock() defer telemetrymu.Unlock() - result := make([]string, len(prebuiltModulesInUse)) - copy(result, prebuiltModulesInUse) - return result + return maps.Keys(prebuiltModulesInUse) } From 7061f42a3edefc3ccaeea518c3c2ae634cf133e5 Mon Sep 17 00:00:00 2001 From: Bryce Kahle Date: Wed, 7 Jun 2023 06:58:36 -0700 Subject: [PATCH 22/76] Add way to log trace_pipe from tests (#17339) --- pkg/ebpf/ebpftest/bpfdebug_linux.go | 83 ++++++++++++++ pkg/ebpf/ebpftest/bpfdebug_unsupported.go | 26 +++++ pkg/ebpf/ebpftest/trace_pipe.go | 24 +++++ pkg/ebpf/ebpftest/trace_pipe_linux.go | 126 ++++++++++++++++++++++ 4 files changed, 259 insertions(+) create mode 100644 pkg/ebpf/ebpftest/bpfdebug_linux.go create mode 100644 pkg/ebpf/ebpftest/bpfdebug_unsupported.go create mode 100644 pkg/ebpf/ebpftest/trace_pipe.go create mode 100644 pkg/ebpf/ebpftest/trace_pipe_linux.go diff --git a/pkg/ebpf/ebpftest/bpfdebug_linux.go b/pkg/ebpf/ebpftest/bpfdebug_linux.go new file mode 100644 index 0000000000000..4360a45187c0f --- /dev/null +++ b/pkg/ebpf/ebpftest/bpfdebug_linux.go @@ -0,0 +1,83 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2016-present Datadog, Inc. + +package ebpftest + +import ( + "os" + "path/filepath" + "strconv" + "testing" + + "github.com/stretchr/testify/require" + + "github.com/DataDog/datadog-agent/pkg/process/util" +) + +// LogTracePipe logs all messages read from /sys/kernel/[debug/]/tracing/trace_pipe during the test. +// This function will set the environment variable BPF_DEBUG=true for the duration of the test. +func LogTracePipe(t *testing.T) { + logTracePipe(t, nil) +} + +// LogTracePipeSelf logs only messages from the current process read from /sys/kernel/[debug/]/tracing/trace_pipe during the test. +// This function will set the environment variable BPF_DEBUG=true for the duration of the test. +func LogTracePipeSelf(t *testing.T) { + LogTracePipeProcess(t, getpid()) +} + +// LogTracePipeProcess logs only messages from the provided process read from /sys/kernel/[debug/]/tracing/trace_pipe during the test. +// This function will set the environment variable BPF_DEBUG=true for the duration of the test. +func LogTracePipeProcess(t *testing.T, pid uint32) { + logTracePipe(t, func(ev *TraceEvent) bool { + return ev.PID == pid + }) +} + +// LogTracePipeFilter logs only messages that pass `filterFn` read from /sys/kernel/[debug/]/tracing/trace_pipe during the test. +// This function will set the environment variable BPF_DEBUG=true for the duration of the test. +func LogTracePipeFilter(t *testing.T, filterFn func(ev *TraceEvent) bool) { + logTracePipe(t, filterFn) +} + +func getpid() uint32 { + p, err := os.Readlink(filepath.Join(util.HostProc(), "/self")) + if err == nil { + if pid, err := strconv.ParseInt(p, 10, 32); err == nil { + return uint32(pid) + } + } + return uint32(os.Getpid()) +} + +func logTracePipe(t *testing.T, filterFn func(ev *TraceEvent) bool) { + t.Setenv("BPF_DEBUG", "true") + tp, err := NewTracePipe() + require.NoError(t, err) + t.Cleanup(func() { _ = tp.Close() }) + + ready := make(chan struct{}) + go func() { + close(ready) + logs, errs := tp.Channel() + for { + select { + case log, ok := <-logs: + if !ok { + return + } + if filterFn == nil || filterFn(log) { + t.Logf("trace_pipe: %s", log) + } + case err, ok := <-errs: + if !ok { + return + } + t.Logf("trace_pipe: error: %s\n", err) + } + } + }() + <-ready +} diff --git a/pkg/ebpf/ebpftest/bpfdebug_unsupported.go b/pkg/ebpf/ebpftest/bpfdebug_unsupported.go new file mode 100644 index 0000000000000..0f8a4dd78340e --- /dev/null +++ b/pkg/ebpf/ebpftest/bpfdebug_unsupported.go @@ -0,0 +1,26 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2016-present Datadog, Inc. + +//go:build !linux + +package ebpftest + +import "testing" + +// LogTracePipe is unsupported +func LogTracePipe(t *testing.T) { +} + +// LogTracePipeSelf is unsupported +func LogTracePipeSelf(t *testing.T) { +} + +// LogTracePipeProcess is unsupported +func LogTracePipeProcess(t *testing.T, pid uint32) { +} + +// LogTracePipeFilter is unsupported +func LogTracePipeFilter(t *testing.T, filterFn func(ev *TraceEvent) bool) { +} diff --git a/pkg/ebpf/ebpftest/trace_pipe.go b/pkg/ebpf/ebpftest/trace_pipe.go new file mode 100644 index 0000000000000..ee7d6744f2c15 --- /dev/null +++ b/pkg/ebpf/ebpftest/trace_pipe.go @@ -0,0 +1,24 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2016-present Datadog, Inc. + +package ebpftest + +// TraceEvent contains the raw event as well as the contents of +// every field as string, as defined under "Output format" in +// https://www.kernel.org/doc/Documentation/trace/ftrace.txt +type TraceEvent struct { + Raw string + Task string + PID uint32 + CPU string + Flags string + Timestamp string + Function string + Message string +} + +func (t TraceEvent) String() string { + return t.Raw +} diff --git a/pkg/ebpf/ebpftest/trace_pipe_linux.go b/pkg/ebpf/ebpftest/trace_pipe_linux.go new file mode 100644 index 0000000000000..eb6d382a82059 --- /dev/null +++ b/pkg/ebpf/ebpftest/trace_pipe_linux.go @@ -0,0 +1,126 @@ +// Copyright 2017 Kinvolk +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package ebpftest + +import ( + "bufio" + "errors" + "fmt" + "io" + "io/fs" + "os" + "regexp" + "strconv" + "strings" + + "github.com/DataDog/ebpf-manager/tracefs" +) + +// TracePipe to read from /sys/kernel/[debug/]tracing/trace_pipe +// Note that data can be read only once, i.e. if you have more than +// one tracer / channel, only one will receive an event: +// "Once data is read from this file, it is consumed, and will not be +// read again with a sequential read." +// https://www.kernel.org/doc/Documentation/trace/ftrace.txt +type TracePipe struct { + file *os.File + reader *bufio.Reader + stop chan struct{} +} + +// NewTracePipe instantiates a new trace pipe +func NewTracePipe() (*TracePipe, error) { + f, err := tracefs.OpenFile("trace_pipe", os.O_RDONLY, 0) + if err != nil { + return nil, err + } + return &TracePipe{ + file: f, + reader: bufio.NewReader(f), + stop: make(chan struct{}), + }, nil +} + +// A line from trace_pipe looks like (leading spaces included): +// ` chromium-15581 [000] d... 92783.722567: : Hello, World!` +var traceLineRegexp = regexp.MustCompile(`(.{16})-(\d+) +\[(\d{3})\] (.{4,5}) +(\d+\.\d+)\: (.*?)\: (.*)`) + +func parseTraceLine(raw string) (*TraceEvent, error) { + if raw == "\n" { + return nil, nil + } + fields := traceLineRegexp.FindStringSubmatch(raw) + if len(fields) != 8 { + return nil, fmt.Errorf("received unexpected input %q", raw) + } + pid, _ := strconv.ParseUint(fields[2], 10, 32) + + return &TraceEvent{ + Raw: raw, + Task: strings.Trim(fields[1], " "), + PID: uint32(pid), + CPU: fields[3], + Flags: fields[4], + Timestamp: fields[5], + Function: fields[6], + Message: fields[7], + }, nil +} + +// ReadLine reads a line +func (t *TracePipe) ReadLine() (*TraceEvent, error) { + line, err := t.reader.ReadString('\n') + if err != nil { + return nil, err + } + traceEvent, err := parseTraceLine(line) + if err != nil { + return nil, err + } + return traceEvent, nil +} + +// Channel returns a channel of events and another for errors +func (t *TracePipe) Channel() (<-chan *TraceEvent, <-chan error) { + channelEvents := make(chan *TraceEvent) + channelErrors := make(chan error) + go func() { + for { + select { + case <-t.stop: + close(channelEvents) + close(channelErrors) + return + default: + } + traceEvent, err := t.ReadLine() + if err != nil { + if errors.Is(err, io.EOF) || errors.Is(err, fs.ErrClosed) { + continue + } + channelErrors <- err + } else if traceEvent != nil { + channelEvents <- traceEvent + } + } + }() + return channelEvents, channelErrors +} + +// Close the trace pipe +func (t *TracePipe) Close() error { + close(t.stop) + return t.file.Close() +} From 3b6621c361bfc923b41f4a84f40af0c54e944492 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 7 Jun 2023 09:59:37 -0400 Subject: [PATCH 23/76] Bump github.com/vektra/mockery/v2 from 2.26.1 to 2.28.1 in /internal/tools (#17424) * Bump github.com/vektra/mockery/v2 in /internal/tools Bumps [github.com/vektra/mockery/v2](https://github.com/vektra/mockery) from 2.26.1 to 2.28.1. - [Release notes](https://github.com/vektra/mockery/releases) - [Changelog](https://github.com/vektra/mockery/blob/master/docs/changelog.md) - [Commits](https://github.com/vektra/mockery/compare/v2.26.1...v2.28.1) --- updated-dependencies: - dependency-name: github.com/vektra/mockery/v2 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * `inv -e security-agent.gen-mocks` * `inv -e process-agent.gen-mocks` --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Paul Cacheux --- internal/tools/go.mod | 4 ++-- internal/tools/go.sum | 11 ++++------- ...nt_monitoring_module__get_process_events_client.go | 2 +- .../proto/api/mocks/event_monitoring_module_client.go | 2 +- .../proto/api/mocks/event_monitoring_module_server.go | 2 +- pkg/process/checks/mocks/check.go | 2 +- pkg/process/net/mocks/sys_probe_util.go | 2 +- pkg/process/procutil/mocks/probe.go | 2 +- pkg/process/runner/mocks/submitter.go | 2 +- .../proto/api/mocks/security_module_client.go | 2 +- .../proto/api/mocks/security_module_server.go | 2 +- 11 files changed, 15 insertions(+), 18 deletions(-) diff --git a/internal/tools/go.mod b/internal/tools/go.mod index 69a8c42ba008f..7465398d1c7dd 100644 --- a/internal/tools/go.mod +++ b/internal/tools/go.mod @@ -9,7 +9,7 @@ require ( github.com/goware/modvendor v0.5.0 github.com/mgechev/revive v1.2.4 github.com/stormcat24/protodep v0.0.0-20210106175019-c95189bc461b - github.com/vektra/mockery/v2 v2.26.1 + github.com/vektra/mockery/v2 v2.28.1 golang.org/x/mobile v0.0.0-20201217150744-e6ae53a27f4f golang.org/x/perf v0.0.0-20210220033136-40a54f11e909 gotest.tools/gotestsum v1.8.2 @@ -44,7 +44,7 @@ require ( github.com/cespare/xxhash/v2 v2.1.2 // indirect github.com/charithe/durationcheck v0.0.9 // indirect github.com/chavacava/garif v0.0.0-20220630083739-93517212f375 // indirect - github.com/chigopher/pathlib v0.13.0 // indirect + github.com/chigopher/pathlib v0.15.0 // indirect github.com/curioswitch/go-reassign v0.2.0 // indirect github.com/daixiang0/gci v0.8.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect diff --git a/internal/tools/go.sum b/internal/tools/go.sum index 5681a0bc7fc68..3896e5881c4ac 100644 --- a/internal/tools/go.sum +++ b/internal/tools/go.sum @@ -109,8 +109,8 @@ github.com/charithe/durationcheck v0.0.9 h1:mPP4ucLrf/rKZiIG/a9IPXHGlh8p4CzgpyTy github.com/charithe/durationcheck v0.0.9/go.mod h1:SSbRIBVfMjCi/kEB6K65XEA83D6prSM8ap1UCpNKtgg= github.com/chavacava/garif v0.0.0-20220630083739-93517212f375 h1:E7LT642ysztPWE0dfz43cWOvMiF42DyTRC+eZIaO4yI= github.com/chavacava/garif v0.0.0-20220630083739-93517212f375/go.mod h1:4m1Rv7xfuwWPNKXlThldNuJvutYM6J95wNuuVmn55To= -github.com/chigopher/pathlib v0.13.0 h1:9AYqYGR+JaYJtZfTSsC+Wvz7CBd2jcZFb4fva7Z4r+4= -github.com/chigopher/pathlib v0.13.0/go.mod h1:EJ5UtJ/sK8Nt6q3VWN+EwZLZ3g0afJiG8NegYiQQ/gQ= +github.com/chigopher/pathlib v0.15.0 h1:1pg96WL3iC1/YyWV4UJSl3E0GBf4B+h5amBtsbAAieY= +github.com/chigopher/pathlib v0.15.0/go.mod h1:3+YPPV21mU9vyw8Mjp+F33CyCfE6iOzinpiqBcccv7I= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= @@ -519,7 +519,6 @@ github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -608,7 +607,6 @@ github.com/sonatard/noctx v0.0.1/go.mod h1:9D2D/EoULe8Yy2joDHJj7bv3sZoq9AaSb8B4l github.com/sourcegraph/go-diff v0.6.1 h1:hmA1LzxW0n1c3Q4YbrFgg4P99GSnebYa3x8gr0HZqLQ= github.com/sourcegraph/go-diff v0.6.1/go.mod h1:iBszgVvyxdc8SFZ7gm69go2KDdt3ag071iBaWPF6cjs= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= -github.com/spf13/afero v1.4.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= github.com/spf13/afero v1.9.3 h1:41FoI0fD7OR7mGcKE/aOiLkGreyf8ifIOQmJANWogMk= github.com/spf13/afero v1.9.3/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= @@ -678,8 +676,8 @@ github.com/ultraware/whitespace v0.0.5 h1:hh+/cpIcopyMYbZNVov9iSxvJU3OYQg78Sfaqz github.com/ultraware/whitespace v0.0.5/go.mod h1:aVMh/gQve5Maj9hQ/hg+F75lr/X5A89uZnzAmWSineA= github.com/uudashr/gocognit v1.0.6 h1:2Cgi6MweCsdB6kpcVQp7EW4U23iBFQWfTXiWlyp842Y= github.com/uudashr/gocognit v1.0.6/go.mod h1:nAIUuVBnYU7pcninia3BHOvQkpQCeO76Uscky5BOwcY= -github.com/vektra/mockery/v2 v2.26.1 h1:Y8mlLkWHWjuUpsJBwhFb1LeG1ZnWFvo+prsIuiABJ88= -github.com/vektra/mockery/v2 v2.26.1/go.mod h1:BOVUIv65DB6wuTYzoPtyMoBYce3n2C1IcsOdWu6Rpu4= +github.com/vektra/mockery/v2 v2.28.1 h1:Au6fg/fTS39HPytnc1Xt/OF5IZv8+yNkT5TPcb/VnM0= +github.com/vektra/mockery/v2 v2.28.1/go.mod h1:S1G0O8RZ66tpqfwSiJvi4bzjpk4ces+qEy0xoUG8wRg= github.com/xanzy/ssh-agent v0.2.1 h1:TCbipTQL2JiiCprBWx9frJ2eJlCYT00NmctrHxVAr70= github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= @@ -719,7 +717,6 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= diff --git a/pkg/eventmonitor/proto/api/mocks/event_monitoring_module__get_process_events_client.go b/pkg/eventmonitor/proto/api/mocks/event_monitoring_module__get_process_events_client.go index 4c69ecd8f1af5..9628234ee50f5 100644 --- a/pkg/eventmonitor/proto/api/mocks/event_monitoring_module__get_process_events_client.go +++ b/pkg/eventmonitor/proto/api/mocks/event_monitoring_module__get_process_events_client.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.26.1. DO NOT EDIT. +// Code generated by mockery v2.28.1. DO NOT EDIT. package mocks diff --git a/pkg/eventmonitor/proto/api/mocks/event_monitoring_module_client.go b/pkg/eventmonitor/proto/api/mocks/event_monitoring_module_client.go index e228b28a543ea..2eab0059f72d1 100644 --- a/pkg/eventmonitor/proto/api/mocks/event_monitoring_module_client.go +++ b/pkg/eventmonitor/proto/api/mocks/event_monitoring_module_client.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.26.1. DO NOT EDIT. +// Code generated by mockery v2.28.1. DO NOT EDIT. package mocks diff --git a/pkg/eventmonitor/proto/api/mocks/event_monitoring_module_server.go b/pkg/eventmonitor/proto/api/mocks/event_monitoring_module_server.go index 0bd62beafa212..2b0e13d706ea3 100644 --- a/pkg/eventmonitor/proto/api/mocks/event_monitoring_module_server.go +++ b/pkg/eventmonitor/proto/api/mocks/event_monitoring_module_server.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.26.1. DO NOT EDIT. +// Code generated by mockery v2.28.1. DO NOT EDIT. package mocks diff --git a/pkg/process/checks/mocks/check.go b/pkg/process/checks/mocks/check.go index c6738dd61e9c1..69c9f6dcc9bf2 100644 --- a/pkg/process/checks/mocks/check.go +++ b/pkg/process/checks/mocks/check.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.26.1. DO NOT EDIT. +// Code generated by mockery v2.28.1. DO NOT EDIT. package mocks diff --git a/pkg/process/net/mocks/sys_probe_util.go b/pkg/process/net/mocks/sys_probe_util.go index 4cd5fde32075b..52f0cea10a639 100644 --- a/pkg/process/net/mocks/sys_probe_util.go +++ b/pkg/process/net/mocks/sys_probe_util.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.26.1. DO NOT EDIT. +// Code generated by mockery v2.28.1. DO NOT EDIT. package mocks diff --git a/pkg/process/procutil/mocks/probe.go b/pkg/process/procutil/mocks/probe.go index fd79d357c5cd3..88e8b495fd8c3 100644 --- a/pkg/process/procutil/mocks/probe.go +++ b/pkg/process/procutil/mocks/probe.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.26.1. DO NOT EDIT. +// Code generated by mockery v2.28.1. DO NOT EDIT. package mocks diff --git a/pkg/process/runner/mocks/submitter.go b/pkg/process/runner/mocks/submitter.go index f93d8cf00343f..5024a59cdee56 100644 --- a/pkg/process/runner/mocks/submitter.go +++ b/pkg/process/runner/mocks/submitter.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.26.1. DO NOT EDIT. +// Code generated by mockery v2.28.1. DO NOT EDIT. package mocks diff --git a/pkg/security/proto/api/mocks/security_module_client.go b/pkg/security/proto/api/mocks/security_module_client.go index bc4070c84dcf4..638e2d289ccb4 100644 --- a/pkg/security/proto/api/mocks/security_module_client.go +++ b/pkg/security/proto/api/mocks/security_module_client.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.26.1. DO NOT EDIT. +// Code generated by mockery v2.28.1. DO NOT EDIT. package mocks diff --git a/pkg/security/proto/api/mocks/security_module_server.go b/pkg/security/proto/api/mocks/security_module_server.go index f2f681df7c74f..15e3c162e82fb 100644 --- a/pkg/security/proto/api/mocks/security_module_server.go +++ b/pkg/security/proto/api/mocks/security_module_server.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.26.1. DO NOT EDIT. +// Code generated by mockery v2.28.1. DO NOT EDIT. package mocks From e83efae53b0554a45557fa1b5f3e7e2f378502f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Momar=20TOUR=C3=89?= <36661127+mftoure@users.noreply.github.com> Date: Wed, 7 Jun 2023 16:03:18 +0200 Subject: [PATCH 24/76] [CWS][SEC-3735] Check self tests results in e2e tests (#17387) * Check self_test results in e2e tests * Check self_test results in e2e tests * Fix self_check tests * fix python lint things * fix python lint thing * Changes after review * fix python lint thing --- test/e2e/cws-tests/tests/test_e2e_cws_docker.py | 10 ++++++++++ test/e2e/cws-tests/tests/test_e2e_cws_kubernetes.py | 10 ++++++++++ 2 files changed, 20 insertions(+) diff --git a/test/e2e/cws-tests/tests/test_e2e_cws_docker.py b/test/e2e/cws-tests/tests/test_e2e_cws_docker.py index 7756c867a3e1e..589b356197098 100644 --- a/test/e2e/cws-tests/tests/test_e2e_cws_docker.py +++ b/test/e2e/cws-tests/tests/test_e2e_cws_docker.py @@ -126,6 +126,16 @@ def test_open_signal(self): self.fail("check ruleset_loaded timeouted") self.app.check_for_ignored_policies(self, attributes) + with Step(msg="check self_tests", emoji=":test_tube:"): + rule_id = "self_test" + event = self.app.wait_app_log(f"rule_id:{rule_id}") + attributes = event["data"][0]["attributes"]["attributes"] + self.assertEqual(rule_id, attributes["agent"]["rule_id"], "unable to find rule_id tag attribute") + self.assertTrue( + "failed_tests" not in attributes, + f"failed tests: {attributes['failed_tests']}" if "failed_tests" in attributes else "success", + ) + with Step(msg="wait for host tags (3m)", emoji=":alarm_clock:"): time.sleep(3 * 60) diff --git a/test/e2e/cws-tests/tests/test_e2e_cws_kubernetes.py b/test/e2e/cws-tests/tests/test_e2e_cws_kubernetes.py index 228c877dc6866..27521b0770589 100644 --- a/test/e2e/cws-tests/tests/test_e2e_cws_kubernetes.py +++ b/test/e2e/cws-tests/tests/test_e2e_cws_kubernetes.py @@ -133,6 +133,16 @@ def test_open_signal(self): self.fail("check ruleset_loaded timeouted") self.app.check_for_ignored_policies(self, attributes) + with Step(msg="check self_tests", emoji=":test_tube:"): + rule_id = "self_test" + event = self.app.wait_app_log(f"rule_id:{rule_id}") + attributes = event["data"][0]["attributes"]["attributes"] + self.assertEqual(rule_id, attributes["agent"]["rule_id"], "unable to find rule_id tag attribute") + self.assertTrue( + "failed_tests" not in attributes, + f"failed tests: {attributes['failed_tests']}" if "failed_tests" in attributes else "success", + ) + with Step(msg="wait for datadog.security_agent.runtime.running metric", emoji="\N{beer mug}"): self.app.wait_for_metric("datadog.security_agent.runtime.running", host=TestE2EKubernetes.hostname) From e7ed1d53142adff76af845da972bc48fbb015328 Mon Sep 17 00:00:00 2001 From: Pierre Guilleminot Date: Wed, 7 Jun 2023 16:03:57 +0200 Subject: [PATCH 25/76] [CSPM] Resolve process env variables only if required (#17461) --- pkg/compliance/resolver.go | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/pkg/compliance/resolver.go b/pkg/compliance/resolver.go index 5e5cfe8683653..bc78c30add314 100644 --- a/pkg/compliance/resolver.go +++ b/pkg/compliance/resolver.go @@ -449,10 +449,13 @@ func (r *defaultResolver) resolveProcess(ctx context.Context, spec InputSpecProc if err != nil { return nil, err } - envs, err := p.Environ() - // NOTE(pierre): security-agent may be executed without the capabilities to get /proc//environ - if err != nil && !os.IsPermission(err) { - return nil, err + var envs []string + if len(spec.Envs) > 0 { + envs, err = p.Environ() + // NOTE(pierre): security-agent may be executed without the capabilities to get /proc//environ + if err != nil && !os.IsPermission(err) { + return nil, err + } } resolved = append(resolved, map[string]interface{}{ "name": spec.Name, From 4723d2132a73ce8de874c385ed43a72a92afc15e Mon Sep 17 00:00:00 2001 From: Hasan Mahmood Date: Wed, 7 Jun 2023 10:04:59 -0400 Subject: [PATCH 26/76] [system-probe] Handle/reduce stat cookie collisions (#17197) --- .../ebpf/c/protocols/classification/defs.h | 16 ------- .../classification/dispatcher-helpers.h | 16 +++++++ pkg/network/ebpf/c/tracer/stats.h | 5 +++ pkg/network/event_common.go | 4 +- pkg/network/event_windows.go | 2 +- pkg/network/state.go | 42 +++++++++++++------ .../tracer/connection/perf_batching.go | 5 ++- .../tracer/connection/tcp_close_consumer.go | 4 +- pkg/network/tracer/connection/tracer.go | 42 +++++++++++++++++-- 9 files changed, 101 insertions(+), 35 deletions(-) diff --git a/pkg/network/ebpf/c/protocols/classification/defs.h b/pkg/network/ebpf/c/protocols/classification/defs.h index 0d1426d6cc96f..b33664af1f13e 100644 --- a/pkg/network/ebpf/c/protocols/classification/defs.h +++ b/pkg/network/ebpf/c/protocols/classification/defs.h @@ -113,20 +113,4 @@ typedef enum { PROG_MAX, } protocol_prog_t; -__maybe_unused static __always_inline protocol_prog_t protocol_to_program(protocol_t proto) { - switch(proto) { - case PROTOCOL_HTTP: - return PROG_HTTP; - case PROTOCOL_HTTP2: - return PROG_HTTP2; - case PROTOCOL_KAFKA: - return PROG_KAFKA; - default: - if (proto != PROTOCOL_UNKNOWN) { - log_debug("protocol doesn't have a matching program: %d\n", proto); - } - return PROG_UNKNOWN; - } -} - #endif diff --git a/pkg/network/ebpf/c/protocols/classification/dispatcher-helpers.h b/pkg/network/ebpf/c/protocols/classification/dispatcher-helpers.h index 43dfc75f7744b..3b8b32b9091c5 100644 --- a/pkg/network/ebpf/c/protocols/classification/dispatcher-helpers.h +++ b/pkg/network/ebpf/c/protocols/classification/dispatcher-helpers.h @@ -16,6 +16,22 @@ #include "protocols/kafka/kafka-classification.h" #include "protocols/kafka/usm-events.h" +__maybe_unused static __always_inline protocol_prog_t protocol_to_program(protocol_t proto) { + switch(proto) { + case PROTOCOL_HTTP: + return PROG_HTTP; + case PROTOCOL_HTTP2: + return PROG_HTTP2; + case PROTOCOL_KAFKA: + return PROG_KAFKA; + default: + if (proto != PROTOCOL_UNKNOWN) { + log_debug("protocol doesn't have a matching program: %d\n", proto); + } + return PROG_UNKNOWN; + } +} + // Returns true if the payload represents a TCP termination by checking if the tcp flags contains TCPHDR_FIN or TCPHDR_RST. static __always_inline bool is_tcp_termination(skb_info_t *skb_info) { return skb_info->tcp_flags & (TCPHDR_FIN | TCPHDR_RST); diff --git a/pkg/network/ebpf/c/tracer/stats.h b/pkg/network/ebpf/c/tracer/stats.h index ef16fcb0846ad..9d158b2fbd3ba 100644 --- a/pkg/network/ebpf/c/tracer/stats.h +++ b/pkg/network/ebpf/c/tracer/stats.h @@ -23,6 +23,11 @@ static __always_inline __u64 offset_rtt_var(); #endif static __always_inline conn_stats_ts_t *get_conn_stats(conn_tuple_t *t, struct sock *sk) { + conn_stats_ts_t *cs = bpf_map_lookup_elem(&conn_stats, t); + if (cs) { + return cs; + } + // initialize-if-no-exist the connection stat, and load it conn_stats_ts_t empty = {}; bpf_memset(&empty, 0, sizeof(conn_stats_ts_t)); diff --git a/pkg/network/event_common.go b/pkg/network/event_common.go index 4764377b9c005..16fe89cddd5e6 100644 --- a/pkg/network/event_common.go +++ b/pkg/network/event_common.go @@ -220,6 +220,8 @@ func (s StatCounters) IsZero() bool { return s == StatCounters{} } +type StatCookie = uint64 + // ConnectionStats stores statistics for a single connection. Field order in the struct should be 8-byte aligned type ConnectionStats struct { Source util.Address @@ -232,7 +234,7 @@ type ConnectionStats struct { Last StatCounters - Cookie uint32 + Cookie StatCookie // Last time the stats for this connection were updated LastUpdateEpoch uint64 diff --git a/pkg/network/event_windows.go b/pkg/network/event_windows.go index b0eac0a0cf529..6f5ffdb868715 100644 --- a/pkg/network/event_windows.go +++ b/pkg/network/event_windows.go @@ -114,7 +114,7 @@ func FlowToConnStat(cs *ConnectionStats, flow *driver.PerFlowData, enableMonoton cs.Family = family cs.Direction = connDirection(flow.Flags) cs.SPortIsEphemeral = IsPortInEphemeralRange(cs.Family, cs.Type, cs.SPort) - cs.Cookie = uint32(flow.FlowHandle) + cs.Cookie = flow.FlowHandle if connectionType == TCP { tf := flow.TCPFlow() if tf != nil { diff --git a/pkg/network/state.go b/pkg/network/state.go index 58995b5d55035..9a89c55046fea 100644 --- a/pkg/network/state.go +++ b/pkg/network/state.go @@ -135,10 +135,10 @@ const minClosedCapacity = 1024 type client struct { lastFetch time.Time - closedConnectionsKeys map[uint32]int + closedConnectionsKeys map[StatCookie]int closedConnections []ConnectionStats - stats map[uint32]StatCounters + stats map[StatCookie]StatCounters // maps by dns key the domain (string) to stats structure dnsStats dns.StatsByKeyByNameByType httpStatsDelta map[http.Key]*http.RequestStats @@ -147,14 +147,14 @@ type client struct { lastTelemetries map[ConnTelemetryType]int64 } -func (c *client) Reset(active map[uint32]*ConnectionStats) { +func (c *client) Reset(active map[StatCookie]*ConnectionStats) { half := cap(c.closedConnections) / 2 if closedLen := len(c.closedConnections); closedLen > minClosedCapacity && closedLen < half { c.closedConnections = make([]ConnectionStats, half) } c.closedConnections = c.closedConnections[:0] - c.closedConnectionsKeys = make(map[uint32]int) + c.closedConnectionsKeys = make(map[StatCookie]int) c.dnsStats = make(dns.StatsByKeyByNameByType) c.httpStatsDelta = make(map[http.Key]*http.RequestStats) c.http2StatsDelta = make(map[http.Key]*http.RequestStats) @@ -162,7 +162,7 @@ func (c *client) Reset(active map[uint32]*ConnectionStats) { // XXX: we should change the way we clean this map once // https://github.com/golang/go/issues/20135 is solved - newStats := make(map[uint32]StatCounters, len(c.stats)) + newStats := make(map[StatCookie]StatCounters, len(c.stats)) for cookie, st := range c.stats { // Only keep active connections stats if _, isActive := active[cookie]; isActive { @@ -395,8 +395,8 @@ func (ns *networkState) RegisterClient(id string) { } // getConnsByCookie returns a mapping of cookie -> connection for easier access + manipulation -func (ns *networkState) getConnsByCookie(conns []ConnectionStats) map[uint32]*ConnectionStats { - connsByKey := make(map[uint32]*ConnectionStats, len(conns)) +func (ns *networkState) getConnsByCookie(conns []ConnectionStats) map[StatCookie]*ConnectionStats { + connsByKey := make(map[StatCookie]*ConnectionStats, len(conns)) for i := range conns { var c *ConnectionStats if c = connsByKey[conns[i].Cookie]; c == nil { @@ -411,6 +411,10 @@ func (ns *networkState) getConnsByCookie(conns []ConnectionStats) map[uint32]*Co if ns.mergeConnectionStats(c, &conns[i]) { // cookie collision stateTelemetry.statsCookieCollisions.Inc() + // pick the latest one + if conns[i].LastUpdateEpoch > c.LastUpdateEpoch { + connsByKey[conns[i].Cookie] = &conns[i] + } } } @@ -431,6 +435,10 @@ func (ns *networkState) storeClosedConnections(conns []ConnectionStats) { if i, ok := client.closedConnectionsKeys[c.Cookie]; ok { if ns.mergeConnectionStats(&client.closedConnections[i], &c) { stateTelemetry.statsCookieCollisions.Inc() + // pick the latest one + if c.LastUpdateEpoch > client.closedConnections[i].LastUpdateEpoch { + client.closedConnections[i] = c + } } continue } @@ -612,9 +620,9 @@ func (ns *networkState) getClient(clientID string) *client { c := &client{ lastFetch: time.Now(), - stats: make(map[uint32]StatCounters), + stats: make(map[StatCookie]StatCounters), closedConnections: make([]ConnectionStats, 0, minClosedCapacity), - closedConnectionsKeys: make(map[uint32]int), + closedConnectionsKeys: make(map[StatCookie]int), dnsStats: dns.StatsByKeyByNameByType{}, httpStatsDelta: map[http.Key]*http.RequestStats{}, http2StatsDelta: map[http.Key]*http.RequestStats{}, @@ -626,7 +634,7 @@ func (ns *networkState) getClient(clientID string) *client { } // mergeConnections return the connections and takes care of updating their last stat counters -func (ns *networkState) mergeConnections(id string, active map[uint32]*ConnectionStats, buffer *clientBuffer) { +func (ns *networkState) mergeConnections(id string, active map[StatCookie]*ConnectionStats, buffer *clientBuffer) { now := time.Now() client := ns.clients[id] @@ -641,6 +649,15 @@ func (ns *networkState) mergeConnections(id string, active map[uint32]*Connectio if activeConn := active[cookie]; activeConn != nil { if ns.mergeConnectionStats(closedConn, activeConn) { stateTelemetry.statsCookieCollisions.Inc() + // remove any previous stats since we + // can't distinguish between the two sets of stats + delete(client.stats, cookie) + if activeConn.LastUpdateEpoch > closedConn.LastUpdateEpoch { + // keep active connection + continue + } + + // keep closed connection } // not an active connection delete(active, cookie) @@ -677,7 +694,7 @@ func (ns *networkState) mergeConnections(id string, active map[uint32]*Connectio aggrConns.WriteTo(buffer) } -func (ns *networkState) updateConnWithStats(client *client, cookie uint32, c *ConnectionStats) { +func (ns *networkState) updateConnWithStats(client *client, cookie StatCookie, c *ConnectionStats) { c.Last = StatCounters{} if sts, ok := client.stats[cookie]; ok { var last StatCounters @@ -700,7 +717,7 @@ func (ns *networkState) updateConnWithStats(client *client, cookie uint32, c *Co } // createStatsForCookie will create a new stats object for a key if it doesn't already exist. -func (ns *networkState) createStatsForCookie(client *client, cookie uint32) { +func (ns *networkState) createStatsForCookie(client *client, cookie StatCookie) { if _, ok := client.stats[cookie]; !ok { if len(client.stats) >= ns.maxClientStats { stateTelemetry.connDropped.Inc() @@ -972,6 +989,7 @@ func (ns *networkState) mergeConnectionStats(a, b *ConnectionStats) (collision b } if bytes.Compare(a.ByteKey(ns.mergeStatsBuffers[0]), b.ByteKey(ns.mergeStatsBuffers[1])) != 0 { + log.Debugf("cookie collision for connections %+v and %+v", a, b) // cookie collision return true } diff --git a/pkg/network/tracer/connection/perf_batching.go b/pkg/network/tracer/connection/perf_batching.go index ec76bddaded85..8d052b0514be2 100644 --- a/pkg/network/tracer/connection/perf_batching.go +++ b/pkg/network/tracer/connection/perf_batching.go @@ -38,6 +38,8 @@ type perfBatchManager struct { stateByCPU []percpuState expiredStateInterval time.Duration + + ch *cookieHasher } // newPerfBatchManager returns a new `PerfBatchManager` and initializes the @@ -62,6 +64,7 @@ func newPerfBatchManager(batchMap *ebpf.Map, numCPUs int) (*perfBatchManager, er batchMap: batchMap, stateByCPU: state, expiredStateInterval: defaultExpiredStateInterval, + ch: newCookieHasher(), }, nil } @@ -152,7 +155,7 @@ func (p *perfBatchManager) extractBatchInto(buffer *network.ConnectionBuffer, b } conn := buffer.Next() - populateConnStats(conn, &ct.Tup, &ct.Conn_stats) + populateConnStats(conn, &ct.Tup, &ct.Conn_stats, p.ch) updateTCPStats(conn, ct.Conn_stats.Cookie, &ct.Tcp_stats) } } diff --git a/pkg/network/tracer/connection/tcp_close_consumer.go b/pkg/network/tracer/connection/tcp_close_consumer.go index bfb65138d485c..2b5d72291d612 100644 --- a/pkg/network/tracer/connection/tcp_close_consumer.go +++ b/pkg/network/tracer/connection/tcp_close_consumer.go @@ -37,6 +37,7 @@ type tcpCloseConsumer struct { requests chan chan struct{} buffer *network.ConnectionBuffer once sync.Once + ch *cookieHasher } func newTCPCloseConsumer(m *manager.Manager, perfHandler *ddebpf.PerfHandler, batchManager *perfBatchManager) (*tcpCloseConsumer, error) { @@ -45,6 +46,7 @@ func newTCPCloseConsumer(m *manager.Manager, perfHandler *ddebpf.PerfHandler, ba batchManager: batchManager, requests: make(chan chan struct{}), buffer: network.NewConnectionBuffer(netebpf.BatchSize, netebpf.BatchSize), + ch: newCookieHasher(), } return c, nil } @@ -72,7 +74,7 @@ func (c *tcpCloseConsumer) Stop() { func (c *tcpCloseConsumer) extractConn(data []byte) { ct := (*netebpf.Conn)(unsafe.Pointer(&data[0])) conn := c.buffer.Next() - populateConnStats(conn, &ct.Tup, &ct.Conn_stats) + populateConnStats(conn, &ct.Tup, &ct.Conn_stats, c.ch) updateTCPStats(conn, ct.Conn_stats.Cookie, &ct.Tcp_stats) } diff --git a/pkg/network/tracer/connection/tracer.go b/pkg/network/tracer/connection/tracer.go index 947d3ecee3c35..9439d693090ae 100644 --- a/pkg/network/tracer/connection/tracer.go +++ b/pkg/network/tracer/connection/tracer.go @@ -8,14 +8,17 @@ package connection import ( + "encoding/binary" "errors" "fmt" + "hash" "math" "sync" "time" "unsafe" "github.com/cilium/ebpf" + "github.com/twmb/murmur3" "golang.org/x/sys/unix" manager "github.com/DataDog/ebpf-manager" @@ -118,6 +121,8 @@ type tracer struct { ebpfTracerType TracerType exitTelemetry chan struct{} + + ch *cookieHasher } // NewTracer creates a new tracer @@ -195,6 +200,7 @@ func NewTracer(config *config.Config, bpfTelemetry *errtelemetry.EBPFTelemetry) closeTracer: closeTracerFn, ebpfTracerType: tracerType, exitTelemetry: make(chan struct{}), + ch: newCookieHasher(), } tr.conns, _, err = m.GetMap(probes.ConnMap) @@ -308,7 +314,7 @@ func (t *tracer) GetConnections(buffer *network.ConnectionBuffer, filter func(*n var tcp4, tcp6, udp4, udp6 float64 entries := t.conns.Iterate() for entries.Next(unsafe.Pointer(key), unsafe.Pointer(stats)) { - populateConnStats(conn, key, stats) + populateConnStats(conn, key, stats, t.ch) isTCP := conn.Type == network.TCP switch conn.Family { @@ -533,7 +539,7 @@ func (t *tracer) getTCPStats(stats *netebpf.TCPStats, tuple *netebpf.ConnTuple, return true } -func populateConnStats(stats *network.ConnectionStats, t *netebpf.ConnTuple, s *netebpf.ConnStats) { +func populateConnStats(stats *network.ConnectionStats, t *netebpf.ConnTuple, s *netebpf.ConnStats, ch *cookieHasher) { *stats = network.ConnectionStats{ Pid: t.Pid, NetNS: t.Netns, @@ -550,7 +556,7 @@ func populateConnStats(stats *network.ConnectionStats, t *netebpf.ConnTuple, s * SPortIsEphemeral: network.IsPortInEphemeralRange(t.Sport), LastUpdateEpoch: s.Timestamp, IsAssured: s.IsAssured(), - Cookie: s.Cookie, + Cookie: network.StatCookie(s.Cookie), } stats.ProtocolStack = protocols.Stack{ @@ -580,6 +586,10 @@ func populateConnStats(stats *network.ConnectionStats, t *netebpf.ConnTuple, s * default: stats.Direction = network.OUTGOING } + + if ch != nil { + ch.Hash(stats) + } } func updateTCPStats(conn *network.ConnectionStats, cookie uint32, tcpStats *netebpf.TCPStats) { @@ -593,3 +603,29 @@ func updateTCPStats(conn *network.ConnectionStats, cookie uint32, tcpStats *nete conn.RTT = tcpStats.Rtt conn.RTTVar = tcpStats.Rtt_var } + +type cookieHasher struct { + hash hash.Hash64 + buf []byte +} + +func newCookieHasher() *cookieHasher { + return &cookieHasher{ + hash: murmur3.New64(), + buf: make([]byte, network.ConnectionByteKeyMaxLen), + } +} + +func (h *cookieHasher) Hash(stats *network.ConnectionStats) { + h.hash.Reset() + if err := binary.Write(h.hash, binary.BigEndian, stats.Cookie); err != nil { + log.Errorf("error writing cookie to hash: %s", err) + return + } + key := stats.ByteKey(h.buf) + if _, err := h.hash.Write(key); err != nil { + log.Errorf("error writing byte key to hash: %s", err) + return + } + stats.Cookie = h.hash.Sum64() +} From aad63bcb5d70d38d37ef0ffe0e04869b5223e19a Mon Sep 17 00:00:00 2001 From: Hasan Mahmood Date: Wed, 7 Jun 2023 10:05:55 -0400 Subject: [PATCH 27/76] [system-probe] Add internal_profiling.delta_profiles option to system-probe (#17475) --- pkg/config/settings/runtime_setting_profiling.go | 5 +++-- pkg/config/system_probe.go | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/pkg/config/settings/runtime_setting_profiling.go b/pkg/config/settings/runtime_setting_profiling.go index d7ce0943d62f3..cb29536c013b4 100644 --- a/pkg/config/settings/runtime_setting_profiling.go +++ b/pkg/config/settings/runtime_setting_profiling.go @@ -92,8 +92,9 @@ func (l ProfilingRuntimeSetting) Set(v interface{}) error { Env: cfg.GetString(l.ConfigPrefix + "env"), Service: l.Service, Period: cfg.GetDuration(l.ConfigPrefix + "internal_profiling.period"), - MutexProfileFraction: profiling.GetMutexProfileFraction(), - BlockProfileRate: profiling.GetBlockProfileRate(), + CPUDuration: cfg.GetDuration(l.ConfigPrefix + "internal_profiling.cpu_duration"), + MutexProfileFraction: cfg.GetInt(l.ConfigPrefix + "internal_profiling.mutex_profile_fraction"), + BlockProfileRate: cfg.GetInt(l.ConfigPrefix + "internal_profiling.block_profile_rate"), WithGoroutineProfile: cfg.GetBool(l.ConfigPrefix + "internal_profiling.enable_goroutine_stacktraces"), WithDeltaProfiles: cfg.GetBool(l.ConfigPrefix + "internal_profiling.delta_profiles"), Tags: []string{fmt.Sprintf("version:%v", v)}, diff --git a/pkg/config/system_probe.go b/pkg/config/system_probe.go index afecb47de3f23..eb8a08298abff 100644 --- a/pkg/config/system_probe.go +++ b/pkg/config/system_probe.go @@ -118,6 +118,7 @@ func InitSystemProbeConfig(cfg Config) { cfg.BindEnvAndSetDefault(join(spNS, "internal_profiling.mutex_profile_fraction"), 0) cfg.BindEnvAndSetDefault(join(spNS, "internal_profiling.block_profile_rate"), 0) cfg.BindEnvAndSetDefault(join(spNS, "internal_profiling.enable_goroutine_stacktraces"), false) + cfg.BindEnvAndSetDefault(join(spNS, "internal_profiling.delta_profiles"), false) cfg.BindEnvAndSetDefault(join(spNS, "memory_controller.enabled"), false) cfg.BindEnvAndSetDefault(join(spNS, "memory_controller.hierarchy"), "v1") From 556361d76c4e6078da3dff146d0e1f46eecfabc3 Mon Sep 17 00:00:00 2001 From: Pierre Guilleminot Date: Wed, 7 Jun 2023 16:11:32 +0200 Subject: [PATCH 28/76] [CSPM] Fix flakyness of TestProcessInput/Sleeps (#17399) --- pkg/compliance/tests/process_test.go | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/pkg/compliance/tests/process_test.go b/pkg/compliance/tests/process_test.go index 30d99ce0822e8..660fe55a3dc39 100644 --- a/pkg/compliance/tests/process_test.go +++ b/pkg/compliance/tests/process_test.go @@ -9,10 +9,13 @@ package tests import ( "context" + "fmt" + "math/rand" "os" "os/exec" "path/filepath" "testing" + "time" "github.com/DataDog/datadog-agent/pkg/compliance" "github.com/stretchr/testify/assert" @@ -155,13 +158,17 @@ findings[f] { `). AssertNoEvent() + src := rand.NewSource(time.Now().UnixNano()) + rnd := rand.New(src) + envFoo := rnd.Int() + b. AddRule("Sleeps"). Setup(func(t *testing.T, ctx context.Context) { cmd1 := exec.CommandContext(ctx, "sleep", "10") cmd2 := exec.CommandContext(ctx, "sleep", "10") - cmd1.Env = []string{"FOO=foo"} - cmd2.Env = []string{"FOO=foo"} + cmd1.Env = []string{fmt.Sprintf("FOO=%d", envFoo)} + cmd2.Env = []string{fmt.Sprintf("FOO=%d", envFoo)} if err := cmd1.Start(); err != nil { t.Fatal(err) } @@ -189,7 +196,7 @@ valid(p) { p.name == "sleep" p.cmdLine[0] == "sleep" p.cmdLine[1] == "10" - p.envs["FOO"] == "foo" + p.envs["FOO"] == "%d" not has_key(p.envs, "BAR") } @@ -201,7 +208,7 @@ findings[f] { {}, ) } -`). +`, envFoo). AssertPassedEvent(func(t *testing.T, evt *compliance.CheckEvent) { assert.Equal(t, "sleep", evt.ResourceID) assert.Equal(t, "sleep", evt.ResourceType) From a30f9af4e3a6e50ad4118bc65e88173a3e369259 Mon Sep 17 00:00:00 2001 From: Guy Arbitman Date: Wed, 7 Jun 2023 17:39:57 +0300 Subject: [PATCH 29/76] system-probe: Remove redundant call for IsAdjusted (#17345) --- cmd/system-probe/config/adjust.go | 13 +++---------- pkg/ebpf/config.go | 4 +--- pkg/network/config/config.go | 4 +--- pkg/network/tracer/tracer.go | 1 + pkg/security/config/config.go | 4 +--- pkg/security/probe/config/config.go | 4 +--- 6 files changed, 8 insertions(+), 22 deletions(-) diff --git a/cmd/system-probe/config/adjust.go b/cmd/system-probe/config/adjust.go index 467e25714f1e1..0e7a7756db970 100644 --- a/cmd/system-probe/config/adjust.go +++ b/cmd/system-probe/config/adjust.go @@ -17,11 +17,11 @@ var adjustMtx sync.Mutex // Adjust makes changes to the raw config based on deprecations and inferences. func Adjust(cfg config.Config) { - if IsAdjusted(cfg) { - return - } adjustMtx.Lock() defer adjustMtx.Unlock() + if cfg.GetBool(spNS("adjusted")) { + return + } deprecateString(cfg, spNS("log_level"), "log_level") deprecateString(cfg, spNS("log_file"), "log_file") @@ -49,13 +49,6 @@ func Adjust(cfg config.Config) { cfg.Set(spNS("adjusted"), true) } -// IsAdjusted returns whether the configuration has already been adjusted by Adjust -func IsAdjusted(cfg config.Config) bool { - adjustMtx.Lock() - defer adjustMtx.Unlock() - return cfg.GetBool(spNS("adjusted")) -} - // validateString validates the string configuration value at `key` using a custom provided function `valFn`. // If `key` is not set or `valFn` returns an error, the `defaultVal` is used instead. func validateString(cfg config.Config, key string, defaultVal string, valFn func(string) error) { diff --git a/pkg/ebpf/config.go b/pkg/ebpf/config.go index 98f2025b09ae0..9925076b3665f 100644 --- a/pkg/ebpf/config.go +++ b/pkg/ebpf/config.go @@ -84,9 +84,7 @@ func key(pieces ...string) string { // NewConfig creates a config with ebpf-related settings func NewConfig() *Config { cfg := aconfig.SystemProbe - if !sysconfig.IsAdjusted(cfg) { - sysconfig.Adjust(cfg) - } + sysconfig.Adjust(cfg) return &Config{ BPFDebug: cfg.GetBool(key(spNS, "bpf_debug")), diff --git a/pkg/network/config/config.go b/pkg/network/config/config.go index b40e5a4b32091..6f6ddff54f633 100644 --- a/pkg/network/config/config.go +++ b/pkg/network/config/config.go @@ -256,9 +256,7 @@ func join(pieces ...string) string { // New creates a config for the network tracer func New() *Config { cfg := ddconfig.SystemProbe - if !sysconfig.IsAdjusted(cfg) { - sysconfig.Adjust(cfg) - } + sysconfig.Adjust(cfg) c := &Config{ Config: *ebpf.NewConfig(), diff --git a/pkg/network/tracer/tracer.go b/pkg/network/tracer/tracer.go index b19f18c96144c..fc1b1fbad2376 100644 --- a/pkg/network/tracer/tracer.go +++ b/pkg/network/tracer/tracer.go @@ -374,6 +374,7 @@ func (t *Tracer) GetActiveConnections(clientID string) (*network.Connections, er log.Tracef("GetActiveConnections clientID=%s", clientID) t.ebpfTracer.FlushPending() + // Set a limit and do that periodically. latestTime, err := t.getConnections(t.activeBuffer) if err != nil { return nil, fmt.Errorf("error retrieving connections: %s", err) diff --git a/pkg/security/config/config.go b/pkg/security/config/config.go index ceffaebb751b9..1de5238799d8f 100644 --- a/pkg/security/config/config.go +++ b/pkg/security/config/config.go @@ -186,9 +186,7 @@ func NewConfig() (*Config, error) { } func NewRuntimeSecurityConfig() (*RuntimeSecurityConfig, error) { - if !sysconfig.IsAdjusted(coreconfig.SystemProbe) { - sysconfig.Adjust(coreconfig.SystemProbe) - } + sysconfig.Adjust(coreconfig.SystemProbe) rsConfig := &RuntimeSecurityConfig{ RuntimeEnabled: coreconfig.SystemProbe.GetBool("runtime_security_config.enabled"), diff --git a/pkg/security/probe/config/config.go b/pkg/security/probe/config/config.go index 2505d5fb7fa0a..511346b3047ec 100644 --- a/pkg/security/probe/config/config.go +++ b/pkg/security/probe/config/config.go @@ -137,9 +137,7 @@ type Config struct { // NewConfig returns a new Config object func NewConfig() (*Config, error) { - if !sysconfig.IsAdjusted(coreconfig.SystemProbe) { - sysconfig.Adjust(coreconfig.SystemProbe) - } + sysconfig.Adjust(coreconfig.SystemProbe) setEnv() From eb0d8287cb7ab275593750b2fa686dace97686fa Mon Sep 17 00:00:00 2001 From: Guy Arbitman Date: Wed, 7 Jun 2023 17:40:22 +0300 Subject: [PATCH 30/76] npm: Remove connection entry from tcpStats map if the connection is TCP (#17353) --- pkg/network/tracer/connection/tracer.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/pkg/network/tracer/connection/tracer.go b/pkg/network/tracer/connection/tracer.go index 9439d693090ae..7c4232e776c44 100644 --- a/pkg/network/tracer/connection/tracer.go +++ b/pkg/network/tracer/connection/tracer.go @@ -408,9 +408,10 @@ func (t *tracer) Remove(conn *network.ConnectionStats) error { // We have to remove the PID to remove the element from the TCP Map since we don't use the pid there t.removeTuple.Pid = 0 - // We can ignore the error for this map since it will not always contain the entry - _ = t.tcpStats.Delete(unsafe.Pointer(t.removeTuple)) - + if conn.Type == network.TCP { + // We can ignore the error for this map since it will not always contain the entry + _ = t.tcpStats.Delete(unsafe.Pointer(t.removeTuple)) + } return nil } From d03351cb3d45a137b970d1d2ced42731d81f824b Mon Sep 17 00:00:00 2001 From: Guy Arbitman Date: Wed, 7 Jun 2023 17:41:45 +0300 Subject: [PATCH 31/76] deprecate usm configuration values (#17216) * usm: Deprecated network_config.http_replace_rules in favor of service_monitoring_config.http_replace_rules * usm: Deprecated network_config.max_tracked_http_connections in favor of service_monitoring_config.max_tracked_http_connections * usm: Deprecated network_config.max_http_stats_buffered in favor of service_monitoring_config.max_http_stats_buffered * usm: Fixed configuration test * Added releasenotes * Fixed CR * Fixed kitchen tests * Fixing CI * Update releasenotes/notes/deprecating-usm-configuration-values-6c43a0181c2cc821.yaml Co-authored-by: Ursula Chen <58821586+urseberry@users.noreply.github.com> * Remove test patches * Fixed cr --------- Co-authored-by: Ursula Chen <58821586+urseberry@users.noreply.github.com> --- cmd/system-probe/config/adjust.go | 24 ++ cmd/system-probe/config/adjust_usm.go | 3 + pkg/config/system_probe.go | 28 +- pkg/network/config/config.go | 6 +- pkg/network/config/config_test.go | 244 ++++++++++++++++-- ...tDDSystemProbeConfig-HTTPReplaceRules.yaml | 7 + ...obeConfig-HTTPReplaceRulesDeprecated.yaml} | 0 ...ystemProbeConfig-MaxHTTPStatsBuffered.yaml | 2 + ...Config-MaxHTTPStatsBufferedDeprecated.yaml | 2 + ...ProbeConfig-MaxTrackedHTTPConnections.yaml | 2 + ...g-MaxTrackedHTTPConnectionsDeprecated.yaml | 2 + ...configuration-values-6c43a0181c2cc821.yaml | 5 + 12 files changed, 294 insertions(+), 31 deletions(-) create mode 100644 pkg/network/config/testdata/TestDDSystemProbeConfig-HTTPReplaceRules.yaml rename pkg/network/config/testdata/{TestDDAgentConfigYamlAndSystemProbeConfig-HTTPReplaceRules.yaml => TestDDSystemProbeConfig-HTTPReplaceRulesDeprecated.yaml} (100%) create mode 100644 pkg/network/config/testdata/TestDDSystemProbeConfig-MaxHTTPStatsBuffered.yaml create mode 100644 pkg/network/config/testdata/TestDDSystemProbeConfig-MaxHTTPStatsBufferedDeprecated.yaml create mode 100644 pkg/network/config/testdata/TestDDSystemProbeConfig-MaxTrackedHTTPConnections.yaml create mode 100644 pkg/network/config/testdata/TestDDSystemProbeConfig-MaxTrackedHTTPConnectionsDeprecated.yaml create mode 100644 releasenotes/notes/deprecating-usm-configuration-values-6c43a0181c2cc821.yaml diff --git a/cmd/system-probe/config/adjust.go b/cmd/system-probe/config/adjust.go index 0e7a7756db970..b68c4c1fc82ab 100644 --- a/cmd/system-probe/config/adjust.go +++ b/cmd/system-probe/config/adjust.go @@ -103,6 +103,30 @@ func deprecateBool(cfg config.Config, oldkey string, newkey string) { }) } +// deprecateInt64 logs a deprecation message if `oldkey` is used. +// It sets `newkey` to the value obtained from `getFn`, but only if `oldkey` is set and `newkey` is not set. +func deprecateInt64(cfg config.Config, oldkey string, newkey string) { + deprecateCustom(cfg, oldkey, newkey, func(cfg config.Config) interface{} { + return cfg.GetInt64(oldkey) + }) +} + +// deprecateGeneric logs a deprecation message if `oldkey` is used. +// It sets `newkey` to the value obtained from `getFn`, but only if `oldkey` is set and `newkey` is not set. +func deprecateGeneric(cfg config.Config, oldkey string, newkey string) { + deprecateCustom(cfg, oldkey, newkey, func(cfg config.Config) interface{} { + return cfg.Get(oldkey) + }) +} + +// deprecateInt logs a deprecation message if `oldkey` is used. +// It sets `newkey` to the value obtained from `getFn`, but only if `oldkey` is set and `newkey` is not set. +func deprecateInt(cfg config.Config, oldkey string, newkey string) { + deprecateCustom(cfg, oldkey, newkey, func(cfg config.Config) interface{} { + return cfg.GetInt(oldkey) + }) +} + // deprecateString logs a deprecation message if `oldkey` is used. // It sets `newkey` to the value obtained from `getFn`, but only if `oldkey` is set and `newkey` is not set. func deprecateString(cfg config.Config, oldkey string, newkey string) { diff --git a/cmd/system-probe/config/adjust_usm.go b/cmd/system-probe/config/adjust_usm.go index 15e87f3c106c7..bd0d3c7caa281 100644 --- a/cmd/system-probe/config/adjust_usm.go +++ b/cmd/system-probe/config/adjust_usm.go @@ -18,6 +18,9 @@ const ( func adjustUSM(cfg config.Config) { deprecateBool(cfg, netNS("enable_http_monitoring"), smNS("enable_http_monitoring")) + deprecateGeneric(cfg, netNS("http_replace_rules"), smNS("http_replace_rules")) + deprecateInt64(cfg, netNS("max_tracked_http_connections"), smNS("max_tracked_http_connections")) + deprecateInt(cfg, netNS("max_http_stats_buffered"), smNS("max_http_stats_buffered")) if cfg.GetBool(dsmNS("enabled")) { // DSM infers USM diff --git a/pkg/config/system_probe.go b/pkg/config/system_probe.go index eb8a08298abff..0248f12b77332 100644 --- a/pkg/config/system_probe.go +++ b/pkg/config/system_probe.go @@ -17,6 +17,8 @@ import ( "github.com/DataDog/datadog-agent/pkg/util/log" ) +type transformerFunction func(string) interface{} + const ( spNS = "system_probe_config" netNS = "network_config" @@ -209,17 +211,27 @@ func InitSystemProbeConfig(cfg Config) { cfg.BindEnvAndSetDefault(join(netNS, "enable_gateway_lookup"), true, "DD_SYSTEM_PROBE_NETWORK_ENABLE_GATEWAY_LOOKUP") cfg.BindEnvAndSetDefault(join(netNS, "max_http_stats_buffered"), 100000, "DD_SYSTEM_PROBE_NETWORK_MAX_HTTP_STATS_BUFFERED") + cfg.BindEnv(join(smNS, "max_http_stats_buffered")) cfg.BindEnvAndSetDefault(join(smNS, "max_kafka_stats_buffered"), 100000) - httpRules := join(netNS, "http_replace_rules") - cfg.BindEnv(httpRules, "DD_SYSTEM_PROBE_NETWORK_HTTP_REPLACE_RULES") - cfg.SetEnvKeyTransformer(httpRules, func(in string) interface{} { - var out []map[string]string - if err := json.Unmarshal([]byte(in), &out); err != nil { - log.Warnf(`%q can not be parsed: %v`, httpRules, err) + + oldHTTPRules := join(netNS, "http_replace_rules") + newHTTPRules := join(smNS, "http_replace_rules") + cfg.BindEnv(newHTTPRules) + cfg.BindEnv(oldHTTPRules, "DD_SYSTEM_PROBE_NETWORK_HTTP_REPLACE_RULES") + httpRulesTransformer := func(key string) transformerFunction { + return func(in string) interface{} { + var out []map[string]string + if err := json.Unmarshal([]byte(in), &out); err != nil { + log.Warnf(`%q can not be parsed: %v`, key, err) + } + return out } - return out - }) + } + cfg.SetEnvKeyTransformer(oldHTTPRules, httpRulesTransformer(oldHTTPRules)) + cfg.SetEnvKeyTransformer(newHTTPRules, httpRulesTransformer(newHTTPRules)) + cfg.BindEnvAndSetDefault(join(netNS, "max_tracked_http_connections"), 1024) + cfg.BindEnv(join(smNS, "max_tracked_http_connections")) cfg.BindEnvAndSetDefault(join(netNS, "http_notification_threshold"), 512) cfg.BindEnvAndSetDefault(join(netNS, "http_max_request_fragment"), 160) diff --git a/pkg/network/config/config.go b/pkg/network/config/config.go index 6f6ddff54f633..2590b65102810 100644 --- a/pkg/network/config/config.go +++ b/pkg/network/config/config.go @@ -299,10 +299,10 @@ func New() *Config { EnableHTTPMonitoring: cfg.GetBool(join(smNS, "enable_http_monitoring")), EnableHTTP2Monitoring: cfg.GetBool(join(smNS, "enable_http2_monitoring")), EnableHTTPSMonitoring: cfg.GetBool(join(netNS, "enable_https_monitoring")), - MaxHTTPStatsBuffered: cfg.GetInt(join(netNS, "max_http_stats_buffered")), + MaxHTTPStatsBuffered: cfg.GetInt(join(smNS, "max_http_stats_buffered")), MaxKafkaStatsBuffered: cfg.GetInt(join(smNS, "max_kafka_stats_buffered")), - MaxTrackedHTTPConnections: cfg.GetInt64(join(netNS, "max_tracked_http_connections")), + MaxTrackedHTTPConnections: cfg.GetInt64(join(smNS, "max_tracked_http_connections")), HTTPNotificationThreshold: cfg.GetInt64(join(netNS, "http_notification_threshold")), HTTPMaxRequestFragment: cfg.GetInt64(join(netNS, "http_max_request_fragment")), @@ -340,7 +340,7 @@ func New() *Config { EnableHTTPStatsByStatusCode: cfg.GetBool(join(smNS, "enable_http_stats_by_status_code")), } - httpRRKey := join(netNS, "http_replace_rules") + httpRRKey := join(smNS, "http_replace_rules") rr, err := parseReplaceRules(cfg, httpRRKey) if err != nil { log.Errorf("error parsing %q: %v", httpRRKey, err) diff --git a/pkg/network/config/config_test.go b/pkg/network/config/config_test.go index b0f420d4c2d51..b2f7bf9fa2e89 100644 --- a/pkg/network/config/config_test.go +++ b/pkg/network/config/config_test.go @@ -444,9 +444,49 @@ func TestHTTPReplaceRules(t *testing.T) { }, } + envContent := ` + [ + { + "pattern": "/users/(.*)", + "repl": "/users/?" + }, + { + "pattern": "foo", + "repl": "bar" + }, + { + "pattern": "payment_id" + } + ] + ` + + t.Run("via deprecated YAML", func(t *testing.T) { + newConfig(t) + _, err := sysconfig.New("./testdata/TestDDSystemProbeConfig-HTTPReplaceRulesDeprecated.yaml") + require.NoError(t, err) + cfg := New() + + require.Len(t, cfg.HTTPReplaceRules, 3) + for i, r := range expected { + assert.Equal(t, r, cfg.HTTPReplaceRules[i]) + } + }) + + t.Run("via deprecated ENV variable", func(t *testing.T) { + newConfig(t) + t.Setenv("DD_SYSTEM_PROBE_NETWORK_HTTP_REPLACE_RULES", envContent) + + cfg := New() + + require.Len(t, cfg.HTTPReplaceRules, 3) + for i, r := range expected { + assert.Equal(t, r, cfg.HTTPReplaceRules[i]) + } + }) + t.Run("via YAML", func(t *testing.T) { newConfig(t) - _, err := sysconfig.New("./testdata/TestDDAgentConfigYamlAndSystemProbeConfig-HTTPReplaceRules.yaml") + _, err := sysconfig.New("./testdata/TestDDSystemProbeConfig-HTTPReplaceRules.yaml") require.NoError(t, err) cfg := New() @@ -458,24 +498,52 @@ func TestHTTPReplaceRules(t *testing.T) { t.Run("via ENV variable", func(t *testing.T) { newConfig(t) + t.Setenv("DD_SERVICE_MONITORING_CONFIG_HTTP_REPLACE_RULES", envContent) + + cfg := New() + + require.Len(t, cfg.HTTPReplaceRules, 3) + for i, r := range expected { + assert.Equal(t, r, cfg.HTTPReplaceRules[i]) + } + }) + + t.Run("Deprecated is enabled, new is disabled", func(t *testing.T) { + newConfig(t) + t.Setenv("DD_SYSTEM_PROBE_NETWORK_HTTP_REPLACE_RULES", envContent) + + cfg := New() + + require.Len(t, cfg.HTTPReplaceRules, 3) + for i, r := range expected { + assert.Equal(t, r, cfg.HTTPReplaceRules[i]) + } + }) + + t.Run("Deprecated is disabled, new is enabled", func(t *testing.T) { + newConfig(t) + t.Setenv("DD_SERVICE_MONITORING_CONFIG_HTTP_REPLACE_RULES", envContent) + + cfg := New() + + require.Len(t, cfg.HTTPReplaceRules, 3) + for i, r := range expected { + assert.Equal(t, r, cfg.HTTPReplaceRules[i]) + } + }) + + t.Run("Both enabled", func(t *testing.T) { + newConfig(t) + t.Setenv("DD_SERVICE_MONITORING_CONFIG_HTTP_REPLACE_RULES", envContent) + // Setting a different value for the old value, as we should override. t.Setenv("DD_SYSTEM_PROBE_NETWORK_HTTP_REPLACE_RULES", ` [ - { - "pattern": "/users/(.*)", - "repl": "/users/?" - }, - { - "pattern": "foo", - "repl": "bar" - }, { "pattern": "payment_id" } ] `) - _, err := sysconfig.New("") - require.NoError(t, err) cfg := New() require.Len(t, cfg.HTTPReplaceRules, 3) @@ -483,6 +551,87 @@ func TestHTTPReplaceRules(t *testing.T) { assert.Equal(t, r, cfg.HTTPReplaceRules[i]) } }) + + t.Run("Not enabled", func(t *testing.T) { + newConfig(t) + cfg := New() + + assert.Empty(t, cfg.HTTPReplaceRules) + }) +} + +func TestMaxTrackedHTTPConnections(t *testing.T) { + t.Run("via deprecated YAML", func(t *testing.T) { + newConfig(t) + _, err := sysconfig.New("./testdata/TestDDSystemProbeConfig-MaxTrackedHTTPConnectionsDeprecated.yaml") + require.NoError(t, err) + cfg := New() + + require.Equal(t, cfg.MaxTrackedHTTPConnections, int64(1025)) + }) + + t.Run("via deprecated ENV variable", func(t *testing.T) { + newConfig(t) + t.Setenv("DD_NETWORK_CONFIG_MAX_TRACKED_HTTP_CONNECTIONS", "1025") + + cfg := New() + + require.Equal(t, cfg.MaxTrackedHTTPConnections, int64(1025)) + }) + + t.Run("via YAML", func(t *testing.T) { + newConfig(t) + _, err := sysconfig.New("./testdata/TestDDSystemProbeConfig-MaxTrackedHTTPConnections.yaml") + require.NoError(t, err) + cfg := New() + + require.Equal(t, cfg.MaxTrackedHTTPConnections, int64(1025)) + }) + + t.Run("via ENV variable", func(t *testing.T) { + newConfig(t) + t.Setenv("DD_SERVICE_MONITORING_CONFIG_MAX_TRACKED_HTTP_CONNECTIONS", "1025") + + cfg := New() + + require.Equal(t, cfg.MaxTrackedHTTPConnections, int64(1025)) + }) + + t.Run("Deprecated is enabled, new is disabled", func(t *testing.T) { + newConfig(t) + t.Setenv("DD_NETWORK_CONFIG_MAX_TRACKED_HTTP_CONNECTIONS", "1025") + + cfg := New() + + require.Equal(t, cfg.MaxTrackedHTTPConnections, int64(1025)) + }) + + t.Run("Deprecated is disabled, new is enabled", func(t *testing.T) { + newConfig(t) + t.Setenv("DD_SERVICE_MONITORING_CONFIG_MAX_TRACKED_HTTP_CONNECTIONS", "1025") + + cfg := New() + + require.Equal(t, cfg.MaxTrackedHTTPConnections, int64(1025)) + }) + + t.Run("Both enabled", func(t *testing.T) { + newConfig(t) + // Setting a different value + t.Setenv("DD_NETWORK_CONFIG_MAX_TRACKED_HTTP_CONNECTIONS", "1026") + t.Setenv("DD_SERVICE_MONITORING_CONFIG_MAX_TRACKED_HTTP_CONNECTIONS", "1025") + + cfg := New() + + require.Equal(t, cfg.MaxTrackedHTTPConnections, int64(1025)) + }) + + t.Run("Not enabled", func(t *testing.T) { + newConfig(t) + cfg := New() + // Default value. + require.Equal(t, cfg.MaxTrackedHTTPConnections, int64(1024)) + }) } func TestHTTPNotificationThreshold(t *testing.T) { @@ -558,20 +707,75 @@ func TestMaxClosedConnectionsBuffered(t *testing.T) { } func TestMaxHTTPStatsBuffered(t *testing.T) { - t.Run("value set through env var", func(t *testing.T) { + t.Run("via deprecated YAML", func(t *testing.T) { + newConfig(t) + _, err := sysconfig.New("./testdata/TestDDSystemProbeConfig-MaxHTTPStatsBufferedDeprecated.yaml") + require.NoError(t, err) + cfg := New() + + require.Equal(t, cfg.MaxHTTPStatsBuffered, 513) + }) + + t.Run("via deprecated ENV variable", func(t *testing.T) { newConfig(t) - t.Setenv("DD_SYSTEM_PROBE_NETWORK_MAX_HTTP_STATS_BUFFERED", "50000") + t.Setenv("DD_SYSTEM_PROBE_NETWORK_MAX_HTTP_STATS_BUFFERED", "513") + cfg := New() - assert.Equal(t, 50000, cfg.MaxHTTPStatsBuffered) + + require.Equal(t, cfg.MaxHTTPStatsBuffered, 513) }) - t.Run("value set through yaml", func(t *testing.T) { + t.Run("via YAML", func(t *testing.T) { newConfig(t) - cfg := configurationFromYAML(t, ` -network_config: - max_http_stats_buffered: 30000 -`) - assert.Equal(t, 30000, cfg.MaxHTTPStatsBuffered) + _, err := sysconfig.New("./testdata/TestDDSystemProbeConfig-MaxHTTPStatsBuffered.yaml") + require.NoError(t, err) + cfg := New() + + require.Equal(t, cfg.MaxHTTPStatsBuffered, 513) + }) + + t.Run("via ENV variable", func(t *testing.T) { + newConfig(t) + t.Setenv("DD_SERVICE_MONITORING_CONFIG_MAX_HTTP_STATS_BUFFERED", "513") + + cfg := New() + + require.Equal(t, cfg.MaxHTTPStatsBuffered, 513) + }) + + t.Run("Deprecated is enabled, new is disabled", func(t *testing.T) { + newConfig(t) + t.Setenv("DD_SYSTEM_PROBE_NETWORK_MAX_HTTP_STATS_BUFFERED", "513") + + cfg := New() + + require.Equal(t, cfg.MaxHTTPStatsBuffered, 513) + }) + + t.Run("Deprecated is disabled, new is enabled", func(t *testing.T) { + newConfig(t) + t.Setenv("DD_SERVICE_MONITORING_CONFIG_MAX_HTTP_STATS_BUFFERED", "513") + + cfg := New() + + require.Equal(t, cfg.MaxHTTPStatsBuffered, 513) + }) + + t.Run("Both enabled", func(t *testing.T) { + newConfig(t) + t.Setenv("DD_SYSTEM_PROBE_NETWORK_MAX_HTTP_STATS_BUFFERED", "514") + t.Setenv("DD_SERVICE_MONITORING_CONFIG_MAX_HTTP_STATS_BUFFERED", "513") + + cfg := New() + + require.Equal(t, cfg.MaxHTTPStatsBuffered, 513) + }) + + t.Run("Not enabled", func(t *testing.T) { + newConfig(t) + cfg := New() + // Default value. + require.Equal(t, cfg.MaxHTTPStatsBuffered, 100000) }) } diff --git a/pkg/network/config/testdata/TestDDSystemProbeConfig-HTTPReplaceRules.yaml b/pkg/network/config/testdata/TestDDSystemProbeConfig-HTTPReplaceRules.yaml new file mode 100644 index 0000000000000..1657f27894b2e --- /dev/null +++ b/pkg/network/config/testdata/TestDDSystemProbeConfig-HTTPReplaceRules.yaml @@ -0,0 +1,7 @@ +service_monitoring_config: + http_replace_rules: + - pattern: "/users/(.*)" + repl: "/users/?" + - pattern: "foo" + repl: "bar" + - pattern: "payment_id" diff --git a/pkg/network/config/testdata/TestDDAgentConfigYamlAndSystemProbeConfig-HTTPReplaceRules.yaml b/pkg/network/config/testdata/TestDDSystemProbeConfig-HTTPReplaceRulesDeprecated.yaml similarity index 100% rename from pkg/network/config/testdata/TestDDAgentConfigYamlAndSystemProbeConfig-HTTPReplaceRules.yaml rename to pkg/network/config/testdata/TestDDSystemProbeConfig-HTTPReplaceRulesDeprecated.yaml diff --git a/pkg/network/config/testdata/TestDDSystemProbeConfig-MaxHTTPStatsBuffered.yaml b/pkg/network/config/testdata/TestDDSystemProbeConfig-MaxHTTPStatsBuffered.yaml new file mode 100644 index 0000000000000..3e0fa225ecf99 --- /dev/null +++ b/pkg/network/config/testdata/TestDDSystemProbeConfig-MaxHTTPStatsBuffered.yaml @@ -0,0 +1,2 @@ +service_monitoring_config: + max_http_stats_buffered: 513 diff --git a/pkg/network/config/testdata/TestDDSystemProbeConfig-MaxHTTPStatsBufferedDeprecated.yaml b/pkg/network/config/testdata/TestDDSystemProbeConfig-MaxHTTPStatsBufferedDeprecated.yaml new file mode 100644 index 0000000000000..f3ec35190078a --- /dev/null +++ b/pkg/network/config/testdata/TestDDSystemProbeConfig-MaxHTTPStatsBufferedDeprecated.yaml @@ -0,0 +1,2 @@ +network_config: + max_http_stats_buffered: 513 diff --git a/pkg/network/config/testdata/TestDDSystemProbeConfig-MaxTrackedHTTPConnections.yaml b/pkg/network/config/testdata/TestDDSystemProbeConfig-MaxTrackedHTTPConnections.yaml new file mode 100644 index 0000000000000..b00672165838a --- /dev/null +++ b/pkg/network/config/testdata/TestDDSystemProbeConfig-MaxTrackedHTTPConnections.yaml @@ -0,0 +1,2 @@ +service_monitoring_config: + max_tracked_http_connections: 1025 diff --git a/pkg/network/config/testdata/TestDDSystemProbeConfig-MaxTrackedHTTPConnectionsDeprecated.yaml b/pkg/network/config/testdata/TestDDSystemProbeConfig-MaxTrackedHTTPConnectionsDeprecated.yaml new file mode 100644 index 0000000000000..ce12247adbb50 --- /dev/null +++ b/pkg/network/config/testdata/TestDDSystemProbeConfig-MaxTrackedHTTPConnectionsDeprecated.yaml @@ -0,0 +1,2 @@ +network_config: + max_tracked_http_connections: 1025 diff --git a/releasenotes/notes/deprecating-usm-configuration-values-6c43a0181c2cc821.yaml b/releasenotes/notes/deprecating-usm-configuration-values-6c43a0181c2cc821.yaml new file mode 100644 index 0000000000000..1f490f3e26708 --- /dev/null +++ b/releasenotes/notes/deprecating-usm-configuration-values-6c43a0181c2cc821.yaml @@ -0,0 +1,5 @@ +--- +deprecations: + - The `network_config.http_replace_rules` configuration has been deprecated. Use `service_monitoring_config.http_replace_rules` instead. + - The `network_config.max_tracked_http_connections` configuration has been deprecated. Use `service_monitoring_config.max_tracked_http_connections` instead. + - The `network_config.max_http_stats_buffered` configuration has been deprecated. Use `service_monitoring_config.max_http_stats_buffered` instead. From 8dd7bc3f22fea8d31430d44610ff16dc1a5d79fe Mon Sep 17 00:00:00 2001 From: Abhinav Vedmala Date: Wed, 7 Jun 2023 10:47:39 -0400 Subject: [PATCH 32/76] Cloud Service implementation for Azure App Service (#17483) This PR is extending serverless Cloud Service support to web apps running in Azure App Service containers. --- .../cloudservice/appservice.go | 49 +++++++++++++++++++ .../cloudservice/appservice_test.go | 29 +++++++++++ cmd/serverless-init/cloudservice/service.go | 4 ++ 3 files changed, 82 insertions(+) create mode 100644 cmd/serverless-init/cloudservice/appservice.go create mode 100644 cmd/serverless-init/cloudservice/appservice_test.go diff --git a/cmd/serverless-init/cloudservice/appservice.go b/cmd/serverless-init/cloudservice/appservice.go new file mode 100644 index 0000000000000..432d1bf3ae6cd --- /dev/null +++ b/cmd/serverless-init/cloudservice/appservice.go @@ -0,0 +1,49 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2016-present Datadog, Inc. + +package cloudservice + +import ( + "os" +) + +// AppService has helper functions for getting specific Azure Container App data +type AppService struct{} + +const ( + WebsiteName = "WEBSITE_SITE_NAME" + RegionName = "REGION_NAME" + RunZip = "APPSVC_RUN_ZIP" +) + +// GetTags returns a map of Azure-related tags +func (a *AppService) GetTags() map[string]string { + appName := os.Getenv(WebsiteName) + region := os.Getenv(RegionName) + + return map[string]string{ + "app_name": appName, + "region": region, + "origin": a.GetOrigin(), + "_dd.origin": a.GetOrigin(), + } +} + +// GetOrigin returns the `origin` attribute type for the given +// cloud service. +func (a *AppService) GetOrigin() string { + return "appservice" +} + +// GetPrefix returns the prefix that we're prefixing all +// metrics with. +func (a *AppService) GetPrefix() string { + return "azure.appservice" +} + +func isAppService() bool { + _, exists := os.LookupEnv(RunZip) + return exists +} diff --git a/cmd/serverless-init/cloudservice/appservice_test.go b/cmd/serverless-init/cloudservice/appservice_test.go new file mode 100644 index 0000000000000..8e783e944b30f --- /dev/null +++ b/cmd/serverless-init/cloudservice/appservice_test.go @@ -0,0 +1,29 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2016-present Datadog, Inc. + +package cloudservice + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestGetAppServiceTags(t *testing.T) { + service := &AppService{} + + t.Setenv("WEBSITE_SITE_NAME", "test_site_name") + t.Setenv("REGION_NAME", "eastus") + t.Setenv("APPSVC_RUN_ZIP", "false") + + tags := service.GetTags() + + assert.Equal(t, map[string]string{ + "app_name": "test_site_name", + "origin": "appservice", + "region": "eastus", + "_dd.origin": "appservice", + }, tags) +} diff --git a/cmd/serverless-init/cloudservice/service.go b/cmd/serverless-init/cloudservice/service.go index 78053c1a8a371..6ad1988434594 100644 --- a/cmd/serverless-init/cloudservice/service.go +++ b/cmd/serverless-init/cloudservice/service.go @@ -48,5 +48,9 @@ func GetCloudServiceType() CloudService { return &ContainerApp{} } + if isAppService() { + return &AppService{} + } + return &LocalService{} } From af9aca50ecae4be11e0771d888d280df280a6419 Mon Sep 17 00:00:00 2001 From: Sylvain Afchain Date: Wed, 7 Jun 2023 16:54:20 +0200 Subject: [PATCH 33/76] [CWS] avoid exec bomb (#17435) --- pkg/security/resolvers/process/resolver.go | 6 ++ .../resolvers/process/resolver_test.go | 75 +++++++++++++++++++ pkg/security/secl/model/model.go | 24 +++++- .../secl/model/process_cache_entry.go | 12 ++- 4 files changed, 114 insertions(+), 3 deletions(-) diff --git a/pkg/security/resolvers/process/resolver.go b/pkg/security/resolvers/process/resolver.go index 78c265b6cd20a..4717fe3ae014f 100644 --- a/pkg/security/resolvers/process/resolver.go +++ b/pkg/security/resolvers/process/resolver.go @@ -529,6 +529,12 @@ func (p *Resolver) insertForkEntry(entry *model.ProcessCacheEntry, origin uint64 func (p *Resolver) insertExecEntry(entry *model.ProcessCacheEntry, origin uint64) { prev := p.entryCache[entry.Pid] if prev != nil { + // check exec bomb + if prev.Equals(entry) { + prev.ApplyExecTimeOf(entry) + return + } + prev.Exec(entry) } diff --git a/pkg/security/resolvers/process/resolver_test.go b/pkg/security/resolvers/process/resolver_test.go index c5f584c2e15dc..b975c59d3612c 100644 --- a/pkg/security/resolvers/process/resolver_test.go +++ b/pkg/security/resolvers/process/resolver_test.go @@ -127,6 +127,7 @@ func TestForkExec(t *testing.T) { exec := resolver.NewProcessCacheEntry(model.PIDContext{Pid: child.Pid, Tid: child.Pid}) exec.PPid = child.PPid + exec.FileEvent.Inode = 123 exec.ExecTime = time.Now() // parent @@ -183,6 +184,7 @@ func TestOrphanExec(t *testing.T) { exec := resolver.NewProcessCacheEntry(model.PIDContext{Pid: child.Pid, Tid: child.Pid}) exec.Pid = child.Pid exec.PPid = child.PPid + exec.FileEvent.Inode = 123 exec.ExecTime = time.Now() // parent @@ -237,11 +239,13 @@ func TestForkExecExec(t *testing.T) { exec1 := resolver.NewProcessCacheEntry(model.PIDContext{Pid: child.Pid, Tid: child.Pid}) exec1.PPid = child.PPid + exec1.FileEvent.Inode = 123 exec1.ExecTime = time.Now() exec2 := resolver.NewProcessCacheEntry(model.PIDContext{Pid: child.Pid, Tid: child.Pid}) exec2.Pid = child.Pid exec2.PPid = child.PPid + exec2.FileEvent.Inode = 456 exec2.ExecTime = time.Now() // parent @@ -306,6 +310,7 @@ func TestForkReuse(t *testing.T) { exec1 := resolver.NewProcessCacheEntry(model.PIDContext{Pid: child1.Pid, Tid: child1.Pid}) exec1.PPid = child1.PPid + exec1.FileEvent.Inode = 123 exec1.ExecTime = time.Now() parent2 := resolver.NewProcessCacheEntry(model.PIDContext{Pid: 1, Tid: 1}) @@ -405,6 +410,7 @@ func TestForkForkExec(t *testing.T) { childExec := resolver.NewProcessCacheEntry(model.PIDContext{Pid: child.Pid, Tid: child.Pid}) childExec.Pid = child.Pid childExec.PPid = child.PPid + childExec.FileEvent.Inode = 123 childExec.ExecTime = time.Now() // parent @@ -459,3 +465,72 @@ func TestForkForkExec(t *testing.T) { testCacheSize(t, resolver) } + +func TestExecBomb(t *testing.T) { + resolver, err := NewResolver(nil, nil, &statsd.NoOpClient{}, nil, nil, nil, nil, nil, nil, nil, NewResolverOpts()) + if err != nil { + t.Fatal(err) + } + + parent := resolver.NewProcessCacheEntry(model.PIDContext{Pid: 1, Tid: 1}) + parent.ForkTime = time.Now() + + child := resolver.NewProcessCacheEntry(model.PIDContext{Pid: 2, Tid: 2}) + child.PPid = parent.Pid + child.ForkTime = time.Now() + + exec1 := resolver.NewProcessCacheEntry(model.PIDContext{Pid: child.Pid, Tid: child.Pid}) + exec1.PPid = child.PPid + exec1.FileEvent.Inode = 123 + exec1.ExecTime = time.Now() + + exec2 := resolver.NewProcessCacheEntry(model.PIDContext{Pid: child.Pid, Tid: child.Pid}) + exec2.Pid = child.Pid + exec2.PPid = child.PPid + exec2.FileEvent.Inode = 123 + exec2.ExecTime = time.Now() + + // parent + resolver.AddForkEntry(parent) + assert.Equal(t, parent, resolver.entryCache[parent.Pid]) + assert.Equal(t, 1, len(resolver.entryCache)) + assert.EqualValues(t, 1, resolver.cacheSize.Load()) + + // parent + // \ child + resolver.AddForkEntry(child) + assert.Equal(t, child, resolver.entryCache[child.Pid]) + assert.Equal(t, 2, len(resolver.entryCache)) + assert.Equal(t, parent, child.Ancestor) + assert.EqualValues(t, 2, resolver.cacheSize.Load()) + + // [parent] + // \ child + resolver.DeleteEntry(parent.Pid, time.Now()) + assert.Nil(t, resolver.entryCache[parent.Pid]) + assert.Equal(t, 1, len(resolver.entryCache)) + assert.Equal(t, parent, child.Ancestor) + + // [parent] + // \ [child] -> exec1 + resolver.AddExecEntry(exec1) + assert.Equal(t, exec1, resolver.entryCache[exec1.Pid]) + assert.Equal(t, 1, len(resolver.entryCache)) + assert.Equal(t, child, exec1.Ancestor) + assert.Equal(t, parent, exec1.Ancestor.Ancestor) + assert.EqualValues(t, 3, resolver.cacheSize.Load()) + + // [parent] + // \ [child] -> [exec1] -> exec2 + resolver.AddExecEntry(exec2) + assert.Equal(t, exec1, resolver.entryCache[exec2.Pid]) + assert.Equal(t, 1, len(resolver.entryCache)) + assert.Equal(t, exec1.ExecTime, exec2.ExecTime) + assert.EqualValues(t, 3, resolver.cacheSize.Load()) + + // nothing + resolver.DeleteEntry(exec1.Pid, time.Now()) + assert.Zero(t, len(resolver.entryCache)) + + testCacheSize(t, resolver) +} diff --git a/pkg/security/secl/model/model.go b/pkg/security/secl/model/model.go index be343d4ee77ed..1721cd7349a52 100644 --- a/pkg/security/secl/model/model.go +++ b/pkg/security/secl/model/model.go @@ -538,6 +538,18 @@ type Credentials struct { CapPermitted uint64 `field:"cap_permitted"` // SECLDoc[cap_permitted] Definition:`Permitted capability set of the process` Constants:`Kernel Capability constants` } +// Equals returns if both credentials are equal +func (c *Credentials) Equals(o *Credentials) bool { + return (c.UID == o.UID && + c.GID == o.GID && + c.EUID == o.EUID && + c.EGID == o.EGID && + c.FSUID == o.FSUID && + c.FSGID == o.FSGID && + c.CapEffective == o.CapEffective && + c.CapPermitted == o.CapPermitted) +} + // GetPathResolutionError returns the path resolution error as a string if there is one func (p *Process) GetPathResolutionError() string { return p.FileEvent.GetPathResolutionError() @@ -584,7 +596,7 @@ type Process struct { PPid uint32 `field:"ppid"` // SECLDoc[ppid] Definition:`Parent process ID` // credentials_t section of pid_cache_t - Credentials `` + Credentials ArgsID uint32 `field:"-" json:"-"` EnvsID uint32 `field:"-" json:"-"` @@ -651,6 +663,11 @@ type FileFields struct { Flags int32 `field:"-" json:"-"` } +// Equals compares two FileFields +func (f *FileFields) Equals(o *FileFields) bool { + return f.Inode == o.Inode && f.MountID == o.MountID && f.MTime == o.MTime && f.UID == o.UID && f.GID == o.GID && f.Mode == o.Mode +} + // IsFileless return whether it is a file less access func (f *FileFields) IsFileless() bool { // TODO(safchain) fix this heuristic by add a flag in the event intead of using mount ID 0 @@ -691,6 +708,11 @@ type FileEvent struct { IsBasenameStrResolved bool `field:"-" json:"-"` } +// Equals compare two FileEvent +func (e *FileEvent) Equals(o *FileEvent) bool { + return e.FileFields.Equals(&o.FileFields) +} + // SetPathnameStr set and mark as resolved func (e *FileEvent) SetPathnameStr(str string) { e.PathnameStr = str diff --git a/pkg/security/secl/model/process_cache_entry.go b/pkg/security/secl/model/process_cache_entry.go index 52a8490c9d217..fc29e467c3e42 100644 --- a/pkg/security/secl/model/process_cache_entry.go +++ b/pkg/security/secl/model/process_cache_entry.go @@ -67,6 +67,11 @@ func copyProcessContext(parent, child *ProcessCacheEntry) { } } +// Replace previous entry values by the given one +func (pc *ProcessCacheEntry) ApplyExecTimeOf(entry *ProcessCacheEntry) { + pc.ExecTime = entry.ExecTime +} + // Exec replace a process func (pc *ProcessCacheEntry) Exec(entry *ProcessCacheEntry) { entry.SetAncestor(pc) @@ -103,9 +108,12 @@ func (pc *ProcessCacheEntry) Fork(childEntry *ProcessCacheEntry) { childEntry.SetParentOfForkChild(pc) } -// Equals returns whether process cache entries share the same values for comm and args/envs +// Equals returns whether process cache entries share the same values for file and args/envs func (pc *ProcessCacheEntry) Equals(entry *ProcessCacheEntry) bool { - return pc.Comm == entry.Comm && pc.ArgsEntry.Equals(entry.ArgsEntry) && pc.EnvsEntry.Equals(entry.EnvsEntry) + return (pc.FileEvent.Equals(&entry.FileEvent) && + pc.Credentials.Equals(&entry.Credentials) && + pc.ArgsEntry.Equals(entry.ArgsEntry) && + pc.EnvsEntry.Equals(entry.EnvsEntry)) } // NewEmptyProcessCacheEntry returns an empty process cache entry for kworker events or failed process resolutions From b679009c30ae68fb1b36f5c769956bc91aaa7521 Mon Sep 17 00:00:00 2001 From: Sylvain Afchain Date: Wed, 7 Jun 2023 16:54:53 +0200 Subject: [PATCH 34/76] [CWS] fix process schema (#17422) --- pkg/security/tests/schemas/process.json | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/pkg/security/tests/schemas/process.json b/pkg/security/tests/schemas/process.json index 675686b9a3240..8cd4e967e62a0 100644 --- a/pkg/security/tests/schemas/process.json +++ b/pkg/security/tests/schemas/process.json @@ -48,6 +48,15 @@ "is_kworker": { "type": "boolean" }, + "args": { + "type": "array", + "items": { + "type": "string" + } + }, + "argv0": { + "type": "string" + }, "credentials": { "type": "object", "properties": { @@ -151,15 +160,6 @@ "items": { "type": "string" } - }, - "args": { - "type": "array", - "items": { - "type": "string" - } - }, - "argv0": { - "type": "string" } }, "required": [ From b203c03302213d7b75b05097e32e8610f34ec88e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 7 Jun 2023 11:00:07 -0400 Subject: [PATCH 35/76] Bump github.com/open-policy-agent/opa from 0.53.0 to 0.53.1 (#17505) Bumps [github.com/open-policy-agent/opa](https://github.com/open-policy-agent/opa) from 0.53.0 to 0.53.1. - [Release notes](https://github.com/open-policy-agent/opa/releases) - [Changelog](https://github.com/open-policy-agent/opa/blob/main/CHANGELOG.md) - [Commits](https://github.com/open-policy-agent/opa/compare/v0.53.0...v0.53.1) --- updated-dependencies: - dependency-name: github.com/open-policy-agent/opa dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index e76922fccce2d..bc84708744ed5 100644 --- a/go.mod +++ b/go.mod @@ -150,7 +150,7 @@ require ( github.com/netsampler/goflow2 v1.3.3 github.com/olekukonko/tablewriter v0.0.5 github.com/oliveagle/jsonpath v0.0.0-20180606110733-2e52cf6e6852 - github.com/open-policy-agent/opa v0.53.0 + github.com/open-policy-agent/opa v0.53.1 github.com/open-telemetry/opentelemetry-collector-contrib/pkg/resourcetotelemetry v0.75.0 github.com/opencontainers/go-digest v1.0.0 github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b diff --git a/go.sum b/go.sum index 34cff51977120..8349907853ede 100644 --- a/go.sum +++ b/go.sum @@ -1475,8 +1475,8 @@ github.com/onsi/gomega v1.10.5/go.mod h1:gza4q3jKQJijlu05nKWRCW/GavJumGt8aNRxWg7 github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs= github.com/onsi/gomega v1.24.1 h1:KORJXNNTzJXzu4ScJWssJfJMnJ+2QJqhoQSRwNlze9E= -github.com/open-policy-agent/opa v0.53.0 h1:zC/0sI+Gof5/oiFNS3DmoJa11D0m0InZeDhZyzi+l6E= -github.com/open-policy-agent/opa v0.53.0/go.mod h1:j3wl8FqSz/+u33Scl72Ms2wxkZx4yZPdqSCrOqBqdsA= +github.com/open-policy-agent/opa v0.53.1 h1:APN8iA7Txgel13kSkc6S8dbUulydiPojXt6iyubmB7Q= +github.com/open-policy-agent/opa v0.53.1/go.mod h1:j3wl8FqSz/+u33Scl72Ms2wxkZx4yZPdqSCrOqBqdsA= github.com/open-telemetry/opentelemetry-collector-contrib/internal/coreinternal v0.75.0 h1:XW4DBJP3+dgdclPVA7d9aetG/FBUmwSNQGWaWoZnyo0= github.com/open-telemetry/opentelemetry-collector-contrib/pkg/resourcetotelemetry v0.75.0 h1:YUku2qImuCj85X7LNGjToa3X1hJUd3VIBGVVbikGv08= github.com/open-telemetry/opentelemetry-collector-contrib/pkg/resourcetotelemetry v0.75.0/go.mod h1:Zx+/9iSrxOX8yI5pq1yQjLkTW/mQRs8kw4t0w4Ro820= From 82ac88d167a7bf867680510cf69161afba0facd0 Mon Sep 17 00:00:00 2001 From: Pierre Guilleminot Date: Wed, 7 Jun 2023 17:10:41 +0200 Subject: [PATCH 36/76] [CSPM] Do not allow http.send and opa.runtime rego builtins (#17409) --- pkg/compliance/evaluator_rego.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pkg/compliance/evaluator_rego.go b/pkg/compliance/evaluator_rego.go index ed42e3bda0c37..14e6f2bcb3a7d 100644 --- a/pkg/compliance/evaluator_rego.go +++ b/pkg/compliance/evaluator_rego.go @@ -68,6 +68,10 @@ func EvaluateRegoRule(ctx context.Context, resolvedInputs ResolvedInputs, benchm options = append(options, rego.Query("data.datadog.findings"), rego.Metrics(metrics.NewRegoTelemetry()), + rego.UnsafeBuiltins(map[string]struct{}{ + "http.send": {}, + "opa.runtime": {}, + }), rego.Input(resolvedInputs), ) From 769962c52661a48ad96250b9373484e5019e6076 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 7 Jun 2023 11:38:14 -0400 Subject: [PATCH 37/76] Bump github.com/hashicorp/golang-lru/v2 from 2.0.2 to 2.0.3 (#17503) Bumps [github.com/hashicorp/golang-lru/v2](https://github.com/hashicorp/golang-lru) from 2.0.2 to 2.0.3. - [Release notes](https://github.com/hashicorp/golang-lru/releases) - [Commits](https://github.com/hashicorp/golang-lru/compare/v2.0.2...v2.0.3) --- updated-dependencies: - dependency-name: github.com/hashicorp/golang-lru/v2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index bc84708744ed5..c74b25270bc24 100644 --- a/go.mod +++ b/go.mod @@ -129,7 +129,7 @@ require ( github.com/h2non/filetype v1.1.3 github.com/hashicorp/consul/api v1.20.0 github.com/hashicorp/go-multierror v1.1.1 - github.com/hashicorp/golang-lru/v2 v2.0.2 + github.com/hashicorp/golang-lru/v2 v2.0.3 github.com/hectane/go-acl v0.0.0-20190604041725-da78bae5fc95 github.com/iceber/iouring-go v0.0.0-20220609112130-b1dc8dd9fbfd github.com/imdario/mergo v0.3.15 diff --git a/go.sum b/go.sum index 8349907853ede..6ea5d03055017 100644 --- a/go.sum +++ b/go.sum @@ -1092,8 +1092,8 @@ github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= -github.com/hashicorp/golang-lru/v2 v2.0.2 h1:Dwmkdr5Nc/oBiXgJS3CDHNhJtIHkuZ3DZF5twqnfBdU= -github.com/hashicorp/golang-lru/v2 v2.0.2/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= +github.com/hashicorp/golang-lru/v2 v2.0.3 h1:kmRrRLlInXvng0SmLxmQpQkpbYAvcXm7NPDrgxJa9mE= +github.com/hashicorp/golang-lru/v2 v2.0.3/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hashicorp/hcl/v2 v2.14.1 h1:x0BpjfZ+CYdbiz+8yZTQ+gdLO7IXvOut7Da+XJayx34= From 8c758bf819340de3f21acbc6cdefc8b60accc205 Mon Sep 17 00:00:00 2001 From: Hasan Mahmood Date: Wed, 7 Jun 2023 12:51:23 -0400 Subject: [PATCH 38/76] [system-probe] Fix race in Stop() for tcp close consumer (#17511) --- pkg/ebpf/perf.go | 3 +- pkg/network/protocols/events/consumer.go | 3 +- .../tracer/connection/tcp_close_consumer.go | 32 ++++++++++++------- .../connection/tcp_close_consumer_test.go | 28 ++++++++++++++++ pkg/network/tracer/connection/tracer.go | 2 +- pkg/network/usm/shared_libraries.go | 6 ++-- 6 files changed, 57 insertions(+), 17 deletions(-) create mode 100644 pkg/network/tracer/connection/tcp_close_consumer_test.go diff --git a/pkg/ebpf/perf.go b/pkg/ebpf/perf.go index 5df806c99d23c..385133d95aa4d 100644 --- a/pkg/ebpf/perf.go +++ b/pkg/ebpf/perf.go @@ -10,8 +10,9 @@ package ebpf import ( "sync" - manager "github.com/DataDog/ebpf-manager" "github.com/cilium/ebpf/perf" + + manager "github.com/DataDog/ebpf-manager" ) // PerfHandler wraps an eBPF perf buffer diff --git a/pkg/network/protocols/events/consumer.go b/pkg/network/protocols/events/consumer.go index e7da6cc0e1423..7266518e73b05 100644 --- a/pkg/network/protocols/events/consumer.go +++ b/pkg/network/protocols/events/consumer.go @@ -13,11 +13,12 @@ import ( "time" "unsafe" + "go.uber.org/atomic" + ddebpf "github.com/DataDog/datadog-agent/pkg/ebpf" "github.com/DataDog/datadog-agent/pkg/network/protocols/telemetry" "github.com/DataDog/datadog-agent/pkg/util/log" manager "github.com/DataDog/ebpf-manager" - "go.uber.org/atomic" ) const ( diff --git a/pkg/network/tracer/connection/tcp_close_consumer.go b/pkg/network/tracer/connection/tcp_close_consumer.go index 2b5d72291d612..3386e6063d173 100644 --- a/pkg/network/tracer/connection/tcp_close_consumer.go +++ b/pkg/network/tracer/connection/tcp_close_consumer.go @@ -17,7 +17,6 @@ import ( netebpf "github.com/DataDog/datadog-agent/pkg/network/ebpf" "github.com/DataDog/datadog-agent/pkg/telemetry" "github.com/DataDog/datadog-agent/pkg/util/log" - manager "github.com/DataDog/ebpf-manager" ) const closeConsumerModuleName = "network_tracer__ebpf" @@ -37,18 +36,19 @@ type tcpCloseConsumer struct { requests chan chan struct{} buffer *network.ConnectionBuffer once sync.Once + closed chan struct{} ch *cookieHasher } -func newTCPCloseConsumer(m *manager.Manager, perfHandler *ddebpf.PerfHandler, batchManager *perfBatchManager) (*tcpCloseConsumer, error) { - c := &tcpCloseConsumer{ +func newTCPCloseConsumer(perfHandler *ddebpf.PerfHandler, batchManager *perfBatchManager) (*tcpCloseConsumer, error) { + return &tcpCloseConsumer{ perfHandler: perfHandler, batchManager: batchManager, requests: make(chan chan struct{}), buffer: network.NewConnectionBuffer(netebpf.BatchSize, netebpf.BatchSize), + closed: make(chan struct{}), ch: newCookieHasher(), } - return c, nil } func (c *tcpCloseConsumer) FlushPending() { @@ -56,9 +56,18 @@ func (c *tcpCloseConsumer) FlushPending() { return } + select { + case <-c.closed: + return + default: + } + wait := make(chan struct{}) - c.requests <- wait - <-wait + select { + case <-c.closed: + case c.requests <- wait: + <-wait + } } func (c *tcpCloseConsumer) Stop() { @@ -67,7 +76,7 @@ func (c *tcpCloseConsumer) Stop() { } c.perfHandler.Stop() c.once.Do(func() { - close(c.requests) + close(c.closed) }) } @@ -88,9 +97,12 @@ func (c *tcpCloseConsumer) Start(callback func([]network.ConnectionStats)) { closedCount uint64 lostCount uint64 ) + go func() { for { select { + case <-c.closed: + return case batchData, ok := <-c.perfHandler.DataChannel: if !ok { return @@ -119,11 +131,7 @@ func (c *tcpCloseConsumer) Start(callback func([]network.ConnectionStats)) { } closerConsumerTelemetry.perfLost.Add(float64(lc * netebpf.BatchSize)) lostCount += lc * netebpf.BatchSize - case request, ok := <-c.requests: - if !ok { - return - } - + case request := <-c.requests: oneTimeBuffer := network.NewConnectionBuffer(32, 32) c.batchManager.GetPendingConns(oneTimeBuffer) callback(oneTimeBuffer.Connections()) diff --git a/pkg/network/tracer/connection/tcp_close_consumer_test.go b/pkg/network/tracer/connection/tcp_close_consumer_test.go new file mode 100644 index 0000000000000..59c60c9d791c5 --- /dev/null +++ b/pkg/network/tracer/connection/tcp_close_consumer_test.go @@ -0,0 +1,28 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2016-present Datadog, Inc. + +//go:build linux_bpf + +package connection + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/DataDog/datadog-agent/pkg/ebpf" +) + +func TestTcpCloseConsumerStopRace(t *testing.T) { + pf := ebpf.NewPerfHandler(10) + require.NotNil(t, pf) + + c, err := newTCPCloseConsumer(pf, nil) + require.NoError(t, err) + require.NotNil(t, c) + + c.Stop() + c.FlushPending() +} diff --git a/pkg/network/tracer/connection/tracer.go b/pkg/network/tracer/connection/tracer.go index 7c4232e776c44..97912055daa35 100644 --- a/pkg/network/tracer/connection/tracer.go +++ b/pkg/network/tracer/connection/tracer.go @@ -187,7 +187,7 @@ func NewTracer(config *config.Config, bpfTelemetry *errtelemetry.EBPFTelemetry) return nil, fmt.Errorf("could not create connection batch maanager: %w", err) } - closeConsumer, err := newTCPCloseConsumer(m, perfHandlerTCP, batchMgr) + closeConsumer, err := newTCPCloseConsumer(perfHandlerTCP, batchMgr) if err != nil { return nil, fmt.Errorf("could not create TCPCloseConsumer: %w", err) } diff --git a/pkg/network/usm/shared_libraries.go b/pkg/network/usm/shared_libraries.go index 54baecbbcca1b..577b69ae0ade4 100644 --- a/pkg/network/usm/shared_libraries.go +++ b/pkg/network/usm/shared_libraries.go @@ -11,7 +11,6 @@ import ( "encoding/base64" "encoding/binary" "fmt" - "go.uber.org/atomic" "os" "regexp" "sync" @@ -19,10 +18,13 @@ import ( "time" "unsafe" - "github.com/DataDog/gopsutil/process" + "go.uber.org/atomic" + "github.com/twmb/murmur3" "golang.org/x/sys/unix" + "github.com/DataDog/gopsutil/process" + ddebpf "github.com/DataDog/datadog-agent/pkg/ebpf" "github.com/DataDog/datadog-agent/pkg/network/protocols/http" "github.com/DataDog/datadog-agent/pkg/process/monitor" From d46892dbf772250cbd6b958d9fde69a3c91991a4 Mon Sep 17 00:00:00 2001 From: pducolin <45568537+pducolin@users.noreply.github.com> Date: Wed, 7 Jun 2023 14:50:41 -0400 Subject: [PATCH 39/76] [e2e] target agent-sandbox account by default with e2e tests (#17484) --- test/new-e2e/runner/local-profile.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/new-e2e/runner/local-profile.go b/test/new-e2e/runner/local-profile.go index 9e04ac3df91cf..0ec688372e6ef 100644 --- a/test/new-e2e/runner/local-profile.go +++ b/test/new-e2e/runner/local-profile.go @@ -36,7 +36,7 @@ func NewLocalProfile() (Profile, error) { } else { store = parameters.NewCascadingStore(envValueStore) } - return localProfile{baseProfile: newProfile("e2elocal", []string{"aws/sandbox"}, store, nil)}, nil + return localProfile{baseProfile: newProfile("e2elocal", []string{"aws/agent-sandbox"}, store, nil)}, nil } func getConfigFilePath() (string, error) { From 50a56235a6e52c1d5b43407f4784b37463af365a Mon Sep 17 00:00:00 2001 From: modernplumbing Date: Wed, 7 Jun 2023 21:03:56 +0200 Subject: [PATCH 40/76] typo (#17430) --- pkg/security/security_profile/profile/manager.go | 2 +- pkg/security/security_profile/profile/profile_dir.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/security/security_profile/profile/manager.go b/pkg/security/security_profile/profile/manager.go index ebc051a17d262..af11ab7d25a50 100644 --- a/pkg/security/security_profile/profile/manager.go +++ b/pkg/security/security_profile/profile/manager.go @@ -588,7 +588,7 @@ func (m *SecurityProfileManager) unloadProfile(profile *SecurityProfile) { // remove kernel space filters if err := m.securityProfileSyscallsMap.Delete(profile.profileCookie); err != nil { - seclog.Errorf("coudln't remove syscalls filter: %v", err) + seclog.Errorf("couldn't remove syscalls filter: %v", err) } // TODO: delete all kernel space programs diff --git a/pkg/security/security_profile/profile/profile_dir.go b/pkg/security/security_profile/profile/profile_dir.go index 075057f94b5d7..39c29d3e0ec95 100644 --- a/pkg/security/security_profile/profile/profile_dir.go +++ b/pkg/security/security_profile/profile/profile_dir.go @@ -100,7 +100,7 @@ func (dp *DirectoryProvider) Start(ctx context.Context) error { if dp.watcherEnabled { var err error if dp.watcher, err = fsnotify.NewWatcher(); err != nil { - return fmt.Errorf("coudln't setup inotify watcher: %w", err) + return fmt.Errorf("couldn't setup inotify watcher: %w", err) } if err = dp.watcher.Add(dp.directory); err != nil { From 661a20f5d34a2932175df8e6a3db4cd97c937155 Mon Sep 17 00:00:00 2001 From: Guy Arbitman Date: Wed, 7 Jun 2023 23:02:52 +0300 Subject: [PATCH 41/76] process-monitor: Change owner (#17510) --- .github/CODEOWNERS | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 16394497748f0..20ba7a6f82c42 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -306,6 +306,7 @@ /pkg/process/util/netns*.go @DataDog/Networks /pkg/process/checks/net*.go @DataDog/Networks /pkg/process/checks/pod*.go @DataDog/container-app +/pkg/process/monitor/ @DataDog/universal-service-monitoring /pkg/process/net/ @DataDog/processes @DataDog/Networks /pkg/proto/datadog/remoteconfig/ @DataDog/remote-config /pkg/proto/pbgo/ # do not notify anyone From d4764da11fd71aed21d0e48c45c929642d122106 Mon Sep 17 00:00:00 2001 From: Guy Arbitman Date: Wed, 7 Jun 2023 23:06:55 +0300 Subject: [PATCH 42/76] npm: Spare copying of active connection twice (#17351) --- pkg/network/tracer/tracer.go | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/pkg/network/tracer/tracer.go b/pkg/network/tracer/tracer.go index fc1b1fbad2376..10f8362cdd983 100644 --- a/pkg/network/tracer/tracer.go +++ b/pkg/network/tracer/tracer.go @@ -374,12 +374,10 @@ func (t *Tracer) GetActiveConnections(clientID string) (*network.Connections, er log.Tracef("GetActiveConnections clientID=%s", clientID) t.ebpfTracer.FlushPending() - // Set a limit and do that periodically. - latestTime, err := t.getConnections(t.activeBuffer) + latestTime, active, err := t.getConnections(t.activeBuffer) if err != nil { return nil, fmt.Errorf("error retrieving connections: %s", err) } - active := t.activeBuffer.Connections() delta := t.state.GetDelta(clientID, latestTime, active, t.reverseDNS.GetDNSStats(), t.usmMonitor.GetHTTPStats(), t.usmMonitor.GetHTTP2Stats(), t.usmMonitor.GetKafkaStats()) t.activeBuffer.Reset() @@ -473,13 +471,13 @@ func (t *Tracer) getRuntimeCompilationTelemetry() map[string]network.RuntimeComp // getConnections returns all the active connections in the ebpf maps along with the latest timestamp. It takes // a reusable buffer for appending the active connections so that this doesn't continuously allocate -func (t *Tracer) getConnections(activeBuffer *network.ConnectionBuffer) (latestUint uint64, err error) { +func (t *Tracer) getConnections(activeBuffer *network.ConnectionBuffer) (latestUint uint64, activeConnections []network.ConnectionStats, err error) { cachedConntrack := newCachedConntrack(t.config.ProcRoot, netlink.NewConntrack, 128) defer func() { _ = cachedConntrack.Close() }() latestTime, err := ddebpf.NowNanoseconds() if err != nil { - return 0, fmt.Errorf("error retrieving latest timestamp: %s", err) + return 0, nil, fmt.Errorf("error retrieving latest timestamp: %s", err) } var expired []network.ConnectionStats @@ -500,23 +498,23 @@ func (t *Tracer) getConnections(activeBuffer *network.ConnectionBuffer) (latestU return true }) if err != nil { - return 0, err + return 0, nil, err } - active := activeBuffer.Connections() + activeConnections = activeBuffer.Connections() _ = t.timeResolver.Sync() - for i := range active { - active[i].IPTranslation = t.conntracker.GetTranslationForConn(active[i]) + for i := range activeConnections { + activeConnections[i].IPTranslation = t.conntracker.GetTranslationForConn(activeConnections[i]) // do gateway resolution only on active connections outside // the map iteration loop to not add to connections while // iterating (leads to ever-increasing connections in the map, // since gateway resolution connects to the ec2 metadata // endpoint) - t.connVia(&active[i]) - t.addProcessInfo(&active[i]) + t.connVia(&activeConnections[i]) + t.addProcessInfo(&activeConnections[i]) } - entryCount := len(active) + entryCount := len(activeConnections) if entryCount >= int(t.config.MaxTrackedConnections) { log.Errorf("connection tracking map size has reached the limit of %d. Accurate connection count and data volume metrics will be affected. Increase config value `system_probe_config.max_tracked_connections` to correct this.", t.config.MaxTrackedConnections) } else if (float64(entryCount) / float64(t.config.MaxTrackedConnections)) >= 0.9 { @@ -532,9 +530,9 @@ func (t *Tracer) getConnections(activeBuffer *network.ConnectionBuffer) (latestU latestTime, err = ddebpf.NowNanoseconds() if err != nil { - return 0, fmt.Errorf("error retrieving latest timestamp: %s", err) + return 0, nil, fmt.Errorf("error retrieving latest timestamp: %s", err) } - return uint64(latestTime), nil + return uint64(latestTime), activeConnections, nil } func (t *Tracer) removeEntries(entries []network.ConnectionStats) { @@ -658,13 +656,13 @@ func (t *Tracer) DebugNetworkState(clientID string) (map[string]interface{}, err // DebugNetworkMaps returns all connections stored in the BPF maps without modifications from network state func (t *Tracer) DebugNetworkMaps() (*network.Connections, error) { activeBuffer := network.NewConnectionBuffer(512, 512) - _, err := t.getConnections(activeBuffer) + _, connections, err := t.getConnections(activeBuffer) if err != nil { return nil, fmt.Errorf("error retrieving connections: %s", err) } return &network.Connections{ BufferedData: network.BufferedData{ - Conns: activeBuffer.Connections(), + Conns: connections, }, }, nil From aee3fed57d4e1aba33176e9aeb861e8b166663bc Mon Sep 17 00:00:00 2001 From: Guy Arbitman Date: Wed, 7 Jun 2023 23:07:50 +0300 Subject: [PATCH 43/76] process-monitor: Change loading order. (#17401) The refactor forced every user of process-monitor to call initialize. We ensured the initialized is being called only once. During the initialize phase we scanned all running processes and tried to trigger the callbacks. But since every user called initialize by itself, we had a race between registering callbacks and scanning the process list. Now we call initialize only once, at the monitor initialization, and by that ensuring no race exists, as callback registrations happens before calling the initialization --- pkg/network/usm/ebpf_gotls.go | 5 --- pkg/network/usm/ebpf_javatls.go | 5 --- pkg/network/usm/shared_libraries.go | 5 --- pkg/network/usm/shared_libraries_test.go | 12 ++++++ pkg/process/monitor/process_monitor.go | 7 ++- pkg/process/monitor/process_monitor_test.go | 48 ++++++++++----------- 6 files changed, 40 insertions(+), 42 deletions(-) diff --git a/pkg/network/usm/ebpf_gotls.go b/pkg/network/usm/ebpf_gotls.go index e11a12778e147..ae520ce3a10ab 100644 --- a/pkg/network/usm/ebpf_gotls.go +++ b/pkg/network/usm/ebpf_gotls.go @@ -257,11 +257,6 @@ func (p *GoTLSProgram) Start() { return } - if err = p.procMonitor.monitor.Initialize(); err != nil { - log.Errorf("failed to initialize process monitor error: %s", err) - return - } - p.wg.Add(1) go func() { processSync := time.NewTicker(scanTerminatedProcessesInterval) diff --git a/pkg/network/usm/ebpf_javatls.go b/pkg/network/usm/ebpf_javatls.go index c08cff6e14663..c5cb7e3c8a76e 100644 --- a/pkg/network/usm/ebpf_javatls.go +++ b/pkg/network/usm/ebpf_javatls.go @@ -253,11 +253,6 @@ func (p *JavaTLSProgram) Start() { log.Errorf("process monitor Subscribe() error: %s", err) return } - - if err = p.processMonitor.Initialize(); err != nil { - log.Errorf("failed to initialize process monitor error: %s", err) - return - } } func (p *JavaTLSProgram) Stop() { diff --git a/pkg/network/usm/shared_libraries.go b/pkg/network/usm/shared_libraries.go index 577b69ae0ade4..e7e56259bbb79 100644 --- a/pkg/network/usm/shared_libraries.go +++ b/pkg/network/usm/shared_libraries.go @@ -217,11 +217,6 @@ func (w *soWatcher) Start() { return nil }) - if err := w.processMonitor.Initialize(); err != nil { - log.Errorf("can't initialize process monitor %s", err) - return - } - cleanupExit, err := w.processMonitor.SubscribeExit(w.registry.unregister) if err != nil { log.Errorf("can't subscribe to process monitor exit event %s", err) diff --git a/pkg/network/usm/shared_libraries_test.go b/pkg/network/usm/shared_libraries_test.go index a9577dd458487..5eebd70194bff 100644 --- a/pkg/network/usm/shared_libraries_test.go +++ b/pkg/network/usm/shared_libraries_test.go @@ -34,8 +34,15 @@ import ( "github.com/DataDog/datadog-agent/pkg/network/protocols/http" "github.com/DataDog/datadog-agent/pkg/network/protocols/http/testutil" errtelemetry "github.com/DataDog/datadog-agent/pkg/network/telemetry" + "github.com/DataDog/datadog-agent/pkg/process/monitor" ) +func launchProcessMonitor(t *testing.T) { + pm := monitor.GetProcessMonitor() + t.Cleanup(pm.Stop) + require.NoError(t, pm.Initialize()) +} + func registerProcessTerminationUponCleanup(t *testing.T, cmd *exec.Cmd) { t.Cleanup(func() { if cmd.Process == nil { @@ -80,6 +87,7 @@ func (s *SharedLibrarySuite) TestSharedLibraryDetection() { }, ) watcher.Start() + launchProcessMonitor(t) // create files clientBin := buildSOWatcherClientBin(t) @@ -145,6 +153,7 @@ func (s *SharedLibrarySuite) TestSharedLibraryDetectionWithPIDandRootNameSpace() }, ) watcher.Start() + launchProcessMonitor(t) time.Sleep(10 * time.Millisecond) // simulate a slow (1 second) : open, write, close of the file @@ -190,6 +199,7 @@ func (s *SharedLibrarySuite) TestSameInodeRegression() { }, ) watcher.Start() + launchProcessMonitor(t) clientBin := buildSOWatcherClientBin(t) command1 := exec.Command(clientBin, fooPath1, fooPath2) @@ -241,6 +251,7 @@ func (s *SharedLibrarySuite) TestSoWatcherLeaks() { }, ) watcher.Start() + launchProcessMonitor(t) // create files clientBin := buildSOWatcherClientBin(t) @@ -333,6 +344,7 @@ func (s *SharedLibrarySuite) TestSoWatcherProcessAlreadyHoldingReferences() { registerProcessTerminationUponCleanup(t, command1) time.Sleep(time.Second) watcher.Start() + launchProcessMonitor(t) require.Eventuallyf(t, func() bool { // Checking both paths exist. diff --git a/pkg/process/monitor/process_monitor.go b/pkg/process/monitor/process_monitor.go index a24c41acbe01b..cdc8e67c4cb5e 100644 --- a/pkg/process/monitor/process_monitor.go +++ b/pkg/process/monitor/process_monitor.go @@ -98,6 +98,7 @@ type ProcessCallback func(pid int) // then the Exit callback will evaluate the same metadata on Exit. // We need to save the metadata here as /proc/pid doesn't exist anymore. func GetProcessMonitor() *ProcessMonitor { + processMonitor.refcount.Inc() return processMonitor } @@ -222,7 +223,6 @@ func (pm *ProcessMonitor) mainEventLoop() { // 2. Run the main event loop in a goroutine. // 4. Scans already running processes and call the Exec callbacks on them. func (pm *ProcessMonitor) Initialize() error { - processMonitor.refcount.Inc() var initErr error pm.initOnce.Do( func() { @@ -298,7 +298,10 @@ func (pm *ProcessMonitor) Stop() { } // We can get here only once, if the refcount is zero. - close(pm.done) + if pm.done != nil { + close(pm.done) + pm.done = nil + } pm.processMonitorWG.Wait() // that's being done for testing purposes. // As tests are running altogether, initOne and processMonitor are being created only once per compilation unit diff --git a/pkg/process/monitor/process_monitor_test.go b/pkg/process/monitor/process_monitor_test.go index 048c87ae41863..eb221479b54ea 100644 --- a/pkg/process/monitor/process_monitor_test.go +++ b/pkg/process/monitor/process_monitor_test.go @@ -22,9 +22,14 @@ import ( "github.com/DataDog/datadog-agent/pkg/util" ) +func getProcessMonitor(t *testing.T) *ProcessMonitor { + pm := GetProcessMonitor() + t.Cleanup(pm.Stop) + return pm +} + func initializePM(t *testing.T, pm *ProcessMonitor) { require.NoError(t, pm.Initialize()) - t.Cleanup(pm.Stop) time.Sleep(time.Millisecond * 500) } @@ -33,7 +38,7 @@ func registerCallback(t *testing.T, pm *ProcessMonitor, isExec bool, callback *P if isExec { registrationFunc = pm.SubscribeExec } - unsubscribe, err := registrationFunc(callback) + unsubscribe, err := registrationFunc(*callback) require.NoError(t, err) t.Cleanup(unsubscribe) return unsubscribe @@ -52,19 +57,18 @@ func getTestBinaryPath(t *testing.T) string { func TestProcessMonitorSingleton(t *testing.T) { // Making sure we get the same process monitor if we call it twice. - pm := GetProcessMonitor() - pm2 := GetProcessMonitor() + pm := getProcessMonitor(t) + pm2 := getProcessMonitor(t) require.Equal(t, pm, pm2) } func TestProcessMonitorSanity(t *testing.T) { - pm := GetProcessMonitor() + pm := getProcessMonitor(t) numberOfExecs := atomic.Int32{} testBinaryPath := getTestBinaryPath(t) - registerCallback(t, pm, true, &ProcessCallback{ - Callback: func(pid int) { numberOfExecs.Inc() }, - }) + callback := func(pid int) { numberOfExecs.Inc() } + registerCallback(t, pm, true, (*ProcessCallback)(&callback)) initializePM(t, pm) require.NoError(t, exec.Command(testBinaryPath, "test").Run()) @@ -75,16 +79,15 @@ func TestProcessMonitorSanity(t *testing.T) { } func TestProcessRegisterMultipleExecCallbacks(t *testing.T) { - pm := GetProcessMonitor() + pm := getProcessMonitor(t) const iterations = 10 counters := make([]*atomic.Int32, iterations) for i := 0; i < iterations; i++ { counters[i] = &atomic.Int32{} c := counters[i] - registerCallback(t, pm, true, &ProcessCallback{ - Callback: func(pid int) { c.Inc() }, - }) + callback := func(pid int) { c.Inc() } + registerCallback(t, pm, true, (*ProcessCallback)(&callback)) } initializePM(t, pm) @@ -101,7 +104,7 @@ func TestProcessRegisterMultipleExecCallbacks(t *testing.T) { } func TestProcessRegisterMultipleExitCallbacks(t *testing.T) { - pm := GetProcessMonitor() + pm := getProcessMonitor(t) const iterations = 10 counters := make([]*atomic.Int32, iterations) @@ -109,9 +112,8 @@ func TestProcessRegisterMultipleExitCallbacks(t *testing.T) { counters[i] = &atomic.Int32{} c := counters[i] // Sanity subscribing a callback. - registerCallback(t, pm, false, &ProcessCallback{ - Callback: func(pid int) { c.Inc() }, - }) + callback := func(pid int) { c.Inc() } + registerCallback(t, pm, true, (*ProcessCallback)(&callback)) } initializePM(t, pm) @@ -128,11 +130,10 @@ func TestProcessRegisterMultipleExitCallbacks(t *testing.T) { } func TestProcessMonitorRefcount(t *testing.T) { - pm := GetProcessMonitor() - require.Equal(t, pm.refcount.Load(), int32(0)) + var pm *ProcessMonitor for i := 1; i <= 10; i++ { - require.NoError(t, pm.Initialize()) + pm = GetProcessMonitor() require.Equal(t, pm.refcount.Load(), int32(i)) } @@ -145,13 +146,10 @@ func TestProcessMonitorRefcount(t *testing.T) { func TestProcessMonitorInNamespace(t *testing.T) { execSet := sync.Map{} - pm := GetProcessMonitor() + pm := getProcessMonitor(t) - registerCallback(t, pm, true, &ProcessCallback{ - Callback: func(pid int) { - execSet.Store(pid, struct{}{}) - }, - }) + callback := func(pid int) { execSet.Store(pid, struct{}{}) } + registerCallback(t, pm, true, (*ProcessCallback)(&callback)) monNs, err := netns.New() require.NoError(t, err, "could not create network namespace for process monitor") From 0e4453eb06f972c4ef42fa0e7f6fe07182233c66 Mon Sep 17 00:00:00 2001 From: pducolin <45568537+pducolin@users.noreply.github.com> Date: Wed, 7 Jun 2023 16:20:47 -0400 Subject: [PATCH 44/76] [e2e] bump test-infra-definition to v0.0.0-20230607143804-fef23444c9da (#17517) --- test/new-e2e/go.mod | 3 ++- test/new-e2e/go.sum | 6 ++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/test/new-e2e/go.mod b/test/new-e2e/go.mod index 8e9acf8461307..a848d241ab55d 100644 --- a/test/new-e2e/go.mod +++ b/test/new-e2e/go.mod @@ -10,7 +10,7 @@ replace github.com/DataDog/datadog-agent/test/fakeintake => ../fakeintake require ( github.com/DataDog/datadog-agent/test/fakeintake v0.46.0-rc.2 - github.com/DataDog/test-infra-definitions v0.0.0-20230526143644-ed785d3a20d5 + github.com/DataDog/test-infra-definitions v0.0.0-20230607143804-fef23444c9da github.com/aws/aws-sdk-go-v2 v1.18.0 github.com/aws/aws-sdk-go-v2/config v1.18.25 github.com/aws/aws-sdk-go-v2/service/ssm v1.36.4 @@ -103,6 +103,7 @@ require ( github.com/zclconf/go-cty v1.13.2 // indirect github.com/zorkian/go-datadog-api v2.30.0+incompatible // indirect go.uber.org/atomic v1.11.0 // indirect + golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 // indirect golang.org/x/mod v0.10.0 // indirect golang.org/x/net v0.10.0 // indirect golang.org/x/sys v0.8.0 // indirect diff --git a/test/new-e2e/go.sum b/test/new-e2e/go.sum index b95fdaebfca9a..1783e50fb0b31 100644 --- a/test/new-e2e/go.sum +++ b/test/new-e2e/go.sum @@ -1,7 +1,7 @@ github.com/DataDog/agent-payload/v5 v5.0.73 h1:fnCnAR+nWY+q//fBZSab4cDFFng0scPEfmLdl9ngmQY= github.com/DataDog/agent-payload/v5 v5.0.73/go.mod h1:oQZi1VZp1e3QvlSUX4iphZCpJaFepUxWq0hNXxihKBM= -github.com/DataDog/test-infra-definitions v0.0.0-20230526143644-ed785d3a20d5 h1:bevg12AMVEL49W5+ZEJ6bw6PK4JWt+oEPfH3MPsOS8Q= -github.com/DataDog/test-infra-definitions v0.0.0-20230526143644-ed785d3a20d5/go.mod h1:WmCQAFypCQB6zjmXl9CGW0qMa5s7krntwld/tt7rjcc= +github.com/DataDog/test-infra-definitions v0.0.0-20230607143804-fef23444c9da h1:2HqYpVpJkn06vNpoTzhTD4DubyTaaj4QT2wquPXg4m0= +github.com/DataDog/test-infra-definitions v0.0.0-20230607143804-fef23444c9da/go.mod h1:VlLmT/PmwpWNV6o0tKFzWuPtHuN9YBb73WjS5SjhFzY= github.com/HdrHistogram/hdrhistogram-go v1.1.2 h1:5IcZpTvzydCQeHzK4Ef/D5rrSqwxob0t8PQPMybUNFM= github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= @@ -237,6 +237,8 @@ golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0 golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g= golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= +golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 h1:k/i9J1pBpvlfR+9QsetwPyERsqu1GIbi967PQMq3Ivc= +golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= From 1db5090c427fdbe973b7eb5d684b9b7f7f46d1e0 Mon Sep 17 00:00:00 2001 From: Guy Arbitman Date: Thu, 8 Jun 2023 00:27:54 +0300 Subject: [PATCH 45/76] npm: Remove redundant err return (#17520) --- pkg/network/tracer/connection/tcp_close_consumer.go | 2 +- pkg/network/tracer/connection/tcp_close_consumer_test.go | 3 +-- pkg/network/tracer/connection/tracer.go | 5 +---- 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/pkg/network/tracer/connection/tcp_close_consumer.go b/pkg/network/tracer/connection/tcp_close_consumer.go index 3386e6063d173..fc24f66b4a11a 100644 --- a/pkg/network/tracer/connection/tcp_close_consumer.go +++ b/pkg/network/tracer/connection/tcp_close_consumer.go @@ -40,7 +40,7 @@ type tcpCloseConsumer struct { ch *cookieHasher } -func newTCPCloseConsumer(perfHandler *ddebpf.PerfHandler, batchManager *perfBatchManager) (*tcpCloseConsumer, error) { +func newTCPCloseConsumer(perfHandler *ddebpf.PerfHandler, batchManager *perfBatchManager) *tcpCloseConsumer { return &tcpCloseConsumer{ perfHandler: perfHandler, batchManager: batchManager, diff --git a/pkg/network/tracer/connection/tcp_close_consumer_test.go b/pkg/network/tracer/connection/tcp_close_consumer_test.go index 59c60c9d791c5..96db4d9bfc04c 100644 --- a/pkg/network/tracer/connection/tcp_close_consumer_test.go +++ b/pkg/network/tracer/connection/tcp_close_consumer_test.go @@ -19,8 +19,7 @@ func TestTcpCloseConsumerStopRace(t *testing.T) { pf := ebpf.NewPerfHandler(10) require.NotNil(t, pf) - c, err := newTCPCloseConsumer(pf, nil) - require.NoError(t, err) + c := newTCPCloseConsumer(pf, nil) require.NotNil(t, c) c.Stop() diff --git a/pkg/network/tracer/connection/tracer.go b/pkg/network/tracer/connection/tracer.go index 97912055daa35..642398c3d7cb1 100644 --- a/pkg/network/tracer/connection/tracer.go +++ b/pkg/network/tracer/connection/tracer.go @@ -187,10 +187,7 @@ func NewTracer(config *config.Config, bpfTelemetry *errtelemetry.EBPFTelemetry) return nil, fmt.Errorf("could not create connection batch maanager: %w", err) } - closeConsumer, err := newTCPCloseConsumer(perfHandlerTCP, batchMgr) - if err != nil { - return nil, fmt.Errorf("could not create TCPCloseConsumer: %w", err) - } + closeConsumer := newTCPCloseConsumer(perfHandlerTCP, batchMgr) tr := &tracer{ m: m, From 098e806ec14c37a5c952dbae0eb6d3c19d880297 Mon Sep 17 00:00:00 2001 From: Guy Arbitman Date: Thu, 8 Jun 2023 06:43:42 +0300 Subject: [PATCH 46/76] system-probe: Avoid unnecessary allocations for trace logs in hot-code-paths (#17354) * system-probe: Avoid unnecessary allocations for trace logs in hot-code-paths * Wrapped more logs --- pkg/network/encoding/http2.go | 9 +++++++-- pkg/network/encoding/kafka.go | 9 +++++++-- pkg/network/go/bininspect/symbols.go | 6 ++++-- pkg/network/netlink/conntracker.go | 9 +++++++-- pkg/network/netlink/consumer.go | 5 ++++- pkg/network/state.go | 8 +++++--- pkg/network/tracer/connection/tracer.go | 5 ++++- pkg/network/tracer/ebpf_conntracker.go | 4 +++- pkg/network/tracer/process_cache.go | 8 ++++---- pkg/network/tracer/tracer.go | 16 ++++++++++------ pkg/network/usm/shared_libraries.go | 12 ++++++++---- 11 files changed, 63 insertions(+), 28 deletions(-) diff --git a/pkg/network/encoding/http2.go b/pkg/network/encoding/http2.go index f756541b63db2..515bcb5b4e43f 100644 --- a/pkg/network/encoding/http2.go +++ b/pkg/network/encoding/http2.go @@ -6,6 +6,7 @@ package encoding import ( + "github.com/cihub/seelog" "github.com/gogo/protobuf/proto" model "github.com/DataDog/agent-payload/v5/process" @@ -99,7 +100,9 @@ func newHTTP2Encoder(payload *network.Connections) *http2Encoder { // this allows us to skip encoding orphan HTTP2 objects that can't be matched to a connection for _, conn := range payload.Conns { for _, key := range network.ConnectionKeysFromConnectionStats(conn) { - log.Tracef("Payload has a connection %v and was converted to http2 key %v", conn, key) + if log.ShouldLog(seelog.TraceLvl) { + log.Tracef("Payload has a connection %v and was converted to http2 key %v", conn, key) + } encoder.aggregations[key] = nil } } @@ -118,7 +121,9 @@ func (e *http2Encoder) buildAggregations(payload *network.Connections) { aggregation, ok := e.aggregations[key.ConnectionKey] if !ok { // if there is no matching connection don't even bother to serialize HTTP2 data - log.Tracef("Found http2 orphan connection %v", key.ConnectionKey) + if log.ShouldLog(seelog.TraceLvl) { + log.Tracef("Found http2 orphan connection %v", key.ConnectionKey) + } e.orphanEntries++ continue } diff --git a/pkg/network/encoding/kafka.go b/pkg/network/encoding/kafka.go index 7f82247fc6658..efefa506e10e5 100644 --- a/pkg/network/encoding/kafka.go +++ b/pkg/network/encoding/kafka.go @@ -7,6 +7,7 @@ package encoding import ( model "github.com/DataDog/agent-payload/v5/process" + "github.com/cihub/seelog" "github.com/DataDog/datadog-agent/pkg/network" "github.com/DataDog/datadog-agent/pkg/network/types" @@ -78,7 +79,9 @@ func newKafkaEncoder(payload *network.Connections) *kafkaEncoder { // this allows us to skip encoding orphan Kafka objects that can't be matched to a connection for _, conn := range payload.Conns { for _, key := range network.ConnectionKeysFromConnectionStats(conn) { - log.Tracef("Payload has a connection %v and was converted to kafka key %v", conn, key) + if log.ShouldLog(seelog.TraceLvl) { + log.Tracef("Payload has a connection %v and was converted to kafka key %v", conn, key) + } encoder.aggregations[key] = nil } } @@ -111,7 +114,9 @@ func (e *kafkaEncoder) buildAggregations(payload *network.Connections) { aggregation, ok := e.aggregations[key.ConnectionKey] if !ok { // if there is no matching connection don't even bother to serialize Kafka data - log.Tracef("Found kafka orphan connection %v", key.ConnectionKey) + if log.ShouldLog(seelog.TraceLvl) { + log.Tracef("Found kafka orphan connection %v", key.ConnectionKey) + } e.orphanEntries++ continue } diff --git a/pkg/network/go/bininspect/symbols.go b/pkg/network/go/bininspect/symbols.go index cef9135e5cbf8..e39e5bd9fccf9 100644 --- a/pkg/network/go/bininspect/symbols.go +++ b/pkg/network/go/bininspect/symbols.go @@ -15,6 +15,8 @@ import ( "io" "math" + "github.com/cihub/seelog" + "github.com/DataDog/datadog-agent/pkg/util/common" "github.com/DataDog/datadog-agent/pkg/util/log" ) @@ -182,7 +184,7 @@ func getSymbols(f *elf.File, typ elf.SectionType, wanted map[string]struct{}) ([ func GetAllSymbolsByName(elfFile *elf.File, symbolSet common.StringSet) (map[string]elf.Symbol, error) { regularSymbols, regularSymbolsErr := getSymbols(elfFile, elf.SHT_SYMTAB, symbolSet) - if regularSymbolsErr != nil { + if regularSymbolsErr != nil && log.ShouldLog(seelog.TraceLvl) { log.Tracef("Failed getting regular symbols of elf file: %s", regularSymbolsErr) } @@ -190,7 +192,7 @@ func GetAllSymbolsByName(elfFile *elf.File, symbolSet common.StringSet) (map[str var dynamicSymbolsErr error if len(regularSymbols) != len(symbolSet) { dynamicSymbols, dynamicSymbolsErr = getSymbols(elfFile, elf.SHT_DYNSYM, symbolSet) - if dynamicSymbolsErr != nil { + if dynamicSymbolsErr != nil && log.ShouldLog(seelog.TraceLvl) { log.Tracef("Failed getting dynamic symbols of elf file: %s", dynamicSymbolsErr) } } diff --git a/pkg/network/netlink/conntracker.go b/pkg/network/netlink/conntracker.go index 302ce7725f4ad..5c9deb9cafeb0 100644 --- a/pkg/network/netlink/conntracker.go +++ b/pkg/network/netlink/conntracker.go @@ -16,6 +16,7 @@ import ( "sync" "time" + "github.com/cihub/seelog" "github.com/hashicorp/golang-lru/v2/simplelru" "golang.org/x/sys/unix" @@ -377,7 +378,9 @@ func (cc *conntrackCache) Add(c Con, orphan bool) (evicts int) { } } - log.Tracef("%s", c) + if log.ShouldLog(seelog.TraceLvl) { + log.Tracef("%s", c) + } registerTuple(&c.Origin, &c.Reply) registerTuple(&c.Reply, &c.Origin) @@ -397,7 +400,9 @@ func (cc *conntrackCache) removeOrphans(now time.Time) (removed int64) { cc.cache.Remove(o.key) removed++ - log.Tracef("removed orphan %+v", o.key) + if log.ShouldLog(seelog.TraceLvl) { + log.Tracef("removed orphan %+v", o.key) + } } return removed diff --git a/pkg/network/netlink/consumer.go b/pkg/network/netlink/consumer.go index 163f6d18c481a..e10e08ff5f453 100644 --- a/pkg/network/netlink/consumer.go +++ b/pkg/network/netlink/consumer.go @@ -14,6 +14,7 @@ import ( "sync" "syscall" + "github.com/cihub/seelog" "github.com/mdlayher/netlink" "github.com/pkg/errors" "github.com/vishvananda/netns" @@ -204,7 +205,9 @@ func (c *Consumer) isPeerNS(conn *netlink.Conn, ns netns.NsHandle) bool { return false } - log.Tracef("netlink reply: %v", msgs) + if log.ShouldLog(seelog.TraceLvl) { + log.Tracef("netlink reply: %v", msgs) + } if msgs[0].Header.Type == netlink.Error { return false diff --git a/pkg/network/state.go b/pkg/network/state.go index 9a89c55046fea..86313b2a13c71 100644 --- a/pkg/network/state.go +++ b/pkg/network/state.go @@ -12,6 +12,8 @@ import ( "sync" "time" + "github.com/cihub/seelog" + "github.com/DataDog/datadog-agent/pkg/network/dns" "github.com/DataDog/datadog-agent/pkg/network/protocols/http" "github.com/DataDog/datadog-agent/pkg/network/protocols/kafka" @@ -404,9 +406,9 @@ func (ns *networkState) getConnsByCookie(conns []ConnectionStats) map[StatCookie continue } - log.TraceFunc(func() string { - return fmt.Sprintf("duplicate connection in collection: cookie: %d, c1: %+v, c2: %+v", c.Cookie, *c, conns[i]) - }) + if log.ShouldLog(seelog.TraceLvl) { + log.Tracef("duplicate connection in collection: cookie: %d, c1: %+v, c2: %+v", c.Cookie, *c, conns[i]) + } if ns.mergeConnectionStats(c, &conns[i]) { // cookie collision diff --git a/pkg/network/tracer/connection/tracer.go b/pkg/network/tracer/connection/tracer.go index 642398c3d7cb1..ea0a5d4c00cc3 100644 --- a/pkg/network/tracer/connection/tracer.go +++ b/pkg/network/tracer/connection/tracer.go @@ -17,6 +17,7 @@ import ( "time" "unsafe" + "github.com/cihub/seelog" "github.com/cilium/ebpf" "github.com/twmb/murmur3" "golang.org/x/sys/unix" @@ -424,7 +425,9 @@ func (t *tracer) getEBPFTelemetry() *netebpf.Telemetry { if err := mp.Lookup(unsafe.Pointer(&zero), unsafe.Pointer(telemetry)); err != nil { // This can happen if we haven't initialized the telemetry object yet // so let's just use a trace log - log.Tracef("error retrieving the telemetry struct: %s", err) + if log.ShouldLog(seelog.TraceLvl) { + log.Tracef("error retrieving the telemetry struct: %s", err) + } return nil } return telemetry diff --git a/pkg/network/tracer/ebpf_conntracker.go b/pkg/network/tracer/ebpf_conntracker.go index c4907fa905656..cca5fed55aaa8 100644 --- a/pkg/network/tracer/ebpf_conntracker.go +++ b/pkg/network/tracer/ebpf_conntracker.go @@ -302,7 +302,9 @@ func (e *ebpfConntracker) delete(key *netebpf.ConntrackTuple) { start := time.Now() if err := e.ctMap.Delete(unsafe.Pointer(key)); err != nil { if errors.Is(err, ebpf.ErrKeyNotExist) { - log.Tracef("connection does not exist in ebpf conntrack map: %s", key) + if log.ShouldLog(seelog.TraceLvl) { + log.Tracef("connection does not exist in ebpf conntrack map: %s", key) + } return } log.Warnf("unable to delete conntrack entry from eBPF map: %s", err) diff --git a/pkg/network/tracer/process_cache.go b/pkg/network/tracer/process_cache.go index bcfca951d4e2b..dafed374a2c6d 100644 --- a/pkg/network/tracer/process_cache.go +++ b/pkg/network/tracer/process_cache.go @@ -8,11 +8,11 @@ package tracer import ( - "fmt" "strings" "sync" "time" + "github.com/cihub/seelog" lru "github.com/hashicorp/golang-lru/v2" smodel "github.com/DataDog/datadog-agent/pkg/security/secl/model" @@ -207,9 +207,9 @@ func (pc *processCache) add(p *process) { pc.Lock() defer pc.Unlock() - log.TraceFunc(func() string { - return fmt.Sprintf("adding process %+v to process cache", p) - }) + if log.ShouldLog(seelog.TraceLvl) { + log.Tracef("adding process %+v to process cache", p) + } evicted := pc.cache.Add(processCacheKey{pid: p.Pid, startTime: p.StartTime}, p) pl, _ := pc.cacheByPid[p.Pid] diff --git a/pkg/network/tracer/tracer.go b/pkg/network/tracer/tracer.go index 10f8362cdd983..68d435dd49e06 100644 --- a/pkg/network/tracer/tracer.go +++ b/pkg/network/tracer/tracer.go @@ -14,6 +14,7 @@ import ( "sync" "time" + "github.com/cihub/seelog" "github.com/cilium/ebpf" "go.uber.org/atomic" @@ -330,9 +331,9 @@ func (t *Tracer) addProcessInfo(c *network.ConnectionStats) { return } - log.TraceFunc(func() string { - return fmt.Sprintf("got process cache entry for pid %d: %+v", c.Pid, p) - }) + if log.ShouldLog(seelog.TraceLvl) { + log.Tracef("got process cache entry for pid %d: %+v", c.Pid, p) + } if c.Tags == nil { c.Tags = make(map[string]struct{}) @@ -371,8 +372,9 @@ func (t *Tracer) Stop() { func (t *Tracer) GetActiveConnections(clientID string) (*network.Connections, error) { t.bufferLock.Lock() defer t.bufferLock.Unlock() - log.Tracef("GetActiveConnections clientID=%s", clientID) - + if log.ShouldLog(seelog.TraceLvl) { + log.Tracef("GetActiveConnections clientID=%s", clientID) + } t.ebpfTracer.FlushPending() latestTime, active, err := t.getConnections(t.activeBuffer) if err != nil { @@ -559,7 +561,9 @@ func (t *Tracer) removeEntries(entries []network.ConnectionStats) { t.state.RemoveConnections(toRemove) - log.Debugf("Removed %d connection entries in %s", len(toRemove), time.Now().Sub(now)) + if log.ShouldLog(seelog.DebugLvl) { + log.Debugf("Removed %d connection entries in %s", len(toRemove), time.Now().Sub(now)) + } } func (t *Tracer) timeoutForConn(c *network.ConnectionStats) uint64 { diff --git a/pkg/network/usm/shared_libraries.go b/pkg/network/usm/shared_libraries.go index e7e56259bbb79..5a288d1e44099 100644 --- a/pkg/network/usm/shared_libraries.go +++ b/pkg/network/usm/shared_libraries.go @@ -20,11 +20,11 @@ import ( "go.uber.org/atomic" + "github.com/DataDog/gopsutil/process" + "github.com/cihub/seelog" "github.com/twmb/murmur3" "golang.org/x/sys/unix" - "github.com/DataDog/gopsutil/process" - ddebpf "github.com/DataDog/datadog-agent/pkg/ebpf" "github.com/DataDog/datadog-agent/pkg/network/protocols/http" "github.com/DataDog/datadog-agent/pkg/process/monitor" @@ -200,7 +200,9 @@ func (w *soWatcher) Start() { } mmaps, err := proc.MemoryMaps(true) if err != nil { - log.Tracef("process %d maps parsing failed %s", pid, err) + if log.ShouldLog(seelog.TraceLvl) { + log.Tracef("process %d maps parsing failed %s", pid, err) + } return nil } @@ -337,7 +339,9 @@ func (r *soRegistry) register(root, libPath string, pid uint32, rule soRule) { if err != nil { // short living process can hit here // as we receive the openat() syscall info after receiving the EXIT netlink process - log.Tracef("can't create path identifier %s", err) + if log.ShouldLog(seelog.TraceLvl) { + log.Tracef("can't create path identifier %s", err) + } return } From ec5212cbfe7fcbee4653c16ab0a752b7dd7ef169 Mon Sep 17 00:00:00 2001 From: Guy Arbitman Date: Thu, 8 Jun 2023 09:35:29 +0300 Subject: [PATCH 47/76] npm: Changed dns resolution to get a set of IPs rather than a list. (#17358) * npm: Changed dns resolution to get a set of IPs rather than a list. * Reduce allocated space, for the average case --- pkg/network/dns/cache.go | 6 +-- pkg/network/dns/cache_test.go | 67 ++++++++++++++++------------ pkg/network/dns/null.go | 2 +- pkg/network/dns/snooper.go | 2 +- pkg/network/dns/snooper_test.go | 2 +- pkg/network/dns/types.go | 2 +- pkg/network/tracer/tracer.go | 5 ++- pkg/network/tracer/tracer_windows.go | 5 ++- 8 files changed, 52 insertions(+), 39 deletions(-) diff --git a/pkg/network/dns/cache.go b/pkg/network/dns/cache.go index 3cea7d2a85fb6..50212ce1b3d5c 100644 --- a/pkg/network/dns/cache.go +++ b/pkg/network/dns/cache.go @@ -100,7 +100,7 @@ func (c *reverseDNSCache) Add(translation *translation) bool { return true } -func (c *reverseDNSCache) Get(ips []util.Address) map[util.Address][]Hostname { +func (c *reverseDNSCache) Get(ips map[util.Address]struct{}) map[util.Address][]Hostname { c.mux.Lock() defer c.mux.Unlock() @@ -141,12 +141,12 @@ func (c *reverseDNSCache) Get(ips []util.Address) map[util.Address][]Hostname { } } - for _, ip := range ips { + for ip := range ips { collectNamesForIP(ip) } // Update stats for telemetry - cacheTelemetry.lookups.Add(int64((len(resolved) + len(unresolved)))) + cacheTelemetry.lookups.Add(int64(len(resolved) + len(unresolved))) cacheTelemetry.resolved.Add(int64(len(resolved))) cacheTelemetry.oversized.Add(int64(len(oversized))) diff --git a/pkg/network/dns/cache_test.go b/pkg/network/dns/cache_test.go index 9b6608bab5c3b..9056f98e37f9b 100644 --- a/pkg/network/dns/cache_test.go +++ b/pkg/network/dns/cache_test.go @@ -33,7 +33,11 @@ func TestMultipleIPsForSameName(t *testing.T) { cache.Add(datadogIPs) localhost := util.AddressFromString("127.0.0.1") - connections := []util.Address{localhost, datadog1, datadog2} + connections := map[util.Address]struct{}{ + localhost: {}, + datadog1: {}, + datadog2: {}, + } actual := cache.Get(connections) expected := map[util.Address][]Hostname{ datadog1: {ToHostname("datadoghq.com")}, @@ -55,7 +59,10 @@ func TestMultipleNamesForSameIP(t *testing.T) { cache.Add(tr2) localhost := util.AddressFromString("127.0.0.1") - connections := []util.Address{localhost, raddr} + connections := map[util.Address]struct{}{ + localhost: {}, + raddr: {}, + } names := cache.Get(connections) expected := []Hostname{ToHostname("i-03e46c9ff42db4abc"), ToHostname("ip-172-22-116-123.ec2.internal")} @@ -93,9 +100,11 @@ func TestDNSCacheExpiration(t *testing.T) { assert.Equal(t, 3, cache.Len()) // Bump host-a and host-b in-use flag - stats := []util.Address{ - laddr1, raddr1, - laddr2, raddr2, + stats := map[util.Address]struct{}{ + laddr1: {}, + raddr1: {}, + laddr2: {}, + raddr2: {}, } cache.Get(stats) @@ -104,10 +113,13 @@ func TestDNSCacheExpiration(t *testing.T) { cache.Expire(t3) assert.Equal(t, 2, cache.Len()) - stats = []util.Address{ - laddr1, raddr1, - laddr2, raddr2, - laddr3, raddr3, + stats = map[util.Address]struct{}{ + laddr1: {}, + raddr1: {}, + laddr2: {}, + raddr2: {}, + laddr3: {}, + raddr3: {}, } names := cache.Get(stats) assert.Contains(t, names[raddr1], ToHostname("host-a")) @@ -120,7 +132,7 @@ func TestDNSCacheExpiration(t *testing.T) { assert.Equal(t, 2, cache.Len()) // All entries should be allowed to expire now - cache.Get([]util.Address{}) + cache.Get(map[util.Address]struct{}{}) cache.Expire(t4) assert.Equal(t, 0, cache.Len()) } @@ -150,11 +162,10 @@ func TestDNSCacheTelemetry(t *testing.T) { } assert.Equal(t, expected["ips"], cacheTelemetry.length.Load()) - conns := []util.Address{ - util.AddressFromString("127.0.0.1"), - util.AddressFromString("192.168.0.1"), - util.AddressFromString("127.0.0.1"), - util.AddressFromString("192.168.0.2"), + conns := map[util.Address]struct{}{ + util.AddressFromString("127.0.0.1"): {}, + util.AddressFromString("192.168.0.1"): {}, + util.AddressFromString("192.168.0.2"): {}, } // Attempt to resolve IPs @@ -171,7 +182,7 @@ func TestDNSCacheTelemetry(t *testing.T) { // Expire IP t2 := t1.Add(ttl + 1*time.Millisecond) - cache.Get([]util.Address{}) + cache.Get(map[util.Address]struct{}{}) cache.Expire(t2) expected = map[string]int64{ "lookups": 3, @@ -197,9 +208,9 @@ func TestDNSCacheMerge(t *testing.T) { ttl := 100 * time.Millisecond cache := newReverseDNSCache(1000, disableAutomaticExpiration) - conns := []util.Address{ - util.AddressFromString("127.0.0.1"), - util.AddressFromString("192.168.0.1"), + conns := map[util.Address]struct{}{ + util.AddressFromString("127.0.0.1"): {}, + util.AddressFromString("192.168.0.1"): {}, } t1 := newTranslation("host-b") @@ -225,8 +236,8 @@ func TestDNSCacheMerge_MixedCaseNames(t *testing.T) { ttl := 100 * time.Millisecond cache := newReverseDNSCache(1000, disableAutomaticExpiration) - conns := []util.Address{ - util.AddressFromString("192.168.0.1"), + conns := map[util.Address]struct{}{ + util.AddressFromString("192.168.0.1"): {}, } tr := newTranslation("host.name.com") @@ -258,8 +269,9 @@ func TestGetOversizedDNS(t *testing.T) { }) } - conns := []util.Address{addr} - + conns := map[util.Address]struct{}{ + addr: {}, + } result := cache.Get(conns) assert.Len(t, result[addr], 5) assert.Len(t, cache.data[addr].names, 5) @@ -271,7 +283,6 @@ func TestGetOversizedDNS(t *testing.T) { }) } - conns = []util.Address{addr} result = cache.Get(conns) assert.Len(t, result[addr], 0) assert.Len(t, cache.data[addr].names, 10) @@ -320,19 +331,19 @@ func randomAddressGen() func() util.Address { } } -func payloadGen(size int, resolveRatio float64, added []util.Address) []util.Address { +func payloadGen(size int, resolveRatio float64, added []util.Address) map[util.Address]struct{} { var ( addrGen = randomAddressGen() - stats = make([]util.Address, size) + stats = make(map[util.Address]struct{}, size) ) for i := 0; i < size; i++ { if rand.Float64() <= resolveRatio { - stats[i] = added[rand.Intn(len(added))] + stats[added[rand.Intn(len(added))]] = struct{}{} continue } - stats[i] = addrGen() + stats[addrGen()] = struct{}{} } return stats diff --git a/pkg/network/dns/null.go b/pkg/network/dns/null.go index 68b523df4b8f9..b19d529b5f90e 100644 --- a/pkg/network/dns/null.go +++ b/pkg/network/dns/null.go @@ -18,7 +18,7 @@ func NewNullReverseDNS() ReverseDNS { type nullReverseDNS struct{} -func (nullReverseDNS) Resolve(_ []util.Address) map[util.Address][]Hostname { +func (nullReverseDNS) Resolve(_ map[util.Address]struct{}) map[util.Address][]Hostname { return nil } diff --git a/pkg/network/dns/snooper.go b/pkg/network/dns/snooper.go index ecc690a9db4be..4e999d852ad4c 100644 --- a/pkg/network/dns/snooper.go +++ b/pkg/network/dns/snooper.go @@ -114,7 +114,7 @@ func newSocketFilterSnooper(cfg *config.Config, source packetSource) (*socketFil } // Resolve IPs to DNS addresses -func (s *socketFilterSnooper) Resolve(ips []util.Address) map[util.Address][]Hostname { +func (s *socketFilterSnooper) Resolve(ips map[util.Address]struct{}) map[util.Address][]Hostname { return s.cache.Get(ips) } diff --git a/pkg/network/dns/snooper_test.go b/pkg/network/dns/snooper_test.go index dec29be9e9d8e..069632e97a88b 100644 --- a/pkg/network/dns/snooper_test.go +++ b/pkg/network/dns/snooper_test.go @@ -35,7 +35,7 @@ func checkSnooping(t *testing.T, destIP string, destName string, reverseDNS *dns }, 1*time.Second, 10*time.Millisecond) // Verify that the IP from the connections above maps to the right name - payload := []util.Address{srcAddr, destAddr} + payload := map[util.Address]struct{}{srcAddr: {}, destAddr: {}} names := reverseDNS.Resolve(payload) require.Len(t, names, 1) assert.Contains(t, names[destAddr], ToHostname(destName)) diff --git a/pkg/network/dns/types.go b/pkg/network/dns/types.go index 61e4327ab2bd0..d02b42a2b4b07 100644 --- a/pkg/network/dns/types.go +++ b/pkg/network/dns/types.go @@ -65,7 +65,7 @@ type StatsByKeyByNameByType map[Key]map[Hostname]map[QueryType]Stats // ReverseDNS translates IPs to names type ReverseDNS interface { - Resolve([]util.Address) map[util.Address][]Hostname + Resolve(map[util.Address]struct{}) map[util.Address][]Hostname GetDNSStats() StatsByKeyByNameByType Start() error Close() diff --git a/pkg/network/tracer/tracer.go b/pkg/network/tracer/tracer.go index 68d435dd49e06..475203af77a99 100644 --- a/pkg/network/tracer/tracer.go +++ b/pkg/network/tracer/tracer.go @@ -386,9 +386,10 @@ func (t *Tracer) GetActiveConnections(clientID string) (*network.Connections, er tracerTelemetry.payloadSizePerClient.Set(float64(len(delta.Conns)), clientID) - ips := make([]util.Address, 0, len(delta.Conns)*2) + ips := make(map[util.Address]struct{}, len(delta.Conns)/2) for _, conn := range delta.Conns { - ips = append(ips, conn.Source, conn.Dest) + ips[conn.Source] = struct{}{} + ips[conn.Dest] = struct{}{} } names := t.reverseDNS.Resolve(ips) ctm := t.state.GetTelemetryDelta(clientID, t.getConnTelemetry(len(active))) diff --git a/pkg/network/tracer/tracer_windows.go b/pkg/network/tracer/tracer_windows.go index 7db6564b93910..3b708afd288b5 100644 --- a/pkg/network/tracer/tracer_windows.go +++ b/pkg/network/tracer/tracer_windows.go @@ -183,9 +183,10 @@ func (t *Tracer) GetActiveConnections(clientID string) (*network.Connections, er t.activeBuffer.Reset() t.closedBuffer.Reset() - ips := make([]util.Address, 0, len(delta.Conns)*2) + ips := make(map[util.Address]struct{}, len(delta.Conns)/2) for _, conn := range delta.Conns { - ips = append(ips, conn.Source, conn.Dest) + ips[conn.Source] = struct{}{} + ips[conn.Dest] = struct{}{} } names := t.reverseDNS.Resolve(ips) telemetryDelta := t.state.GetTelemetryDelta(clientID, t.getConnTelemetry()) From c85186ebc3140d143a7893b950953e33038aaf1d Mon Sep 17 00:00:00 2001 From: Vickenty Fesunov Date: Thu, 8 Jun 2023 10:06:28 +0200 Subject: [PATCH 48/76] Fix potentital use of uninitialized memory (#17490) This fixes potential use of uninitialized memory when PyList_GetItem returns NULL. This code path is impossible to hit in practice with the current versions of Python, as long as the object is a list and index is in bounds, which is ensured by the prior call to PyList_Size. These functions do not use the Python sequence protocol, so evil python code can not supply incorrect length or throw an unexpected exception either. --- rtloader/three/three.cpp | 2 +- rtloader/two/two.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/rtloader/three/three.cpp b/rtloader/three/three.cpp index 463a28e13aa5a..562555179c0d4 100644 --- a/rtloader/three/three.cpp +++ b/rtloader/three/three.cpp @@ -520,7 +520,7 @@ char **Three::getCheckWarnings(RtLoaderPyObject *check) if (warn == NULL) { setError("there was an error browsing 'warnings' list: " + _fetchPythonError()); - for (int jdx = 0; jdx < numWarnings && warnings[jdx]; jdx++) { + for (int jdx = 0; jdx < idx; jdx++) { _free(warnings[jdx]); } _free(warnings); diff --git a/rtloader/two/two.cpp b/rtloader/two/two.cpp index 7f5c0a4e1e48d..38d769dabeae4 100644 --- a/rtloader/two/two.cpp +++ b/rtloader/two/two.cpp @@ -513,7 +513,7 @@ char **Two::getCheckWarnings(RtLoaderPyObject *check) if (warn == NULL) { setError("there was an error browsing 'warnings' list: " + _fetchPythonError()); - for (int jdx = 0; jdx < numWarnings && warnings[jdx]; jdx++) { + for (int jdx = 0; jdx < idx; jdx++) { _free(warnings[jdx]); } _free(warnings); From 2d11f7b8a45a25748c3a40027ce78d2e048abb4b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 8 Jun 2023 10:54:16 +0200 Subject: [PATCH 49/76] Bump github.com/stretchr/testify from 1.8.2 to 1.8.4 in /pkg/gohai (#17363) Bumps [github.com/stretchr/testify](https://github.com/stretchr/testify) from 1.8.2 to 1.8.4. - [Release notes](https://github.com/stretchr/testify/releases) - [Commits](https://github.com/stretchr/testify/compare/v1.8.2...v1.8.4) --- updated-dependencies: - dependency-name: github.com/stretchr/testify dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkg/gohai/go.mod | 2 +- pkg/gohai/go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/gohai/go.mod b/pkg/gohai/go.mod index 07a1fd5cf12ec..79e8f9d7826a3 100644 --- a/pkg/gohai/go.mod +++ b/pkg/gohai/go.mod @@ -7,7 +7,7 @@ go 1.18 require ( github.com/cihub/seelog v0.0.0-20151216151435-d2c6e5aa9fbf github.com/shirou/gopsutil/v3 v3.22.12 - github.com/stretchr/testify v1.8.2 + github.com/stretchr/testify v1.8.4 golang.org/x/sys v0.8.0 ) diff --git a/pkg/gohai/go.sum b/pkg/gohai/go.sum index a9e92a927efce..1e92c0b1a6a92 100644 --- a/pkg/gohai/go.sum +++ b/pkg/gohai/go.sum @@ -22,8 +22,8 @@ github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpE github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= -github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/tklauser/go-sysconf v0.3.11 h1:89WgdJhk5SNwJfu+GKyYveZ4IaJ7xAkecBo+KdJV0CM= github.com/tklauser/go-sysconf v0.3.11/go.mod h1:GqXfhXY3kiPa0nAXPDIQIWzJbMCB7AmcWpGR8lSZfqI= github.com/tklauser/numcpus v0.6.0 h1:kebhY2Qt+3U6RNK7UqpYNA+tJ23IBEGKkB7JQBfDYms= From 05b9829e91b48f7f8e2c88185b06166703e6544e Mon Sep 17 00:00:00 2001 From: Guillaume Fournier <36961134+Gui774ume@users.noreply.github.com> Date: Thu, 8 Jun 2023 12:03:17 +0200 Subject: [PATCH 50/76] allow snapshot to fail (#17386) --- pkg/security/probe/probe_monitor.go | 2 +- .../activity_tree/activity_tree.go | 7 +--- .../activity_tree/process_node_snapshot.go | 41 +++++++++---------- .../security_profile/dump/activity_dump.go | 4 +- 4 files changed, 23 insertions(+), 31 deletions(-) diff --git a/pkg/security/probe/probe_monitor.go b/pkg/security/probe/probe_monitor.go index 45b8b667f892d..0e4bbaf2c8f7d 100644 --- a/pkg/security/probe/probe_monitor.go +++ b/pkg/security/probe/probe_monitor.go @@ -67,7 +67,7 @@ func (m *Monitor) Init() error { } } - if p.Config.RuntimeSecurity.SecurityProfileEnabled { + if p.IsSecurityProfileEnabled() { m.securityProfileManager, err = profile.NewSecurityProfileManager(p.Config, p.StatsdClient, p.resolvers.CGroupResolver, p.resolvers.TimeResolver, p.Manager) if err != nil { return fmt.Errorf("couldn't create the security profile manager: %w", err) diff --git a/pkg/security/security_profile/activity_tree/activity_tree.go b/pkg/security/security_profile/activity_tree/activity_tree.go index 33ea029611b97..78025d047b887 100644 --- a/pkg/security/security_profile/activity_tree/activity_tree.go +++ b/pkg/security/security_profile/activity_tree/activity_tree.go @@ -443,15 +443,12 @@ func (at *ActivityTree) FindMatchingRootNodes(arg0 string) []*ProcessNode { } // Snapshot uses procfs to snapshot the nodes of the tree -func (at *ActivityTree) Snapshot(newEvent func() *model.Event) error { +func (at *ActivityTree) Snapshot(newEvent func() *model.Event) { for _, pn := range at.ProcessNodes { - if err := pn.snapshot(at.validator, at.Stats, newEvent); err != nil { - return err - } + pn.snapshot(at.validator, at.Stats, newEvent) // iterate slowly time.Sleep(50 * time.Millisecond) } - return nil } // SendStats sends the tree statistics diff --git a/pkg/security/security_profile/activity_tree/process_node_snapshot.go b/pkg/security/security_profile/activity_tree/process_node_snapshot.go index f90e386a9f2fd..5852b481dc3a9 100644 --- a/pkg/security/security_profile/activity_tree/process_node_snapshot.go +++ b/pkg/security/security_profile/activity_tree/process_node_snapshot.go @@ -31,12 +31,10 @@ import ( ) // snapshot uses procfs to retrieve information about the current process -func (pn *ProcessNode) snapshot(owner ActivityTreeOwner, stats *ActivityTreeStats, newEvent func() *model.Event) error { +func (pn *ProcessNode) snapshot(owner ActivityTreeOwner, stats *ActivityTreeStats, newEvent func() *model.Event) { // call snapshot for all the children of the current node for _, child := range pn.Children { - if err := child.snapshot(owner, stats, newEvent); err != nil { - return err - } + child.snapshot(owner, stats, newEvent) // iterate slowly time.Sleep(50 * time.Millisecond) } @@ -45,30 +43,25 @@ func (pn *ProcessNode) snapshot(owner ActivityTreeOwner, stats *ActivityTreeStat p, err := process.NewProcess(int32(pn.Process.Pid)) if err != nil { // the process doesn't exist anymore, ignore - return nil + return } // snapshot files if owner.IsEventTypeValid(model.FileOpenEventType) { - if err = pn.snapshotFiles(p, stats, newEvent); err != nil { - return err - } + pn.snapshotFiles(p, stats, newEvent) } // snapshot sockets if owner.IsEventTypeValid(model.BindEventType) { - if err = pn.snapshotBoundSockets(p, stats, newEvent); err != nil { - return err - } + pn.snapshotBoundSockets(p, stats, newEvent) } - return nil } -func (pn *ProcessNode) snapshotFiles(p *process.Process, stats *ActivityTreeStats, newEvent func() *model.Event) error { +func (pn *ProcessNode) snapshotFiles(p *process.Process, stats *ActivityTreeStats, newEvent func() *model.Event) { // list the files opened by the process fileFDs, err := p.OpenFiles() if err != nil { - return err + seclog.Warnf("error while listing files (pid: %v): %s", p.Pid, err) } var files []string @@ -79,7 +72,11 @@ func (pn *ProcessNode) snapshotFiles(p *process.Process, stats *ActivityTreeStat // list the mmaped files of the process mmapedFiles, err := snapshotMemoryMappedFiles(p.Pid, pn.Process.FileEvent.PathnameStr) if err != nil { - return err + seclog.Warnf("error while listing memory maps (pid: %v): %s", p.Pid, err) + } + + if len(files) == 0 { + return } files = append(files, mmapedFiles...) @@ -125,7 +122,6 @@ func (pn *ProcessNode) snapshotFiles(p *process.Process, stats *ActivityTreeStat _ = pn.InsertFileEvent(&evt.Open.File, evt, Snapshot, stats, false) } - return nil } const MAX_MMAPED_FILES = 128 @@ -156,11 +152,12 @@ func snapshotMemoryMappedFiles(pid int32, processEventPath string) ([]string, er return files, nil } -func (pn *ProcessNode) snapshotBoundSockets(p *process.Process, stats *ActivityTreeStats, newEvent func() *model.Event) error { +func (pn *ProcessNode) snapshotBoundSockets(p *process.Process, stats *ActivityTreeStats, newEvent func() *model.Event) { // list all the file descriptors opened by the process FDs, err := p.OpenFiles() if err != nil { - return err + seclog.Warnf("error while listing files (pid: %v): %s", p.Pid, err) + return } // sockets have the following pattern "socket:[inode]" @@ -169,7 +166,8 @@ func (pn *ProcessNode) snapshotBoundSockets(p *process.Process, stats *ActivityT if strings.HasPrefix(fd.Path, "socket:[") { sock, err := strconv.Atoi(strings.TrimPrefix(fd.Path[:len(fd.Path)-1], "socket:[")) if err != nil { - return err + seclog.Warnf("error while parsing socket inode (pid: %v): %s", p.Pid, err) + continue } if sock < 0 { continue @@ -178,13 +176,13 @@ func (pn *ProcessNode) snapshotBoundSockets(p *process.Process, stats *ActivityT } } if len(sockets) <= 0 { - return nil + return } // use /proc/[pid]/net/tcp,tcp6,udp,udp6 to extract the ports opened by the current process proc, _ := procfs.NewFS(filepath.Join(util.HostProc(fmt.Sprintf("%d", p.Pid)))) if err != nil { - return err + seclog.Warnf("error while opening procfs (pid: %v): %s", p.Pid, err) } // looking for AF_INET sockets TCP, err := proc.NetTCP() @@ -233,7 +231,6 @@ func (pn *ProcessNode) snapshotBoundSockets(p *process.Process, stats *ActivityT } // not necessary found here, can be also another kind of socket (AF_UNIX, AF_NETLINK, etc) } - return nil } func (pn *ProcessNode) insertSnapshottedSocket(family uint16, ip net.IP, port uint16, stats *ActivityTreeStats, newEvent func() *model.Event) { diff --git a/pkg/security/security_profile/dump/activity_dump.go b/pkg/security/security_profile/dump/activity_dump.go index 732c4dc0e2b31..597491a33af31 100644 --- a/pkg/security/security_profile/dump/activity_dump.go +++ b/pkg/security/security_profile/dump/activity_dump.go @@ -557,9 +557,7 @@ func (ad *ActivityDump) Snapshot() error { ad.Lock() defer ad.Unlock() - if err := ad.ActivityTree.Snapshot(ad.adm.newEvent); err != nil { - return fmt.Errorf("couldn't snapshot [%s]: %v", ad.getSelectorStr(), err) - } + ad.ActivityTree.Snapshot(ad.adm.newEvent) // try to resolve the tags now _ = ad.resolveTags() From d33dc70537e4c39d79fe1dadc5d83e737ed5ded6 Mon Sep 17 00:00:00 2001 From: Guillaume Fournier <36961134+Gui774ume@users.noreply.github.com> Date: Thu, 8 Jun 2023 12:03:43 +0200 Subject: [PATCH 51/76] add JSON decoder for activity dumps (#17444) --- .../security_profile/dump/activity_dump.go | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/pkg/security/security_profile/dump/activity_dump.go b/pkg/security/security_profile/dump/activity_dump.go index 597491a33af31..4564bae06e2c3 100644 --- a/pkg/security/security_profile/dump/activity_dump.go +++ b/pkg/security/security_profile/dump/activity_dump.go @@ -768,6 +768,8 @@ func (ad *ActivityDump) DecodeFromReader(reader io.Reader, format config.Storage return ad.DecodeProtobuf(reader) case config.Profile: return ad.DecodeProfileProtobuf(reader) + case config.Json: + return ad.DecodeJSON(reader) default: return fmt.Errorf("unsupported input format: %s", format) } @@ -812,3 +814,26 @@ func (ad *ActivityDump) DecodeProfileProtobuf(reader io.Reader) error { return nil } + +func (ad *ActivityDump) DecodeJSON(reader io.Reader) error { + ad.Lock() + defer ad.Unlock() + + raw, err := io.ReadAll(reader) + if err != nil { + return fmt.Errorf("couldn't open security profile file: %w", err) + } + + opts := protojson.UnmarshalOptions{ + AllowPartial: true, + DiscardUnknown: true, + } + inter := &adproto.SecDump{} + if err = opts.Unmarshal(raw, inter); err != nil { + return fmt.Errorf("couldn't decode json file: %w", err) + } + + protoToActivityDump(ad, inter) + + return nil +} From 5a063e73e18970ef5b73797203fff16865aa4fac Mon Sep 17 00:00:00 2001 From: Guillaume Fournier <36961134+Gui774ume@users.noreply.github.com> Date: Thu, 8 Jun 2023 12:04:11 +0200 Subject: [PATCH 52/76] add activity tree stats in activity dump list command (#17369) --- .../subcommands/runtime/command.go | 4 +- .../subcommands/runtime/security_profile.go | 16 +- pkg/security/proto/api/api.pb.go | 542 +++++++++--------- pkg/security/proto/api/api.proto | 3 +- pkg/security/proto/api/api_vtproto.pb.go | 50 ++ .../security_profile/dump/activity_dump.go | 12 +- 6 files changed, 353 insertions(+), 274 deletions(-) diff --git a/cmd/security-agent/subcommands/runtime/command.go b/cmd/security-agent/subcommands/runtime/command.go index 4c9fee239cee7..6a67e93d689bb 100644 --- a/cmd/security-agent/subcommands/runtime/command.go +++ b/cmd/security-agent/subcommands/runtime/command.go @@ -21,6 +21,8 @@ import ( "github.com/spf13/cobra" "go.uber.org/fx" + ddgostatsd "github.com/DataDog/datadog-go/v5/statsd" + "github.com/DataDog/datadog-agent/cmd/security-agent/command" "github.com/DataDog/datadog-agent/cmd/security-agent/flags" "github.com/DataDog/datadog-agent/comp/core" @@ -42,7 +44,6 @@ import ( httputils "github.com/DataDog/datadog-agent/pkg/util/http" "github.com/DataDog/datadog-agent/pkg/util/startstop" "github.com/DataDog/datadog-agent/pkg/version" - ddgostatsd "github.com/DataDog/datadog-go/v5/statsd" ) func Commands(globalParams *command.GlobalParams) []*cobra.Command { @@ -410,6 +411,7 @@ func printSecurityActivityDumpMessage(prefix string, msg *api.ActivityDumpMessag fmt.Printf("%s tags: %s\n", prefix, strings.Join(msg.GetTags(), ", ")) } fmt.Printf("%s differentiate args: %v\n", prefix, msg.GetMetadata().GetDifferentiateArgs()) + printActivityTreeStats(prefix, msg.GetStats()) if len(msg.GetStorage()) > 0 { fmt.Printf("%s storage:\n", prefix) for _, storage := range msg.GetStorage() { diff --git a/cmd/security-agent/subcommands/runtime/security_profile.go b/cmd/security-agent/subcommands/runtime/security_profile.go index fac8f1d6b845a..961c9e5e66890 100644 --- a/cmd/security-agent/subcommands/runtime/security_profile.go +++ b/cmd/security-agent/subcommands/runtime/security_profile.go @@ -148,6 +148,15 @@ func listSecurityProfiles(log log.Component, config config.Component, args *secu return nil } +func printActivityTreeStats(prefix string, msg *api.ActivityTreeStatsMessage) { + fmt.Printf("%s activity_tree_stats:\n", prefix) + fmt.Printf("%s approximate_size: %v\n", prefix, msg.GetApproximateSize()) + fmt.Printf("%s process_nodes_count: %v\n", prefix, msg.GetProcessNodesCount()) + fmt.Printf("%s file_nodes_count: %v\n", prefix, msg.GetFileNodesCount()) + fmt.Printf("%s dns_nodes_count: %v\n", prefix, msg.GetDNSNodesCount()) + fmt.Printf("%s socket_nodes_count: %v\n", prefix, msg.GetSocketNodesCount()) +} + func printSecurityProfileMessage(msg *api.SecurityProfileMessage) { prefix := " " fmt.Printf("%s- name: %s\n", prefix, msg.GetMetadata().GetName()) @@ -178,13 +187,8 @@ func printSecurityProfileMessage(msg *api.SecurityProfileMessage) { fmt.Printf("%s tags: %v\n", prefix, inst.GetTags()) } } - fmt.Printf("%s activity_tree_stats:\n", prefix) - fmt.Printf("%s approximate_size: %v\n", prefix, msg.GetStats().GetApproximateSize()) - fmt.Printf("%s process_nodes_count: %v\n", prefix, msg.GetStats().GetProcessNodesCount()) - fmt.Printf("%s file_nodes_count: %v\n", prefix, msg.GetStats().GetFileNodesCount()) - fmt.Printf("%s dns_nodes_count: %v\n", prefix, msg.GetStats().GetDNSNodesCount()) - fmt.Printf("%s socket_nodes_count: %v\n", prefix, msg.GetStats().GetSocketNodesCount()) fmt.Printf("%s tags: %v\n", prefix, msg.GetTags()) + printActivityTreeStats(prefix, msg.GetStats()) } func saveSecurityProfileCommands(globalParams *command.GlobalParams) []*cobra.Command { diff --git a/pkg/security/proto/api/api.pb.go b/pkg/security/proto/api/api.pb.go index 8b678c67741a6..15d2c93404550 100644 --- a/pkg/security/proto/api/api.pb.go +++ b/pkg/security/proto/api/api.pb.go @@ -1427,14 +1427,15 @@ type ActivityDumpMessage struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Host string `protobuf:"bytes,1,opt,name=Host,proto3" json:"Host,omitempty"` - Source string `protobuf:"bytes,2,opt,name=Source,proto3" json:"Source,omitempty"` - Service string `protobuf:"bytes,3,opt,name=Service,proto3" json:"Service,omitempty"` - Tags []string `protobuf:"bytes,4,rep,name=Tags,proto3" json:"Tags,omitempty"` - Storage []*StorageRequestMessage `protobuf:"bytes,5,rep,name=Storage,proto3" json:"Storage,omitempty"` - Metadata *MetadataMessage `protobuf:"bytes,6,opt,name=Metadata,proto3" json:"Metadata,omitempty"` - DNSNames []string `protobuf:"bytes,8,rep,name=DNSNames,proto3" json:"DNSNames,omitempty"` - Error string `protobuf:"bytes,7,opt,name=Error,proto3" json:"Error,omitempty"` + Host string `protobuf:"bytes,1,opt,name=Host,proto3" json:"Host,omitempty"` + Source string `protobuf:"bytes,2,opt,name=Source,proto3" json:"Source,omitempty"` + Service string `protobuf:"bytes,3,opt,name=Service,proto3" json:"Service,omitempty"` + Tags []string `protobuf:"bytes,4,rep,name=Tags,proto3" json:"Tags,omitempty"` + Storage []*StorageRequestMessage `protobuf:"bytes,5,rep,name=Storage,proto3" json:"Storage,omitempty"` + Metadata *MetadataMessage `protobuf:"bytes,6,opt,name=Metadata,proto3" json:"Metadata,omitempty"` + Error string `protobuf:"bytes,7,opt,name=Error,proto3" json:"Error,omitempty"` + DNSNames []string `protobuf:"bytes,8,rep,name=DNSNames,proto3" json:"DNSNames,omitempty"` + Stats *ActivityTreeStatsMessage `protobuf:"bytes,9,opt,name=Stats,proto3" json:"Stats,omitempty"` } func (x *ActivityDumpMessage) Reset() { @@ -1511,6 +1512,13 @@ func (x *ActivityDumpMessage) GetMetadata() *MetadataMessage { return nil } +func (x *ActivityDumpMessage) GetError() string { + if x != nil { + return x.Error + } + return "" +} + func (x *ActivityDumpMessage) GetDNSNames() []string { if x != nil { return x.DNSNames @@ -1518,11 +1526,11 @@ func (x *ActivityDumpMessage) GetDNSNames() []string { return nil } -func (x *ActivityDumpMessage) GetError() string { +func (x *ActivityDumpMessage) GetStats() *ActivityTreeStatsMessage { if x != nil { - return x.Error + return x.Stats } - return "" + return nil } type ActivityDumpListParams struct { @@ -2690,7 +2698,7 @@ var file_pkg_security_proto_api_api_proto_rawDesc = []byte{ 0x0a, 0x0b, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x46, 0x69, 0x6c, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, - 0x46, 0x69, 0x6c, 0x65, 0x22, 0x89, 0x02, 0x0a, 0x13, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, + 0x46, 0x69, 0x6c, 0x65, 0x22, 0xbe, 0x02, 0x0a, 0x13, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x44, 0x75, 0x6d, 0x70, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x48, 0x6f, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x48, 0x6f, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, @@ -2703,216 +2711,219 @@ var file_pkg_security_proto_api_api_proto_rawDesc = []byte{ 0x61, 0x67, 0x65, 0x52, 0x07, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x12, 0x30, 0x0a, 0x08, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x4d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x52, 0x08, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x1a, - 0x0a, 0x08, 0x44, 0x4e, 0x53, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x09, - 0x52, 0x08, 0x44, 0x4e, 0x53, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x45, 0x72, - 0x72, 0x6f, 0x72, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x45, 0x72, 0x72, 0x6f, 0x72, - 0x22, 0x18, 0x0a, 0x16, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x44, 0x75, 0x6d, 0x70, - 0x4c, 0x69, 0x73, 0x74, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x22, 0x5f, 0x0a, 0x17, 0x41, 0x63, - 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x44, 0x75, 0x6d, 0x70, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x2e, 0x0a, 0x05, 0x44, 0x75, 0x6d, 0x70, 0x73, 0x18, 0x01, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x76, - 0x69, 0x74, 0x79, 0x44, 0x75, 0x6d, 0x70, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x05, - 0x44, 0x75, 0x6d, 0x70, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x62, 0x0a, 0x16, 0x41, - 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x44, 0x75, 0x6d, 0x70, 0x53, 0x74, 0x6f, 0x70, 0x50, - 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x43, 0x6f, 0x6e, - 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x44, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, - 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x44, 0x12, 0x12, 0x0a, 0x04, 0x43, - 0x6f, 0x6d, 0x6d, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x43, 0x6f, 0x6d, 0x6d, 0x22, - 0x2f, 0x0a, 0x17, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x44, 0x75, 0x6d, 0x70, 0x53, - 0x74, 0x6f, 0x70, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x45, 0x72, - 0x72, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x45, 0x72, 0x72, 0x6f, 0x72, - 0x22, 0x7b, 0x0a, 0x18, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x2a, 0x0a, 0x10, - 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x44, 0x75, 0x6d, 0x70, 0x46, 0x69, 0x6c, 0x65, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, - 0x44, 0x75, 0x6d, 0x70, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x33, 0x0a, 0x07, 0x53, 0x74, 0x6f, 0x72, - 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x61, 0x70, 0x69, 0x2e, - 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x50, 0x61, - 0x72, 0x61, 0x6d, 0x73, 0x52, 0x07, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x22, 0x67, 0x0a, - 0x19, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x45, 0x72, - 0x72, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x45, 0x72, 0x72, 0x6f, 0x72, - 0x12, 0x34, 0x0a, 0x07, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x1a, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x07, 0x53, - 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x22, 0x1a, 0x0a, 0x18, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, - 0x74, 0x79, 0x44, 0x75, 0x6d, 0x70, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x50, 0x61, 0x72, 0x61, - 0x6d, 0x73, 0x22, 0x5d, 0x0a, 0x19, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x44, 0x75, - 0x6d, 0x70, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, - 0x2c, 0x0a, 0x04, 0x44, 0x75, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, - 0x61, 0x70, 0x69, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x44, 0x75, 0x6d, 0x70, - 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x04, 0x44, 0x75, 0x6d, 0x70, 0x12, 0x12, 0x0a, - 0x04, 0x44, 0x61, 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x44, 0x61, 0x74, - 0x61, 0x22, 0x3f, 0x0a, 0x17, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x65, 0x6c, - 0x65, 0x63, 0x74, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x12, 0x0a, 0x04, - 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, - 0x12, 0x10, 0x0a, 0x03, 0x54, 0x61, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x54, - 0x61, 0x67, 0x22, 0x87, 0x01, 0x0a, 0x1b, 0x4c, 0x61, 0x73, 0x74, 0x41, 0x6e, 0x6f, 0x6d, 0x61, - 0x6c, 0x79, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x4d, 0x65, 0x73, 0x73, 0x61, - 0x67, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, - 0x12, 0x1c, 0x0a, 0x09, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x09, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x2c, - 0x0a, 0x11, 0x49, 0x73, 0x53, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x54, - 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x49, 0x73, 0x53, 0x74, 0x61, - 0x62, 0x6c, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x22, 0x47, 0x0a, 0x0f, - 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, - 0x20, 0x0a, 0x0b, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x44, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, - 0x44, 0x12, 0x12, 0x0a, 0x04, 0x54, 0x61, 0x67, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, - 0x04, 0x54, 0x61, 0x67, 0x73, 0x22, 0xec, 0x01, 0x0a, 0x18, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, - 0x74, 0x79, 0x54, 0x72, 0x65, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x4d, 0x65, 0x73, 0x73, 0x61, - 0x67, 0x65, 0x12, 0x2c, 0x0a, 0x11, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x4e, 0x6f, 0x64, - 0x65, 0x73, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x11, 0x50, - 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x43, 0x6f, 0x75, 0x6e, 0x74, - 0x12, 0x26, 0x0a, 0x0e, 0x46, 0x69, 0x6c, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x43, 0x6f, 0x75, - 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x46, 0x69, 0x6c, 0x65, 0x4e, 0x6f, - 0x64, 0x65, 0x73, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x24, 0x0a, 0x0d, 0x44, 0x4e, 0x53, 0x4e, - 0x6f, 0x64, 0x65, 0x73, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, - 0x0d, 0x44, 0x4e, 0x53, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x2a, - 0x0a, 0x10, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x43, 0x6f, 0x75, - 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x10, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, - 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x28, 0x0a, 0x0f, 0x41, 0x70, - 0x70, 0x72, 0x6f, 0x78, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x18, 0x05, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x0f, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x78, 0x69, 0x6d, 0x61, 0x74, 0x65, - 0x53, 0x69, 0x7a, 0x65, 0x22, 0xbb, 0x04, 0x0a, 0x16, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, - 0x79, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, - 0x26, 0x0a, 0x0e, 0x4c, 0x6f, 0x61, 0x64, 0x65, 0x64, 0x49, 0x6e, 0x4b, 0x65, 0x72, 0x6e, 0x65, - 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x4c, 0x6f, 0x61, 0x64, 0x65, 0x64, 0x49, - 0x6e, 0x4b, 0x65, 0x72, 0x6e, 0x65, 0x6c, 0x12, 0x38, 0x0a, 0x17, 0x4c, 0x6f, 0x61, 0x64, 0x65, - 0x64, 0x49, 0x6e, 0x4b, 0x65, 0x72, 0x6e, 0x65, 0x6c, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, - 0x6d, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x17, 0x4c, 0x6f, 0x61, 0x64, 0x65, 0x64, - 0x49, 0x6e, 0x4b, 0x65, 0x72, 0x6e, 0x65, 0x6c, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, - 0x70, 0x12, 0x38, 0x0a, 0x08, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, - 0x61, 0x64, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, - 0x65, 0x52, 0x08, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x24, 0x0a, 0x0d, 0x50, - 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x43, 0x6f, 0x6f, 0x6b, 0x69, 0x65, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x04, 0x52, 0x0d, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x43, 0x6f, 0x6f, 0x6b, 0x69, - 0x65, 0x12, 0x36, 0x0a, 0x16, 0x41, 0x6e, 0x6f, 0x6d, 0x61, 0x6c, 0x79, 0x44, 0x65, 0x74, 0x65, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, - 0x09, 0x52, 0x16, 0x41, 0x6e, 0x6f, 0x6d, 0x61, 0x6c, 0x79, 0x44, 0x65, 0x74, 0x65, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x46, 0x0a, 0x0d, 0x4c, 0x61, 0x73, - 0x74, 0x41, 0x6e, 0x6f, 0x6d, 0x61, 0x6c, 0x69, 0x65, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x20, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x61, 0x73, 0x74, 0x41, 0x6e, 0x6f, 0x6d, 0x61, - 0x6c, 0x79, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x4d, 0x65, 0x73, 0x73, 0x61, - 0x67, 0x65, 0x52, 0x0d, 0x4c, 0x61, 0x73, 0x74, 0x41, 0x6e, 0x6f, 0x6d, 0x61, 0x6c, 0x69, 0x65, - 0x73, 0x12, 0x32, 0x0a, 0x09, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x18, 0x07, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x49, 0x6e, 0x73, 0x74, 0x61, - 0x6e, 0x63, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x09, 0x49, 0x6e, 0x73, 0x74, - 0x61, 0x6e, 0x63, 0x65, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, - 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x18, 0x0a, - 0x07, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, - 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x30, 0x0a, 0x08, 0x4d, 0x65, 0x74, 0x61, 0x64, - 0x61, 0x74, 0x61, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x61, 0x70, 0x69, 0x2e, - 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, - 0x08, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x12, 0x0a, 0x04, 0x54, 0x61, 0x67, - 0x73, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x54, 0x61, 0x67, 0x73, 0x12, 0x33, 0x0a, - 0x05, 0x53, 0x74, 0x61, 0x74, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x61, - 0x70, 0x69, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x54, 0x72, 0x65, 0x65, 0x53, - 0x74, 0x61, 0x74, 0x73, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x05, 0x53, 0x74, 0x61, - 0x74, 0x73, 0x22, 0x3f, 0x0a, 0x19, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x50, 0x72, - 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, - 0x22, 0x0a, 0x0c, 0x49, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x49, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x43, 0x61, - 0x63, 0x68, 0x65, 0x22, 0x6b, 0x0a, 0x1a, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x50, - 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, - 0x65, 0x12, 0x37, 0x0a, 0x08, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, - 0x74, 0x79, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x52, 0x08, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x45, 0x72, + 0x73, 0x61, 0x67, 0x65, 0x52, 0x08, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x14, + 0x0a, 0x05, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x45, + 0x72, 0x72, 0x6f, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x44, 0x4e, 0x53, 0x4e, 0x61, 0x6d, 0x65, 0x73, + 0x18, 0x08, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x44, 0x4e, 0x53, 0x4e, 0x61, 0x6d, 0x65, 0x73, + 0x12, 0x33, 0x0a, 0x05, 0x53, 0x74, 0x61, 0x74, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x1d, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x54, 0x72, + 0x65, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x05, + 0x53, 0x74, 0x61, 0x74, 0x73, 0x22, 0x18, 0x0a, 0x16, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, + 0x79, 0x44, 0x75, 0x6d, 0x70, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x22, + 0x5f, 0x0a, 0x17, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x44, 0x75, 0x6d, 0x70, 0x4c, + 0x69, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x2e, 0x0a, 0x05, 0x44, 0x75, + 0x6d, 0x70, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x61, 0x70, 0x69, 0x2e, + 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x44, 0x75, 0x6d, 0x70, 0x4d, 0x65, 0x73, 0x73, + 0x61, 0x67, 0x65, 0x52, 0x05, 0x44, 0x75, 0x6d, 0x70, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x45, 0x72, 0x72, 0x6f, 0x72, - 0x22, 0x55, 0x0a, 0x19, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x66, - 0x69, 0x6c, 0x65, 0x53, 0x61, 0x76, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x38, 0x0a, - 0x08, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x1c, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x65, - 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x08, 0x53, - 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x22, 0x46, 0x0a, 0x1a, 0x53, 0x65, 0x63, 0x75, 0x72, - 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x53, 0x61, 0x76, 0x65, 0x4d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x46, - 0x69, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x46, 0x69, 0x6c, 0x65, 0x32, - 0xb3, 0x09, 0x0a, 0x0e, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x4d, 0x6f, 0x64, 0x75, - 0x6c, 0x65, 0x12, 0x3f, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x12, - 0x13, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x50, 0x61, - 0x72, 0x61, 0x6d, 0x73, 0x1a, 0x19, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x65, 0x63, 0x75, 0x72, - 0x69, 0x74, 0x79, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, - 0x00, 0x30, 0x01, 0x12, 0x57, 0x0a, 0x10, 0x44, 0x75, 0x6d, 0x70, 0x50, 0x72, 0x6f, 0x63, 0x65, - 0x73, 0x73, 0x43, 0x61, 0x63, 0x68, 0x65, 0x12, 0x1b, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x44, 0x75, - 0x6d, 0x70, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x43, 0x61, 0x63, 0x68, 0x65, 0x50, 0x61, - 0x72, 0x61, 0x6d, 0x73, 0x1a, 0x24, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x65, 0x63, 0x75, 0x72, - 0x69, 0x74, 0x79, 0x44, 0x75, 0x6d, 0x70, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x43, 0x61, - 0x63, 0x68, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x00, 0x12, 0x3f, 0x0a, 0x09, - 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x14, 0x2e, 0x61, 0x70, 0x69, 0x2e, - 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x1a, - 0x1a, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x43, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x00, 0x12, 0x30, 0x0a, - 0x09, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x14, 0x2e, 0x61, 0x70, 0x69, - 0x2e, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, - 0x1a, 0x0b, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x00, 0x12, - 0x4b, 0x0a, 0x0b, 0x52, 0x75, 0x6e, 0x53, 0x65, 0x6c, 0x66, 0x54, 0x65, 0x73, 0x74, 0x12, 0x16, - 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x52, 0x75, 0x6e, 0x53, 0x65, 0x6c, 0x66, 0x54, 0x65, 0x73, 0x74, - 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x1a, 0x22, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x65, 0x63, - 0x75, 0x72, 0x69, 0x74, 0x79, 0x53, 0x65, 0x6c, 0x66, 0x54, 0x65, 0x73, 0x74, 0x52, 0x65, 0x73, - 0x75, 0x6c, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x00, 0x12, 0x4f, 0x0a, 0x0e, - 0x52, 0x65, 0x6c, 0x6f, 0x61, 0x64, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x12, 0x19, + 0x22, 0x62, 0x0a, 0x16, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x44, 0x75, 0x6d, 0x70, + 0x53, 0x74, 0x6f, 0x70, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, + 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x20, + 0x0a, 0x0b, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x44, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0b, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x44, + 0x12, 0x12, 0x0a, 0x04, 0x43, 0x6f, 0x6d, 0x6d, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, + 0x43, 0x6f, 0x6d, 0x6d, 0x22, 0x2f, 0x0a, 0x17, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, + 0x44, 0x75, 0x6d, 0x70, 0x53, 0x74, 0x6f, 0x70, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, + 0x14, 0x0a, 0x05, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, + 0x45, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x7b, 0x0a, 0x18, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x63, 0x6f, + 0x64, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x50, 0x61, 0x72, 0x61, 0x6d, + 0x73, 0x12, 0x2a, 0x0a, 0x10, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x44, 0x75, 0x6d, + 0x70, 0x46, 0x69, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x41, 0x63, 0x74, + 0x69, 0x76, 0x69, 0x74, 0x79, 0x44, 0x75, 0x6d, 0x70, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x33, 0x0a, + 0x07, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, + 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x07, 0x53, 0x74, 0x6f, 0x72, 0x61, + 0x67, 0x65, 0x22, 0x67, 0x0a, 0x19, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x63, 0x6f, 0x64, 0x69, 0x6e, + 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, + 0x14, 0x0a, 0x05, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, + 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x34, 0x0a, 0x07, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, + 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x74, 0x6f, + 0x72, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, + 0x67, 0x65, 0x52, 0x07, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x22, 0x1a, 0x0a, 0x18, 0x41, + 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x44, 0x75, 0x6d, 0x70, 0x53, 0x74, 0x72, 0x65, 0x61, + 0x6d, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x22, 0x5d, 0x0a, 0x19, 0x41, 0x63, 0x74, 0x69, 0x76, + 0x69, 0x74, 0x79, 0x44, 0x75, 0x6d, 0x70, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x4d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x12, 0x2c, 0x0a, 0x04, 0x44, 0x75, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, + 0x79, 0x44, 0x75, 0x6d, 0x70, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x04, 0x44, 0x75, + 0x6d, 0x70, 0x12, 0x12, 0x0a, 0x04, 0x44, 0x61, 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, + 0x52, 0x04, 0x44, 0x61, 0x74, 0x61, 0x22, 0x3f, 0x0a, 0x17, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, + 0x61, 0x64, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x54, 0x61, 0x67, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x03, 0x54, 0x61, 0x67, 0x22, 0x87, 0x01, 0x0a, 0x1b, 0x4c, 0x61, 0x73, 0x74, + 0x41, 0x6e, 0x6f, 0x6d, 0x61, 0x6c, 0x79, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, + 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x45, 0x76, 0x65, 0x6e, 0x74, + 0x54, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x45, 0x76, 0x65, 0x6e, + 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, + 0x6d, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, + 0x61, 0x6d, 0x70, 0x12, 0x2c, 0x0a, 0x11, 0x49, 0x73, 0x53, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x45, + 0x76, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, + 0x49, 0x73, 0x53, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, + 0x65, 0x22, 0x47, 0x0a, 0x0f, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x4d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, + 0x72, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x43, 0x6f, 0x6e, 0x74, 0x61, + 0x69, 0x6e, 0x65, 0x72, 0x49, 0x44, 0x12, 0x12, 0x0a, 0x04, 0x54, 0x61, 0x67, 0x73, 0x18, 0x02, + 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x54, 0x61, 0x67, 0x73, 0x22, 0xec, 0x01, 0x0a, 0x18, 0x41, + 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x54, 0x72, 0x65, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, + 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x2c, 0x0a, 0x11, 0x50, 0x72, 0x6f, 0x63, 0x65, + 0x73, 0x73, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x11, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x4e, 0x6f, 0x64, 0x65, 0x73, + 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x26, 0x0a, 0x0e, 0x46, 0x69, 0x6c, 0x65, 0x4e, 0x6f, 0x64, + 0x65, 0x73, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x46, + 0x69, 0x6c, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x24, 0x0a, + 0x0d, 0x44, 0x4e, 0x53, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x44, 0x4e, 0x53, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x43, 0x6f, + 0x75, 0x6e, 0x74, 0x12, 0x2a, 0x0a, 0x10, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x4e, 0x6f, 0x64, + 0x65, 0x73, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x10, 0x53, + 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, + 0x28, 0x0a, 0x0f, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x78, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x53, 0x69, + 0x7a, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x78, + 0x69, 0x6d, 0x61, 0x74, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x22, 0xbb, 0x04, 0x0a, 0x16, 0x53, 0x65, + 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x4d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x12, 0x26, 0x0a, 0x0e, 0x4c, 0x6f, 0x61, 0x64, 0x65, 0x64, 0x49, 0x6e, + 0x4b, 0x65, 0x72, 0x6e, 0x65, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x4c, 0x6f, + 0x61, 0x64, 0x65, 0x64, 0x49, 0x6e, 0x4b, 0x65, 0x72, 0x6e, 0x65, 0x6c, 0x12, 0x38, 0x0a, 0x17, + 0x4c, 0x6f, 0x61, 0x64, 0x65, 0x64, 0x49, 0x6e, 0x4b, 0x65, 0x72, 0x6e, 0x65, 0x6c, 0x54, 0x69, + 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x17, 0x4c, + 0x6f, 0x61, 0x64, 0x65, 0x64, 0x49, 0x6e, 0x4b, 0x65, 0x72, 0x6e, 0x65, 0x6c, 0x54, 0x69, 0x6d, + 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x38, 0x0a, 0x08, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, + 0x6f, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x57, + 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x4d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x08, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, + 0x12, 0x24, 0x0a, 0x0d, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x43, 0x6f, 0x6f, 0x6b, 0x69, + 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0d, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, + 0x43, 0x6f, 0x6f, 0x6b, 0x69, 0x65, 0x12, 0x36, 0x0a, 0x16, 0x41, 0x6e, 0x6f, 0x6d, 0x61, 0x6c, + 0x79, 0x44, 0x65, 0x74, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, + 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x16, 0x41, 0x6e, 0x6f, 0x6d, 0x61, 0x6c, 0x79, 0x44, + 0x65, 0x74, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x46, + 0x0a, 0x0d, 0x4c, 0x61, 0x73, 0x74, 0x41, 0x6e, 0x6f, 0x6d, 0x61, 0x6c, 0x69, 0x65, 0x73, 0x18, + 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x61, 0x73, 0x74, + 0x41, 0x6e, 0x6f, 0x6d, 0x61, 0x6c, 0x79, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, + 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x0d, 0x4c, 0x61, 0x73, 0x74, 0x41, 0x6e, 0x6f, + 0x6d, 0x61, 0x6c, 0x69, 0x65, 0x73, 0x12, 0x32, 0x0a, 0x09, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, + 0x63, 0x65, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x61, 0x70, 0x69, 0x2e, + 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, + 0x09, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x53, 0x74, + 0x61, 0x74, 0x75, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x53, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x09, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x07, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x30, 0x0a, 0x08, + 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, + 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x4d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x52, 0x08, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x12, + 0x0a, 0x04, 0x54, 0x61, 0x67, 0x73, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x54, 0x61, + 0x67, 0x73, 0x12, 0x33, 0x0a, 0x05, 0x53, 0x74, 0x61, 0x74, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x1d, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, + 0x54, 0x72, 0x65, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x52, 0x05, 0x53, 0x74, 0x61, 0x74, 0x73, 0x22, 0x3f, 0x0a, 0x19, 0x53, 0x65, 0x63, 0x75, 0x72, + 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x61, + 0x72, 0x61, 0x6d, 0x73, 0x12, 0x22, 0x0a, 0x0c, 0x49, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x43, + 0x61, 0x63, 0x68, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x49, 0x6e, 0x63, 0x6c, + 0x75, 0x64, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x22, 0x6b, 0x0a, 0x1a, 0x53, 0x65, 0x63, 0x75, + 0x72, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x4d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x37, 0x0a, 0x08, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, + 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x53, + 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x4d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x08, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x12, + 0x14, 0x0a, 0x05, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, + 0x45, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x55, 0x0a, 0x19, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, + 0x79, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x53, 0x61, 0x76, 0x65, 0x50, 0x61, 0x72, 0x61, + 0x6d, 0x73, 0x12, 0x38, 0x0a, 0x08, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x6c, + 0x6f, 0x61, 0x64, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, + 0x67, 0x65, 0x52, 0x08, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x22, 0x46, 0x0a, 0x1a, + 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x53, + 0x61, 0x76, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x45, 0x72, + 0x72, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x45, 0x72, 0x72, 0x6f, 0x72, + 0x12, 0x12, 0x0a, 0x04, 0x46, 0x69, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, + 0x46, 0x69, 0x6c, 0x65, 0x32, 0xb3, 0x09, 0x0a, 0x0e, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, + 0x79, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x12, 0x3f, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x45, 0x76, + 0x65, 0x6e, 0x74, 0x73, 0x12, 0x13, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x45, 0x76, + 0x65, 0x6e, 0x74, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x1a, 0x19, 0x2e, 0x61, 0x70, 0x69, 0x2e, + 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, 0x57, 0x0a, 0x10, 0x44, 0x75, 0x6d, 0x70, + 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x43, 0x61, 0x63, 0x68, 0x65, 0x12, 0x1b, 0x2e, 0x61, + 0x70, 0x69, 0x2e, 0x44, 0x75, 0x6d, 0x70, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x43, 0x61, + 0x63, 0x68, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x1a, 0x24, 0x2e, 0x61, 0x70, 0x69, 0x2e, + 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x44, 0x75, 0x6d, 0x70, 0x50, 0x72, 0x6f, 0x63, + 0x65, 0x73, 0x73, 0x43, 0x61, 0x63, 0x68, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, + 0x00, 0x12, 0x3f, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x14, + 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x50, 0x61, + 0x72, 0x61, 0x6d, 0x73, 0x1a, 0x1a, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x65, 0x63, 0x75, 0x72, + 0x69, 0x74, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x22, 0x00, 0x12, 0x30, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, + 0x14, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x50, + 0x61, 0x72, 0x61, 0x6d, 0x73, 0x1a, 0x0b, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x22, 0x00, 0x12, 0x4b, 0x0a, 0x0b, 0x52, 0x75, 0x6e, 0x53, 0x65, 0x6c, 0x66, 0x54, + 0x65, 0x73, 0x74, 0x12, 0x16, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x52, 0x75, 0x6e, 0x53, 0x65, 0x6c, + 0x66, 0x54, 0x65, 0x73, 0x74, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x1a, 0x22, 0x2e, 0x61, 0x70, + 0x69, 0x2e, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x53, 0x65, 0x6c, 0x66, 0x54, 0x65, + 0x73, 0x74, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, + 0x00, 0x12, 0x4f, 0x0a, 0x0e, 0x52, 0x65, 0x6c, 0x6f, 0x61, 0x64, 0x50, 0x6f, 0x6c, 0x69, 0x63, + 0x69, 0x65, 0x73, 0x12, 0x19, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x52, 0x65, 0x6c, 0x6f, 0x61, 0x64, + 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x1a, 0x20, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x52, 0x65, 0x6c, 0x6f, 0x61, 0x64, 0x50, 0x6f, 0x6c, 0x69, 0x63, - 0x69, 0x65, 0x73, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x1a, 0x20, 0x2e, 0x61, 0x70, 0x69, 0x2e, - 0x52, 0x65, 0x6c, 0x6f, 0x61, 0x64, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x52, 0x65, - 0x73, 0x75, 0x6c, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x00, 0x12, 0x5b, 0x0a, - 0x14, 0x44, 0x75, 0x6d, 0x70, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x4e, 0x61, 0x6d, 0x65, - 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x1f, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x44, 0x75, 0x6d, 0x70, - 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, - 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x1a, 0x20, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x44, 0x75, 0x6d, - 0x70, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, - 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x00, 0x12, 0x49, 0x0a, 0x0e, 0x44, 0x75, - 0x6d, 0x70, 0x44, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x65, 0x72, 0x73, 0x12, 0x19, 0x2e, 0x61, + 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x22, 0x00, 0x12, 0x5b, 0x0a, 0x14, 0x44, 0x75, 0x6d, 0x70, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, + 0x6b, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x1f, 0x2e, 0x61, 0x70, 0x69, + 0x2e, 0x44, 0x75, 0x6d, 0x70, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x4e, 0x61, 0x6d, 0x65, + 0x73, 0x70, 0x61, 0x63, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x1a, 0x20, 0x2e, 0x61, 0x70, + 0x69, 0x2e, 0x44, 0x75, 0x6d, 0x70, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x4e, 0x61, 0x6d, + 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x00, 0x12, + 0x49, 0x0a, 0x0e, 0x44, 0x75, 0x6d, 0x70, 0x44, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x65, 0x72, + 0x73, 0x12, 0x19, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x44, 0x75, 0x6d, 0x70, 0x44, 0x69, 0x73, 0x63, + 0x61, 0x72, 0x64, 0x65, 0x72, 0x73, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x1a, 0x1a, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x44, 0x75, 0x6d, 0x70, 0x44, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x65, 0x72, - 0x73, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x1a, 0x1a, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x44, 0x75, - 0x6d, 0x70, 0x44, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x65, 0x72, 0x73, 0x4d, 0x65, 0x73, 0x73, - 0x61, 0x67, 0x65, 0x22, 0x00, 0x12, 0x43, 0x0a, 0x0c, 0x44, 0x75, 0x6d, 0x70, 0x41, 0x63, 0x74, - 0x69, 0x76, 0x69, 0x74, 0x79, 0x12, 0x17, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x41, 0x63, 0x74, 0x69, - 0x76, 0x69, 0x74, 0x79, 0x44, 0x75, 0x6d, 0x70, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x1a, 0x18, - 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x44, 0x75, 0x6d, - 0x70, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x00, 0x12, 0x50, 0x0a, 0x11, 0x4c, 0x69, - 0x73, 0x74, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x44, 0x75, 0x6d, 0x70, 0x73, 0x12, - 0x1b, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x44, 0x75, - 0x6d, 0x70, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x1a, 0x1c, 0x2e, 0x61, - 0x70, 0x69, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x44, 0x75, 0x6d, 0x70, 0x4c, - 0x69, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x00, 0x12, 0x4f, 0x0a, 0x10, - 0x53, 0x74, 0x6f, 0x70, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x44, 0x75, 0x6d, 0x70, - 0x12, 0x1b, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x44, - 0x75, 0x6d, 0x70, 0x53, 0x74, 0x6f, 0x70, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x1a, 0x1c, 0x2e, - 0x61, 0x70, 0x69, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x44, 0x75, 0x6d, 0x70, - 0x53, 0x74, 0x6f, 0x70, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x00, 0x12, 0x55, 0x0a, - 0x12, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x12, 0x1d, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x63, - 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x50, 0x61, 0x72, 0x61, - 0x6d, 0x73, 0x1a, 0x1e, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x63, 0x6f, - 0x64, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, - 0x67, 0x65, 0x22, 0x00, 0x12, 0x5a, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x41, 0x63, 0x74, 0x69, 0x76, - 0x69, 0x74, 0x79, 0x44, 0x75, 0x6d, 0x70, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x1d, 0x2e, - 0x61, 0x70, 0x69, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x44, 0x75, 0x6d, 0x70, - 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x1a, 0x1e, 0x2e, 0x61, - 0x70, 0x69, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x44, 0x75, 0x6d, 0x70, 0x53, - 0x74, 0x72, 0x65, 0x61, 0x6d, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x00, 0x30, 0x01, - 0x12, 0x59, 0x0a, 0x14, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, - 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x12, 0x1e, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x53, - 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x4c, 0x69, - 0x73, 0x74, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x1a, 0x1f, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x53, - 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x4c, 0x69, - 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x00, 0x12, 0x58, 0x0a, 0x13, 0x53, - 0x61, 0x76, 0x65, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x66, 0x69, - 0x6c, 0x65, 0x12, 0x1e, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, - 0x79, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x53, 0x61, 0x76, 0x65, 0x50, 0x61, 0x72, 0x61, - 0x6d, 0x73, 0x1a, 0x1f, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, - 0x79, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x53, 0x61, 0x76, 0x65, 0x4d, 0x65, 0x73, 0x73, - 0x61, 0x67, 0x65, 0x22, 0x00, 0x42, 0x18, 0x5a, 0x16, 0x70, 0x6b, 0x67, 0x2f, 0x73, 0x65, 0x63, - 0x75, 0x72, 0x69, 0x74, 0x79, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x61, 0x70, 0x69, 0x62, - 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x73, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x00, 0x12, 0x43, 0x0a, 0x0c, 0x44, 0x75, + 0x6d, 0x70, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x12, 0x17, 0x2e, 0x61, 0x70, 0x69, + 0x2e, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x44, 0x75, 0x6d, 0x70, 0x50, 0x61, 0x72, + 0x61, 0x6d, 0x73, 0x1a, 0x18, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, + 0x74, 0x79, 0x44, 0x75, 0x6d, 0x70, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x00, 0x12, + 0x50, 0x0a, 0x11, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x44, + 0x75, 0x6d, 0x70, 0x73, 0x12, 0x1b, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x76, + 0x69, 0x74, 0x79, 0x44, 0x75, 0x6d, 0x70, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x61, 0x72, 0x61, 0x6d, + 0x73, 0x1a, 0x1c, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, + 0x44, 0x75, 0x6d, 0x70, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, + 0x00, 0x12, 0x4f, 0x0a, 0x10, 0x53, 0x74, 0x6f, 0x70, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, + 0x79, 0x44, 0x75, 0x6d, 0x70, 0x12, 0x1b, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x41, 0x63, 0x74, 0x69, + 0x76, 0x69, 0x74, 0x79, 0x44, 0x75, 0x6d, 0x70, 0x53, 0x74, 0x6f, 0x70, 0x50, 0x61, 0x72, 0x61, + 0x6d, 0x73, 0x1a, 0x1c, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, + 0x79, 0x44, 0x75, 0x6d, 0x70, 0x53, 0x74, 0x6f, 0x70, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x22, 0x00, 0x12, 0x55, 0x0a, 0x12, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x63, 0x6f, 0x64, 0x69, 0x6e, + 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x54, + 0x72, 0x61, 0x6e, 0x73, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x1a, 0x1e, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x54, 0x72, + 0x61, 0x6e, 0x73, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x00, 0x12, 0x5a, 0x0a, 0x15, 0x47, 0x65, 0x74, + 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x44, 0x75, 0x6d, 0x70, 0x53, 0x74, 0x72, 0x65, + 0x61, 0x6d, 0x12, 0x1d, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, + 0x79, 0x44, 0x75, 0x6d, 0x70, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x50, 0x61, 0x72, 0x61, 0x6d, + 0x73, 0x1a, 0x1e, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, + 0x44, 0x75, 0x6d, 0x70, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, 0x59, 0x0a, 0x14, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x65, 0x63, + 0x75, 0x72, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x12, 0x1e, 0x2e, + 0x61, 0x70, 0x69, 0x2e, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x66, + 0x69, 0x6c, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x1a, 0x1f, 0x2e, + 0x61, 0x70, 0x69, 0x2e, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x66, + 0x69, 0x6c, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x00, + 0x12, 0x58, 0x0a, 0x13, 0x53, 0x61, 0x76, 0x65, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, + 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x12, 0x1e, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x65, + 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x53, 0x61, 0x76, + 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x1a, 0x1f, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x65, + 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x53, 0x61, 0x76, + 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x00, 0x42, 0x18, 0x5a, 0x16, 0x70, 0x6b, + 0x67, 0x2f, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x2f, 0x61, 0x70, 0x69, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -2980,52 +2991,53 @@ var file_pkg_security_proto_api_api_proto_depIdxs = []int32{ 20, // 4: api.ActivityDumpParams.Storage:type_name -> api.StorageRequestParams 23, // 5: api.ActivityDumpMessage.Storage:type_name -> api.StorageRequestMessage 22, // 6: api.ActivityDumpMessage.Metadata:type_name -> api.MetadataMessage - 24, // 7: api.ActivityDumpListMessage.Dumps:type_name -> api.ActivityDumpMessage - 20, // 8: api.TranscodingRequestParams.Storage:type_name -> api.StorageRequestParams - 23, // 9: api.TranscodingRequestMessage.Storage:type_name -> api.StorageRequestMessage - 24, // 10: api.ActivityDumpStreamMessage.Dump:type_name -> api.ActivityDumpMessage - 33, // 11: api.SecurityProfileMessage.Selector:type_name -> api.WorkloadSelectorMessage - 34, // 12: api.SecurityProfileMessage.LastAnomalies:type_name -> api.LastAnomalyTimestampMessage - 35, // 13: api.SecurityProfileMessage.Instances:type_name -> api.InstanceMessage - 22, // 14: api.SecurityProfileMessage.Metadata:type_name -> api.MetadataMessage - 36, // 15: api.SecurityProfileMessage.Stats:type_name -> api.ActivityTreeStatsMessage - 37, // 16: api.SecurityProfileListMessage.Profiles:type_name -> api.SecurityProfileMessage - 33, // 17: api.SecurityProfileSaveParams.Selector:type_name -> api.WorkloadSelectorMessage - 0, // 18: api.SecurityModule.GetEvents:input_type -> api.GetEventParams - 2, // 19: api.SecurityModule.DumpProcessCache:input_type -> api.DumpProcessCacheParams - 6, // 20: api.SecurityModule.GetConfig:input_type -> api.GetConfigParams - 12, // 21: api.SecurityModule.GetStatus:input_type -> api.GetStatusParams - 8, // 22: api.SecurityModule.RunSelfTest:input_type -> api.RunSelfTestParams - 9, // 23: api.SecurityModule.ReloadPolicies:input_type -> api.ReloadPoliciesParams - 4, // 24: api.SecurityModule.DumpNetworkNamespace:input_type -> api.DumpNetworkNamespaceParams - 18, // 25: api.SecurityModule.DumpDiscarders:input_type -> api.DumpDiscardersParams - 21, // 26: api.SecurityModule.DumpActivity:input_type -> api.ActivityDumpParams - 25, // 27: api.SecurityModule.ListActivityDumps:input_type -> api.ActivityDumpListParams - 27, // 28: api.SecurityModule.StopActivityDump:input_type -> api.ActivityDumpStopParams - 29, // 29: api.SecurityModule.TranscodingRequest:input_type -> api.TranscodingRequestParams - 31, // 30: api.SecurityModule.GetActivityDumpStream:input_type -> api.ActivityDumpStreamParams - 38, // 31: api.SecurityModule.ListSecurityProfiles:input_type -> api.SecurityProfileListParams - 40, // 32: api.SecurityModule.SaveSecurityProfile:input_type -> api.SecurityProfileSaveParams - 1, // 33: api.SecurityModule.GetEvents:output_type -> api.SecurityEventMessage - 3, // 34: api.SecurityModule.DumpProcessCache:output_type -> api.SecurityDumpProcessCacheMessage - 7, // 35: api.SecurityModule.GetConfig:output_type -> api.SecurityConfigMessage - 15, // 36: api.SecurityModule.GetStatus:output_type -> api.Status - 11, // 37: api.SecurityModule.RunSelfTest:output_type -> api.SecuritySelfTestResultMessage - 10, // 38: api.SecurityModule.ReloadPolicies:output_type -> api.ReloadPoliciesResultMessage - 5, // 39: api.SecurityModule.DumpNetworkNamespace:output_type -> api.DumpNetworkNamespaceMessage - 19, // 40: api.SecurityModule.DumpDiscarders:output_type -> api.DumpDiscardersMessage - 24, // 41: api.SecurityModule.DumpActivity:output_type -> api.ActivityDumpMessage - 26, // 42: api.SecurityModule.ListActivityDumps:output_type -> api.ActivityDumpListMessage - 28, // 43: api.SecurityModule.StopActivityDump:output_type -> api.ActivityDumpStopMessage - 30, // 44: api.SecurityModule.TranscodingRequest:output_type -> api.TranscodingRequestMessage - 32, // 45: api.SecurityModule.GetActivityDumpStream:output_type -> api.ActivityDumpStreamMessage - 39, // 46: api.SecurityModule.ListSecurityProfiles:output_type -> api.SecurityProfileListMessage - 41, // 47: api.SecurityModule.SaveSecurityProfile:output_type -> api.SecurityProfileSaveMessage - 33, // [33:48] is the sub-list for method output_type - 18, // [18:33] is the sub-list for method input_type - 18, // [18:18] is the sub-list for extension type_name - 18, // [18:18] is the sub-list for extension extendee - 0, // [0:18] is the sub-list for field type_name + 36, // 7: api.ActivityDumpMessage.Stats:type_name -> api.ActivityTreeStatsMessage + 24, // 8: api.ActivityDumpListMessage.Dumps:type_name -> api.ActivityDumpMessage + 20, // 9: api.TranscodingRequestParams.Storage:type_name -> api.StorageRequestParams + 23, // 10: api.TranscodingRequestMessage.Storage:type_name -> api.StorageRequestMessage + 24, // 11: api.ActivityDumpStreamMessage.Dump:type_name -> api.ActivityDumpMessage + 33, // 12: api.SecurityProfileMessage.Selector:type_name -> api.WorkloadSelectorMessage + 34, // 13: api.SecurityProfileMessage.LastAnomalies:type_name -> api.LastAnomalyTimestampMessage + 35, // 14: api.SecurityProfileMessage.Instances:type_name -> api.InstanceMessage + 22, // 15: api.SecurityProfileMessage.Metadata:type_name -> api.MetadataMessage + 36, // 16: api.SecurityProfileMessage.Stats:type_name -> api.ActivityTreeStatsMessage + 37, // 17: api.SecurityProfileListMessage.Profiles:type_name -> api.SecurityProfileMessage + 33, // 18: api.SecurityProfileSaveParams.Selector:type_name -> api.WorkloadSelectorMessage + 0, // 19: api.SecurityModule.GetEvents:input_type -> api.GetEventParams + 2, // 20: api.SecurityModule.DumpProcessCache:input_type -> api.DumpProcessCacheParams + 6, // 21: api.SecurityModule.GetConfig:input_type -> api.GetConfigParams + 12, // 22: api.SecurityModule.GetStatus:input_type -> api.GetStatusParams + 8, // 23: api.SecurityModule.RunSelfTest:input_type -> api.RunSelfTestParams + 9, // 24: api.SecurityModule.ReloadPolicies:input_type -> api.ReloadPoliciesParams + 4, // 25: api.SecurityModule.DumpNetworkNamespace:input_type -> api.DumpNetworkNamespaceParams + 18, // 26: api.SecurityModule.DumpDiscarders:input_type -> api.DumpDiscardersParams + 21, // 27: api.SecurityModule.DumpActivity:input_type -> api.ActivityDumpParams + 25, // 28: api.SecurityModule.ListActivityDumps:input_type -> api.ActivityDumpListParams + 27, // 29: api.SecurityModule.StopActivityDump:input_type -> api.ActivityDumpStopParams + 29, // 30: api.SecurityModule.TranscodingRequest:input_type -> api.TranscodingRequestParams + 31, // 31: api.SecurityModule.GetActivityDumpStream:input_type -> api.ActivityDumpStreamParams + 38, // 32: api.SecurityModule.ListSecurityProfiles:input_type -> api.SecurityProfileListParams + 40, // 33: api.SecurityModule.SaveSecurityProfile:input_type -> api.SecurityProfileSaveParams + 1, // 34: api.SecurityModule.GetEvents:output_type -> api.SecurityEventMessage + 3, // 35: api.SecurityModule.DumpProcessCache:output_type -> api.SecurityDumpProcessCacheMessage + 7, // 36: api.SecurityModule.GetConfig:output_type -> api.SecurityConfigMessage + 15, // 37: api.SecurityModule.GetStatus:output_type -> api.Status + 11, // 38: api.SecurityModule.RunSelfTest:output_type -> api.SecuritySelfTestResultMessage + 10, // 39: api.SecurityModule.ReloadPolicies:output_type -> api.ReloadPoliciesResultMessage + 5, // 40: api.SecurityModule.DumpNetworkNamespace:output_type -> api.DumpNetworkNamespaceMessage + 19, // 41: api.SecurityModule.DumpDiscarders:output_type -> api.DumpDiscardersMessage + 24, // 42: api.SecurityModule.DumpActivity:output_type -> api.ActivityDumpMessage + 26, // 43: api.SecurityModule.ListActivityDumps:output_type -> api.ActivityDumpListMessage + 28, // 44: api.SecurityModule.StopActivityDump:output_type -> api.ActivityDumpStopMessage + 30, // 45: api.SecurityModule.TranscodingRequest:output_type -> api.TranscodingRequestMessage + 32, // 46: api.SecurityModule.GetActivityDumpStream:output_type -> api.ActivityDumpStreamMessage + 39, // 47: api.SecurityModule.ListSecurityProfiles:output_type -> api.SecurityProfileListMessage + 41, // 48: api.SecurityModule.SaveSecurityProfile:output_type -> api.SecurityProfileSaveMessage + 34, // [34:49] is the sub-list for method output_type + 19, // [19:34] is the sub-list for method input_type + 19, // [19:19] is the sub-list for extension type_name + 19, // [19:19] is the sub-list for extension extendee + 0, // [0:19] is the sub-list for field type_name } func init() { file_pkg_security_proto_api_api_proto_init() } diff --git a/pkg/security/proto/api/api.proto b/pkg/security/proto/api/api.proto index 821d2ccd6742a..d7a03928b20a1 100644 --- a/pkg/security/proto/api/api.proto +++ b/pkg/security/proto/api/api.proto @@ -139,8 +139,9 @@ message ActivityDumpMessage { repeated string Tags = 4; repeated StorageRequestMessage Storage = 5; MetadataMessage Metadata = 6; - repeated string DNSNames = 8; string Error = 7; + repeated string DNSNames = 8; + ActivityTreeStatsMessage Stats = 9; } message ActivityDumpListParams {} diff --git a/pkg/security/proto/api/api_vtproto.pb.go b/pkg/security/proto/api/api_vtproto.pb.go index 5a7d4c2aff0c9..1aa20c7e6b74c 100644 --- a/pkg/security/proto/api/api_vtproto.pb.go +++ b/pkg/security/proto/api/api_vtproto.pb.go @@ -1319,6 +1319,16 @@ func (m *ActivityDumpMessage) MarshalToSizedBufferVT(dAtA []byte) (int, error) { i -= len(m.unknownFields) copy(dAtA[i:], m.unknownFields) } + if m.Stats != nil { + size, err := m.Stats.MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x4a + } if len(m.DNSNames) > 0 { for iNdEx := len(m.DNSNames) - 1; iNdEx >= 0; iNdEx-- { i -= len(m.DNSNames[iNdEx]) @@ -2823,6 +2833,10 @@ func (m *ActivityDumpMessage) SizeVT() (n int) { n += 1 + l + sov(uint64(l)) } } + if m.Stats != nil { + l = m.Stats.SizeVT() + n += 1 + l + sov(uint64(l)) + } n += len(m.unknownFields) return n } @@ -6419,6 +6433,42 @@ func (m *ActivityDumpMessage) UnmarshalVT(dAtA []byte) error { } m.DNSNames = append(m.DNSNames, string(dAtA[iNdEx:postIndex])) iNdEx = postIndex + case 9: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Stats", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Stats == nil { + m.Stats = &ActivityTreeStatsMessage{} + } + if err := m.Stats.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skip(dAtA[iNdEx:]) diff --git a/pkg/security/security_profile/dump/activity_dump.go b/pkg/security/security_profile/dump/activity_dump.go index 4564bae06e2c3..f4016f48b07d2 100644 --- a/pkg/security/security_profile/dump/activity_dump.go +++ b/pkg/security/security_profile/dump/activity_dump.go @@ -597,7 +597,7 @@ func (ad *ActivityDump) ToSecurityActivityDumpMessage() *api.ActivityDumpMessage } } - return &api.ActivityDumpMessage{ + msg := &api.ActivityDumpMessage{ Host: ad.Host, Source: ad.Source, Service: ad.Service, @@ -620,6 +620,16 @@ func (ad *ActivityDump) ToSecurityActivityDumpMessage() *api.ActivityDumpMessage }, DNSNames: ad.DNSNames.Keys(), } + if ad.ActivityTree != nil { + msg.Stats = &api.ActivityTreeStatsMessage{ + ProcessNodesCount: ad.ActivityTree.Stats.ProcessNodes, + FileNodesCount: ad.ActivityTree.Stats.FileNodes, + DNSNodesCount: ad.ActivityTree.Stats.DNSNodes, + SocketNodesCount: ad.ActivityTree.Stats.SocketNodes, + ApproximateSize: ad.ActivityTree.Stats.ApproximateSize(), + } + } + return msg } // ToTranscodingRequestMessage returns a pointer to a TranscodingRequestMessage From 8fbe9971dc5acec6c080cadfeff7756752a2e07a Mon Sep 17 00:00:00 2001 From: Jonathan Ribas Date: Thu, 8 Jun 2023 12:08:16 +0200 Subject: [PATCH 53/76] fix secprofile unstable guards (#17509) --- pkg/security/security_profile/profile/manager.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pkg/security/security_profile/profile/manager.go b/pkg/security/security_profile/profile/manager.go index af11ab7d25a50..ebcf396f43a09 100644 --- a/pkg/security/security_profile/profile/manager.go +++ b/pkg/security/security_profile/profile/manager.go @@ -692,6 +692,7 @@ func (m *SecurityProfileManager) tryAutolearn(profile *SecurityProfile, event *m profile.lastAnomalyNano[event.GetEventType()] = profile.loadedNano lastAnomalyNano = profile.loadedNano } + if time.Duration(event.TimestampRaw-lastAnomalyNano) >= m.config.RuntimeSecurity.AnomalyDetectionMinimumStablePeriod { return StableProfile } @@ -710,6 +711,9 @@ func (m *SecurityProfileManager) tryAutolearn(profile *SecurityProfile, event *m // check if the unstable size limit was reached if profile.ActivityTree.Stats.ApproximateSize() >= m.config.RuntimeSecurity.AnomalyDetectionUnstableProfileSizeThreshold { + if newEntry, err := profile.ActivityTree.Contains(event, nodeType); err == nil && newEntry { + profile.lastAnomalyNano[event.GetEventType()] = event.TimestampRaw + } m.incrementEventFilteringStat(event.GetEventType(), UnstableProfile, NA) return UnstableProfile } From 0412fa5d57eb4f0aba54878b687ff735feb4bb61 Mon Sep 17 00:00:00 2001 From: Guillaume Fournier <36961134+Gui774ume@users.noreply.github.com> Date: Thu, 8 Jun 2023 12:17:21 +0200 Subject: [PATCH 54/76] use the remote storage from a command line (#17525) --- .../subcommands/runtime/activity_dump.go | 2 +- .../security_profile/dump/storage_manager.go | 22 +++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/cmd/security-agent/subcommands/runtime/activity_dump.go b/cmd/security-agent/subcommands/runtime/activity_dump.go index 201bcb0d49159..6acc0795684ad 100644 --- a/cmd/security-agent/subcommands/runtime/activity_dump.go +++ b/cmd/security-agent/subcommands/runtime/activity_dump.go @@ -349,7 +349,7 @@ func generateEncodingFromActivityDump(log log.Component, config config.Component return fmt.Errorf("couldn't load configuration: %w", err) } - storage, err := dump.NewActivityDumpStorageManager(cfg, nil, nil) + storage, err := dump.NewSecurityAgentCommandStorageManager(cfg) if err != nil { return fmt.Errorf("couldn't instantiate storage manager: %w", err) } diff --git a/pkg/security/security_profile/dump/storage_manager.go b/pkg/security/security_profile/dump/storage_manager.go index 811ba78c413e4..b34466f453305 100644 --- a/pkg/security/security_profile/dump/storage_manager.go +++ b/pkg/security/security_profile/dump/storage_manager.go @@ -59,6 +59,28 @@ func NewSecurityAgentStorageManager() (*ActivityDumpStorageManager, error) { return manager, nil } +// NewSecurityAgentCommandStorageManager returns a new instance of ActivityDumpStorageManager +func NewSecurityAgentCommandStorageManager(cfg *config.Config) (*ActivityDumpStorageManager, error) { + manager := &ActivityDumpStorageManager{ + storages: make(map[config.StorageType]ActivityDumpStorage), + } + + storage, err := NewActivityDumpLocalStorage(cfg) + if err != nil { + return nil, fmt.Errorf("couldn't instantiate storage: %w", err) + } + manager.storages[storage.GetStorageType()] = storage + + // create remote storage + remote, err := NewActivityDumpRemoteStorage() + if err != nil { + return nil, fmt.Errorf("couldn't instantiate remote storage: %w", err) + } + manager.storages[remote.GetStorageType()] = remote + + return manager, nil +} + // NewActivityDumpStorageManager returns a new instance of ActivityDumpStorageManager func NewActivityDumpStorageManager(cfg *config.Config, statsdClient statsd.ClientInterface, handler ActivityDumpHandler) (*ActivityDumpStorageManager, error) { manager := &ActivityDumpStorageManager{ From 846ba2bf5ecd9add606216944a631a748887638f Mon Sep 17 00:00:00 2001 From: Nenad Noveljic <18366081+nenadnoveljic@users.noreply.github.com> Date: Thu, 8 Jun 2023 12:26:31 +0200 Subject: [PATCH 55/76] Adding shared pool monitoring for Oracle databases (#17360) * finished * release notes * relnotes correction * review --- .../conf.d/oracle-dbm.d/conf.yaml.example | 9 ++++ .../corechecks/oracle-dbm/config/config.go | 6 +++ pkg/collector/corechecks/oracle-dbm/oracle.go | 6 +++ .../corechecks/oracle-dbm/processes.go | 8 +-- .../corechecks/oracle-dbm/shared_memory.go | 50 +++++++++++++++++++ .../corechecks/oracle-dbm/sql/setup-rds.sql | 1 + .../corechecks/oracle-dbm/sql/setup.sql | 1 + .../oracle-shared-memoy-06e54ebb7173317b.yaml | 11 ++++ 8 files changed, 88 insertions(+), 4 deletions(-) create mode 100644 pkg/collector/corechecks/oracle-dbm/shared_memory.go create mode 100644 releasenotes/notes/oracle-shared-memoy-06e54ebb7173317b.yaml diff --git a/cmd/agent/dist/conf.d/oracle-dbm.d/conf.yaml.example b/cmd/agent/dist/conf.d/oracle-dbm.d/conf.yaml.example index c22d9bd7ecd41..7326b1e119401 100644 --- a/cmd/agent/dist/conf.d/oracle-dbm.d/conf.yaml.example +++ b/cmd/agent/dist/conf.d/oracle-dbm.d/conf.yaml.example @@ -164,6 +164,15 @@ instances: # # collect_comments: true + ## Configure collection of shared memory usage + # + # shared_memory: + + ## @param enabled - boolean - optional - default: true. Requires `dbm: true`. + ## Enable collection of database shared memory usages + # + # enabled: true + ## @param tags - list of strings - optional ## A list of tags to attach to every metric and service check emitted by this instance. ## diff --git a/pkg/collector/corechecks/oracle-dbm/config/config.go b/pkg/collector/corechecks/oracle-dbm/config/config.go index 930bd9ba826f4..e1fe070272235 100644 --- a/pkg/collector/corechecks/oracle-dbm/config/config.go +++ b/pkg/collector/corechecks/oracle-dbm/config/config.go @@ -43,6 +43,10 @@ type ProcessMemoryConfig struct { Enabled bool `yaml:"enabled"` } +type SharedMemoryConfig struct { + Enabled bool `yaml:"enabled"` +} + type ExecutionPlansConfig struct { Enabled bool `yaml:"enabled"` } @@ -74,6 +78,7 @@ type InstanceConfig struct { SysMetrics SysMetricsConfig `yaml:"sysmetrics"` Tablespaces TablespacesConfig `yaml:"tablespaces"` ProcessMemory ProcessMemoryConfig `yaml:"process_memory"` + SharedMemory SharedMemoryConfig `yaml:"shared_memory"` ExecutionPlans ExecutionPlansConfig `yaml:"execution_plans"` AgentSQLTrace AgentSQLTrace `yaml:"agent_sql_trace"` } @@ -110,6 +115,7 @@ func NewCheckConfig(rawInstance integration.Data, rawInitConfig integration.Data instance.SysMetrics.Enabled = true instance.Tablespaces.Enabled = true instance.ProcessMemory.Enabled = true + instance.SharedMemory.Enabled = true // Defaults end if err := yaml.Unmarshal(rawInstance, &instance); err != nil { diff --git a/pkg/collector/corechecks/oracle-dbm/oracle.go b/pkg/collector/corechecks/oracle-dbm/oracle.go index 8ecfffe5b4e7b..d1af9bc5350c5 100644 --- a/pkg/collector/corechecks/oracle-dbm/oracle.go +++ b/pkg/collector/corechecks/oracle-dbm/oracle.go @@ -116,6 +116,12 @@ func (c *Check) Run() error { } } } + if c.config.SharedMemory.Enabled { + err := c.SharedMemory() + if err != nil { + return err + } + } } if c.config.AgentSQLTrace.Enabled { diff --git a/pkg/collector/corechecks/oracle-dbm/processes.go b/pkg/collector/corechecks/oracle-dbm/processes.go index 6daa24c7aa9da..9e5d27fe8f190 100644 --- a/pkg/collector/corechecks/oracle-dbm/processes.go +++ b/pkg/collector/corechecks/oracle-dbm/processes.go @@ -51,10 +51,10 @@ func (c *Check) ProcessMemory() error { if r.Program.Valid { tags = append(tags, "program:"+r.Program.String) } - sender.Gauge(fmt.Sprintf("%s.process.pga_used_mem", common.IntegrationName), r.PGAUsedMem, "", tags) - sender.Gauge(fmt.Sprintf("%s.process.pga_alloc_mem", common.IntegrationName), r.PGAAllocMem, "", tags) - sender.Gauge(fmt.Sprintf("%s.process.pga_freeable_mem", common.IntegrationName), r.PGAFreeableMem, "", tags) - sender.Gauge(fmt.Sprintf("%s.process.pga_max_mem", common.IntegrationName), r.PGAMaxMem, "", tags) + sender.Gauge(fmt.Sprintf("%s.process.pga_used_memory", common.IntegrationName), r.PGAUsedMem, "", tags) + sender.Gauge(fmt.Sprintf("%s.process.pga_allocated_memory", common.IntegrationName), r.PGAAllocMem, "", tags) + sender.Gauge(fmt.Sprintf("%s.process.pga_freeable_memory", common.IntegrationName), r.PGAFreeableMem, "", tags) + sender.Gauge(fmt.Sprintf("%s.process.pga_max_memory", common.IntegrationName), r.PGAMaxMem, "", tags) } sender.Commit() return nil diff --git a/pkg/collector/corechecks/oracle-dbm/shared_memory.go b/pkg/collector/corechecks/oracle-dbm/shared_memory.go new file mode 100644 index 0000000000000..7934020942d7e --- /dev/null +++ b/pkg/collector/corechecks/oracle-dbm/shared_memory.go @@ -0,0 +1,50 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2016-present Datadog, Inc. + +package oracle + +import ( + "database/sql" + "fmt" + "strings" + + "github.com/DataDog/datadog-agent/pkg/collector/corechecks/oracle-dbm/common" +) + +const QUERY_SHM = `SELECT + c.name pdb_name, s.name, ROUND(bytes/1024/1024,2) size_ + FROM v$sgainfo s, v$containers c + WHERE + c.con_id(+) = s.con_id + AND s.name NOT IN ('Maximum SGA Size','Startup overhead in Shared Pool','Granule Size','Shared IO Pool Size') +` + +type SHMRow struct { + PdbName sql.NullString `db:"PDB_NAME"` + Memory string `db:"NAME"` + Size float64 `db:"SIZE_"` +} + +func (c *Check) SharedMemory() error { + rows := []SHMRow{} + err := c.db.Select(&rows, QUERY_SHM) + if err != nil { + return fmt.Errorf("failed to collect shared memory info: %w", err) + } + sender, err := c.GetSender() + if err != nil { + return fmt.Errorf("failed to initialize sender: %w", err) + } + for _, r := range rows { + tags := appendPDBTag(c.tags, r.PdbName) + memoryTag := strings.ReplaceAll(r.Memory, " ", "_") + memoryTag = strings.ToLower(memoryTag) + memoryTag = strings.ReplaceAll(memoryTag, "_size", "") + tags = append(tags, fmt.Sprintf("memory:%s", memoryTag)) + sender.Gauge(fmt.Sprintf("%s.shared_memory.size", common.IntegrationName), r.Size, "", tags) + } + sender.Commit() + return nil +} diff --git a/pkg/collector/corechecks/oracle-dbm/sql/setup-rds.sql b/pkg/collector/corechecks/oracle-dbm/sql/setup-rds.sql index 0234da956da10..758544db3cc7f 100644 --- a/pkg/collector/corechecks/oracle-dbm/sql/setup-rds.sql +++ b/pkg/collector/corechecks/oracle-dbm/sql/setup-rds.sql @@ -20,3 +20,4 @@ exec rdsadmin.rdsadmin_util.grant_sys_object('CDB_TABLESPACE_USAGE_METRICS','DAT exec rdsadmin.rdsadmin_util.grant_sys_object('CDB_TABLESPACES','DATADOG','SELECT',p_grant_option => false); exec rdsadmin.rdsadmin_util.grant_sys_object('V_$SQLCOMMAND','DATADOG','SELECT',p_grant_option => false); exec rdsadmin.rdsadmin_util.grant_sys_object('V_$DATAFILE','DATADOG','SELECT',p_grant_option => false); +exec rdsadmin.rdsadmin_util.grant_sys_object('V_$SGAINFO','DATADOG','SELECT',p_grant_option => false); diff --git a/pkg/collector/corechecks/oracle-dbm/sql/setup.sql b/pkg/collector/corechecks/oracle-dbm/sql/setup.sql index 541a10c51f534..81eb8b38fa6db 100644 --- a/pkg/collector/corechecks/oracle-dbm/sql/setup.sql +++ b/pkg/collector/corechecks/oracle-dbm/sql/setup.sql @@ -19,6 +19,7 @@ grant select on v_$con_sysmetric to c##datadog ; grant select on cdb_tablespace_usage_metrics to c##datadog ; grant select on cdb_tablespaces to c##datadog ; grant select on v_$process to c##datadog ; +grant select on v_$sgainfo to c##datadog ; CREATE OR REPLACE VIEW dd_session AS SELECT diff --git a/releasenotes/notes/oracle-shared-memoy-06e54ebb7173317b.yaml b/releasenotes/notes/oracle-shared-memoy-06e54ebb7173317b.yaml new file mode 100644 index 0000000000000..fc0561e7ee4f6 --- /dev/null +++ b/releasenotes/notes/oracle-shared-memoy-06e54ebb7173317b.yaml @@ -0,0 +1,11 @@ +# Each section from every release note are combined when the +# CHANGELOG.rst is rendered. So the text needs to be worded so that +# it does not depend on any information only available in another +# section. This may mean repeating some details, but each section +# must be readable independently of the other. +# +# Each section note must be formatted as reStructuredText. +--- +features: + - | + Add shared memory (a.k.a. system global area - SGA) metric for Oracle databases: `oracle.shared_memory.size` From 97ce0719ec97e7a7777eddb55c7d1b737cd31f1a Mon Sep 17 00:00:00 2001 From: Nenad Noveljic <18366081+nenadnoveljic@users.noreply.github.com> Date: Thu, 8 Jun 2023 12:28:05 +0200 Subject: [PATCH 56/76] Adding more sysmetrics to Oracle monitoring (#17466) * both metrics * send only 60s interval for sysmetrics * latency & refactoring * bg cpu usage * indexes * io * more metrics * new metrics * metrics * completed * completed * release notes * disable cursor cache hit ratio --- pkg/collector/corechecks/oracle-dbm/oracle.go | 4 +- .../corechecks/oracle-dbm/sql/setup-rds.sql | 1 + .../corechecks/oracle-dbm/sql/setup.sql | 1 + .../corechecks/oracle-dbm/sysmetrics.go | 156 ++++++++++++++---- .../add-sysmetrics-ec02c963203c26d6.yaml | 19 +++ 5 files changed, 148 insertions(+), 33 deletions(-) create mode 100644 releasenotes/notes/add-sysmetrics-ec02c963203c26d6.yaml diff --git a/pkg/collector/corechecks/oracle-dbm/oracle.go b/pkg/collector/corechecks/oracle-dbm/oracle.go index d1af9bc5350c5..7806734d146bc 100644 --- a/pkg/collector/corechecks/oracle-dbm/oracle.go +++ b/pkg/collector/corechecks/oracle-dbm/oracle.go @@ -26,6 +26,7 @@ import ( var MAX_OPEN_CONNECTIONS = 10 var DEFAULT_SQL_TRACED_RUNS = 10 + var DB_TIMEOUT = "20000" // The structure is filled by activity sampling and serves as a filter for query metrics @@ -85,9 +86,10 @@ func (c *Check) Run() error { } if c.config.SysMetrics.Enabled { + log.Trace("Entered sysmetrics") err := c.SysMetrics() if err != nil { - return err + return fmt.Errorf("failed to collecr sysmetrics %w", err) } } if c.config.Tablespaces.Enabled { diff --git a/pkg/collector/corechecks/oracle-dbm/sql/setup-rds.sql b/pkg/collector/corechecks/oracle-dbm/sql/setup-rds.sql index 758544db3cc7f..0071b992e6811 100644 --- a/pkg/collector/corechecks/oracle-dbm/sql/setup-rds.sql +++ b/pkg/collector/corechecks/oracle-dbm/sql/setup-rds.sql @@ -16,6 +16,7 @@ exec rdsadmin.rdsadmin_util.grant_sys_object('DBA_FEATURE_USAGE_STATISTICS','DAT exec rdsadmin.rdsadmin_util.grant_sys_object('V_$PROCESS','DATADOG','SELECT',p_grant_option => false); exec rdsadmin.rdsadmin_util.grant_sys_object('V_$SESSION','DATADOG','SELECT',p_grant_option => false); exec rdsadmin.rdsadmin_util.grant_sys_object('V_$CON_SYSMETRIC','DATADOG','SELECT',p_grant_option => false); +exec rdsadmin.rdsadmin_util.grant_sys_object('V_$SYSMETRIC','DATADOG','SELECT',p_grant_option => false); exec rdsadmin.rdsadmin_util.grant_sys_object('CDB_TABLESPACE_USAGE_METRICS','DATADOG','SELECT',p_grant_option => false); exec rdsadmin.rdsadmin_util.grant_sys_object('CDB_TABLESPACES','DATADOG','SELECT',p_grant_option => false); exec rdsadmin.rdsadmin_util.grant_sys_object('V_$SQLCOMMAND','DATADOG','SELECT',p_grant_option => false); diff --git a/pkg/collector/corechecks/oracle-dbm/sql/setup.sql b/pkg/collector/corechecks/oracle-dbm/sql/setup.sql index 81eb8b38fa6db..943e18832df62 100644 --- a/pkg/collector/corechecks/oracle-dbm/sql/setup.sql +++ b/pkg/collector/corechecks/oracle-dbm/sql/setup.sql @@ -16,6 +16,7 @@ grant select on v_$sql_plan_statistics_all to c##datadog ; grant select on dba_feature_usage_statistics to c##datadog ; grant select on v_$datafile to c##datadog ; grant select on v_$con_sysmetric to c##datadog ; +grant select on v_$sysmetric to c##datadog ; grant select on cdb_tablespace_usage_metrics to c##datadog ; grant select on cdb_tablespaces to c##datadog ; grant select on v_$process to c##datadog ; diff --git a/pkg/collector/corechecks/oracle-dbm/sysmetrics.go b/pkg/collector/corechecks/oracle-dbm/sysmetrics.go index e3a834fce7ee8..0c7eda54f1908 100644 --- a/pkg/collector/corechecks/oracle-dbm/sysmetrics.go +++ b/pkg/collector/corechecks/oracle-dbm/sysmetrics.go @@ -9,59 +9,151 @@ import ( "database/sql" "fmt" + "github.com/DataDog/datadog-agent/pkg/aggregator" "github.com/DataDog/datadog-agent/pkg/collector/corechecks/oracle-dbm/common" + "github.com/DataDog/datadog-agent/pkg/trace/log" ) -const SYSMETRICS_QUERY = "SELECT metric_name, value, name pdb_name FROM v$con_sysmetric s, v$containers c WHERE s.con_id = c.con_id(+)" +const SYSMETRICS_QUERY = `SELECT + metric_name, + value, + metric_unit, + --(end_time - begin_time)*24*3600 interval_length, + name pdb_name + FROM %s s, v$containers c + WHERE s.con_id = c.con_id(+)` + +const ( + Count int = 0 +) type SysmetricsRowDB struct { MetricName string `db:"METRIC_NAME"` Value float64 `db:"VALUE"` + MetricUnit string `db:"METRIC_UNIT"` PdbName sql.NullString `db:"PDB_NAME"` } +type sysMetricsDefinition struct { + DDmetric string + DBM bool +} + +var SYSMETRICS_COLS = map[string]sysMetricsDefinition{ + "Average Active Sessions": {DDmetric: "active_sessions"}, + "Average Synchronous Single-Block Read Latency": {DDmetric: "avg_synchronous_single_block_read_latency", DBM: true}, + "Background CPU Usage Per Sec": {DDmetric: "active_background_on_cpu", DBM: true}, + "Background Time Per Sec": {DDmetric: "active_background", DBM: true}, + "Branch Node Splits Per Sec": {DDmetric: "branch_node_splits", DBM: true}, + "Buffer Cache Hit Ratio": {DDmetric: "buffer_cachehit_ratio"}, + "Consistent Read Changes Per Sec": {DDmetric: "consistent_read_changes", DBM: true}, + "Consistent Read Gets Per Sec": {DDmetric: "consistent_read_gets", DBM: true}, + "CPU Usage Per Sec": {DDmetric: "active_sessions_on_cpu", DBM: true}, + "Current OS Load": {DDmetric: "os_load", DBM: true}, + //"Cursor Cache Hit Ratio": {DDmetric: "cursor_cachehit_ratio"}, + "Database CPU Time Ratio": {DDmetric: "database_cpu_time_ratio", DBM: true}, + "Database Wait Time Ratio": {DDmetric: "database_wait_time_ratio"}, + "DB Block Changes Per Sec": {DDmetric: "db_block_changes", DBM: true}, + "DB Block Gets Per Sec": {DDmetric: "db_block_gets", DBM: true}, + "DBWR Checkpoints Per Sec": {DDmetric: "dbwr_checkpoints", DBM: true}, + "Disk Sort Per Sec": {DDmetric: "disk_sorts"}, + "Enqueue Deadlocks Per Sec": {DDmetric: "enqueue_deadlocks", DBM: true}, + "Enqueue Timeouts Per Sec": {DDmetric: "enqueue_timeouts"}, + "Execute Without Parse Ratio": {DDmetric: "execute_without_parse", DBM: true}, + "GC CR Block Received Per Second": {DDmetric: "gc_cr_block_received"}, + "GC Current Block Received Per Second": {DDmetric: "gc_current_block_received", DBM: true}, + "Global Cache Average CR Get Time": {DDmetric: "gc_average_cr_get_time", DBM: true}, + "Global Cache Average Current Get Time": {DDmetric: "gc_average_current_get_time", DBM: true}, + "Global Cache Blocks Corrupted": {DDmetric: "cache_blocks_corrupt"}, + "Global Cache Blocks Lost": {DDmetric: "cache_blocks_lost"}, + "Hard Parse Count Per Sec": {DDmetric: "hard_parses", DBM: true}, + "Host CPU Utilization (%)": {DDmetric: "host_cpu_utilization", DBM: true}, + "Leaf Node Splits Per Sec": {DDmetric: "leaf_nodes_splits", DBM: true}, + "Library Cache Hit Ratio": {DDmetric: "library_cachehit_ratio"}, + "Logical Reads Per Sec": {DDmetric: "logical_reads", DBM: true}, + "Logons Per Sec": {DDmetric: "logons"}, + "Long Table Scans Per Sec": {DDmetric: "long_table_scans"}, + "Memory Sorts Ratio": {DDmetric: "memory_sorts_ratio"}, + "Network Traffic Volume Per Sec": {DDmetric: "network_traffic_volume", DBM: true}, + "PGA Cache Hit %": {DDmetric: "pga_cache_hit", DBM: true}, + "Parse Failure Count Per Sec": {DDmetric: "parse_failures", DBM: true}, + "Physical Read Bytes Per Sec": {DDmetric: "physical_read_bytes", DBM: true}, + "Physical Read IO Requests Per Sec": {DDmetric: "physical_read_io_requests", DBM: true}, + "Physical Read Total IO Requests Per Sec": {DDmetric: "physical_read_total_io_requests", DBM: true}, + "Physical Reads Direct Lobs Per Sec": {DDmetric: "physical_reads_direct_lobs", DBM: true}, + "Physical Read Total Bytes Per Sec": {DDmetric: "physical_read_total_bytes", DBM: true}, + "Physical Reads Direct Per Sec": {DDmetric: "physical_reads_direct", DBM: true}, + "Physical Reads Per Sec": {DDmetric: "physical_reads"}, + "Physical Write Bytes Per Sec": {DDmetric: "physical_write_bytes", DBM: true}, + "Physical Write IO Requests Per Sec": {DDmetric: "physical_write_io_requests", DBM: true}, + "Physical Write Total Bytes Per Sec": {DDmetric: "physical_write_total_bytes", DBM: true}, + "Physical Write Total IO Requests Per Sec": {DDmetric: "physical_write_total_io_requests", DBM: true}, + "Physical Writes Direct Lobs Per Sec": {DDmetric: "physical_writes_direct_lobs", DBM: true}, + "Physical Writes Direct Per Sec": {DDmetric: "physical_writes_direct", DBM: true}, + "Physical Writes Per Sec": {DDmetric: "physical_writes"}, + "Process Limit %": {DDmetric: "process_limit", DBM: true}, + "Redo Allocation Hit Ratio": {DDmetric: "redo_allocation_hit_ratio", DBM: true}, + "Redo Generated Per Sec": {DDmetric: "redo_generated", DBM: true}, + "Redo Writes Per Sec": {DDmetric: "redo_writes", DBM: true}, + "Row Cache Hit Ratio": {DDmetric: "row_cache_hit_ratio", DBM: true}, + "Rows Per Sort": {DDmetric: "rows_per_sort"}, + "SQL Service Response Time": {DDmetric: "service_response_time"}, + "Session Count": {DDmetric: "session_count"}, + "Session Limit %": {DDmetric: "session_limit_usage"}, + "Shared Pool Free %": {DDmetric: "shared_pool_free"}, + "Soft Parse Ratio": {DDmetric: "soft_parse_ratio", DBM: true}, + "Temp Space Used": {DDmetric: "temp_space_used"}, + "Total Parse Count Per Sec": {DDmetric: "total_parse_count", DBM: true}, + "Total Sorts Per User Call": {DDmetric: "sorts_per_user_call"}, + "User Commits Per Sec": {DDmetric: "user_commits", DBM: true}, + "User Rollbacks Per Sec": {DDmetric: "user_rollbacks"}, +} + +func (c *Check) sendMetric(s aggregator.Sender, r SysmetricsRowDB, seen map[string]bool) { + if metric, ok := SYSMETRICS_COLS[r.MetricName]; ok { + value := r.Value + if r.MetricUnit == "CentiSeconds Per Second" { + value = value / 100 + } + if !SYSMETRICS_COLS[r.MetricName].DBM || SYSMETRICS_COLS[r.MetricName].DBM && c.dbmEnabled { + log.Tracef("%s: %f", metric.DDmetric, value) + s.Gauge(fmt.Sprintf("%s.%s", common.IntegrationName, metric.DDmetric), value, "", appendPDBTag(c.tags, r.PdbName)) + seen[r.MetricName] = true + } + } +} + func (c *Check) SysMetrics() error { - SYSMETRICS_COLS := map[string]string{ - "Buffer Cache Hit Ratio": "buffer_cachehit_ratio", - "Cursor Cache Hit Ratio": "cursor_cachehit_ratio", - "Library Cache Hit Ratio": "library_cachehit_ratio", - "Shared Pool Free %": "shared_pool_free", - "Physical Reads Per Sec": "physical_reads", - "Physical Writes Per Sec": "physical_writes", - "Enqueue Timeouts Per Sec": "enqueue_timeouts", - "GC CR Block Received Per Second": "gc_cr_block_received", - "Global Cache Blocks Corrupted": "cache_blocks_corrupt", - "Global Cache Blocks Lost": "cache_blocks_lost", - "Logons Per Sec": "logons", - "Average Active Sessions": "active_sessions", - "Long Table Scans Per Sec": "long_table_scans", - "SQL Service Response Time": "service_response_time", - "User Rollbacks Per Sec": "user_rollbacks", - "Total Sorts Per User Call": "sorts_per_user_call", - "Rows Per Sort": "rows_per_sort", - "Disk Sort Per Sec": "disk_sorts", - "Memory Sorts Ratio": "memory_sorts_ratio", - "Database Wait Time Ratio": "database_wait_time_ratio", - "Session Limit %": "session_limit_usage", - "Session Count": "session_count", - "Temp Space Used": "temp_space_used", + sender, err := c.GetSender() + if err != nil { + return fmt.Errorf("failed to initialize sender: %w", err) } metricRows := []SysmetricsRowDB{} - err := c.db.Select(&metricRows, SYSMETRICS_QUERY) - + err = c.db.Select(&metricRows, fmt.Sprintf(SYSMETRICS_QUERY, "v$con_sysmetric")) if err != nil { - return fmt.Errorf("failed to collect sysmetrics: %w", err) + return fmt.Errorf("failed to collect container sysmetrics: %w", err) } - sender, err := c.GetSender() + seenInContainerMetrics := make(map[string]bool) + for _, r := range metricRows { + c.sendMetric(sender, r, seenInContainerMetrics) + } + + seenInGlobalMetrics := make(map[string]bool) + err = c.db.Select(&metricRows, fmt.Sprintf(SYSMETRICS_QUERY, "v$sysmetric")+" ORDER BY begin_time ASC, metric_name ASC") if err != nil { - return fmt.Errorf("failed to initialize sender: %w", err) + return fmt.Errorf("failed to collect sysmetrics: %w", err) } for _, r := range metricRows { - if metric, ok := SYSMETRICS_COLS[r.MetricName]; ok { - sender.Gauge(fmt.Sprintf("%s.%s", common.IntegrationName, metric), r.Value, "", appendPDBTag(c.tags, r.PdbName)) + if _, ok := seenInContainerMetrics[r.MetricName]; !ok { + if _, ok := seenInGlobalMetrics[r.MetricName]; ok { + break + } else { + c.sendMetric(sender, r, seenInGlobalMetrics) + } } } + sender.Commit() return nil } diff --git a/releasenotes/notes/add-sysmetrics-ec02c963203c26d6.yaml b/releasenotes/notes/add-sysmetrics-ec02c963203c26d6.yaml new file mode 100644 index 0000000000000..6e0783529aea7 --- /dev/null +++ b/releasenotes/notes/add-sysmetrics-ec02c963203c26d6.yaml @@ -0,0 +1,19 @@ +# Each section from every release note are combined when the +# CHANGELOG.rst is rendered. So the text needs to be worded so that +# it does not depend on any information only available in another +# section. This may mean repeating some details, but each section +# must be readable independently of the other. +# +# Each section note must be formatted as reStructuredText. +--- +enhancements: + - | + Add the following sysmetrics to improve DBA/SRE/SE perspective: + avg_synchronous_single_block_read_latency, active_background_on_cpu, active_background, branch_node_splits, consistent_read_changes, + consistent_read_gets, active_sessions_on_cpu, os_load, database_cpu_time_ratio, db_block_changes, db_block_gets, dbwr_checkpoints, + enqueue_deadlocks, execute_without_parse, gc_current_block_received, gc_average_cr_get_time, gc_average_current_get_time, + hard_parses, host_cpu_utilization, leaf_nodes_splits, logical_reads, network_traffic_volume, pga_cache_hit, parse_failures, + physical_read_bytes, physical_read_io_requests, physical_read_total_io_requests, physical_reads_direct_lobs, + physical_read_total_bytes, physical_reads_direct, physical_write_bytes, physical_write_io_requests, physical_write_total_bytes, + physical_write_total_io_requests, physical_writes_direct_lobs, physical_writes_direct, process_limit, redo_allocation_hit_ratio, + redo_generated, redo_writes, row_cache_hit_ratio, soft_parse_ratio, total_parse_count, user_commits From 98acb701c650b16c8e45f427c91a421748a92998 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Momar=20TOUR=C3=89?= <36661127+mftoure@users.noreply.github.com> Date: Thu, 8 Jun 2023 14:09:58 +0200 Subject: [PATCH 57/76] Revert "[CWS][SEC-3735] Check self tests results in e2e tests (#17387)" (#17526) This reverts commit e83efae53b0554a45557fa1b5f3e7e2f378502f4. --- test/e2e/cws-tests/tests/test_e2e_cws_docker.py | 10 ---------- test/e2e/cws-tests/tests/test_e2e_cws_kubernetes.py | 10 ---------- 2 files changed, 20 deletions(-) diff --git a/test/e2e/cws-tests/tests/test_e2e_cws_docker.py b/test/e2e/cws-tests/tests/test_e2e_cws_docker.py index 589b356197098..7756c867a3e1e 100644 --- a/test/e2e/cws-tests/tests/test_e2e_cws_docker.py +++ b/test/e2e/cws-tests/tests/test_e2e_cws_docker.py @@ -126,16 +126,6 @@ def test_open_signal(self): self.fail("check ruleset_loaded timeouted") self.app.check_for_ignored_policies(self, attributes) - with Step(msg="check self_tests", emoji=":test_tube:"): - rule_id = "self_test" - event = self.app.wait_app_log(f"rule_id:{rule_id}") - attributes = event["data"][0]["attributes"]["attributes"] - self.assertEqual(rule_id, attributes["agent"]["rule_id"], "unable to find rule_id tag attribute") - self.assertTrue( - "failed_tests" not in attributes, - f"failed tests: {attributes['failed_tests']}" if "failed_tests" in attributes else "success", - ) - with Step(msg="wait for host tags (3m)", emoji=":alarm_clock:"): time.sleep(3 * 60) diff --git a/test/e2e/cws-tests/tests/test_e2e_cws_kubernetes.py b/test/e2e/cws-tests/tests/test_e2e_cws_kubernetes.py index 27521b0770589..228c877dc6866 100644 --- a/test/e2e/cws-tests/tests/test_e2e_cws_kubernetes.py +++ b/test/e2e/cws-tests/tests/test_e2e_cws_kubernetes.py @@ -133,16 +133,6 @@ def test_open_signal(self): self.fail("check ruleset_loaded timeouted") self.app.check_for_ignored_policies(self, attributes) - with Step(msg="check self_tests", emoji=":test_tube:"): - rule_id = "self_test" - event = self.app.wait_app_log(f"rule_id:{rule_id}") - attributes = event["data"][0]["attributes"]["attributes"] - self.assertEqual(rule_id, attributes["agent"]["rule_id"], "unable to find rule_id tag attribute") - self.assertTrue( - "failed_tests" not in attributes, - f"failed tests: {attributes['failed_tests']}" if "failed_tests" in attributes else "success", - ) - with Step(msg="wait for datadog.security_agent.runtime.running metric", emoji="\N{beer mug}"): self.app.wait_for_metric("datadog.security_agent.runtime.running", host=TestE2EKubernetes.hostname) From f4ed6fcded04c4b6c8edaebe261956816b659750 Mon Sep 17 00:00:00 2001 From: Guillaume Fournier <36961134+Gui774ume@users.noreply.github.com> Date: Thu, 8 Jun 2023 14:56:24 +0200 Subject: [PATCH 58/76] MetricSecurityProfileAnomalyDetectionGenerated tracks the number of generated anomalies (#17462) --- pkg/security/metrics/metrics.go | 4 ++-- pkg/security/probe/probe_linux.go | 24 ++++++++++++------------ 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/pkg/security/metrics/metrics.go b/pkg/security/metrics/metrics.go index 1c0d115e1d9f3..65f814acf6c3e 100644 --- a/pkg/security/metrics/metrics.go +++ b/pkg/security/metrics/metrics.go @@ -253,9 +253,9 @@ var ( // MetricSecurityProfileCacheMiss is the name of the metric used to report the count of Security Profile cache misses // Tags: - MetricSecurityProfileCacheMiss = newRuntimeMetric(".security_profile.cache.miss") - // MetricSecurityProfileAnomalyDetectionSent + // MetricSecurityProfileAnomalyDetectionGenerated // Tags: event_type - MetricSecurityProfileAnomalyDetectionSent = newRuntimeMetric(".security_profile.anomaly_detection.sent") + MetricSecurityProfileAnomalyDetectionGenerated = newRuntimeMetric(".security_profile.anomaly_detection.generated") // MetricSecurityProfileEventFiltering // Tags: event_type, profile_state ('no_profile', 'unstable', 'unstable_event_type', 'stable', 'auto_learning', 'workload_warmup'), in_profile ('true', 'false' or none) MetricSecurityProfileEventFiltering = newRuntimeMetric(".security_profile.evaluation.hit") diff --git a/pkg/security/probe/probe_linux.go b/pkg/security/probe/probe_linux.go index 2b06639c0d67c..6fbc381b1cd88 100644 --- a/pkg/security/probe/probe_linux.go +++ b/pkg/security/probe/probe_linux.go @@ -105,7 +105,7 @@ type PlatformProbe struct { approvers map[eval.EventType]kfilters.ActiveApprovers // Events section - anomalyDetectionSent map[model.EventType]*atomic.Uint64 + generatedAnomalyDetection map[model.EventType]*atomic.Uint64 // Approvers / discarders section notifyDiscarderPushedCallbacksLock sync.Mutex @@ -335,7 +335,7 @@ func (p *Probe) sendAnomalyDetection(event *model.Event) { events.NewCustomRule(events.AnomalyDetectionRuleID, events.AnomalyDetectionRuleDesc), events.NewCustomEventLazy(event.GetEventType(), p.EventMarshallerCtor(event), tags...), ) - p.anomalyDetectionSent[event.GetEventType()].Inc() + p.generatedAnomalyDetection[event.GetEventType()].Inc() } func (p *Probe) handleAnomalyDetection(event *model.Event) bool { @@ -433,11 +433,11 @@ func traceEvent(fmt string, marshaller func() ([]byte, model.EventType, error)) func (p *Probe) SendStats() error { p.resolvers.TCResolver.SendTCProgramsStats(p.StatsdClient) - for evtType, count := range p.anomalyDetectionSent { + for evtType, count := range p.generatedAnomalyDetection { tags := []string{fmt.Sprintf("event_type:%s", evtType)} if value := count.Swap(0); value > 0 { - if err := p.StatsdClient.Count(metrics.MetricSecurityProfileAnomalyDetectionSent, int64(value), tags, 1.0); err != nil { - return fmt.Errorf("couldn't send MetricSecurityProfileAnomalyDetectionSent metric: %w", err) + if err := p.StatsdClient.Count(metrics.MetricSecurityProfileAnomalyDetectionGenerated, int64(value), tags, 1.0); err != nil { + return fmt.Errorf("couldn't send MetricSecurityProfileAnomalyDetectionGenerated metric: %w", err) } } } @@ -1428,19 +1428,19 @@ func NewProbe(config *config.Config, opts Opts) (*Probe, error) { StatsdClient: opts.StatsdClient, discarderRateLimiter: rate.NewLimiter(rate.Every(time.Second/5), 100), PlatformProbe: PlatformProbe{ - approvers: make(map[eval.EventType]kfilters.ActiveApprovers), - managerOptions: ebpf.NewDefaultOptions(), - Erpc: nerpc, - erpcRequest: &erpc.ERPCRequest{}, - isRuntimeDiscarded: !opts.DontDiscardRuntime, - anomalyDetectionSent: make(map[model.EventType]*atomic.Uint64), + approvers: make(map[eval.EventType]kfilters.ActiveApprovers), + managerOptions: ebpf.NewDefaultOptions(), + Erpc: nerpc, + erpcRequest: &erpc.ERPCRequest{}, + isRuntimeDiscarded: !opts.DontDiscardRuntime, + generatedAnomalyDetection: make(map[model.EventType]*atomic.Uint64), }, } p.event = NewEvent(p.fieldHandlers) for i := model.EventType(0); i < model.MaxKernelEventType; i++ { - p.anomalyDetectionSent[i] = atomic.NewUint64(0) + p.generatedAnomalyDetection[i] = atomic.NewUint64(0) } if err := p.detectKernelVersion(); err != nil { From d23cd148a2f7742a68aebaabfcab3c016f7e301b Mon Sep 17 00:00:00 2001 From: Yoann Ghigoff Date: Thu, 8 Jun 2023 15:04:09 +0200 Subject: [PATCH 59/76] [CWS] fix race when playing snapshot process data (#17527) --- pkg/security/probe/probe_linux.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkg/security/probe/probe_linux.go b/pkg/security/probe/probe_linux.go index 6fbc381b1cd88..e041e17ceaafb 100644 --- a/pkg/security/probe/probe_linux.go +++ b/pkg/security/probe/probe_linux.go @@ -310,6 +310,7 @@ func (p *Probe) PlaySnapshot() { if entry.Source != model.ProcessCacheEntryFromProcFS { return } + entry.Retain() event := NewEvent(p.fieldHandlers) event.Type = uint32(model.ExecEventType) event.TimestampRaw = uint64(time.Now().UnixNano()) @@ -322,6 +323,7 @@ func (p *Probe) PlaySnapshot() { p.GetResolvers().ProcessResolver.Walk(entryToEvent) for _, event := range events { p.DispatchEvent(event) + event.ProcessCacheEntry.Release() } } From 30faf6fff721e46944ec77763607eace5534485a Mon Sep 17 00:00:00 2001 From: Nicolas Schweitzer Date: Thu, 8 Jun 2023 18:09:44 +0200 Subject: [PATCH 60/76] AP-2099 Prevent jobs that trigger child pipelines to download artefacts (#17117) --- .gitlab/trigger_release.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitlab/trigger_release.yml b/.gitlab/trigger_release.yml index 62818debd082f..c0e0f8cb0a38d 100644 --- a/.gitlab/trigger_release.yml +++ b/.gitlab/trigger_release.yml @@ -20,6 +20,7 @@ # when triggered with major version 7 - export RELEASE_VERSION=$(inv agent.version --major-version 7 --url-safe --omnibus-format)-1 - inv pipeline.trigger-child-pipeline --no-follow --project-name "DataDog/agent-release-management" --git-ref "main" --variables "ACTION,AUTO_RELEASE,BUILD_PIPELINE_ID,RELEASE_PRODUCT,RELEASE_VERSION,TARGET_REPO,TARGET_REPO_BRANCH" + dependencies: [] trigger_auto_staging_release: extends: .agent_release_management_trigger From d1cccaf7c93cabf687789a51064a52459c556a1d Mon Sep 17 00:00:00 2001 From: Alexandre Menasria <47357713+amenasria@users.noreply.github.com> Date: Thu, 8 Jun 2023 13:16:21 -0400 Subject: [PATCH 61/76] Fix broken loop (#17534) --- omnibus/config/software/datadog-agent-integrations-py2.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/omnibus/config/software/datadog-agent-integrations-py2.rb b/omnibus/config/software/datadog-agent-integrations-py2.rb index 9e449eda2f548..edb7fb221197a 100644 --- a/omnibus/config/software/datadog-agent-integrations-py2.rb +++ b/omnibus/config/software/datadog-agent-integrations-py2.rb @@ -222,8 +222,8 @@ end # In any case we add the lib to the requirements files to avoid inconsistency in the installed versions # For example if aerospike has dependency A>1.2.3 and a package in the big requirements file has A<1.2.3, the install process would succeed but the integration wouldn't work. - requirements.push(line) end + requirements.push(line) end end From ad72a192b6c9f1dbf37af006ec38aee86eb3d6af Mon Sep 17 00:00:00 2001 From: Hasan Mahmood Date: Thu, 8 Jun 2023 14:00:37 -0400 Subject: [PATCH 62/76] Report conntrack ebpf module loading telemetry (#17539) --- pkg/network/ebpf/bpf_module.go | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/pkg/network/ebpf/bpf_module.go b/pkg/network/ebpf/bpf_module.go index 00bab7a26957e..ebb76e36f90e2 100644 --- a/pkg/network/ebpf/bpf_module.go +++ b/pkg/network/ebpf/bpf_module.go @@ -67,17 +67,7 @@ func ReadFentryTracerModule(bpfDir string, debug bool) (bytecode.AssetReader, er // ReadConntrackBPFModule from the asset file func ReadConntrackBPFModule(bpfDir string, debug bool) (bytecode.AssetReader, error) { - file := "conntrack.o" - if debug { - file = "conntrack-debug.o" - } - - ebpfReader, err := bytecode.GetReader(bpfDir, file) - if err != nil { - return nil, fmt.Errorf("couldn't find asset: %s", err) - } - - return ebpfReader, nil + return readModule(bpfDir, "conntrack", debug) } func GetModulesInUse() []string { From 91fbd333600d56b9afd456885a6fc28f52decf8f Mon Sep 17 00:00:00 2001 From: pducolin <45568537+pducolin@users.noreply.github.com> Date: Thu, 8 Jun 2023 14:15:21 -0400 Subject: [PATCH 63/76] [fakeintake] add godoc (#17474) * [fakeintake] add godoc * [e2e] fix test example * [fakeintake] add helpers to client to get payload names * [fakeintake] move s in api.Payload inside doc link * [e2e] bump test-infra to 20230607221957 * [e2e] add logs example * [e2e] fix test-infra version * [e2e] remove unused config file --- test/fakeintake/client/client.go | 154 +++++++++++++++----- test/fakeintake/client/client_test.go | 8 +- test/fakeintake/doc.go | 7 + test/fakeintake/{ => docs}/README.md | 0 test/fakeintake/server/server.go | 9 ++ test/new-e2e/examples/vm_fakeintake_test.go | 92 +++++++++++- test/new-e2e/go.mod | 2 +- test/new-e2e/go.sum | 4 +- 8 files changed, 228 insertions(+), 48 deletions(-) rename test/fakeintake/{ => docs}/README.md (100%) diff --git a/test/fakeintake/client/client.go b/test/fakeintake/client/client.go index de0da3971d3bd..cfb53a55f0989 100644 --- a/test/fakeintake/client/client.go +++ b/test/fakeintake/client/client.go @@ -3,6 +3,39 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2016-present Datadog, Inc. +// Package client implements helpers APIs to interact with a [fakeintake server] from go tests +// Helpers fetch fakeintake endpoints, unpackage payloads and store parsed data in aggregators +// +// # Using fakeintake in go tests +// +// In this example we assert that a fakeintake running at localhost on port 8080 received +// "system.uptime" metrics with tags "app:system" and values in range 4226000 < value < 4226050. +// +// client := NewClient("http://localhost:8080") +// metrics, err := client.FilterMetrics("system.uptime", +// WithTags[*aggregator.MetricSeries]([]string{"app:system"}), +// WithMetricValueInRange(4226000, 4226050)) +// assert.NoError(t, err) +// assert.NotEmpty(t, metrics) +// +// In this example we assert that a fakeintake running at localhost on port 8080 received +// logs by service "system" with tags "app:system" and content containing "totoro" +// +// client := NewClient("http://localhost:8080") +// logs, err := client.FilterLogs("system", +// WithTags[*aggregator.Log]([]string{"totoro"}), +// assert.NoError(t, err) +// assert.NotEmpty(t, logs) +// +// In this example we assert that a fakeintake running at localhost on port 8080 received +// check runs by name "totoro" with tags "status:ok" +// +// client := NewClient("http://localhost:8080") +// logs, err := client.GetCheckRun("totoro") +// assert.NoError(t, err) +// assert.NotEmpty(t, logs) +// +// [fakeintake server]: https://pkg.go.dev/github.com/DataDog/datadog-agent@main/test/fakeintake/server package client import ( @@ -83,6 +116,8 @@ func (c *Client) getFakePayloads(endpoint string) (rawPayloads []api.Payload, er return response.Payloads, nil } +// GetServerHealth fetches fakeintake health status and returns an error if +// fakeintake is unhealthy func (c *Client) GetServerHealth() error { resp, err := http.Get(fmt.Sprintf("%s/fakeintake/health", c.fakeIntakeURL)) if err != nil { @@ -95,7 +130,7 @@ func (c *Client) GetServerHealth() error { return nil } -func (c *Client) GetMetric(name string) ([]*aggregator.MetricSeries, error) { +func (c *Client) getMetric(name string) ([]*aggregator.MetricSeries, error) { err := c.getMetrics() if err != nil { return nil, err @@ -103,8 +138,48 @@ func (c *Client) GetMetric(name string) ([]*aggregator.MetricSeries, error) { return c.metricAggregator.GetPayloadsByName(name), nil } +// A MatchOpt to filter fakeintake payloads type MatchOpt[P aggregator.PayloadItem] func(payload P) (bool, error) +// GetMetricNames fetches fakeintake on `/api/v2/series` endpoint and returns +// all received metric names +func (c *Client) GetMetricNames() ([]string, error) { + err := c.getMetrics() + if err != nil { + return []string{}, nil + } + return c.metricAggregator.GetNames(), nil +} + +// FilterMetrics fetches fakeintake on `/api/v2/series` endpoint and returns +// metrics matching `name` and any [MatchOpt](#MatchOpt) options +func (c *Client) FilterMetrics(name string, options ...MatchOpt[*aggregator.MetricSeries]) ([]*aggregator.MetricSeries, error) { + metrics, err := c.getMetric(name) + if err != nil { + return nil, err + } + // apply filters one after the other + filteredMetrics := []*aggregator.MetricSeries{} + for _, metric := range metrics { + matchCount := 0 + for _, matchOpt := range options { + isMatch, err := matchOpt(metric) + if err != nil { + return nil, err + } + if !isMatch { + break + } + matchCount++ + } + if matchCount == len(options) { + filteredMetrics = append(filteredMetrics, metric) + } + } + return filteredMetrics, nil +} + +// WithTags filters by `tags` func WithTags[P aggregator.PayloadItem](tags []string) MatchOpt[P] { return func(payload P) (bool, error) { if aggregator.AreTagsSubsetOfOtherTags(tags, payload.GetTags()) { @@ -115,6 +190,7 @@ func WithTags[P aggregator.PayloadItem](tags []string) MatchOpt[P] { } } +// WithMetricValueInRange filters metrics with values in range `minValue < value < maxValue` func WithMetricValueInRange(minValue float64, maxValue float64) MatchOpt[*aggregator.MetricSeries] { return func(metric *aggregator.MetricSeries) (bool, error) { isMatch, err := WithMetricValueHigherThan(minValue)(metric) @@ -125,6 +201,7 @@ func WithMetricValueInRange(minValue float64, maxValue float64) MatchOpt[*aggreg } } +// WithMetricValueLowerThan filters metrics with values lower than `maxValue` func WithMetricValueLowerThan(maxValue float64) MatchOpt[*aggregator.MetricSeries] { return func(metric *aggregator.MetricSeries) (bool, error) { for _, point := range metric.Points { @@ -137,6 +214,7 @@ func WithMetricValueLowerThan(maxValue float64) MatchOpt[*aggregator.MetricSerie } } +// WithMetricValueLowerThan filters metrics with values higher than `minValue` func WithMetricValueHigherThan(minValue float64) MatchOpt[*aggregator.MetricSeries] { return func(metric *aggregator.MetricSeries) (bool, error) { for _, point := range metric.Points { @@ -149,17 +227,37 @@ func WithMetricValueHigherThan(minValue float64) MatchOpt[*aggregator.MetricSeri } } -func (c *Client) FilterMetrics(name string, options ...MatchOpt[*aggregator.MetricSeries]) ([]*aggregator.MetricSeries, error) { - metrics, err := c.GetMetric(name) +func (c *Client) getLog(service string) ([]*aggregator.Log, error) { + err := c.getLogs() + if err != nil { + return nil, err + } + return c.logAggregator.GetPayloadsByName(service), nil +} + +// GetLogNames fetches fakeintake on `/api/v2/logs` endpoint and returns +// all received log service names +func (c *Client) GetLogServiceNames() ([]string, error) { + err := c.getLogs() + if err != nil { + return []string{}, nil + } + return c.logAggregator.GetNames(), nil +} + +// FilterLogs fetches fakeintake on `/api/v2/logs` endpoint, unpackage payloads and returns +// logs matching `service` and any [MatchOpt](#MatchOpt) options +func (c *Client) FilterLogs(service string, options ...MatchOpt[*aggregator.Log]) ([]*aggregator.Log, error) { + logs, err := c.getLog(service) if err != nil { return nil, err } // apply filters one after the other - filteredMetrics := []*aggregator.MetricSeries{} - for _, metric := range metrics { + filteredLogs := []*aggregator.Log{} + for _, log := range logs { matchCount := 0 for _, matchOpt := range options { - isMatch, err := matchOpt(metric) + isMatch, err := matchOpt(log) if err != nil { return nil, err } @@ -169,20 +267,13 @@ func (c *Client) FilterMetrics(name string, options ...MatchOpt[*aggregator.Metr matchCount++ } if matchCount == len(options) { - filteredMetrics = append(filteredMetrics, metric) + filteredLogs = append(filteredLogs, log) } } - return filteredMetrics, nil -} - -func (c *Client) GetLog(name string) ([]*aggregator.Log, error) { - err := c.getLogs() - if err != nil { - return nil, err - } - return c.logAggregator.GetPayloadsByName(name), nil + return filteredLogs, nil } +// WithMessageContaining filters logs by message containing `content` func WithMessageContaining(content string) MatchOpt[*aggregator.Log] { return func(log *aggregator.Log) (bool, error) { if strings.Contains(log.Message, content) { @@ -193,6 +284,7 @@ func WithMessageContaining(content string) MatchOpt[*aggregator.Log] { } } +// WithMessageMatching filters logs by message matching [regexp](https://pkg.go.dev/regexp) `pattern` func WithMessageMatching(pattern string) MatchOpt[*aggregator.Log] { return func(log *aggregator.Log) (bool, error) { matched, err := regexp.MatchString(pattern, log.Message) @@ -207,32 +299,18 @@ func WithMessageMatching(pattern string) MatchOpt[*aggregator.Log] { } } -func (c *Client) FilterLogs(name string, options ...MatchOpt[*aggregator.Log]) ([]*aggregator.Log, error) { - logs, err := c.GetLog(name) +// GetCheckRunNames fetches fakeintake on `/api/v1/check_run` endpoint and returns +// all received check run names +func (c *Client) GetCheckRunNames() ([]string, error) { + err := c.getCheckRuns() if err != nil { - return nil, err + return []string{}, nil } - // apply filters one after the other - filteredLogs := []*aggregator.Log{} - for _, log := range logs { - matchCount := 0 - for _, matchOpt := range options { - isMatch, err := matchOpt(log) - if err != nil { - return nil, err - } - if !isMatch { - break - } - matchCount++ - } - if matchCount == len(options) { - filteredLogs = append(filteredLogs, log) - } - } - return filteredLogs, nil + return c.checkRunAggregator.GetNames(), nil } +// FilterLogs fetches fakeintake on `/api/v1/check_run` endpoint, unpackage payloads and returns +// checks matching `name` func (c *Client) GetCheckRun(name string) ([]*aggregator.CheckRun, error) { err := c.getCheckRuns() if err != nil { diff --git a/test/fakeintake/client/client_test.go b/test/fakeintake/client/client_test.go index 871dcaafc9692..73d5847a9cfe5 100644 --- a/test/fakeintake/client/client_test.go +++ b/test/fakeintake/client/client_test.go @@ -91,14 +91,14 @@ func TestClient(t *testing.T) { assert.False(t, client.metricAggregator.ContainsPayloadNameAndTags("snmp.ifAdminStatus", []string{"totoro"})) }) - t.Run("GetMetric", func(t *testing.T) { + t.Run("getMetric", func(t *testing.T) { ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Write(apiV2SeriesResponse) })) defer ts.Close() client := NewClient(ts.URL) - metrics, err := client.GetMetric("snmp.ifAdminStatus") + metrics, err := client.getMetric("snmp.ifAdminStatus") assert.NoError(t, err) assert.NotEmpty(t, aggregator.FilterByTags(metrics, []string{"interface:lo", "snmp_profile:generic-router"})) assert.Empty(t, aggregator.FilterByTags(metrics, []string{"totoro"})) @@ -161,14 +161,14 @@ func TestClient(t *testing.T) { assert.False(t, client.logAggregator.ContainsPayloadName("totoro")) }) - t.Run("GetLog", func(t *testing.T) { + t.Run("getLog", func(t *testing.T) { ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Write(apiV2LogsResponse) })) defer ts.Close() client := NewClient(ts.URL) - logs, err := client.GetLog("testapp") + logs, err := client.getLog("testapp") assert.NoError(t, err) assert.Equal(t, 2, len(logs)) assert.Equal(t, "hello there, can you hear me", logs[0].Message) diff --git a/test/fakeintake/doc.go b/test/fakeintake/doc.go index 8c228a3f4c93c..38f36a63c301d 100644 --- a/test/fakeintake/doc.go +++ b/test/fakeintake/doc.go @@ -3,4 +3,11 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2016-present Datadog, Inc. +// Module fakeintake provides a dummy [Server] implementation of Datadog intake, meant to be used with integration and e2e tests. +// Package [Client] implements an API to interact with a fakeintake server from go tests +// fakeintake server is available as a [docker container] +// +// [Server]: https://pkg.go.dev/github.com/DataDog/datadog-agent@main/test/fakeintake/server +// [Client]: https://pkg.go.dev/github.com/DataDog/datadog-agent@main/test/fakeintake/client +// [docker container]: https://hub.docker.com/r/datadog/fakeintake package fakeintake diff --git a/test/fakeintake/README.md b/test/fakeintake/docs/README.md similarity index 100% rename from test/fakeintake/README.md rename to test/fakeintake/docs/README.md diff --git a/test/fakeintake/server/server.go b/test/fakeintake/server/server.go index 4eca27a8183dd..6a696efc4bc55 100644 --- a/test/fakeintake/server/server.go +++ b/test/fakeintake/server/server.go @@ -3,6 +3,15 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2016-present Datadog, Inc. +// Package server implements a dummy http Datadog intake, meant to be used with integration and e2e tests. +// It runs an catch-all http server that stores submitted payloads into a dictionary of [api.Payloads], indexed by the route +// It implements 3 testing endpoints: +// - /fakeintake/payloads/ returns any received payloads on the specified route as [api.Payload]s +// - /fakeintake/health returns current fakeintake server health +// - /fakeintake/routestats returns stats for collected payloads, by route +// - /fakeintake/flushPayloads returns all stored payloads and clear them up +// +// [api.Payloads]: https://pkg.go.dev/github.com/DataDog/datadog-agent@main/test/fakeintake/api#Payload package server import ( diff --git a/test/new-e2e/examples/vm_fakeintake_test.go b/test/new-e2e/examples/vm_fakeintake_test.go index a39c3ca78e27b..da37726af89c4 100644 --- a/test/new-e2e/examples/vm_fakeintake_test.go +++ b/test/new-e2e/examples/vm_fakeintake_test.go @@ -8,12 +8,19 @@ package examples import ( _ "embed" "errors" + "fmt" "time" "testing" + fi "github.com/DataDog/datadog-agent/test/fakeintake/client" "github.com/DataDog/datadog-agent/test/new-e2e/utils/e2e" + "github.com/DataDog/datadog-agent/test/new-e2e/utils/e2e/client" + "github.com/DataDog/test-infra-definitions/components/datadog/agent" + "github.com/DataDog/test-infra-definitions/scenarios/aws/ecs" + ec2vm "github.com/DataDog/test-infra-definitions/scenarios/aws/vm/ec2VM" "github.com/cenkalti/backoff/v4" + "github.com/pulumi/pulumi/sdk/v3/go/pulumi" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -44,7 +51,7 @@ func (s *vmFakeintakeSuite) TestAgent() { func (s *vmFakeintakeSuite) TestMetrics() { t := s.T() err := backoff.Retry(func() error { - metrics, err := s.Env().Fakeintake.Client.GetMetric("system.uptime") + metrics, err := s.Env().Fakeintake.Client.FilterMetrics("system.uptime") if err != nil { return err } @@ -55,7 +62,7 @@ func (s *vmFakeintakeSuite) TestMetrics() { return errors.New("") } return nil - }, backoff.WithMaxRetries(backoff.NewConstantBackOff(500*time.Millisecond), 20)) + }, backoff.WithMaxRetries(backoff.NewConstantBackOff(500*time.Millisecond), 60)) require.NoError(t, err) } @@ -70,6 +77,85 @@ func (s *vmFakeintakeSuite) TestCheckRuns() { return errors.New("No check run yet") } return nil - }, backoff.WithMaxRetries(backoff.NewConstantBackOff(500*time.Millisecond), 20)) + }, backoff.WithMaxRetries(backoff.NewConstantBackOff(500*time.Millisecond), 60)) + require.NoError(t, err) +} + +func LogsExampleStackDef(vmParams []e2e.Ec2VMOption, agentParams ...func(*agent.Params) error) *e2e.StackDefinition[e2e.AgentEnv] { + return e2e.EnvFactoryStackDef( + func(ctx *pulumi.Context) (*e2e.AgentEnv, error) { + vm, err := ec2vm.NewEc2VM(ctx, vmParams...) + if err != nil { + return nil, err + } + + fakeintakeExporter, err := ecs.NewEcsFakeintake(vm.Infra) + if err != nil { + return nil, err + } + + agentParams = append(agentParams, agent.WithFakeintake(fakeintakeExporter)) + agentParams = append(agentParams, agent.WithIntegration("custom_logs.d", `logs: +- type: file + path: "/tmp/test.log" + service: "custom_logs" + source: "custom"`)) + agentParams = append(agentParams, agent.WithLogs()) + + installer, err := agent.NewInstaller(vm, agentParams...) + if err != nil { + return nil, err + } + return &e2e.AgentEnv{ + VM: client.NewVM(vm), + Agent: client.NewAgent(installer), + Fakeintake: client.NewFakeintake(fakeintakeExporter), + }, nil + }, + ) +} + +func (s *vmFakeintakeSuite) TestLogs() { + s.UpdateEnv(LogsExampleStackDef(nil)) + t := s.T() + fakeintake := s.Env().Fakeintake + err := backoff.Retry(func() error { + logs, err := fakeintake.FilterLogs("custom_logs") + if err != nil { + return err + } + if len(logs) != 0 { + return errors.New("logs received while none expected") + } + return nil + }, backoff.WithMaxRetries(backoff.NewConstantBackOff(500*time.Millisecond), 60)) + require.NoError(t, err) + _, err = s.Env().VM.ExecuteWithError("echo 'totoro' > /tmp/test.log") + require.NoError(t, err) + err = backoff.Retry(func() error { + names, err := fakeintake.GetLogServiceNames() + if err != nil { + return err + } + if len(names) == 0 { + return errors.New("no logs received") + } + logs, err := fakeintake.FilterLogs("custom_logs") + if err != nil { + return err + } + if len(logs) != 1 { + return errors.New("no logs received") + } + logs, err = fakeintake.FilterLogs("custom_logs", fi.WithMessageContaining("totoro")) + if err != nil { + return err + } + if len(logs) != 1 { + return fmt.Errorf("received %v logs with 'tororo', expecting 1", len(logs)) + } + return nil + }, backoff.WithMaxRetries(backoff.NewConstantBackOff(500*time.Millisecond), 60)) + require.NoError(t, err) } diff --git a/test/new-e2e/go.mod b/test/new-e2e/go.mod index a848d241ab55d..fac9c135f1e20 100644 --- a/test/new-e2e/go.mod +++ b/test/new-e2e/go.mod @@ -10,7 +10,7 @@ replace github.com/DataDog/datadog-agent/test/fakeintake => ../fakeintake require ( github.com/DataDog/datadog-agent/test/fakeintake v0.46.0-rc.2 - github.com/DataDog/test-infra-definitions v0.0.0-20230607143804-fef23444c9da + github.com/DataDog/test-infra-definitions v0.0.0-20230608123532-949c05dac7e9 github.com/aws/aws-sdk-go-v2 v1.18.0 github.com/aws/aws-sdk-go-v2/config v1.18.25 github.com/aws/aws-sdk-go-v2/service/ssm v1.36.4 diff --git a/test/new-e2e/go.sum b/test/new-e2e/go.sum index 1783e50fb0b31..859edd981e3fa 100644 --- a/test/new-e2e/go.sum +++ b/test/new-e2e/go.sum @@ -1,7 +1,7 @@ github.com/DataDog/agent-payload/v5 v5.0.73 h1:fnCnAR+nWY+q//fBZSab4cDFFng0scPEfmLdl9ngmQY= github.com/DataDog/agent-payload/v5 v5.0.73/go.mod h1:oQZi1VZp1e3QvlSUX4iphZCpJaFepUxWq0hNXxihKBM= -github.com/DataDog/test-infra-definitions v0.0.0-20230607143804-fef23444c9da h1:2HqYpVpJkn06vNpoTzhTD4DubyTaaj4QT2wquPXg4m0= -github.com/DataDog/test-infra-definitions v0.0.0-20230607143804-fef23444c9da/go.mod h1:VlLmT/PmwpWNV6o0tKFzWuPtHuN9YBb73WjS5SjhFzY= +github.com/DataDog/test-infra-definitions v0.0.0-20230608123532-949c05dac7e9 h1:viUxY/ySGeI/s/fvmClGp5z806X61LusKuwmXWA/Bdg= +github.com/DataDog/test-infra-definitions v0.0.0-20230608123532-949c05dac7e9/go.mod h1:VlLmT/PmwpWNV6o0tKFzWuPtHuN9YBb73WjS5SjhFzY= github.com/HdrHistogram/hdrhistogram-go v1.1.2 h1:5IcZpTvzydCQeHzK4Ef/D5rrSqwxob0t8PQPMybUNFM= github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= From e79ba621d2da807ef77aa9ece673e9af8337df20 Mon Sep 17 00:00:00 2001 From: Guy Arbitman Date: Thu, 8 Jun 2023 22:33:55 +0300 Subject: [PATCH 64/76] usm: process monitor: Call heavy operation only if needed (#17457) * usm: process monitor: Call heavy operation only if needed From now on, we're scanning already running processes if and only if there are registered exec callbacks. Furthermore, we maintain 2 atomic booleans to indicate if we have any exec or exit callbacks, if we don't have, then we're sparing mutex acquiring * Added documentation * Removed filed --- pkg/process/monitor/process_monitor.go | 44 ++++++++++++++++++++------ 1 file changed, 34 insertions(+), 10 deletions(-) diff --git a/pkg/process/monitor/process_monitor.go b/pkg/process/monitor/process_monitor.go index cdc8e67c4cb5e..a69b60d383584 100644 --- a/pkg/process/monitor/process_monitor.go +++ b/pkg/process/monitor/process_monitor.go @@ -56,8 +56,10 @@ type ProcessMonitor struct { netlinkErrorsChannel chan error // callback registration and parallel execution management + hasExecCallbacks atomic.Bool processExecCallbacksMutex sync.RWMutex processExecCallbacks map[*ProcessCallback]struct{} + hasExitCallbacks atomic.Bool processExitCallbacksMutex sync.RWMutex processExitCallbacks map[*ProcessCallback]struct{} callbackRunner chan func() @@ -188,10 +190,20 @@ func (pm *ProcessMonitor) mainEventLoop() { switch ev := event.Msg.(type) { case *netlink.ExecProcEvent: pm.execCount.Inc() - pm.handleProcessExec(int(ev.ProcessPid)) + // handleProcessExec locks a mutex to access the exec callbacks array, if it is empty, then we're + // wasting "resources" to check it. Since it is a hot-code-path, it has some cpu load. + // Checking an atomic boolean, is an atomic operation, hence much faster. + if pm.hasExecCallbacks.Load() { + pm.handleProcessExec(int(ev.ProcessPid)) + } case *netlink.ExitProcEvent: pm.exitCount.Inc() - pm.handleProcessExit(int(ev.ProcessPid)) + // handleProcessExit locks a mutex to access the exit callbacks array, if it is empty, then we're + // wasting "resources" to check it. Since it is a hot-code-path, it has some cpu load. + // Checking an atomic boolean, is an atomic operation, hence much faster. + if pm.hasExitCallbacks.Load() { + pm.handleProcessExit(int(ev.ProcessPid)) + } } case err, ok := <-pm.netlinkErrorsChannel: if !ok { @@ -243,14 +255,22 @@ func (pm *ProcessMonitor) Initialize() error { initErr = fmt.Errorf("couldn't initialize process monitor: %w", err) } - handleProcessExecWrapper := func(pid int) error { - pm.handleProcessExec(pid) - return nil - } - // Scanning already running processes - if err := util.WithAllProcs(util.GetProcRoot(), handleProcessExecWrapper); err != nil { - initErr = fmt.Errorf("process monitor init, scanning all process failed %s", err) - return + pm.processExecCallbacksMutex.RLock() + execCallbacksLength := len(pm.processExecCallbacks) + pm.processExecCallbacksMutex.RUnlock() + + // Initialize should be called only once after we registered all callbacks. Thus, if we have no registered + // callback, no need to scan already running processes. + if execCallbacksLength > 0 { + handleProcessExecWrapper := func(pid int) error { + pm.handleProcessExec(pid) + return nil + } + // Scanning already running processes + if err := util.WithAllProcs(util.GetProcRoot(), handleProcessExecWrapper); err != nil { + initErr = fmt.Errorf("process monitor init, scanning all process failed %s", err) + return + } } }, ) @@ -263,6 +283,7 @@ func (pm *ProcessMonitor) Initialize() error { // Exit callback. func (pm *ProcessMonitor) SubscribeExec(callback ProcessCallback) (func(), error) { pm.processExecCallbacksMutex.Lock() + pm.hasExecCallbacks.Store(true) pm.processExecCallbacks[&callback] = struct{}{} pm.processExecCallbacksMutex.Unlock() @@ -270,6 +291,7 @@ func (pm *ProcessMonitor) SubscribeExec(callback ProcessCallback) (func(), error return func() { pm.processExecCallbacksMutex.Lock() delete(pm.processExecCallbacks, &callback) + pm.hasExecCallbacks.Store(len(pm.processExecCallbacks) > 0) pm.processExecCallbacksMutex.Unlock() }, nil } @@ -277,6 +299,7 @@ func (pm *ProcessMonitor) SubscribeExec(callback ProcessCallback) (func(), error // SubscribeExit register an exit callback and returns unsubscribe function callback that removes the callback. func (pm *ProcessMonitor) SubscribeExit(callback ProcessCallback) (func(), error) { pm.processExitCallbacksMutex.Lock() + pm.hasExitCallbacks.Store(true) pm.processExitCallbacks[&callback] = struct{}{} pm.processExitCallbacksMutex.Unlock() @@ -284,6 +307,7 @@ func (pm *ProcessMonitor) SubscribeExit(callback ProcessCallback) (func(), error return func() { pm.processExitCallbacksMutex.Lock() delete(pm.processExitCallbacks, &callback) + pm.hasExitCallbacks.Store(len(pm.processExitCallbacks) > 0) pm.processExitCallbacksMutex.Unlock() }, nil } From ef820b71cce66f9dfdaaaa2c51f3a0b0d6d5f060 Mon Sep 17 00:00:00 2001 From: Rey Abolofia Date: Thu, 8 Jun 2023 13:08:01 -0700 Subject: [PATCH 65/76] Update java integration tests to use latest layers. (#17194) --- test/integration/serverless/run.sh | 2 +- .../serverless/snapshots/error-java | 48 +++++++++++++++++++ .../integration/serverless/snapshots/log-java | 45 +++++++++++++++++ .../serverless/snapshots/trace-java | 44 +++++------------ .../serverless/src/java-tests/error/pom.xml | 5 -- .../error/src/main/java/ErrorHandler.java | 4 +- .../serverless/src/java-tests/log/pom.xml | 5 -- .../log/src/main/java/LogHandler.java | 42 ++++++++-------- .../serverless/src/java-tests/metric/pom.xml | 5 -- .../metric/src/main/java/Handler.java | 12 ++--- .../serverless/src/java-tests/timeout/pom.xml | 5 -- .../timeout/src/main/java/TimeoutHandler.java | 25 ++++------ .../serverless/src/java-tests/trace/pom.xml | 5 -- .../trace/src/main/java/TraceHandler.java | 12 ++--- 14 files changed, 144 insertions(+), 115 deletions(-) diff --git a/test/integration/serverless/run.sh b/test/integration/serverless/run.sh index b1a3ac053fa0b..bba34bbe576f9 100755 --- a/test/integration/serverless/run.sh +++ b/test/integration/serverless/run.sh @@ -21,7 +21,7 @@ DEFAULT_NODE_LAYER_VERSION=67 DEFAULT_PYTHON_LAYER_VERSION=50 -DEFAULT_JAVA_TRACE_LAYER_VERSION=4 +DEFAULT_JAVA_TRACE_LAYER_VERSION=10 DEFAULT_DOTNET_TRACE_LAYER_VERSION=3 DEFAULT_ARCHITECTURE=amd64 diff --git a/test/integration/serverless/snapshots/error-java b/test/integration/serverless/snapshots/error-java index e39cc94b00592..fb851620e8a41 100644 --- a/test/integration/serverless/snapshots/error-java +++ b/test/integration/serverless/snapshots/error-java @@ -99,6 +99,54 @@ ], "dogsketches": [] }, + { + "metric": "aws.lambda.enhanced.errors", + "distributions": null, + "tags": [ + "account_id:425362996713", + "architecture:XXX", + "aws_account:425362996713", + "dd_extension_version:123", + "env:integration-tests-env", + "function_arn:arn:aws:lambda:eu-west-1:425362996713:function:integration-tests-extension-XXXXXX-error-java", + "functionname:integration-tests-extension-XXXXXX-error-java", + "memorysize:1024", + "region:eu-west-1", + "resource:integration-tests-extension-XXXXXX-error-java", + "runtime:java8.al2", + "service:integration-tests-service", + "taga:valuea", + "tagb:valueb", + "tagc:valuec", + "tagd:valued", + "version:integration-tests-version" + ], + "dogsketches": [] + }, + { + "metric": "aws.lambda.enhanced.errors", + "distributions": null, + "tags": [ + "account_id:425362996713", + "architecture:XXX", + "aws_account:425362996713", + "dd_extension_version:123", + "env:integration-tests-env", + "function_arn:arn:aws:lambda:eu-west-1:425362996713:function:integration-tests-extension-XXXXXX-error-java", + "functionname:integration-tests-extension-XXXXXX-error-java", + "memorysize:1024", + "region:eu-west-1", + "resource:integration-tests-extension-XXXXXX-error-java", + "runtime:java8.al2", + "service:integration-tests-service", + "taga:valuea", + "tagb:valueb", + "tagc:valuec", + "tagd:valued", + "version:integration-tests-version" + ], + "dogsketches": [] + }, { "metric": "aws.lambda.enhanced.estimated_cost", "distributions": null, diff --git a/test/integration/serverless/snapshots/log-java b/test/integration/serverless/snapshots/log-java index 3d4b9a038af53..ea68e6a0bdc33 100644 --- a/test/integration/serverless/snapshots/log-java +++ b/test/integration/serverless/snapshots/log-java @@ -194,6 +194,51 @@ "ddsource": "lambda", "ddtags": "account_id:425362996713,architecture:XXX,aws_account:425362996713,dd_extension_version:123,env:integration-tests-env,function_arn:arn:aws:lambda:eu-west-1:425362996713:function:integration-tests-extension-XXXXXX-log-java,functionname:integration-tests-extension-XXXXXX-log-java,memorysize:1024,region:eu-west-1,resource:integration-tests-extension-XXXXXX-log-java,runtime:java8.al2,service:integration-tests-service,taga:valuea,tagb:valueb,tagc:valuec,tagd:valued,version:integration-tests-version" }, + { + "message": { + "message": "[dd.trace TIMESTAMP +0000] [main] ERROR datadog.trace.lambda.LambdaHandler - could not notify the extension as the lambda span is null or no sampling priority has been found\n", + "lambda": { + "arn": "arn:aws:lambda:eu-west-1:425362996713:function:integration-tests-extension-XXXXXX-log-java", + "request_id": "XXX" + } + }, + "status": "info", + "timestamp": "XXX", + "hostname": "arn:aws:lambda:eu-west-1:425362996713:function:integration-tests-extension-XXXXXX-log-java", + "service": "integration-tests-service", + "ddsource": "lambda", + "ddtags": "account_id:425362996713,architecture:XXX,aws_account:425362996713,dd_extension_version:123,env:integration-tests-env,function_arn:arn:aws:lambda:eu-west-1:425362996713:function:integration-tests-extension-XXXXXX-log-java,functionname:integration-tests-extension-XXXXXX-log-java,memorysize:1024,region:eu-west-1,resource:integration-tests-extension-XXXXXX-log-java,runtime:java8.al2,service:integration-tests-service,taga:valuea,tagb:valueb,tagc:valuec,tagd:valued,version:integration-tests-version" + }, + { + "message": { + "message": "[dd.trace TIMESTAMP +0000] [main] ERROR datadog.trace.lambda.LambdaHandler - could not notify the extension as the lambda span is null or no sampling priority has been found\n", + "lambda": { + "arn": "arn:aws:lambda:eu-west-1:425362996713:function:integration-tests-extension-XXXXXX-log-java", + "request_id": "XXX" + } + }, + "status": "info", + "timestamp": "XXX", + "hostname": "arn:aws:lambda:eu-west-1:425362996713:function:integration-tests-extension-XXXXXX-log-java", + "service": "integration-tests-service", + "ddsource": "lambda", + "ddtags": "account_id:425362996713,architecture:XXX,aws_account:425362996713,dd_extension_version:123,env:integration-tests-env,function_arn:arn:aws:lambda:eu-west-1:425362996713:function:integration-tests-extension-XXXXXX-log-java,functionname:integration-tests-extension-XXXXXX-log-java,memorysize:1024,region:eu-west-1,resource:integration-tests-extension-XXXXXX-log-java,runtime:java8.al2,service:integration-tests-service,taga:valuea,tagb:valueb,tagc:valuec,tagd:valued,version:integration-tests-version" + }, + { + "message": { + "message": "[dd.trace TIMESTAMP +0000] [main] INFO com.datadog.appsec.AppSecSystem - AppSec is ENABLED_INACTIVE with powerwaf(libddwaf: 1.10.0) no rules loaded\n", + "lambda": { + "arn": "arn:aws:lambda:eu-west-1:425362996713:function:integration-tests-extension-XXXXXX-log-java", + "request_id": "XXX" + } + }, + "status": "info", + "timestamp": "XXX", + "hostname": "arn:aws:lambda:eu-west-1:425362996713:function:integration-tests-extension-XXXXXX-log-java", + "service": "integration-tests-service", + "ddsource": "lambda", + "ddtags": "account_id:425362996713,architecture:XXX,aws_account:425362996713,dd_extension_version:123,env:integration-tests-env,function_arn:arn:aws:lambda:eu-west-1:425362996713:function:integration-tests-extension-XXXXXX-log-java,functionname:integration-tests-extension-XXXXXX-log-java,memorysize:1024,region:eu-west-1,resource:integration-tests-extension-XXXXXX-log-java,runtime:java8.al2,service:integration-tests-service,taga:valuea,tagb:valueb,tagc:valuec,tagd:valued,version:integration-tests-version" + }, { "message": { "message": "[dd.trace TIMESTAMP +0000] [main] INFO datadog.trace.agent.common.writer.WriterFactory - Detected serverless environment. Serverless extension has been detected, using DDAgentWriter\n", diff --git a/test/integration/serverless/snapshots/trace-java b/test/integration/serverless/snapshots/trace-java index aaf87289e326a..7ce751309db2e 100644 --- a/test/integration/serverless/snapshots/trace-java +++ b/test/integration/serverless/snapshots/trace-java @@ -1,7 +1,7 @@ [ { "container_id": "", - "language_name": "java", + "language_name": "", "language_version": null, "tracer_version": null, "runtime_id": "", @@ -26,38 +26,28 @@ "account_id": "425362996713", "architecture": "XXX", "aws_account": "425362996713", - "cold_start": "false", - "datadog_lambda": "X.X.X", "dd_extension_version": "123", "env": "integration-tests-env", + "function.request": "{\"isBase64Encoded\":false}", + "function.response": "{}", "function_arn": "arn:aws:lambda:eu-west-1:425362996713:function:integration-tests-extension-XXXXXX-trace-java", - "function_version": "$LATEST", "functionname": "integration-tests-extension-XXXXXX-trace-java", - "language": "jvm", "memorysize": "1024", "region": "eu-west-1", "request_id": "null", - "resource_names": "integration-tests-extension-XXXXXX-trace-java", "runtime": "java8.al2", - "runtime-id": "null", "service": "integration-tests-service", - "tagA": "valueA", - "tagB": "valueB", "taga": "valuea", "tagb": "valueb", "tagc": "valuec", "tagd": "valued", - "thread.name": "main", "version": "integration-tests-version" }, "metrics": { - "_dd.agent_psr": 1, - "_dd.top_level": 1, - "_sampling_priority_v1": 1, - "_top_level": 1, - "thread.id": 1 + "_sampling_priority_rate_v1": 1, + "_top_level": 1 }, - "type": "" + "type": "serverless" } ], "tags": null, @@ -71,7 +61,7 @@ }, { "container_id": "", - "language_name": "java", + "language_name": "", "language_version": null, "tracer_version": null, "runtime_id": "", @@ -96,38 +86,28 @@ "account_id": "425362996713", "architecture": "XXX", "aws_account": "425362996713", - "cold_start": "true", - "datadog_lambda": "X.X.X", "dd_extension_version": "123", "env": "integration-tests-env", + "function.request": "{\"body\":\"testing request payload\",\"isBase64Encoded\":false}", + "function.response": "{}", "function_arn": "arn:aws:lambda:eu-west-1:425362996713:function:integration-tests-extension-XXXXXX-trace-java", - "function_version": "$LATEST", "functionname": "integration-tests-extension-XXXXXX-trace-java", - "language": "jvm", "memorysize": "1024", "region": "eu-west-1", "request_id": "null", - "resource_names": "integration-tests-extension-XXXXXX-trace-java", "runtime": "java8.al2", - "runtime-id": "null", "service": "integration-tests-service", - "tagA": "valueA", - "tagB": "valueB", "taga": "valuea", "tagb": "valueb", "tagc": "valuec", "tagd": "valued", - "thread.name": "main", "version": "integration-tests-version" }, "metrics": { - "_dd.agent_psr": 1, - "_dd.top_level": 1, - "_sampling_priority_v1": 1, - "_top_level": 1, - "thread.id": 1 + "_sampling_priority_rate_v1": 1, + "_top_level": 1 }, - "type": "" + "type": "serverless" } ], "tags": null, diff --git a/test/integration/serverless/src/java-tests/error/pom.xml b/test/integration/serverless/src/java-tests/error/pom.xml index d4548e64b71ac..48320879bf17e 100644 --- a/test/integration/serverless/src/java-tests/error/pom.xml +++ b/test/integration/serverless/src/java-tests/error/pom.xml @@ -29,11 +29,6 @@ log4j-core 2.17.1 - - com.datadoghq - datadog-lambda-java - 1.4.0 - diff --git a/test/integration/serverless/src/java-tests/error/src/main/java/ErrorHandler.java b/test/integration/serverless/src/java-tests/error/src/main/java/ErrorHandler.java index 73b0f382d45d1..bbd4853d99a26 100644 --- a/test/integration/serverless/src/java-tests/error/src/main/java/ErrorHandler.java +++ b/test/integration/serverless/src/java-tests/error/src/main/java/ErrorHandler.java @@ -1,4 +1,3 @@ - import java.util.Map; import java.util.LinkedHashMap; import java.lang.Error; @@ -6,10 +5,9 @@ import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.RequestHandler; import com.amazonaws.services.lambda.runtime.events.APIGatewayV2ProxyRequestEvent; -import com.datadoghq.datadog_lambda_java.DDLambda; public class ErrorHandler implements RequestHandler>{ public Map handleRequest(APIGatewayV2ProxyRequestEvent request, Context context){ - throw new Error("oops"); + throw new Error("oops"); } } diff --git a/test/integration/serverless/src/java-tests/log/pom.xml b/test/integration/serverless/src/java-tests/log/pom.xml index e33a724fd7c16..02c385c6e1a44 100644 --- a/test/integration/serverless/src/java-tests/log/pom.xml +++ b/test/integration/serverless/src/java-tests/log/pom.xml @@ -29,11 +29,6 @@ log4j-core 2.17.1 - - com.datadoghq - datadog-lambda-java - 1.4.0 - diff --git a/test/integration/serverless/src/java-tests/log/src/main/java/LogHandler.java b/test/integration/serverless/src/java-tests/log/src/main/java/LogHandler.java index fb04d3730eff4..656161de2bdc1 100644 --- a/test/integration/serverless/src/java-tests/log/src/main/java/LogHandler.java +++ b/test/integration/serverless/src/java-tests/log/src/main/java/LogHandler.java @@ -1,37 +1,33 @@ - import java.util.Map; import java.util.LinkedHashMap; import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.RequestHandler; import com.amazonaws.services.lambda.runtime.events.APIGatewayV2ProxyRequestEvent; -import com.datadoghq.datadog_lambda_java.DDLambda; public class LogHandler implements RequestHandler>{ public Map handleRequest(APIGatewayV2ProxyRequestEvent request, Context context) { - DDLambda ddl = new DDLambda(context); //Required to initialize the trace - Map res = new LinkedHashMap(); - res.put("statusCode", 200); - res.put("body", "ok"); + Map res = new LinkedHashMap(); + res.put("statusCode", 200); + res.put("body", "ok"); - // Sleep to ensure correct log ordering - sleepHelper(); - System.out.println("XXX Log 0 XXX"); - sleepHelper(); - System.out.println("XXX Log 1 XXX"); - sleepHelper(); - System.out.println("XXX Log 2 XXX"); - sleepHelper(); + // Sleep to ensure correct log ordering + sleepHelper(); + System.out.println("XXX Log 0 XXX"); + sleepHelper(); + System.out.println("XXX Log 1 XXX"); + sleepHelper(); + System.out.println("XXX Log 2 XXX"); + sleepHelper(); - ddl.finish(); - return res; + return res; } - private void sleepHelper() { - try { - Thread.sleep(250); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } + private void sleepHelper() { + try { + Thread.sleep(250); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } } diff --git a/test/integration/serverless/src/java-tests/metric/pom.xml b/test/integration/serverless/src/java-tests/metric/pom.xml index e1b6095fae987..738bc5e0d5a1f 100644 --- a/test/integration/serverless/src/java-tests/metric/pom.xml +++ b/test/integration/serverless/src/java-tests/metric/pom.xml @@ -29,11 +29,6 @@ log4j-core 2.17.1 - - com.datadoghq - datadog-lambda-java - 1.4.0 - diff --git a/test/integration/serverless/src/java-tests/metric/src/main/java/Handler.java b/test/integration/serverless/src/java-tests/metric/src/main/java/Handler.java index d2ec9cdcb1d7b..936ef52f2a22e 100644 --- a/test/integration/serverless/src/java-tests/metric/src/main/java/Handler.java +++ b/test/integration/serverless/src/java-tests/metric/src/main/java/Handler.java @@ -1,19 +1,15 @@ - import java.util.Map; import java.util.LinkedHashMap; import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.RequestHandler; import com.amazonaws.services.lambda.runtime.events.*; -import com.datadoghq.datadog_lambda_java.DDLambda; public class Handler implements RequestHandler>{ public Map handleRequest(APIGatewayV2ProxyRequestEvent request, Context context){ - DDLambda ddl = new DDLambda(context); //Required to initialize the trace - Map res = new LinkedHashMap(); - res.put("statusCode", 200); - res.put("body", "ok"); - ddl.finish(); - return res; + Map res = new LinkedHashMap(); + res.put("statusCode", 200); + res.put("body", "ok"); + return res; } } diff --git a/test/integration/serverless/src/java-tests/timeout/pom.xml b/test/integration/serverless/src/java-tests/timeout/pom.xml index c7ae51b8ee083..660910c108594 100644 --- a/test/integration/serverless/src/java-tests/timeout/pom.xml +++ b/test/integration/serverless/src/java-tests/timeout/pom.xml @@ -29,11 +29,6 @@ log4j-core 2.17.1 - - com.datadoghq - datadog-lambda-java - 1.4.0 - diff --git a/test/integration/serverless/src/java-tests/timeout/src/main/java/TimeoutHandler.java b/test/integration/serverless/src/java-tests/timeout/src/main/java/TimeoutHandler.java index 9945f5ccb3562..c9a34b23ea22c 100644 --- a/test/integration/serverless/src/java-tests/timeout/src/main/java/TimeoutHandler.java +++ b/test/integration/serverless/src/java-tests/timeout/src/main/java/TimeoutHandler.java @@ -1,4 +1,3 @@ - import java.util.Map; import java.util.LinkedHashMap; import java.lang.Thread; @@ -6,23 +5,19 @@ import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.RequestHandler; import com.amazonaws.services.lambda.runtime.events.APIGatewayV2ProxyRequestEvent; -import com.datadoghq.datadog_lambda_java.DDLambda; public class TimeoutHandler implements RequestHandler>{ public Map handleRequest(APIGatewayV2ProxyRequestEvent request, Context context){ - DDLambda ddl = new DDLambda(context); //Required to initialize the trace - - //trigger a timeout - try { - Thread.sleep(10000); - } catch (InterruptedException e) { - e.printStackTrace(); - } + //trigger a timeout + try { + Thread.sleep(10000); + } catch (InterruptedException e) { + e.printStackTrace(); + } - Map res = new LinkedHashMap(); - res.put("statusCode", 200); - res.put("body", "ok"); - ddl.finish(); - return res; + Map res = new LinkedHashMap(); + res.put("statusCode", 200); + res.put("body", "ok"); + return res; } } diff --git a/test/integration/serverless/src/java-tests/trace/pom.xml b/test/integration/serverless/src/java-tests/trace/pom.xml index f011bb0fa6778..e90d30c9a526f 100644 --- a/test/integration/serverless/src/java-tests/trace/pom.xml +++ b/test/integration/serverless/src/java-tests/trace/pom.xml @@ -29,11 +29,6 @@ log4j-core 2.17.1 - - com.datadoghq - datadog-lambda-java - 1.4.0 - diff --git a/test/integration/serverless/src/java-tests/trace/src/main/java/TraceHandler.java b/test/integration/serverless/src/java-tests/trace/src/main/java/TraceHandler.java index 3540bba008ed5..f66bb17cbc170 100644 --- a/test/integration/serverless/src/java-tests/trace/src/main/java/TraceHandler.java +++ b/test/integration/serverless/src/java-tests/trace/src/main/java/TraceHandler.java @@ -1,19 +1,15 @@ - import java.util.Map; import java.util.LinkedHashMap; import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.RequestHandler; import com.amazonaws.services.lambda.runtime.events.APIGatewayV2ProxyRequestEvent; -import com.datadoghq.datadog_lambda_java.DDLambda; public class TraceHandler implements RequestHandler>{ public Map handleRequest(APIGatewayV2ProxyRequestEvent request, Context context){ - DDLambda ddl = new DDLambda(context); //Required to initialize the trace - Map res = new LinkedHashMap(); - res.put("statusCode", 200); - res.put("body", "ok"); - ddl.finish(); - return res; + Map res = new LinkedHashMap(); + res.put("statusCode", 200); + res.put("body", "ok"); + return res; } } From 6e493bb94bca69b936898f58c27734a85c673b84 Mon Sep 17 00:00:00 2001 From: Nenad Noveljic <18366081+nenadnoveljic@users.noreply.github.com> Date: Fri, 9 Jun 2023 09:12:18 +0200 Subject: [PATCH 66/76] Add workaround for database connection loss (#17486) * implemented * release notes * Update releasenotes/notes/connection-loss-workaround-c457738d985fda2a.yaml Co-authored-by: Austin Lai <76412946+alai97@users.noreply.github.com> * Update pkg/collector/corechecks/oracle-dbm/oracle.go Co-authored-by: Alexandre Normand * removed comments * corrected syntac errors after merging --------- Co-authored-by: Austin Lai <76412946+alai97@users.noreply.github.com> Co-authored-by: Alexandre Normand --- pkg/collector/corechecks/oracle-dbm/activity.go | 2 +- pkg/collector/corechecks/oracle-dbm/oracle.go | 14 ++++++++++++++ pkg/collector/corechecks/oracle-dbm/processes.go | 2 +- pkg/collector/corechecks/oracle-dbm/sysmetrics.go | 4 ++-- pkg/collector/corechecks/oracle-dbm/tablespaces.go | 2 +- ...onnection-loss-workaround-c457738d985fda2a.yaml | 11 +++++++++++ 6 files changed, 30 insertions(+), 5 deletions(-) create mode 100644 releasenotes/notes/connection-loss-workaround-c457738d985fda2a.yaml diff --git a/pkg/collector/corechecks/oracle-dbm/activity.go b/pkg/collector/corechecks/oracle-dbm/activity.go index 71b9544c89e81..ad184e36a84a6 100644 --- a/pkg/collector/corechecks/oracle-dbm/activity.go +++ b/pkg/collector/corechecks/oracle-dbm/activity.go @@ -334,7 +334,7 @@ func (c *Check) SampleSession() error { activityQuery = ACTIVITY_QUERY } - err := c.db.Select(&sessionSamples, activityQuery) + err := selectWrapper(c, &sessionSamples, activityQuery) if err != nil { return fmt.Errorf("failed to collect session sampling activity: %w", err) diff --git a/pkg/collector/corechecks/oracle-dbm/oracle.go b/pkg/collector/corechecks/oracle-dbm/oracle.go index 7806734d146bc..36b8c27f5dc9d 100644 --- a/pkg/collector/corechecks/oracle-dbm/oracle.go +++ b/pkg/collector/corechecks/oracle-dbm/oracle.go @@ -321,3 +321,17 @@ func appendPDBTag(tags []string, pdb sql.NullString) []string { } return append(tags, "pdb:"+pdb.String) } + +func selectWrapper[T any](c *Check, s T, sql string) error { + err := c.db.Select(s, sql) + if err != nil && (strings.Contains(err.Error(), "ORA-01012") || strings.Contains(err.Error(), "database is closed")) { + db, err := c.Connect() + if err != nil { + c.Teardown() + return err + } + c.db = db + } + + return err +} diff --git a/pkg/collector/corechecks/oracle-dbm/processes.go b/pkg/collector/corechecks/oracle-dbm/processes.go index 9e5d27fe8f190..f60f1756f1d10 100644 --- a/pkg/collector/corechecks/oracle-dbm/processes.go +++ b/pkg/collector/corechecks/oracle-dbm/processes.go @@ -37,7 +37,7 @@ type ProcessesRowDB struct { func (c *Check) ProcessMemory() error { rows := []ProcessesRowDB{} - err := c.db.Select(&rows, PGA_QUERY) + err := selectWrapper(c, &rows, PGA_QUERY) if err != nil { return fmt.Errorf("failed to collect processes info: %w", err) } diff --git a/pkg/collector/corechecks/oracle-dbm/sysmetrics.go b/pkg/collector/corechecks/oracle-dbm/sysmetrics.go index 0c7eda54f1908..ba1b4da35bc2b 100644 --- a/pkg/collector/corechecks/oracle-dbm/sysmetrics.go +++ b/pkg/collector/corechecks/oracle-dbm/sysmetrics.go @@ -130,7 +130,7 @@ func (c *Check) SysMetrics() error { } metricRows := []SysmetricsRowDB{} - err = c.db.Select(&metricRows, fmt.Sprintf(SYSMETRICS_QUERY, "v$con_sysmetric")) + err = selectWrapper(c, &metricRows, fmt.Sprintf(SYSMETRICS_QUERY, "v$con_sysmetric")) if err != nil { return fmt.Errorf("failed to collect container sysmetrics: %w", err) } @@ -140,7 +140,7 @@ func (c *Check) SysMetrics() error { } seenInGlobalMetrics := make(map[string]bool) - err = c.db.Select(&metricRows, fmt.Sprintf(SYSMETRICS_QUERY, "v$sysmetric")+" ORDER BY begin_time ASC, metric_name ASC") + err = selectWrapper(c, &metricRows, fmt.Sprintf(SYSMETRICS_QUERY, "v$sysmetric")+" ORDER BY begin_time ASC, metric_name ASC") if err != nil { return fmt.Errorf("failed to collect sysmetrics: %w", err) } diff --git a/pkg/collector/corechecks/oracle-dbm/tablespaces.go b/pkg/collector/corechecks/oracle-dbm/tablespaces.go index bfbdb68e45dfc..102a81a21b2f3 100644 --- a/pkg/collector/corechecks/oracle-dbm/tablespaces.go +++ b/pkg/collector/corechecks/oracle-dbm/tablespaces.go @@ -35,7 +35,7 @@ type RowDB struct { func (c *Check) Tablespaces() error { rows := []RowDB{} - err := c.db.Select(&rows, QUERY) + err := selectWrapper(c, &rows, QUERY) if err != nil { return fmt.Errorf("failed to collect tablespace info: %w", err) } diff --git a/releasenotes/notes/connection-loss-workaround-c457738d985fda2a.yaml b/releasenotes/notes/connection-loss-workaround-c457738d985fda2a.yaml new file mode 100644 index 0000000000000..e5d72a8dea139 --- /dev/null +++ b/releasenotes/notes/connection-loss-workaround-c457738d985fda2a.yaml @@ -0,0 +1,11 @@ +# Each section from every release note are combined when the +# CHANGELOG.rst is rendered. So the text needs to be worded so that +# it does not depend on any information only available in another +# section. This may mean repeating some details, but each section +# must be readable independently of the other. +# +# Each section note must be formatted as reStructuredText. +--- +fixes: + - | + Add a workaround for erroneous database connection loss handling in go-ora. From 0eba84152fb4c58030fd6393237150611de75c9f Mon Sep 17 00:00:00 2001 From: Sylvain Afchain Date: Fri, 9 Jun 2023 09:40:09 +0200 Subject: [PATCH 67/76] [CWS] remove load controller (#17220) --- pkg/config/system_probe.go | 3 - pkg/security/events/custom.go | 6 - pkg/security/metrics/metrics.go | 6 - pkg/security/probe/config/config.go | 55 ++--- pkg/security/probe/custom_events.go | 38 ---- pkg/security/probe/custom_events_easyjson.go | 130 ++--------- pkg/security/probe/discarders.go | 5 +- pkg/security/probe/load_controller.go | 216 ------------------- pkg/security/probe/probe_linux.go | 2 - pkg/security/probe/probe_monitor.go | 22 +- pkg/security/secl/model/events.go | 4 - pkg/security/tests/module_tester.go | 2 - pkg/security/tests/probe_monitor_test.go | 48 ----- 13 files changed, 38 insertions(+), 499 deletions(-) delete mode 100644 pkg/security/probe/load_controller.go diff --git a/pkg/config/system_probe.go b/pkg/config/system_probe.go index 0248f12b77332..3870221e2f94e 100644 --- a/pkg/config/system_probe.go +++ b/pkg/config/system_probe.go @@ -265,9 +265,6 @@ func InitSystemProbeConfig(cfg Config) { eventMonitorBindEnvAndSetDefault(cfg, join(evNS, "enable_kernel_filters"), true) eventMonitorBindEnvAndSetDefault(cfg, join(evNS, "flush_discarder_window"), 3) eventMonitorBindEnvAndSetDefault(cfg, join(evNS, "pid_cache_size"), 10000) - eventMonitorBindEnvAndSetDefault(cfg, join(evNS, "load_controller.events_count_threshold"), 20000) - eventMonitorBindEnvAndSetDefault(cfg, join(evNS, "load_controller.discarder_timeout"), 60) - eventMonitorBindEnvAndSetDefault(cfg, join(evNS, "load_controller.control_period"), 2) eventMonitorBindEnvAndSetDefault(cfg, join(evNS, "events_stats.tags_cardinality"), "high") eventMonitorBindEnvAndSetDefault(cfg, join(evNS, "custom_sensitive_words"), []string{}) eventMonitorBindEnvAndSetDefault(cfg, join(evNS, "erpc_dentry_resolution_enabled"), true) diff --git a/pkg/security/events/custom.go b/pkg/security/events/custom.go index b232ccabcae8d..5c51866b74322 100644 --- a/pkg/security/events/custom.go +++ b/pkg/security/events/custom.go @@ -30,11 +30,6 @@ const ( // RulesetLoadedRuleDesc is the rule description for the ruleset_loaded events RulesetLoadedRuleDesc = "New ruleset loaded" - // NoisyProcessRuleID is the rule ID for the noisy_process events - NoisyProcessRuleID = "noisy_process" - // NoisyProcessRuleDesc is the rule description for the noisy_process events - NoisyProcessRuleDesc = "Noisy process detected" - // AbnormalPathRuleID is the rule ID for the abnormal_path events AbnormalPathRuleID = "abnormal_path" // AbnormalPathRuleDesc is the rule description for the abnormal_path events @@ -84,7 +79,6 @@ func AllCustomRuleIDs() []string { return []string{ LostEventsRuleID, RulesetLoadedRuleID, - NoisyProcessRuleID, AbnormalPathRuleID, SelfTestRuleID, AnomalyDetectionRuleID, diff --git a/pkg/security/metrics/metrics.go b/pkg/security/metrics/metrics.go index 65f814acf6c3e..36bb796279519 100644 --- a/pkg/security/metrics/metrics.go +++ b/pkg/security/metrics/metrics.go @@ -29,12 +29,6 @@ var ( // Tags: - MetricProcessEventsServerExpired = newRuntimeMetric(".event_server.process_events_expired") - // Load controller metrics - - // MetricLoadControllerPidDiscarder is the name of the metric used to count the number of pid discarders - // Tags: - - MetricLoadControllerPidDiscarder = newRuntimeMetric(".load_controller.pids_discarder") - // Rate limiter metrics // MetricRateLimiterDrop is the name of the metric used to count the amount of events dropped by the rate limiter diff --git a/pkg/security/probe/config/config.go b/pkg/security/probe/config/config.go index 511346b3047ec..3372627141406 100644 --- a/pkg/security/probe/config/config.go +++ b/pkg/security/probe/config/config.go @@ -61,16 +61,6 @@ type Config struct { // PIDCacheSize is the size of the user space PID caches PIDCacheSize int - // LoadControllerEventsCountThreshold defines the amount of events past which we will trigger the in-kernel circuit breaker - LoadControllerEventsCountThreshold int64 - - // LoadControllerDiscarderTimeout defines the amount of time discarders set by the load controller should last - LoadControllerDiscarderTimeout time.Duration - - // LoadControllerControlPeriod defines the period at which the load controller will empty the user space counter used - // to evaluate the amount of events brought back to user space - LoadControllerControlPeriod time.Duration - // StatsTagsCardinality determines the cardinality level of the tags added to the exported metrics StatsTagsCardinality string @@ -142,30 +132,27 @@ func NewConfig() (*Config, error) { setEnv() c := &Config{ - Config: *ebpf.NewConfig(), - EnableKernelFilters: getBool("enable_kernel_filters"), - EnableApprovers: getBool("enable_approvers"), - EnableDiscarders: getBool("enable_discarders"), - FlushDiscarderWindow: getInt("flush_discarder_window"), - PIDCacheSize: getInt("pid_cache_size"), - LoadControllerEventsCountThreshold: int64(getInt("load_controller.events_count_threshold")), - LoadControllerDiscarderTimeout: time.Duration(getInt("load_controller.discarder_timeout")) * time.Second, - LoadControllerControlPeriod: time.Duration(getInt("load_controller.control_period")) * time.Second, - StatsTagsCardinality: getString("events_stats.tags_cardinality"), - CustomSensitiveWords: getStringSlice("custom_sensitive_words"), - ERPCDentryResolutionEnabled: getBool("erpc_dentry_resolution_enabled"), - MapDentryResolutionEnabled: getBool("map_dentry_resolution_enabled"), - DentryCacheSize: getInt("dentry_cache_size"), - RemoteTaggerEnabled: getBool("remote_tagger"), - RuntimeMonitor: getBool("runtime_monitor.enabled"), - NetworkLazyInterfacePrefixes: getStringSlice("network.lazy_interface_prefixes"), - NetworkClassifierPriority: uint16(getInt("network.classifier_priority")), - NetworkClassifierHandle: uint16(getInt("network.classifier_handle")), - EventStreamUseRingBuffer: getBool("event_stream.use_ring_buffer"), - EventStreamBufferSize: getInt("event_stream.buffer_size"), - EnvsWithValue: getStringSlice("envs_with_value"), - NetworkEnabled: getBool("network.enabled"), - StatsPollingInterval: time.Duration(getInt("events_stats.polling_interval")) * time.Second, + Config: *ebpf.NewConfig(), + EnableKernelFilters: getBool("enable_kernel_filters"), + EnableApprovers: getBool("enable_approvers"), + EnableDiscarders: getBool("enable_discarders"), + FlushDiscarderWindow: getInt("flush_discarder_window"), + PIDCacheSize: getInt("pid_cache_size"), + StatsTagsCardinality: getString("events_stats.tags_cardinality"), + CustomSensitiveWords: getStringSlice("custom_sensitive_words"), + ERPCDentryResolutionEnabled: getBool("erpc_dentry_resolution_enabled"), + MapDentryResolutionEnabled: getBool("map_dentry_resolution_enabled"), + DentryCacheSize: getInt("dentry_cache_size"), + RemoteTaggerEnabled: getBool("remote_tagger"), + RuntimeMonitor: getBool("runtime_monitor.enabled"), + NetworkLazyInterfacePrefixes: getStringSlice("network.lazy_interface_prefixes"), + NetworkClassifierPriority: uint16(getInt("network.classifier_priority")), + NetworkClassifierHandle: uint16(getInt("network.classifier_handle")), + EventStreamUseRingBuffer: getBool("event_stream.use_ring_buffer"), + EventStreamBufferSize: getInt("event_stream.buffer_size"), + EnvsWithValue: getStringSlice("envs_with_value"), + NetworkEnabled: getBool("network.enabled"), + StatsPollingInterval: time.Duration(getInt("events_stats.polling_interval")) * time.Second, // event server SocketPath: coreconfig.SystemProbe.GetString(join(evNS, "socket")), diff --git a/pkg/security/probe/custom_events.go b/pkg/security/probe/custom_events.go index b6614ae4b62a3..e97dde8c079c3 100644 --- a/pkg/security/probe/custom_events.go +++ b/pkg/security/probe/custom_events.go @@ -10,8 +10,6 @@ package probe import ( - "time" - "github.com/DataDog/datadog-agent/pkg/security/events" "github.com/DataDog/datadog-agent/pkg/security/resolvers/dentry" "github.com/DataDog/datadog-agent/pkg/security/secl/model" @@ -58,42 +56,6 @@ func NewEventLostWriteEvent(mapName string, perEventPerCPU map[string]uint64) (* return events.NewCustomRule(events.LostEventsRuleID, events.LostEventsRuleDesc), events.NewCustomEvent(model.CustomLostWriteEventType, evt) } -// NoisyProcessEvent is used to report that a noisy process was temporarily discarded -// easyjson:json -type NoisyProcessEvent struct { - events.CustomEventCommonFields - Count uint64 `json:"pid_count"` - Threshold int64 `json:"threshold"` - ControlPeriod time.Duration `json:"control_period"` - DiscardedUntil time.Time `json:"discarded_until"` - Pid uint32 `json:"pid"` - Comm string `json:"comm"` -} - -// NewNoisyProcessEvent returns the rule and a populated custom event for a noisy_process event -func NewNoisyProcessEvent(count uint64, - threshold int64, - controlPeriod time.Duration, - discardedUntil time.Time, - pid uint32, - comm string, - timestamp time.Time) (*rules.Rule, *events.CustomEvent) { - - evt := NoisyProcessEvent{ - Count: count, - Threshold: threshold, - ControlPeriod: controlPeriod, - DiscardedUntil: discardedUntil, - Pid: pid, - Comm: comm, - } - evt.FillCustomEventCommonFields() - // Overwrite common timestamp - evt.Timestamp = timestamp - - return events.NewCustomRule(events.NoisyProcessRuleID, events.NoisyProcessRuleDesc), events.NewCustomEvent(model.CustomNoisyProcessEventType, evt) -} - func errorToEventType(err error) model.EventType { switch err.(type) { case dentry.ErrTruncatedParents, dentry.ErrTruncatedParentsERPC: diff --git a/pkg/security/probe/custom_events_easyjson.go b/pkg/security/probe/custom_events_easyjson.go index 9f3020fe4495f..2e001f71b3935 100644 --- a/pkg/security/probe/custom_events_easyjson.go +++ b/pkg/security/probe/custom_events_easyjson.go @@ -11,7 +11,6 @@ import ( easyjson "github.com/mailru/easyjson" jlexer "github.com/mailru/easyjson/jlexer" jwriter "github.com/mailru/easyjson/jwriter" - time "time" ) // suppress unused package warning @@ -22,112 +21,7 @@ var ( _ easyjson.Marshaler ) -func easyjsonF8f9ddd1DecodeGithubComDataDogDatadogAgentPkgSecurityProbe(in *jlexer.Lexer, out *NoisyProcessEvent) { - isTopLevel := in.IsStart() - if in.IsNull() { - if isTopLevel { - in.Consumed() - } - in.Skip() - return - } - in.Delim('{') - for !in.IsDelim('}') { - key := in.UnsafeFieldName(false) - in.WantColon() - if in.IsNull() { - in.Skip() - in.WantComma() - continue - } - switch key { - case "pid_count": - out.Count = uint64(in.Uint64()) - case "threshold": - out.Threshold = int64(in.Int64()) - case "control_period": - out.ControlPeriod = time.Duration(in.Int64()) - case "discarded_until": - if data := in.Raw(); in.Ok() { - in.AddError((out.DiscardedUntil).UnmarshalJSON(data)) - } - case "pid": - out.Pid = uint32(in.Uint32()) - case "comm": - out.Comm = string(in.String()) - case "date": - if data := in.Raw(); in.Ok() { - in.AddError((out.Timestamp).UnmarshalJSON(data)) - } - case "service": - out.Service = string(in.String()) - default: - in.SkipRecursive() - } - in.WantComma() - } - in.Delim('}') - if isTopLevel { - in.Consumed() - } -} -func easyjsonF8f9ddd1EncodeGithubComDataDogDatadogAgentPkgSecurityProbe(out *jwriter.Writer, in NoisyProcessEvent) { - out.RawByte('{') - first := true - _ = first - { - const prefix string = ",\"pid_count\":" - out.RawString(prefix[1:]) - out.Uint64(uint64(in.Count)) - } - { - const prefix string = ",\"threshold\":" - out.RawString(prefix) - out.Int64(int64(in.Threshold)) - } - { - const prefix string = ",\"control_period\":" - out.RawString(prefix) - out.Int64(int64(in.ControlPeriod)) - } - { - const prefix string = ",\"discarded_until\":" - out.RawString(prefix) - out.Raw((in.DiscardedUntil).MarshalJSON()) - } - { - const prefix string = ",\"pid\":" - out.RawString(prefix) - out.Uint32(uint32(in.Pid)) - } - { - const prefix string = ",\"comm\":" - out.RawString(prefix) - out.String(string(in.Comm)) - } - { - const prefix string = ",\"date\":" - out.RawString(prefix) - out.Raw((in.Timestamp).MarshalJSON()) - } - { - const prefix string = ",\"service\":" - out.RawString(prefix) - out.String(string(in.Service)) - } - out.RawByte('}') -} - -// MarshalEasyJSON supports easyjson.Marshaler interface -func (v NoisyProcessEvent) MarshalEasyJSON(w *jwriter.Writer) { - easyjsonF8f9ddd1EncodeGithubComDataDogDatadogAgentPkgSecurityProbe(w, v) -} - -// UnmarshalEasyJSON supports easyjson.Unmarshaler interface -func (v *NoisyProcessEvent) UnmarshalEasyJSON(l *jlexer.Lexer) { - easyjsonF8f9ddd1DecodeGithubComDataDogDatadogAgentPkgSecurityProbe(l, v) -} -func easyjsonF8f9ddd1DecodeGithubComDataDogDatadogAgentPkgSecurityProbe1(in *jlexer.Lexer, out *EventLostWrite) { +func easyjsonF8f9ddd1DecodeGithubComDataDogDatadogAgentPkgSecurityProbe(in *jlexer.Lexer, out *EventLostWrite) { isTopLevel := in.IsStart() if in.IsNull() { if isTopLevel { @@ -180,7 +74,7 @@ func easyjsonF8f9ddd1DecodeGithubComDataDogDatadogAgentPkgSecurityProbe1(in *jle in.Consumed() } } -func easyjsonF8f9ddd1EncodeGithubComDataDogDatadogAgentPkgSecurityProbe1(out *jwriter.Writer, in EventLostWrite) { +func easyjsonF8f9ddd1EncodeGithubComDataDogDatadogAgentPkgSecurityProbe(out *jwriter.Writer, in EventLostWrite) { out.RawByte('{') first := true _ = first @@ -225,14 +119,14 @@ func easyjsonF8f9ddd1EncodeGithubComDataDogDatadogAgentPkgSecurityProbe1(out *jw // MarshalEasyJSON supports easyjson.Marshaler interface func (v EventLostWrite) MarshalEasyJSON(w *jwriter.Writer) { - easyjsonF8f9ddd1EncodeGithubComDataDogDatadogAgentPkgSecurityProbe1(w, v) + easyjsonF8f9ddd1EncodeGithubComDataDogDatadogAgentPkgSecurityProbe(w, v) } // UnmarshalEasyJSON supports easyjson.Unmarshaler interface func (v *EventLostWrite) UnmarshalEasyJSON(l *jlexer.Lexer) { - easyjsonF8f9ddd1DecodeGithubComDataDogDatadogAgentPkgSecurityProbe1(l, v) + easyjsonF8f9ddd1DecodeGithubComDataDogDatadogAgentPkgSecurityProbe(l, v) } -func easyjsonF8f9ddd1DecodeGithubComDataDogDatadogAgentPkgSecurityProbe2(in *jlexer.Lexer, out *EventLostRead) { +func easyjsonF8f9ddd1DecodeGithubComDataDogDatadogAgentPkgSecurityProbe1(in *jlexer.Lexer, out *EventLostRead) { isTopLevel := in.IsStart() if in.IsNull() { if isTopLevel { @@ -271,7 +165,7 @@ func easyjsonF8f9ddd1DecodeGithubComDataDogDatadogAgentPkgSecurityProbe2(in *jle in.Consumed() } } -func easyjsonF8f9ddd1EncodeGithubComDataDogDatadogAgentPkgSecurityProbe2(out *jwriter.Writer, in EventLostRead) { +func easyjsonF8f9ddd1EncodeGithubComDataDogDatadogAgentPkgSecurityProbe1(out *jwriter.Writer, in EventLostRead) { out.RawByte('{') first := true _ = first @@ -300,14 +194,14 @@ func easyjsonF8f9ddd1EncodeGithubComDataDogDatadogAgentPkgSecurityProbe2(out *jw // MarshalEasyJSON supports easyjson.Marshaler interface func (v EventLostRead) MarshalEasyJSON(w *jwriter.Writer) { - easyjsonF8f9ddd1EncodeGithubComDataDogDatadogAgentPkgSecurityProbe2(w, v) + easyjsonF8f9ddd1EncodeGithubComDataDogDatadogAgentPkgSecurityProbe1(w, v) } // UnmarshalEasyJSON supports easyjson.Unmarshaler interface func (v *EventLostRead) UnmarshalEasyJSON(l *jlexer.Lexer) { - easyjsonF8f9ddd1DecodeGithubComDataDogDatadogAgentPkgSecurityProbe2(l, v) + easyjsonF8f9ddd1DecodeGithubComDataDogDatadogAgentPkgSecurityProbe1(l, v) } -func easyjsonF8f9ddd1DecodeGithubComDataDogDatadogAgentPkgSecurityProbe3(in *jlexer.Lexer, out *AbnormalEvent) { +func easyjsonF8f9ddd1DecodeGithubComDataDogDatadogAgentPkgSecurityProbe2(in *jlexer.Lexer, out *AbnormalEvent) { isTopLevel := in.IsStart() if in.IsNull() { if isTopLevel { @@ -354,7 +248,7 @@ func easyjsonF8f9ddd1DecodeGithubComDataDogDatadogAgentPkgSecurityProbe3(in *jle in.Consumed() } } -func easyjsonF8f9ddd1EncodeGithubComDataDogDatadogAgentPkgSecurityProbe3(out *jwriter.Writer, in AbnormalEvent) { +func easyjsonF8f9ddd1EncodeGithubComDataDogDatadogAgentPkgSecurityProbe2(out *jwriter.Writer, in AbnormalEvent) { out.RawByte('{') first := true _ = first @@ -387,10 +281,10 @@ func easyjsonF8f9ddd1EncodeGithubComDataDogDatadogAgentPkgSecurityProbe3(out *jw // MarshalEasyJSON supports easyjson.Marshaler interface func (v AbnormalEvent) MarshalEasyJSON(w *jwriter.Writer) { - easyjsonF8f9ddd1EncodeGithubComDataDogDatadogAgentPkgSecurityProbe3(w, v) + easyjsonF8f9ddd1EncodeGithubComDataDogDatadogAgentPkgSecurityProbe2(w, v) } // UnmarshalEasyJSON supports easyjson.Unmarshaler interface func (v *AbnormalEvent) UnmarshalEasyJSON(l *jlexer.Lexer) { - easyjsonF8f9ddd1DecodeGithubComDataDogDatadogAgentPkgSecurityProbe3(l, v) + easyjsonF8f9ddd1DecodeGithubComDataDogDatadogAgentPkgSecurityProbe2(l, v) } diff --git a/pkg/security/probe/discarders.go b/pkg/security/probe/discarders.go index 947f127d10b65..b31d4fd7c79a5 100644 --- a/pkg/security/probe/discarders.go +++ b/pkg/security/probe/discarders.go @@ -37,7 +37,7 @@ const ( maxParentDiscarderDepth = 3 // allEventTypes is a mask to match all the events - allEventTypes = math.MaxUint32 + allEventTypes = math.MaxUint32 //nolint:deadcode,unused // inode/mountid that won't be resubmitted maxRecentlyAddedCacheSize = uint64(64) @@ -125,10 +125,12 @@ func marshalDiscardHeader(req *erpc.ERPCRequest, eventType model.EventType, time return 16 } +//nolint:deadcode,unused type pidDiscarders struct { erpc *erpc.ERPC } +//nolint:deadcode,unused func (p *pidDiscarders) discardWithTimeout(req *erpc.ERPCRequest, eventType model.EventType, pid uint32, timeout int64) error { req.OP = erpc.DiscardPidOp offset := marshalDiscardHeader(req, eventType, uint64(timeout)) @@ -137,6 +139,7 @@ func (p *pidDiscarders) discardWithTimeout(req *erpc.ERPCRequest, eventType mode return p.erpc.Request(req) } +//nolint:deadcode,unused func newPidDiscarders(erpc *erpc.ERPC) *pidDiscarders { return &pidDiscarders{erpc: erpc} } diff --git a/pkg/security/probe/load_controller.go b/pkg/security/probe/load_controller.go deleted file mode 100644 index 6a4b9072a13cc..0000000000000 --- a/pkg/security/probe/load_controller.go +++ /dev/null @@ -1,216 +0,0 @@ -// Unless explicitly stated otherwise all files in this repository are licensed -// under the Apache License Version 2.0. -// This product includes software developed at Datadog (https://www.datadoghq.com/). -// Copyright 2016-present Datadog, Inc. - -//go:build linux - -package probe - -import ( - "context" - "fmt" - "sync" - "time" - - "github.com/hashicorp/golang-lru/v2/simplelru" - "go.uber.org/atomic" - "golang.org/x/time/rate" - - "github.com/DataDog/datadog-agent/pkg/security/metrics" - "github.com/DataDog/datadog-agent/pkg/security/probe/erpc" - "github.com/DataDog/datadog-agent/pkg/security/secl/model" - "github.com/DataDog/datadog-agent/pkg/security/seclog" -) - -const ( - defaultRateLimit = 1 // per second -) - -type eventCounterLRUKey struct { - Pid uint32 - Cookie uint32 -} - -// LoadController is used to monitor and control the pressure put on the host -type LoadController struct { - sync.RWMutex - probe *Probe - - eventsTotal *atomic.Int64 - eventsCounters *simplelru.LRU[eventCounterLRUKey, *atomic.Uint64] - pidDiscardersCount *atomic.Int64 - - EventsCountThreshold int64 - DiscarderTimeout time.Duration - ControllerPeriod time.Duration - - NoisyProcessCustomEventRate *rate.Limiter -} - -// NewLoadController instantiates a new load controller -func NewLoadController(probe *Probe) (*LoadController, error) { - lru, err := simplelru.NewLRU[eventCounterLRUKey, *atomic.Uint64](probe.Config.Probe.PIDCacheSize, nil) - if err != nil { - return nil, err - } - - lc := &LoadController{ - probe: probe, - - eventsTotal: atomic.NewInt64(0), - eventsCounters: lru, - pidDiscardersCount: atomic.NewInt64(0), - - EventsCountThreshold: probe.Config.Probe.LoadControllerEventsCountThreshold, - DiscarderTimeout: probe.Config.Probe.LoadControllerDiscarderTimeout, - ControllerPeriod: probe.Config.Probe.LoadControllerControlPeriod, - - NoisyProcessCustomEventRate: rate.NewLimiter(rate.Every(time.Second), defaultRateLimit), - } - return lc, nil -} - -// SendStats sends load controller stats -func (lc *LoadController) SendStats() error { - // send load_controller.pids_discarder metric - if count := lc.pidDiscardersCount.Swap(0); count > 0 { - if err := lc.probe.StatsdClient.Count(metrics.MetricLoadControllerPidDiscarder, count, []string{}, 1.0); err != nil { - return fmt.Errorf("couldn't send load_controller.pids_discarder metric: %w", err) - } - } - return nil -} - -// Count processes the provided events and ensures the load of the provided event type is within the configured limits -func (lc *LoadController) Count(event *model.Event) { - switch event.GetEventType() { - case model.ExecEventType, model.InvalidateDentryEventType, model.ForkEventType: - case model.ExitEventType: - lc.cleanupCounter(event.ProcessContext.Pid, event.ProcessContext.Cookie) - default: - lc.GenericCount(event) - } -} - -// GenericCount increments the event counter of the provided event type and pid -func (lc *LoadController) GenericCount(event *model.Event) { - lc.Lock() - defer lc.Unlock() - - entry, ok := lc.eventsCounters.Get(eventCounterLRUKey{Pid: event.ProcessContext.Pid, Cookie: event.ProcessContext.Cookie}) - if ok { - entry.Inc() - } else { - lc.eventsCounters.Add(eventCounterLRUKey{Pid: event.ProcessContext.Pid, Cookie: event.ProcessContext.Cookie}, atomic.NewUint64(1)) - } - newTotal := lc.eventsTotal.Inc() - - if newTotal >= lc.EventsCountThreshold { - lc.discardNoisiestProcess() - } -} - -// discardNoisiestProcess determines the noisiest process and event_type tuple and pushes a temporary discarder -func (lc *LoadController) discardNoisiestProcess() { - // iterate over the LRU map to retrieve the noisiest process & event_type tuple - var maxKey eventCounterLRUKey - var maxCount *atomic.Uint64 - for _, key := range lc.eventsCounters.Keys() { - entry, ok := lc.eventsCounters.Peek(key) - if !ok || entry == nil { - continue - } - - // update max if necessary - if maxCount == nil || maxCount.Load() < entry.Load() { - maxCount = entry - maxKey = key - } - } - if maxCount == nil { - // LRU is empty nothing to discard - return - } - - var erpcRequest erpc.ERPCRequest - - // push a temporary discarder on the noisiest process & event type tuple - seclog.Tracef("discarding events from pid %d for %s seconds", maxKey.Pid, lc.DiscarderTimeout) - if err := lc.probe.pidDiscarders.discardWithTimeout(&erpcRequest, allEventTypes, maxKey.Pid, lc.DiscarderTimeout.Nanoseconds()); err != nil { - seclog.Warnf("couldn't insert temporary discarder: %v", err) - return - } - - // update current total and remove biggest entry from cache. Note that there - // is a chance of the maxCount value being incremented between these two atomic - // operations, but that's OK -- the event is still counted. - oldMaxCount := maxCount.Swap(0) - lc.eventsTotal.Sub(int64(oldMaxCount)) - - lc.pidDiscardersCount.Inc() - - if lc.NoisyProcessCustomEventRate.Allow() { - process := lc.probe.resolvers.ProcessResolver.Resolve(maxKey.Pid, maxKey.Pid, 0, false) - if process == nil { - seclog.Warnf("Unable to resolve process with pid: %d", maxKey.Pid) - return - } - - ts := time.Now() - lc.probe.DispatchCustomEvent( - NewNoisyProcessEvent( - oldMaxCount, - lc.EventsCountThreshold, - lc.ControllerPeriod, - ts.Add(lc.DiscarderTimeout), - maxKey.Pid, - process.Comm, - ts, - ), - ) - } -} - -// cleanupCounter resets the internal counter of the provided pid -func (lc *LoadController) cleanupCounter(pid uint32, cookie uint32) { - lc.Lock() - defer lc.Unlock() - - key := eventCounterLRUKey{Pid: pid, Cookie: cookie} - counter, ok := lc.eventsCounters.Get(key) - if ok { - lc.eventsTotal.Sub(int64(counter.Load())) - lc.eventsCounters.Remove(key) - } -} - -// cleanup resets the internal counters -func (lc *LoadController) cleanup() { - lc.Lock() - defer lc.Unlock() - - // purge counters - lc.eventsCounters.Purge() - lc.eventsTotal.Store(0) -} - -// Start resets the internal counters periodically -func (lc *LoadController) Start(ctx context.Context, wg *sync.WaitGroup) { - defer wg.Done() - - ctx, cancel := context.WithCancel(ctx) - defer cancel() - - ticker := time.NewTicker(lc.ControllerPeriod) - defer ticker.Stop() - - for { - select { - case <-ticker.C: - lc.cleanup() - case <-ctx.Done(): - return - } - } -} diff --git a/pkg/security/probe/probe_linux.go b/pkg/security/probe/probe_linux.go index e041e17ceaafb..b13ac9eeb88fe 100644 --- a/pkg/security/probe/probe_linux.go +++ b/pkg/security/probe/probe_linux.go @@ -99,7 +99,6 @@ type PlatformProbe struct { // Approvers / discarders section Erpc *erpc.ERPC erpcRequest *erpc.ERPCRequest - pidDiscarders *pidDiscarders inodeDiscarders *inodeDiscarders notifyDiscarderPushedCallbacks []NotifyDiscarderPushedCallback approvers map[eval.EventType]kfilters.ActiveApprovers @@ -252,7 +251,6 @@ func (p *Probe) Init() error { return fmt.Errorf("failed to init manager: %w", err) } - p.pidDiscarders = newPidDiscarders(p.Erpc) p.inodeDiscarders = newInodeDiscarders(p.Erpc, p.resolvers.DentryResolver) if err := p.resolvers.Start(p.ctx); err != nil { diff --git a/pkg/security/probe/probe_monitor.go b/pkg/security/probe/probe_monitor.go index 0e4bbaf2c8f7d..abfc140167639 100644 --- a/pkg/security/probe/probe_monitor.go +++ b/pkg/security/probe/probe_monitor.go @@ -26,7 +26,6 @@ import ( type Monitor struct { probe *Probe - loadController *LoadController perfBufferMonitor *PerfBufferMonitor activityDumpManager *dump.ActivityDumpManager securityProfileManager *profile.SecurityProfileManager @@ -48,12 +47,6 @@ func (m *Monitor) Init() error { var err error p := m.probe - // instantiate a new load controller - m.loadController, err = NewLoadController(p) - if err != nil { - return err - } - // instantiate a new event statistics monitor m.perfBufferMonitor, err = NewPerfBufferMonitor(p) if err != nil { @@ -109,15 +102,8 @@ func (m *Monitor) GetSecurityProfileManager() *profile.SecurityProfileManager { // Start triggers the goroutine of all the underlying controllers and monitors of the Monitor func (m *Monitor) Start(ctx context.Context, wg *sync.WaitGroup) error { - delta := 1 - if m.activityDumpManager != nil { - delta++ - } - wg.Add(delta) - - go m.loadController.Start(ctx, wg) - if m.activityDumpManager != nil { + wg.Add(1) go m.activityDumpManager.Start(ctx, wg) } if m.securityProfileManager != nil { @@ -159,10 +145,6 @@ func (m *Monitor) SendStats() error { } time.Sleep(delay) - if err := m.loadController.SendStats(); err != nil { - return fmt.Errorf("failed to send load controller stats: %w", err) - } - if m.activityDumpManager != nil { if err := m.activityDumpManager.SendStats(); err != nil { return fmt.Errorf("failed to send activity dump manager stats: %w", err) @@ -198,8 +180,6 @@ func (m *Monitor) SendStats() error { // ProcessEvent processes an event through the various monitors and controllers of the probe func (m *Monitor) ProcessEvent(event *model.Event) { - m.loadController.Count(event) - // handle event errors if event.Error == nil { return diff --git a/pkg/security/secl/model/events.go b/pkg/security/secl/model/events.go index 6bbe6aec76bd6..dee0a191dbe6e 100644 --- a/pkg/security/secl/model/events.go +++ b/pkg/security/secl/model/events.go @@ -115,8 +115,6 @@ const ( CustomLostWriteEventType // CustomRulesetLoadedEventType is the custom event used to report that a new ruleset was loaded CustomRulesetLoadedEventType - // CustomNoisyProcessEventType is the custom event used to report the detection of a noisy process - CustomNoisyProcessEventType // CustomForkBombEventType is the custom event used to report the detection of a fork bomb CustomForkBombEventType // CustomTruncatedParentsEventType is the custom event used to report that the parents of a path were truncated @@ -214,8 +212,6 @@ func (t EventType) String() string { return "lost_events_write" case CustomRulesetLoadedEventType: return "ruleset_loaded" - case CustomNoisyProcessEventType: - return "noisy_process" case CustomForkBombEventType: return "fork_bomb" case CustomTruncatedParentsEventType: diff --git a/pkg/security/tests/module_tester.go b/pkg/security/tests/module_tester.go index ebb01a7965105..e4e694fe4c9de 100644 --- a/pkg/security/tests/module_tester.go +++ b/pkg/security/tests/module_tester.go @@ -93,8 +93,6 @@ event_monitoring_config: network: enabled: true flush_discarder_window: 0 - load_controller: - events_count_threshold: {{ .EventsCountThreshold }} {{if .DisableFilters}} enable_kernel_filters: false {{end}} diff --git a/pkg/security/tests/probe_monitor_test.go b/pkg/security/tests/probe_monitor_test.go index fc675efdd7082..e52b6dec69fd6 100644 --- a/pkg/security/tests/probe_monitor_test.go +++ b/pkg/security/tests/probe_monitor_test.go @@ -151,51 +151,3 @@ func TestTruncatedParentsMap(t *testing.T) { func TestTruncatedParentsERPC(t *testing.T) { truncatedParents(t, testOpts{disableMapDentryResolution: true, disableAbnormalPathCheck: true}) } - -func TestNoisyProcess(t *testing.T) { - rule := &rules.RuleDefinition{ - ID: "path_test", - // use the basename as an approver. The rule won't match as the parent folder differs but we will get the event because of the approver. - Expression: `open.file.path == "{{.Root}}/do_not_match/test-open"`, - } - - test, err := newTestModule(t, nil, []*rules.RuleDefinition{rule}, testOpts{disableDiscarders: true, eventsCountThreshold: 1000}) - if err != nil { - t.Fatal(err) - } - defer test.Close() - - file, _, err := test.Path("test-open") - if err != nil { - t.Fatal(err) - } - - t.Run("noisy_process", func(t *testing.T) { - err = test.GetCustomEventSent(t, func() error { - // generate load - for i := int64(0); i < testMod.secconfig.Probe.LoadControllerEventsCountThreshold*2; i++ { - f, err := os.OpenFile(file, os.O_CREATE, 0755) - if err != nil { - return err - } - if err = f.Close(); err != nil { - return err - } - if err = os.Remove(file); err != nil { - return err - } - } - return nil - }, func(rule *rules.Rule, customEvent *events.CustomEvent) bool { - assert.Equal(t, events.NoisyProcessRuleID, rule.ID, "wrong rule") - return true - }, getEventTimeout, model.CustomNoisyProcessEventType) - if err != nil { - t.Fatal(err) - } - - // make sure the discarder has expired before moving on to other tests - t.Logf("waiting for the discarder to expire (%s)", testMod.secconfig.Probe.LoadControllerDiscarderTimeout) - time.Sleep(testMod.secconfig.Probe.LoadControllerDiscarderTimeout + 1*time.Second) - }) -} From a50b46f5ca46b2572db60f286ae0b969c738c4dc Mon Sep 17 00:00:00 2001 From: Jonathan Ribas Date: Fri, 9 Jun 2023 09:53:27 +0200 Subject: [PATCH 68/76] [CWS] rework secprofile warmup tests (#17377) --- pkg/security/tests/fake_tags_resolver.go | 38 +++++++ pkg/security/tests/module_tester.go | 8 +- pkg/security/tests/security_profile_test.go | 120 +++++++++++++++----- 3 files changed, 136 insertions(+), 30 deletions(-) diff --git a/pkg/security/tests/fake_tags_resolver.go b/pkg/security/tests/fake_tags_resolver.go index d0c266d7333b5..484bb00984e2a 100644 --- a/pkg/security/tests/fake_tags_resolver.go +++ b/pkg/security/tests/fake_tags_resolver.go @@ -16,6 +16,8 @@ import ( "github.com/DataDog/datadog-agent/pkg/security/utils" ) +// This fake resolver will give a different image_name for each different container ID + // Resolver represents a cache resolver type FakeResolver struct { sync.Mutex @@ -59,3 +61,39 @@ func (t *FakeResolver) GetValue(id string, tag string) string { func NewFakeResolver() tags.Resolver { return &FakeResolver{} } + +// This fake resolver will allways give the same image_name, no matter the container ID + +// Resolver represents a cache resolver +type FakeMonoResolver struct { +} + +// Start the resolver +func (t *FakeMonoResolver) Start(ctx context.Context) error { + return nil +} + +// Stop the resolver +func (t *FakeMonoResolver) Stop() error { + return nil +} + +// Resolve returns the tags for the given id +func (t *FakeMonoResolver) Resolve(containerID string) []string { + return []string{"container_id:" + containerID, "image_name:fake_ubuntu"} +} + +// ResolveWithErr returns the tags for the given id +func (t *FakeMonoResolver) ResolveWithErr(id string) ([]string, error) { + return t.Resolve(id), nil +} + +// GetValue return the tag value for the given id and tag name +func (t *FakeMonoResolver) GetValue(id string, tag string) string { + return utils.GetTagValue(tag, t.Resolve(id)) +} + +// NewFakeMonoResolver returns a new tags resolver +func NewFakeMonoResolver() tags.Resolver { + return &FakeMonoResolver{} +} diff --git a/pkg/security/tests/module_tester.go b/pkg/security/tests/module_tester.go index e4e694fe4c9de..1d044c42478e0 100644 --- a/pkg/security/tests/module_tester.go +++ b/pkg/security/tests/module_tester.go @@ -51,6 +51,7 @@ import ( sprobe "github.com/DataDog/datadog-agent/pkg/security/probe" "github.com/DataDog/datadog-agent/pkg/security/proto/api" cgroupModel "github.com/DataDog/datadog-agent/pkg/security/resolvers/cgroup/model" + "github.com/DataDog/datadog-agent/pkg/security/resolvers/tags" "github.com/DataDog/datadog-agent/pkg/security/secl/compiler/eval" "github.com/DataDog/datadog-agent/pkg/security/secl/model" "github.com/DataDog/datadog-agent/pkg/security/secl/rules" @@ -249,6 +250,7 @@ type testOpts struct { disableRuntimeSecurity bool enableSBOM bool preStartCallback func(test *testModule) + tagsResolver tags.Resolver } func (s *stringSlice) String() string { @@ -920,9 +922,13 @@ func newTestModule(t testing.TB, macroDefs []*rules.MacroDefinition, ruleDefs [] StatsdClient: statsdClient, DontDiscardRuntime: true, PathResolutionEnabled: true, - TagsResolver: NewFakeResolver(), }, } + if opts.tagsResolver != nil { + emopts.ProbeOpts.TagsResolver = opts.tagsResolver + } else { + emopts.ProbeOpts.TagsResolver = NewFakeResolver() + } testMod.eventMonitor, err = eventmonitor.NewEventMonitor(emconfig, secconfig, emopts) if err != nil { return nil, err diff --git a/pkg/security/tests/security_profile_test.go b/pkg/security/tests/security_profile_test.go index d83efcff71410..d8130548be26e 100644 --- a/pkg/security/tests/security_profile_test.go +++ b/pkg/security/tests/security_profile_test.go @@ -400,7 +400,7 @@ func TestAnomalyDetectionWarmup(t *testing.T) { } var expectedFormats = []string{"profile"} - var testActivityDumpTracedEventTypes = []string{"exec"} + var testActivityDumpTracedEventTypes = []string{"exec", "dns"} outputDir := t.TempDir() os.MkdirAll(outputDir, 0755) @@ -418,29 +418,28 @@ func TestAnomalyDetectionWarmup(t *testing.T) { securityProfileDir: outputDir, securityProfileWatchDir: true, anomalyDetectionMinimumStablePeriod: 0, - anomalyDetectionWarmupPeriod: 17 * time.Second, + anomalyDetectionWarmupPeriod: 3 * time.Second, + tagsResolver: NewFakeMonoResolver(), }) if err != nil { t.Fatal(err) } defer test.Close() - syscallTester, err := loadSyscallTester(t, test, "syscall_tester") + + err = test.StopAllActivityDumps() if err != nil { t.Fatal(err) } - dockerInstance, dump, err := test.StartADockerGetDump() + mainDockerInstance, dump, err := test.StartADockerGetDump() if err != nil { t.Fatal(err) } - defer dockerInstance.stop() + defer mainDockerInstance.stop() time.Sleep(time.Second * 1) // to ensure we did not get ratelimited - cmd := dockerInstance.Command(syscallTester, []string{"sleep", "1"}, []string{}) - _, err = cmd.CombinedOutput() - if err != nil { - t.Fatal(err) - } + cmd := mainDockerInstance.Command("nslookup", []string{"google.fr"}, []string{}) + cmd.CombinedOutput() time.Sleep(1 * time.Second) // a quick sleep to let events to be added to the dump err = test.StopActivityDump(dump.Name, "", "") @@ -449,48 +448,111 @@ func TestAnomalyDetectionWarmup(t *testing.T) { } time.Sleep(6 * time.Second) // a quick sleep to let the profile to be loaded (5sec debounce + 1sec spare) - t.Run("anomaly-detection-warmup", func(t *testing.T) { + testDockerInstance1, _, err := test.StartADockerGetDump() + if err != nil { + t.Fatal(err) + } + defer testDockerInstance1.stop() + + t.Run("anomaly-detection-warmup-1", func(t *testing.T) { test.GetCustomEventSent(t, func() error { - cmd := dockerInstance.Command("getconf", []string{"-a"}, []string{}) - _, err = cmd.CombinedOutput() - return err + cmd := testDockerInstance1.Command("nslookup", []string{"foo.bar"}, []string{}) + cmd.CombinedOutput() + return nil }, func(r *rules.Rule, event *events.CustomEvent) bool { if r.Rule.ID == events.AnomalyDetectionRuleID { t.Fatal("Should not had receive any anomaly detection during warm up.") } return false - }, time.Second*3, model.ExecEventType) + }, time.Second*5, model.DNSEventType) }) - time.Sleep(time.Second * 10) - - t.Run("anomaly-detection-warmed-up-autolearned", func(t *testing.T) { + t.Run("anomaly-detection-warmed-up-autolearned-1", func(t *testing.T) { test.GetCustomEventSent(t, func() error { - cmd := dockerInstance.Command("getconf", []string{"-a"}, []string{}) - _, err = cmd.CombinedOutput() - return err + cmd := testDockerInstance1.Command("nslookup", []string{"foo.bar"}, []string{}) + cmd.CombinedOutput() + return nil }, func(r *rules.Rule, event *events.CustomEvent) bool { if r.Rule.ID == events.AnomalyDetectionRuleID { - t.Fatalf("Should not had receive any anomaly detection because of auto learn during warm up") + t.Fatal("Should not had receive any anomaly detection during warm up.") } return false - }, time.Second*3, model.ExecEventType) + }, time.Second*3, model.DNSEventType) }) - t.Run("anomaly-detection-warmed-up", func(t *testing.T) { - err = test.GetCustomEventSent(t, func() error { - cmd := dockerInstance.Command("getent", []string{"hosts"}, []string{}) - _, err = cmd.CombinedOutput() - return err + t.Run("anomaly-detection-warmed-up-not-autolearned-1", func(t *testing.T) { + test.GetCustomEventSent(t, func() error { + cmd := testDockerInstance1.Command("nslookup", []string{"foo.baz"}, []string{}) + cmd.CombinedOutput() + return nil }, func(r *rules.Rule, event *events.CustomEvent) bool { assert.Equal(t, events.AnomalyDetectionRuleID, r.Rule.ID, "wrong custom event rule ID") return true - }, time.Second*3, model.ExecEventType) + }, time.Second*3, model.DNSEventType) if err != nil { t.Error(err) } }) + testDockerInstance2, _, err := test.StartADockerGetDump() + if err != nil { + t.Fatal(err) + } + defer testDockerInstance1.stop() + + t.Run("anomaly-detection-warmup-2", func(t *testing.T) { + test.GetCustomEventSent(t, func() error { + cmd := testDockerInstance2.Command("nslookup", []string{"foo.baz"}, []string{}) + cmd.CombinedOutput() + return nil + }, func(r *rules.Rule, event *events.CustomEvent) bool { + if r.Rule.ID == events.AnomalyDetectionRuleID { + t.Fatal("Should not had receive any anomaly detection during warm up.") + } + return false + }, time.Second*5, model.DNSEventType) + }) + + // already sleep for timeout for warmup period + 2sec spare (5s) + + t.Run("anomaly-detection-warmed-up-autolearned-2", func(t *testing.T) { + test.GetCustomEventSent(t, func() error { + cmd := testDockerInstance2.Command("nslookup", []string{"foo.bar"}, []string{}) + cmd.CombinedOutput() + return nil + }, func(r *rules.Rule, event *events.CustomEvent) bool { + if r.Rule.ID == events.AnomalyDetectionRuleID { + t.Fatal("Should not had receive any anomaly detection during warm up.") + } + return false + }, time.Second*3, model.DNSEventType) + }) + + t.Run("anomaly-detection-warmed-up-autolearned-bis-2", func(t *testing.T) { + test.GetCustomEventSent(t, func() error { + cmd := testDockerInstance2.Command("nslookup", []string{"foo.baz"}, []string{}) + cmd.CombinedOutput() + return nil + }, func(r *rules.Rule, event *events.CustomEvent) bool { + if r.Rule.ID == events.AnomalyDetectionRuleID { + t.Fatal("Should not had receive any anomaly detection during warm up.") + } + return false + }, time.Second*3, model.DNSEventType) + }) + + t.Run("anomaly-detection-warmed-up-autolearned-bis-1", func(t *testing.T) { + test.GetCustomEventSent(t, func() error { + cmd := testDockerInstance1.Command("nslookup", []string{"foo.baz"}, []string{}) + cmd.CombinedOutput() + return nil + }, func(r *rules.Rule, event *events.CustomEvent) bool { + if r.Rule.ID == events.AnomalyDetectionRuleID { + t.Fatal("Should not had receive any anomaly detection during warm up.") + } + return false + }, time.Second*3, model.DNSEventType) + }) } func TestSecurityProfileReinsertionPeriod(t *testing.T) { From 04b77a72cfd7ce6fa49c12fe21c6f4d85d7159fe Mon Sep 17 00:00:00 2001 From: Arthur Bellal Date: Fri, 9 Jun 2023 12:38:16 +0200 Subject: [PATCH 69/76] (rcm) simplify the RC thin client (#17468) * (rcm) simplify the RC thin client * simplify listeners as well * fix apm and security agent * fix cws profiles * fix apm client --- .../admission/patch/rc_provider.go | 6 +- .../admission/patch/rc_provider_test.go | 2 +- pkg/config/remote/client.go | 150 ++----- pkg/remoteconfig/state/README.md | 5 + pkg/remoteconfig/state/configs.go | 400 +----------------- pkg/remoteconfig/state/configs_asm.go | 159 +++++++ pkg/remoteconfig/state/products.go | 36 ++ pkg/remoteconfig/state/repository.go | 8 +- pkg/remoteconfig/state/repository_test.go | 84 ++-- pkg/security/rconfig/policies.go | 12 +- pkg/security/rconfig/profiles.go | 4 +- pkg/trace/config/config.go | 2 +- .../remoteconfighandler/mock_remote_client.go | 12 +- .../remote_config_handler.go | 5 +- .../remote_config_handler_test.go | 18 +- 15 files changed, 341 insertions(+), 562 deletions(-) create mode 100644 pkg/remoteconfig/state/README.md create mode 100644 pkg/remoteconfig/state/configs_asm.go create mode 100644 pkg/remoteconfig/state/products.go diff --git a/pkg/clusteragent/admission/patch/rc_provider.go b/pkg/clusteragent/admission/patch/rc_provider.go index c24c45d04cb76..48a8b03648b52 100644 --- a/pkg/clusteragent/admission/patch/rc_provider.go +++ b/pkg/clusteragent/admission/patch/rc_provider.go @@ -41,13 +41,13 @@ func newRemoteConfigProvider(client *remote.Client, isLeaderNotif <-chan struct{ func (rcp *remoteConfigProvider) start(stopCh <-chan struct{}) { log.Info("Starting remote-config patch provider") - rcp.client.RegisterAPMTracing(rcp.process) + rcp.client.Subscribe(state.ProductAPMTracing, rcp.process) rcp.client.Start() for { select { case <-rcp.isLeaderNotif: log.Info("Got a leader notification, polling from remote-config") - rcp.process(rcp.client.APMTracingConfigs()) + rcp.process(rcp.client.GetConfigs(state.ProductAPMTracing)) case <-stopCh: log.Info("Shutting down remote-config patch provider") rcp.client.Close() @@ -63,7 +63,7 @@ func (rcp *remoteConfigProvider) subscribe(kind TargetObjKind) chan PatchRequest } // process is the event handler called by the RC client on config updates -func (rcp *remoteConfigProvider) process(update map[string]state.APMTracingConfig) { +func (rcp *remoteConfigProvider) process(update map[string]state.RawConfig) { log.Infof("Got %d updates from remote-config", len(update)) var valid, invalid float64 for path, config := range update { diff --git a/pkg/clusteragent/admission/patch/rc_provider_test.go b/pkg/clusteragent/admission/patch/rc_provider_test.go index 28e4117cbef90..1362f73c53183 100644 --- a/pkg/clusteragent/admission/patch/rc_provider_test.go +++ b/pkg/clusteragent/admission/patch/rc_provider_test.go @@ -41,7 +41,7 @@ func TestProcess(t *testing.T) { rcp, err := newRemoteConfigProvider(&remote.Client{}, make(chan struct{}), "dev") require.NoError(t, err) notifs := rcp.subscribe(KindDeployment) - in := map[string]state.APMTracingConfig{ + in := map[string]state.RawConfig{ "path1": {Config: genConfig("dev", "deployment")}, // valid config "path2": {Config: []byte("invalid")}, // invalid json "path3": {Config: genConfig("dev", "wrong")}, // kind mismatch diff --git a/pkg/config/remote/client.go b/pkg/config/remote/client.go index 44838b24b52bb..1085a7d6c3684 100644 --- a/pkg/config/remote/client.go +++ b/pkg/config/remote/client.go @@ -72,12 +72,7 @@ type Client struct { state *state.Repository - // Listeners - apmListeners []func(update map[string]state.APMSamplingConfig) - cwsListeners []func(update map[string]state.ConfigCWSDD) - cwsCustomListeners []func(update map[string]state.ConfigCWSCustom) - cwsProfilesListeners []func(update map[string]state.ConfigCWSProfiles) - apmTracingListeners []func(update map[string]state.APMTracingConfig) + listeners map[string][]func(update map[string]state.RawConfig) } // agentGRPCConfigFetcher defines how to retrieve config updates over a @@ -187,24 +182,21 @@ func newClient(agentName string, updater ConfigUpdater, doTufVerification bool, ctx, close := context.WithCancel(context.Background()) return &Client{ - ID: generateID(), - startupSync: sync.Once{}, - ctx: ctx, - close: close, - agentName: agentName, - agentVersion: agentVersion, - clusterName: clusterName, - clusterID: clusterID, - cwsWorkloads: make([]string, 0), - products: data.ProductListToString(products), - state: repository, - pollInterval: pollInterval, - backoffPolicy: backoffPolicy, - apmListeners: make([]func(update map[string]state.APMSamplingConfig), 0), - cwsListeners: make([]func(update map[string]state.ConfigCWSDD), 0), - cwsCustomListeners: make([]func(update map[string]state.ConfigCWSCustom), 0), - apmTracingListeners: make([]func(update map[string]state.APMTracingConfig), 0), - updater: updater, + ID: generateID(), + startupSync: sync.Once{}, + ctx: ctx, + close: close, + agentName: agentName, + agentVersion: agentVersion, + clusterName: clusterName, + clusterID: clusterID, + cwsWorkloads: make([]string, 0), + products: data.ProductListToString(products), + state: repository, + pollInterval: pollInterval, + backoffPolicy: backoffPolicy, + listeners: make(map[string][]func(update map[string]state.RawConfig)), + updater: updater, }, nil } @@ -223,6 +215,28 @@ func (c *Client) Close() { c.close() } +// Subscribe subscribes to config updates of a product. +func (c *Client) Subscribe(product string, fn func(update map[string]state.RawConfig)) { + c.m.Lock() + defer c.m.Unlock() + c.listeners[product] = append(c.listeners[product], fn) + fn(c.state.GetConfigs(product)) +} + +// GetConfigs returns the current configs applied of a product. +func (c *Client) GetConfigs(product string) map[string]state.RawConfig { + c.m.Lock() + defer c.m.Unlock() + return c.state.GetConfigs(product) +} + +// SetCWSWorkloads updates the list of workloads that needs cws profiles +func (c *Client) SetCWSWorkloads(workloads []string) { + c.m.Lock() + defer c.m.Unlock() + c.cwsWorkloads = workloads +} + func (c *Client) startFn() { go c.pollLoop() } @@ -280,32 +294,13 @@ func (c *Client) update() error { c.m.Lock() defer c.m.Unlock() - if containsProduct(changedProducts, state.ProductAPMSampling) { - for _, listener := range c.apmListeners { - listener(c.state.APMConfigs()) - } - } - if containsProduct(changedProducts, state.ProductCWSDD) { - for _, listener := range c.cwsListeners { - listener(c.state.CWSDDConfigs()) - } - } - if containsProduct(changedProducts, state.ProductCWSCustom) { - for _, listener := range c.cwsCustomListeners { - listener(c.state.CWSCustomConfigs()) - } - } - if containsProduct(changedProducts, state.ProductCWSProfiles) { - for _, listener := range c.cwsProfilesListeners { - listener(c.state.CWSProfilesConfigs()) - } - } - if containsProduct(changedProducts, state.ProductAPMTracing) { - for _, listener := range c.apmTracingListeners { - listener(c.state.APMTracingConfigs()) + for product, productListeners := range c.listeners { + if containsProduct(changedProducts, product) { + for _, listener := range productListeners { + listener(c.state.GetConfigs(product)) + } } } - return nil } @@ -319,65 +314,6 @@ func containsProduct(products []string, product string) bool { return false } -// RegisterAPMUpdate registers a callback function to be called after a successful client update that will -// contain the current state of the APMSampling product. -func (c *Client) RegisterAPMUpdate(fn func(update map[string]state.APMSamplingConfig)) { - c.m.Lock() - defer c.m.Unlock() - c.apmListeners = append(c.apmListeners, fn) - fn(c.state.APMConfigs()) -} - -// RegisterCWSDDUpdate registers a callback function to be called after a successful client update that will -// contain the current state of the CWSDD product. -func (c *Client) RegisterCWSDDUpdate(fn func(update map[string]state.ConfigCWSDD)) { - c.m.Lock() - defer c.m.Unlock() - c.cwsListeners = append(c.cwsListeners, fn) - fn(c.state.CWSDDConfigs()) -} - -// RegisterCWSCustomUpdate registers a callback function to be called after a successful client update that will -// contain the current state of the CWS_CUSTOM product. -func (c *Client) RegisterCWSCustomUpdate(fn func(update map[string]state.ConfigCWSCustom)) { - c.m.Lock() - defer c.m.Unlock() - c.cwsCustomListeners = append(c.cwsCustomListeners, fn) - fn(c.state.CWSCustomConfigs()) -} - -// RegisterCWSCustomUpdate registers a callback function to be called after a successful client update that will -// contain the current state of the CWS_SECURITY_PROFILES product. -func (c *Client) RegisterCWSProfilesUpdate(fn func(update map[string]state.ConfigCWSProfiles)) { - c.m.Lock() - defer c.m.Unlock() - c.cwsProfilesListeners = append(c.cwsProfilesListeners, fn) - fn(c.state.CWSProfilesConfigs()) -} - -// RegisterAPMTracing registers a callback function to be called after a successful client update that will -// contain the current state of the APMTracing product. -func (c *Client) RegisterAPMTracing(fn func(update map[string]state.APMTracingConfig)) { - c.m.Lock() - defer c.m.Unlock() - c.apmTracingListeners = append(c.apmTracingListeners, fn) - fn(c.state.APMTracingConfigs()) -} - -// APMTracingConfigs returns the current set of valid APM Tracing configs -func (c *Client) APMTracingConfigs() map[string]state.APMTracingConfig { - c.m.Lock() - defer c.m.Unlock() - return c.state.APMTracingConfigs() -} - -// SetCWSWorkloads updates the list of workloads that needs cws profiles -func (c *Client) SetCWSWorkloads(workloads []string) { - c.m.Lock() - defer c.m.Unlock() - c.cwsWorkloads = workloads -} - func (c *Client) applyUpdate(pbUpdate *pbgo.ClientGetConfigsResponse) ([]string, error) { fileMap := make(map[string][]byte, len(pbUpdate.TargetFiles)) for _, f := range pbUpdate.TargetFiles { diff --git a/pkg/remoteconfig/state/README.md b/pkg/remoteconfig/state/README.md new file mode 100644 index 0000000000000..a42ffb54e49b9 --- /dev/null +++ b/pkg/remoteconfig/state/README.md @@ -0,0 +1,5 @@ +# Remote Config Go client + +This package powers the Remote Config client shipped in the Go tracer and in all the agent processes (core-agent, trace-agent, system-probe, ...). + +To add a new product simply add it to `products.go` as a constant and in the `validProducts` set. diff --git a/pkg/remoteconfig/state/configs.go b/pkg/remoteconfig/state/configs.go index 0df551cc966f8..62199f41fb94f 100644 --- a/pkg/remoteconfig/state/configs.go +++ b/pkg/remoteconfig/state/configs.go @@ -13,308 +13,47 @@ import ( "github.com/DataDog/go-tuf/data" ) -/* - To add support for a new product: - - 1. Add the definition of the product to the const() block of products and the `allProducts` list. - 2. Define the serialized configuration struct as well as a function to parse the config from a []byte. - 3. Add the product to the `parseConfig` function - 4. Add a method on the `Repository` to retrieved typed configs for the product. -*/ - -var allProducts = []string{ProductAPMSampling, ProductCWSDD, ProductCWSCustom, ProductCWSProfiles, ProductASM, ProductASMFeatures, ProductASMDD, ProductASMData, ProductAPMTracing} - -const ( - // ProductAPMSampling is the apm sampling product - ProductAPMSampling = "APM_SAMPLING" - // ProductCWSDD is the cloud workload security product managed by datadog employees - ProductCWSDD = "CWS_DD" - // ProductCWSCustom is the cloud workload security product managed by datadog customers - ProductCWSCustom = "CWS_CUSTOM" - // ProductCWSProfile is the cloud workload security profile product - ProductCWSProfiles = "CWS_SECURITY_PROFILES" - // ProductASM is the ASM product used by customers to issue rules configurations - ProductASM = "ASM" - // ProductASMFeatures is the ASM product used form ASM activation through remote config - ProductASMFeatures = "ASM_FEATURES" - // ProductASMDD is the application security monitoring product managed by datadog employees - ProductASMDD = "ASM_DD" - // ProductASMData is the ASM product used to configure WAF rules data - ProductASMData = "ASM_DATA" - // ProductAPMTracing is the apm tracing product - ProductAPMTracing = "APM_TRACING" -) - // ErrNoConfigVersion occurs when a target file's custom meta is missing the config version var ErrNoConfigVersion = errors.New("version missing in custom file meta") func parseConfig(product string, raw []byte, metadata Metadata) (interface{}, error) { - var c interface{} - var err error + if _, validProduct := validProducts[product]; !validProduct { + return nil, fmt.Errorf("unknown product: %s", product) + } + switch product { - case ProductAPMSampling: - c, err = parseConfigAPMSampling(raw, metadata) + // ASM products are parsed directly in this client case ProductASMFeatures: - c, err = parseASMFeaturesConfig(raw, metadata) - case ProductCWSDD: - c, err = parseConfigCWSDD(raw, metadata) - case ProductCWSCustom: - c, err = parseConfigCWSCustom(raw, metadata) - case ProductCWSProfiles: - c, err = parseConfigCWSProfiles(raw, metadata) - case ProductASM: - c, err = parseConfigASM(raw, metadata) + return parseASMFeaturesConfig(raw, metadata) case ProductASMDD: - c, err = parseConfigASMDD(raw, metadata) + return parseConfigASMDD(raw, metadata) case ProductASMData: - c, err = parseConfigASMData(raw, metadata) - case ProductAPMTracing: - c, err = parseConfigAPMTracing(raw, metadata) + return parseConfigASMData(raw, metadata) + // Other products are parsed separately default: - return nil, fmt.Errorf("unknown product - %s", product) - } - - return c, err -} - -// APMSamplingConfig is a deserialized APM Sampling configuration file -// along with its associated remote config metadata. -type APMSamplingConfig struct { - Config []byte - Metadata Metadata -} - -func parseConfigAPMSampling(data []byte, metadata Metadata) (APMSamplingConfig, error) { - // We actually don't parse the payload here, we delegate this responsibility to the trace agent - return APMSamplingConfig{ - Config: data, - Metadata: metadata, - }, nil -} - -// APMConfigs returns the currently active APM configs -func (r *Repository) APMConfigs() map[string]APMSamplingConfig { - typedConfigs := make(map[string]APMSamplingConfig) - - configs := r.getConfigs(ProductAPMSampling) - - for path, conf := range configs { - // We control this, so if this has gone wrong something has gone horribly wrong - typed, ok := conf.(APMSamplingConfig) - if !ok { - panic("unexpected config stored as APMSamplingConfig") - } - - typedConfigs[path] = typed - } - - return typedConfigs -} - -// ConfigCWSDD is a deserialized CWS DD configuration file along with its -// associated remote config metadata -type ConfigCWSDD struct { - Config []byte - Metadata Metadata -} - -func parseConfigCWSDD(data []byte, metadata Metadata) (ConfigCWSDD, error) { - return ConfigCWSDD{ - Config: data, - Metadata: metadata, - }, nil -} - -// CWSDDConfigs returns the currently active CWSDD config files -func (r *Repository) CWSDDConfigs() map[string]ConfigCWSDD { - typedConfigs := make(map[string]ConfigCWSDD) - - configs := r.getConfigs(ProductCWSDD) - - for path, conf := range configs { - // We control this, so if this has gone wrong something has gone horribly wrong - typed, ok := conf.(ConfigCWSDD) - if !ok { - panic("unexpected config stored as CWSDD Config") - } - - typedConfigs[path] = typed - } - - return typedConfigs -} - -// ConfigCWSCustom is a deserialized CWS Custom configuration file along with its -// associated remote config metadata -type ConfigCWSCustom struct { - Config []byte - Metadata Metadata -} - -func parseConfigCWSCustom(data []byte, metadata Metadata) (ConfigCWSCustom, error) { - return ConfigCWSCustom{ - Config: data, - Metadata: metadata, - }, nil -} - -// CWSCustomConfigs returns the currently active CWSCustom config files -func (r *Repository) CWSCustomConfigs() map[string]ConfigCWSCustom { - typedConfigs := make(map[string]ConfigCWSCustom) - - configs := r.getConfigs(ProductCWSCustom) - - for path, conf := range configs { - // We control this, so if this has gone wrong something has gone horribly wrong - typed, ok := conf.(ConfigCWSCustom) - if !ok { - panic("unexpected config stored as CWS_CUSTOM Config") - } - - typedConfigs[path] = typed - } - - return typedConfigs -} - -// ConfigCWSProfiles is a deserialized CWS Profile configuration file along with its -// associated remote config metadata -type ConfigCWSProfiles struct { - Config []byte - Metadata Metadata -} - -func parseConfigCWSProfiles(data []byte, metadata Metadata) (ConfigCWSProfiles, error) { - return ConfigCWSProfiles{ - Config: data, - Metadata: metadata, - }, nil -} - -// CWSProfilesConfigs returns the currently active CWSProfiles config files -func (r *Repository) CWSProfilesConfigs() map[string]ConfigCWSProfiles { - typedConfigs := make(map[string]ConfigCWSProfiles) - - configs := r.getConfigs(ProductCWSProfiles) - - for path, conf := range configs { - // We control this, so if this has gone wrong something has gone horribly wrong - typed, ok := conf.(ConfigCWSProfiles) - if !ok { - panic("unexpected config stored as CWS_SECURITY_PROFILES Config") - } - - typedConfigs[path] = typed - } - - return typedConfigs -} - -// ConfigASM is a deserialized ASM configuration file along with its -// associated remote config metadata -type ConfigASM struct { - Config []byte - Metadata Metadata -} - -func parseConfigASM(data []byte, metadata Metadata) (ConfigASMDD, error) { - return ConfigASMDD{ - Config: data, - Metadata: metadata, - }, nil -} - -// ASMConfigs returns the currently active ASM configs -func (r *Repository) ASMConfigs() map[string]ConfigASM { - typedConfigs := make(map[string]ConfigASM) - - configs := r.getConfigs(ProductASM) - - for path, conf := range configs { - // We control this, so if this has gone wrong something has gone horribly wrong - typed, ok := conf.(ConfigASM) - if !ok { - panic("unexpected config stored as ASM Config") - } - - typedConfigs[path] = typed + return RawConfig{ + Config: raw, + Metadata: metadata, + }, nil } - - return typedConfigs } -// ConfigASMDD is a deserialized ASM DD configuration file along with its -// associated remote config metadata -type ConfigASMDD struct { +// RawConfig holds a config that will be parsed separately +type RawConfig struct { Config []byte Metadata Metadata } -func parseConfigASMDD(data []byte, metadata Metadata) (ConfigASMDD, error) { - return ConfigASMDD{ - Config: data, - Metadata: metadata, - }, nil -} - -// ASMDDConfigs returns the currently active ASMDD configs -func (r *Repository) ASMDDConfigs() map[string]ConfigASMDD { - typedConfigs := make(map[string]ConfigASMDD) - - configs := r.getConfigs(ProductASMDD) - - for path, conf := range configs { - // We control this, so if this has gone wrong something has gone horribly wrong - typed, ok := conf.(ConfigASMDD) - if !ok { - panic("unexpected config stored as ASMDD Config") - } - - typedConfigs[path] = typed - } - - return typedConfigs -} - -// ASMFeaturesConfig is a deserialized configuration file that indicates whether ASM should be enabled -// within a tracer, along with its associated remote config metadata. -type ASMFeaturesConfig struct { - Config ASMFeaturesData - Metadata Metadata -} - -// ASMFeaturesData describes the enabled state of ASM features -type ASMFeaturesData struct { - ASM struct { - Enabled bool `json:"enabled"` - } `json:"asm"` -} - -func parseASMFeaturesConfig(data []byte, metadata Metadata) (ASMFeaturesConfig, error) { - var f ASMFeaturesData - - err := json.Unmarshal(data, &f) - if err != nil { - return ASMFeaturesConfig{}, nil - } - - return ASMFeaturesConfig{ - Config: f, - Metadata: metadata, - }, nil -} - -// ASMFeaturesConfigs returns the currently active ASMFeatures configs -func (r *Repository) ASMFeaturesConfigs() map[string]ASMFeaturesConfig { - typedConfigs := make(map[string]ASMFeaturesConfig) - - configs := r.getConfigs(ProductASMFeatures) +// GetRawConfigs returns the current configs of a given product +func (r *Repository) GetConfigs(product string) map[string]RawConfig { + typedConfigs := make(map[string]RawConfig) + configs := r.getConfigs(product) for path, conf := range configs { // We control this, so if this has gone wrong something has gone horribly wrong - typed, ok := conf.(ASMFeaturesConfig) + typed, ok := conf.(RawConfig) if !ok { - panic("unexpected config stored as ASMFeaturesConfig") + panic("unexpected config stored as RawConfig") } typedConfigs[path] = typed @@ -323,103 +62,6 @@ func (r *Repository) ASMFeaturesConfigs() map[string]ASMFeaturesConfig { return typedConfigs } -// ApplyState represents the status of a configuration application by a remote configuration client -// Clients need to either ack the correct application of received configurations, or communicate that -// they haven't applied it yet, or communicate any error that may have happened while doing so -type ApplyState uint64 - -const ( - ApplyStateUnknown ApplyState = iota - ApplyStateUnacknowledged - ApplyStateAcknowledged - ApplyStateError -) - -// ApplyStatus is the processing status for a given configuration. -// It basically represents whether a config was successfully processed and apply, or if an error occurred -type ApplyStatus struct { - State ApplyState - Error string -} - -// ASMDataConfig is a deserialized configuration file that holds rules data that can be used -// by the ASM WAF for specific features (example: ip blocking). -type ASMDataConfig struct { - Config ASMDataRulesData - Metadata Metadata -} - -// ASMDataRulesData is a serializable array of rules data entries -type ASMDataRulesData struct { - RulesData []ASMDataRuleData `json:"rules_data"` -} - -// ASMDataRuleData is an entry in the rules data list held by an ASMData configuration -type ASMDataRuleData struct { - ID string `json:"id"` - Type string `json:"type"` - Data []ASMDataRuleDataEntry `json:"data"` -} - -// ASMDataRuleDataEntry represents a data entry in a rule data file -type ASMDataRuleDataEntry struct { - Expiration int64 `json:"expiration,omitempty"` - Value string `json:"value"` -} - -func parseConfigASMData(data []byte, metadata Metadata) (ASMDataConfig, error) { - cfg := ASMDataConfig{ - Metadata: metadata, - } - err := json.Unmarshal(data, &cfg.Config) - return cfg, err -} - -// ASMDataConfigs returns the currently active ASMData configs -func (r *Repository) ASMDataConfigs() map[string]ASMDataConfig { - typedConfigs := make(map[string]ASMDataConfig) - configs := r.getConfigs(ProductASMData) - - for path, cfg := range configs { - // We control this, so if this has gone wrong something has gone horribly wrong - typed, ok := cfg.(ASMDataConfig) - if !ok { - panic("unexpected config stored as ASMDataConfig") - } - typedConfigs[path] = typed - } - - return typedConfigs -} - -type APMTracingConfig struct { - Config []byte - Metadata Metadata -} - -func parseConfigAPMTracing(data []byte, metadata Metadata) (APMTracingConfig, error) { - // Delegate the parsing responsibility to the cluster agent - return APMTracingConfig{ - Config: data, - Metadata: metadata, - }, nil -} - -// APMTracingConfigs returns the currently active APMTracing configs -func (r *Repository) APMTracingConfigs() map[string]APMTracingConfig { - typedConfigs := make(map[string]APMTracingConfig) - configs := r.getConfigs(ProductAPMTracing) - for path, conf := range configs { - // We control this, so if this has gone wrong something has gone horribly wrong - typed, ok := conf.(APMTracingConfig) - if !ok { - panic("unexpected config stored as APMTracingConfig") - } - typedConfigs[path] = typed - } - return typedConfigs -} - // Metadata stores remote config metadata for a given configuration type Metadata struct { Product string diff --git a/pkg/remoteconfig/state/configs_asm.go b/pkg/remoteconfig/state/configs_asm.go new file mode 100644 index 0000000000000..ac7a918e8e2a5 --- /dev/null +++ b/pkg/remoteconfig/state/configs_asm.go @@ -0,0 +1,159 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2022-present Datadog, Inc. + +package state + +import ( + "encoding/json" +) + +// ConfigASMDD is a deserialized ASM DD configuration file along with its +// associated remote config metadata +type ConfigASMDD struct { + Config []byte + Metadata Metadata +} + +func parseConfigASMDD(data []byte, metadata Metadata) (ConfigASMDD, error) { + return ConfigASMDD{ + Config: data, + Metadata: metadata, + }, nil +} + +// ASMDDConfigs returns the currently active ASMDD configs +func (r *Repository) ASMDDConfigs() map[string]ConfigASMDD { + typedConfigs := make(map[string]ConfigASMDD) + + configs := r.getConfigs(ProductASMDD) + + for path, conf := range configs { + // We control this, so if this has gone wrong something has gone horribly wrong + typed, ok := conf.(ConfigASMDD) + if !ok { + panic("unexpected config stored as ASMDD Config") + } + + typedConfigs[path] = typed + } + + return typedConfigs +} + +// ASMFeaturesConfig is a deserialized configuration file that indicates whether ASM should be enabled +// within a tracer, along with its associated remote config metadata. +type ASMFeaturesConfig struct { + Config ASMFeaturesData + Metadata Metadata +} + +// ASMFeaturesData describes the enabled state of ASM features +type ASMFeaturesData struct { + ASM struct { + Enabled bool `json:"enabled"` + } `json:"asm"` +} + +func parseASMFeaturesConfig(data []byte, metadata Metadata) (ASMFeaturesConfig, error) { + var f ASMFeaturesData + + err := json.Unmarshal(data, &f) + if err != nil { + return ASMFeaturesConfig{}, nil + } + + return ASMFeaturesConfig{ + Config: f, + Metadata: metadata, + }, nil +} + +// ASMFeaturesConfigs returns the currently active ASMFeatures configs +func (r *Repository) ASMFeaturesConfigs() map[string]ASMFeaturesConfig { + typedConfigs := make(map[string]ASMFeaturesConfig) + + configs := r.getConfigs(ProductASMFeatures) + + for path, conf := range configs { + // We control this, so if this has gone wrong something has gone horribly wrong + typed, ok := conf.(ASMFeaturesConfig) + if !ok { + panic("unexpected config stored as ASMFeaturesConfig") + } + + typedConfigs[path] = typed + } + + return typedConfigs +} + +// ApplyState represents the status of a configuration application by a remote configuration client +// Clients need to either ack the correct application of received configurations, or communicate that +// they haven't applied it yet, or communicate any error that may have happened while doing so +type ApplyState uint64 + +const ( + ApplyStateUnknown ApplyState = iota + ApplyStateUnacknowledged + ApplyStateAcknowledged + ApplyStateError +) + +// ApplyStatus is the processing status for a given configuration. +// It basically represents whether a config was successfully processed and apply, or if an error occurred +type ApplyStatus struct { + State ApplyState + Error string +} + +// ASMDataConfig is a deserialized configuration file that holds rules data that can be used +// by the ASM WAF for specific features (example: ip blocking). +type ASMDataConfig struct { + Config ASMDataRulesData + Metadata Metadata +} + +// ASMDataRulesData is a serializable array of rules data entries +type ASMDataRulesData struct { + RulesData []ASMDataRuleData `json:"rules_data"` +} + +// ASMDataRuleData is an entry in the rules data list held by an ASMData configuration +type ASMDataRuleData struct { + ID string `json:"id"` + Type string `json:"type"` + Data []ASMDataRuleDataEntry `json:"data"` +} + +// ASMDataRuleDataEntry represents a data entry in a rule data file +type ASMDataRuleDataEntry struct { + Expiration int64 `json:"expiration,omitempty"` + Value string `json:"value"` +} + +func parseConfigASMData(data []byte, metadata Metadata) (ASMDataConfig, error) { + cfg := ASMDataConfig{ + Metadata: metadata, + } + err := json.Unmarshal(data, &cfg.Config) + return cfg, err +} + +// ASMDataConfigs returns the currently active ASMData configs +func (r *Repository) ASMDataConfigs() map[string]ASMDataConfig { + typedConfigs := make(map[string]ASMDataConfig) + configs := r.getConfigs(ProductASMData) + + for path, cfg := range configs { + // We control this, so if this has gone wrong something has gone horribly wrong + typed, ok := cfg.(ASMDataConfig) + if !ok { + panic("unexpected config stored as ASMDataConfig") + } + typedConfigs[path] = typed + } + + return typedConfigs +} diff --git a/pkg/remoteconfig/state/products.go b/pkg/remoteconfig/state/products.go new file mode 100644 index 0000000000000..2da8c19823be7 --- /dev/null +++ b/pkg/remoteconfig/state/products.go @@ -0,0 +1,36 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2022-present Datadog, Inc. + +package state + +var validProducts = map[string]struct{}{ + ProductAPMSampling: {}, + ProductCWSDD: {}, + ProductCWSCustom: {}, + ProductCWSProfiles: {}, + ProductASMFeatures: {}, + ProductASMDD: {}, + ProductASMData: {}, + ProductAPMTracing: {}, +} + +const ( + // ProductAPMSampling is the apm sampling product + ProductAPMSampling = "APM_SAMPLING" + // ProductCWSDD is the cloud workload security product managed by datadog employees + ProductCWSDD = "CWS_DD" + // ProductCWSCustom is the cloud workload security product managed by datadog customers + ProductCWSCustom = "CWS_CUSTOM" + // ProductCWSProfile is the cloud workload security profile product + ProductCWSProfiles = "CWS_SECURITY_PROFILES" + // ProductASMFeatures is the ASM product used form ASM activation through remote config + ProductASMFeatures = "ASM_FEATURES" + // ProductASMDD is the application security monitoring product managed by datadog employees + ProductASMDD = "ASM_DD" + // ProductASMData is the ASM product used to configure WAF rules data + ProductASMData = "ASM_DATA" + // ProductAPMTracing is the apm tracing product + ProductAPMTracing = "APM_TRACING" +) diff --git a/pkg/remoteconfig/state/repository.go b/pkg/remoteconfig/state/repository.go index eedbabd38a31b..15fa99681c45f 100644 --- a/pkg/remoteconfig/state/repository.go +++ b/pkg/remoteconfig/state/repository.go @@ -92,7 +92,7 @@ func NewRepository(embeddedRoot []byte) (*Repository, error) { } configs := make(map[string]map[string]interface{}) - for _, product := range allProducts { + for product := range validProducts { configs[product] = make(map[string]interface{}) } @@ -117,7 +117,7 @@ func NewRepository(embeddedRoot []byte) (*Repository, error) { // to not have to send the initial "embedded" root. func NewUnverifiedRepository() (*Repository, error) { configs := make(map[string]map[string]interface{}) - for _, product := range allProducts { + for product := range validProducts { configs[product] = make(map[string]interface{}) } @@ -356,8 +356,8 @@ type updateResult struct { func newUpdateResult() updateResult { changed := make(map[string]map[string]interface{}) - for _, p := range allProducts { - changed[p] = make(map[string]interface{}) + for product := range validProducts { + changed[product] = make(map[string]interface{}) } return updateResult{ diff --git a/pkg/remoteconfig/state/repository_test.go b/pkg/remoteconfig/state/repository_test.go index bb699caf50dc2..37057eb86a41d 100644 --- a/pkg/remoteconfig/state/repository_test.go +++ b/pkg/remoteconfig/state/repository_test.go @@ -49,8 +49,8 @@ func TestEmptyUpdateZeroTypes(t *testing.T) { updatedProducts, err := r.Update(emptyUpdate) assert.Nil(t, err) assert.Equal(t, 0, len(updatedProducts), "An empty update shouldn't indicate any updated products") - assert.Equal(t, 0, len(r.APMConfigs()), "An empty update shoudldn't add any APM configs") - assert.Equal(t, 0, len(r.CWSDDConfigs()), "An empty update shouldn't add any CWSDD configs") + assert.Equal(t, 0, len(r.GetConfigs(ProductAPMSampling)), "An empty update shoudldn't add any APM configs") + assert.Equal(t, 0, len(r.GetConfigs(ProductCWSDD)), "An empty update shouldn't add any CWSDD configs") state, err := r.CurrentState() assert.NoError(t, err) @@ -66,8 +66,8 @@ func TestEmptyUpdateZeroTypes(t *testing.T) { updatedProducts, err = r.Update(emptyUpdate) assert.Nil(t, err) assert.Equal(t, 0, len(updatedProducts), "An empty update shouldn't indicate any updated products") - assert.Equal(t, 0, len(r.APMConfigs()), "An empty update shoudldn't add any APM configs") - assert.Equal(t, 0, len(r.CWSDDConfigs()), "An empty update shouldn't add any CWSDD configs") + assert.Equal(t, 0, len(r.GetConfigs(ProductAPMSampling)), "An empty update shoudldn't add any APM configs") + assert.Equal(t, 0, len(r.GetConfigs(ProductCWSDD)), "An empty update shouldn't add any CWSDD configs") state, err = r.CurrentState() assert.NoError(t, err) @@ -95,8 +95,8 @@ func TestEmptyUpdateNilTypes(t *testing.T) { updatedProducts, err := r.Update(emptyUpdate) assert.Nil(t, err) assert.Equal(t, 0, len(updatedProducts), "An empty update shouldn't indicate any updated products") - assert.Equal(t, 0, len(r.APMConfigs()), "An empty update shoudldn't add any APM configs") - assert.Equal(t, 0, len(r.CWSDDConfigs()), "An empty update shouldn't add any CWSDD configs") + assert.Equal(t, 0, len(r.GetConfigs(ProductAPMSampling)), "An empty update shoudldn't add any APM configs") + assert.Equal(t, 0, len(r.GetConfigs(ProductCWSDD)), "An empty update shouldn't add any CWSDD configs") state, err := r.CurrentState() assert.NoError(t, err) @@ -112,8 +112,8 @@ func TestEmptyUpdateNilTypes(t *testing.T) { updatedProducts, err = r.Update(emptyUpdate) assert.Nil(t, err) assert.Equal(t, 0, len(updatedProducts), "An empty update shouldn't indicate any updated products") - assert.Equal(t, 0, len(r.APMConfigs()), "An empty update shoudldn't add any APM configs") - assert.Equal(t, 0, len(r.CWSDDConfigs()), "An empty update shouldn't add any CWSDD configs") + assert.Equal(t, 0, len(r.GetConfigs(ProductAPMSampling)), "An empty update shoudldn't add any APM configs") + assert.Equal(t, 0, len(r.GetConfigs(ProductCWSDD)), "An empty update shouldn't add any CWSDD configs") state, err = r.CurrentState() assert.NoError(t, err) @@ -145,10 +145,10 @@ func TestUpdateNewConfig(t *testing.T) { assert.Equal(t, 1, len(updatedProducts)) assert.Contains(t, updatedProducts, ProductCWSDD) - assert.Equal(t, 0, len(r.APMConfigs())) - assert.Equal(t, 1, len(r.CWSDDConfigs())) + assert.Equal(t, 0, len(r.GetConfigs(ProductAPMSampling))) + assert.Equal(t, 1, len(r.GetConfigs(ProductCWSDD))) - storedFile, ok := r.CWSDDConfigs()[path] + storedFile, ok := r.GetConfigs(ProductCWSDD)[path] assert.True(t, ok) assert.Equal(t, file, storedFile.Config) assert.EqualValues(t, 1, storedFile.Metadata.Version) @@ -181,10 +181,10 @@ func TestUpdateNewConfig(t *testing.T) { assert.Equal(t, 1, len(updatedProducts)) assert.Contains(t, updatedProducts, ProductCWSDD) - assert.Equal(t, 0, len(r.APMConfigs())) - assert.Equal(t, 1, len(r.CWSDDConfigs())) + assert.Equal(t, 0, len(r.GetConfigs(ProductAPMSampling))) + assert.Equal(t, 1, len(r.GetConfigs(ProductCWSDD))) - storedFile, ok = r.CWSDDConfigs()[path] + storedFile, ok = r.GetConfigs(ProductCWSDD)[path] assert.True(t, ok) assert.Equal(t, file, storedFile.Config) assert.EqualValues(t, 1, storedFile.Metadata.Version) @@ -246,8 +246,8 @@ func TestUpdateNewConfigThenRemove(t *testing.T) { updatedProducts, err := r.Update(removalUpdate) assert.Nil(t, err) assert.Equal(t, 0, len(updatedProducts)) - assert.Equal(t, 0, len(r.APMConfigs())) - assert.Equal(t, 0, len(r.CWSDDConfigs())) + assert.Equal(t, 0, len(r.GetConfigs(ProductAPMSampling))) + assert.Equal(t, 0, len(r.GetConfigs(ProductCWSDD))) state, err := r.CurrentState() assert.NoError(t, err) @@ -262,8 +262,8 @@ func TestUpdateNewConfigThenRemove(t *testing.T) { updatedProducts, err = r.Update(removalUpdate) assert.Nil(t, err) assert.Equal(t, 0, len(updatedProducts)) - assert.Equal(t, 0, len(r.APMConfigs())) - assert.Equal(t, 0, len(r.CWSDDConfigs())) + assert.Equal(t, 0, len(r.GetConfigs(ProductAPMSampling))) + assert.Equal(t, 0, len(r.GetConfigs(ProductCWSDD))) state, err = r.CurrentState() assert.NoError(t, err) @@ -308,10 +308,10 @@ func TestUpdateNewConfigThenModify(t *testing.T) { assert.Equal(t, 1, len(updatedProducts)) assert.Contains(t, updatedProducts, ProductCWSDD) - assert.Equal(t, 0, len(r.APMConfigs())) - assert.Equal(t, 1, len(r.CWSDDConfigs())) + assert.Equal(t, 0, len(r.GetConfigs(ProductAPMSampling))) + assert.Equal(t, 1, len(r.GetConfigs(ProductCWSDD))) - storedFile, ok := r.CWSDDConfigs()[path] + storedFile, ok := r.GetConfigs(ProductCWSDD)[path] assert.True(t, ok) assert.Equal(t, file, storedFile.Config) assert.EqualValues(t, 2, storedFile.Metadata.Version) @@ -343,10 +343,10 @@ func TestUpdateNewConfigThenModify(t *testing.T) { assert.Equal(t, 1, len(updatedProducts)) assert.Contains(t, updatedProducts, ProductCWSDD) - assert.Equal(t, 0, len(r.APMConfigs())) - assert.Equal(t, 1, len(r.CWSDDConfigs())) + assert.Equal(t, 0, len(r.GetConfigs(ProductAPMSampling))) + assert.Equal(t, 1, len(r.GetConfigs(ProductCWSDD))) - storedFile, ok = r.CWSDDConfigs()[path] + storedFile, ok = r.GetConfigs(ProductCWSDD)[path] assert.True(t, ok) assert.Equal(t, file, storedFile.Config) assert.EqualValues(t, 2, storedFile.Metadata.Version) @@ -516,10 +516,10 @@ func TestUpdateWithNewRoot(t *testing.T) { assert.Equal(t, 1, len(updatedProducts)) assert.Contains(t, updatedProducts, ProductCWSDD) - assert.Equal(t, 0, len(r.APMConfigs())) - assert.Equal(t, 1, len(r.CWSDDConfigs())) + assert.Equal(t, 0, len(r.GetConfigs(ProductAPMSampling))) + assert.Equal(t, 1, len(r.GetConfigs(ProductCWSDD))) - storedFile, ok := r.CWSDDConfigs()[path] + storedFile, ok := r.GetConfigs(ProductCWSDD)[path] assert.True(t, ok) assert.Equal(t, file, storedFile.Config) assert.EqualValues(t, 1, storedFile.Metadata.Version) @@ -552,10 +552,10 @@ func TestUpdateWithNewRoot(t *testing.T) { assert.Equal(t, 1, len(updatedProducts)) assert.Contains(t, updatedProducts, ProductCWSDD) - assert.Equal(t, 0, len(r.APMConfigs())) - assert.Equal(t, 1, len(r.CWSDDConfigs())) + assert.Equal(t, 0, len(r.GetConfigs(ProductAPMSampling))) + assert.Equal(t, 1, len(r.GetConfigs(ProductCWSDD))) - storedFile, ok = r.CWSDDConfigs()[path] + storedFile, ok = r.GetConfigs(ProductCWSDD)[path] assert.True(t, ok) assert.Equal(t, file, storedFile.Config) assert.EqualValues(t, 1, storedFile.Metadata.Version) @@ -599,8 +599,8 @@ func TestClientOnlyTakesActionOnFilesInClientConfig(t *testing.T) { updatedProducts, err := r.Update(update) assert.Nil(t, err) assert.Equal(t, 0, len(updatedProducts)) - assert.Equal(t, 0, len(r.APMConfigs())) - assert.Equal(t, 0, len(r.CWSDDConfigs())) + assert.Equal(t, 0, len(r.GetConfigs(ProductAPMSampling))) + assert.Equal(t, 0, len(r.GetConfigs(ProductCWSDD))) state, err := r.CurrentState() assert.NoError(t, err) @@ -615,8 +615,8 @@ func TestClientOnlyTakesActionOnFilesInClientConfig(t *testing.T) { updatedProducts, err = r.Update(update) assert.Nil(t, err) assert.Equal(t, 0, len(updatedProducts)) - assert.Equal(t, 0, len(r.APMConfigs())) - assert.Equal(t, 0, len(r.CWSDDConfigs())) + assert.Equal(t, 0, len(r.GetConfigs(ProductAPMSampling))) + assert.Equal(t, 0, len(r.GetConfigs(ProductCWSDD))) state, err = r.CurrentState() assert.NoError(t, err) @@ -650,10 +650,10 @@ func TestUpdateWithTwoProducts(t *testing.T) { assert.Contains(t, updatedProducts, ProductCWSDD) assert.Contains(t, updatedProducts, ProductAPMSampling) - assert.Equal(t, 1, len(r.APMConfigs())) - assert.Equal(t, 1, len(r.CWSDDConfigs())) + assert.Equal(t, 1, len(r.GetConfigs(ProductAPMSampling))) + assert.Equal(t, 1, len(r.GetConfigs(ProductCWSDD))) - storedFile, ok := r.CWSDDConfigs()[path] + storedFile, ok := r.GetConfigs(ProductCWSDD)[path] assert.True(t, ok) assert.Equal(t, file, storedFile.Config) assert.EqualValues(t, 1, storedFile.Metadata.Version) @@ -662,7 +662,7 @@ func TestUpdateWithTwoProducts(t *testing.T) { assert.Equal(t, ProductCWSDD, storedFile.Metadata.Product) assert.EqualValues(t, len(data), storedFile.Metadata.RawLength) - storedFileAPM, ok := r.APMConfigs()[pathAPM] + storedFileAPM, ok := r.GetConfigs(ProductAPMSampling)[pathAPM] assert.True(t, ok) assert.Equal(t, fileAPM, storedFileAPM.Config) assert.EqualValues(t, 3, storedFileAPM.Metadata.Version) @@ -679,10 +679,10 @@ func TestUpdateWithTwoProducts(t *testing.T) { assert.Contains(t, updatedProducts, ProductCWSDD) assert.Contains(t, updatedProducts, ProductAPMSampling) - assert.Equal(t, 1, len(r.APMConfigs())) - assert.Equal(t, 1, len(r.CWSDDConfigs())) + assert.Equal(t, 1, len(r.GetConfigs(ProductAPMSampling))) + assert.Equal(t, 1, len(r.GetConfigs(ProductCWSDD))) - storedFile, ok = r.CWSDDConfigs()[path] + storedFile, ok = r.GetConfigs(ProductCWSDD)[path] assert.True(t, ok) assert.Equal(t, file, storedFile.Config) assert.EqualValues(t, 1, storedFile.Metadata.Version) @@ -691,7 +691,7 @@ func TestUpdateWithTwoProducts(t *testing.T) { assert.Equal(t, ProductCWSDD, storedFile.Metadata.Product) assert.EqualValues(t, len(data), storedFile.Metadata.RawLength) - storedFileAPM, ok = r.APMConfigs()[pathAPM] + storedFileAPM, ok = r.GetConfigs(ProductAPMSampling)[pathAPM] assert.True(t, ok) assert.Equal(t, fileAPM, storedFileAPM.Config) assert.EqualValues(t, 3, storedFileAPM.Metadata.Version) diff --git a/pkg/security/rconfig/policies.go b/pkg/security/rconfig/policies.go index bcd134d161823..03b7237d486bb 100644 --- a/pkg/security/rconfig/policies.go +++ b/pkg/security/rconfig/policies.go @@ -36,8 +36,8 @@ type RCPolicyProvider struct { client *remote.Client onNewPoliciesReadyCb func() - lastDefaults map[string]state.ConfigCWSDD - lastCustoms map[string]state.ConfigCWSCustom + lastDefaults map[string]state.RawConfig + lastCustoms map[string]state.RawConfig debouncer *debouncer.Debouncer } @@ -69,13 +69,13 @@ func (r *RCPolicyProvider) Start() { r.debouncer.Start() - r.client.RegisterCWSDDUpdate(r.rcDefaultsUpdateCallback) - r.client.RegisterCWSCustomUpdate(r.rcCustomsUpdateCallback) + r.client.Subscribe(state.ProductCWSDD, r.rcDefaultsUpdateCallback) + r.client.Subscribe(state.ProductCWSCustom, r.rcCustomsUpdateCallback) r.client.Start() } -func (r *RCPolicyProvider) rcDefaultsUpdateCallback(configs map[string]state.ConfigCWSDD) { +func (r *RCPolicyProvider) rcDefaultsUpdateCallback(configs map[string]state.RawConfig) { r.Lock() r.lastDefaults = configs r.Unlock() @@ -85,7 +85,7 @@ func (r *RCPolicyProvider) rcDefaultsUpdateCallback(configs map[string]state.Con r.debouncer.Call() } -func (r *RCPolicyProvider) rcCustomsUpdateCallback(configs map[string]state.ConfigCWSCustom) { +func (r *RCPolicyProvider) rcCustomsUpdateCallback(configs map[string]state.RawConfig) { r.Lock() r.lastCustoms = configs r.Unlock() diff --git a/pkg/security/rconfig/profiles.go b/pkg/security/rconfig/profiles.go index 5bc0349ec5672..39bcddd6eb091 100644 --- a/pkg/security/rconfig/profiles.go +++ b/pkg/security/rconfig/profiles.go @@ -47,7 +47,7 @@ func (r *RCProfileProvider) Stop() error { return nil } -func (r *RCProfileProvider) rcProfilesUpdateCallback(configs map[string]state.ConfigCWSProfiles) { +func (r *RCProfileProvider) rcProfilesUpdateCallback(configs map[string]state.RawConfig) { for _, config := range configs { var profCfg ProfileConfig if err := json.Unmarshal(config.Config, &profCfg); err != nil { @@ -91,7 +91,7 @@ func (r *RCProfileProvider) Start(ctx context.Context) error { log.Info("remote-config profile provider started") r.client.Start() - r.client.RegisterCWSProfilesUpdate(r.rcProfilesUpdateCallback) + r.client.Subscribe(state.ProductCWSProfiles, r.rcProfilesUpdateCallback) go func() { <-ctx.Done() diff --git a/pkg/trace/config/config.go b/pkg/trace/config/config.go index 1c3028c19a3b2..15f11560f2fb2 100644 --- a/pkg/trace/config/config.go +++ b/pkg/trace/config/config.go @@ -451,7 +451,7 @@ type AgentConfig struct { type RemoteClient interface { Close() Start() - RegisterAPMUpdate(func(update map[string]state.APMSamplingConfig)) + Subscribe(string, func(update map[string]state.RawConfig)) } // Tag represents a key/value pair. diff --git a/pkg/trace/remoteconfighandler/mock_remote_client.go b/pkg/trace/remoteconfighandler/mock_remote_client.go index 0e2cc56754bba..62c98c6c8829e 100644 --- a/pkg/trace/remoteconfighandler/mock_remote_client.go +++ b/pkg/trace/remoteconfighandler/mock_remote_client.go @@ -45,16 +45,16 @@ func (mr *MockRemoteClientMockRecorder) Close() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Close", reflect.TypeOf((*MockRemoteClient)(nil).Close)) } -// RegisterAPMUpdate mocks base method. -func (m *MockRemoteClient) RegisterAPMUpdate(arg0 func(map[string]state.APMSamplingConfig)) { +// Subscribe mocks base method. +func (m *MockRemoteClient) Subscribe(arg0 string, arg1 func(map[string]state.RawConfig)) { m.ctrl.T.Helper() - m.ctrl.Call(m, "RegisterAPMUpdate", arg0) + m.ctrl.Call(m, "Subscribe", arg0, arg1) } -// RegisterAPMUpdate indicates an expected call of RegisterAPMUpdate. -func (mr *MockRemoteClientMockRecorder) RegisterAPMUpdate(arg0 interface{}) *gomock.Call { +// Subscribe indicates an expected call of Subscribe. +func (mr *MockRemoteClientMockRecorder) Subscribe(arg0 interface{}, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RegisterAPMUpdate", reflect.TypeOf((*MockRemoteClient)(nil).RegisterAPMUpdate), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Subscribe", reflect.TypeOf((*MockRemoteClient)(nil).Subscribe), arg0, arg1) } // Start mocks base method. diff --git a/pkg/trace/remoteconfighandler/remote_config_handler.go b/pkg/trace/remoteconfighandler/remote_config_handler.go index e1a7ace0f0c62..3df3fea55595a 100644 --- a/pkg/trace/remoteconfighandler/remote_config_handler.go +++ b/pkg/trace/remoteconfighandler/remote_config_handler.go @@ -7,6 +7,7 @@ package remoteconfighandler import ( "encoding/json" + "github.com/DataDog/datadog-agent/pkg/remoteconfig/state" "github.com/DataDog/datadog-agent/pkg/remoteconfig/state/products/apmsampling" "github.com/DataDog/datadog-agent/pkg/trace/config" @@ -55,10 +56,10 @@ func (h *RemoteConfigHandler) Start() { } h.remoteClient.Start() - h.remoteClient.RegisterAPMUpdate(h.onUpdate) + h.remoteClient.Subscribe(state.ProductAPMSampling, h.onUpdate) } -func (h *RemoteConfigHandler) onUpdate(update map[string]state.APMSamplingConfig) { +func (h *RemoteConfigHandler) onUpdate(update map[string]state.RawConfig) { if len(update) == 0 { log.Debugf("no samplers configuration in remote config update payload") return diff --git a/pkg/trace/remoteconfighandler/remote_config_handler_test.go b/pkg/trace/remoteconfighandler/remote_config_handler_test.go index 21cc52bc9c8b3..d8f4bc36c8521 100644 --- a/pkg/trace/remoteconfighandler/remote_config_handler_test.go +++ b/pkg/trace/remoteconfighandler/remote_config_handler_test.go @@ -27,7 +27,7 @@ func TestStart(t *testing.T) { h := New(&agentConfig, prioritySampler, rareSampler, errorsSampler) - remoteClient.EXPECT().RegisterAPMUpdate(gomock.Any()).Times(1) + remoteClient.EXPECT().Subscribe(state.ProductAPMSampling, gomock.Any()).Times(1) remoteClient.EXPECT().Start().Times(1) h.Start() @@ -57,7 +57,7 @@ func TestPrioritySampler(t *testing.T) { } raw, _ := json.Marshal(payload) - config := state.APMSamplingConfig{ + config := state.RawConfig{ Config: raw, } @@ -65,7 +65,7 @@ func TestPrioritySampler(t *testing.T) { errorsSampler.EXPECT().UpdateTargetTPS(float64(41)).Times(1) rareSampler.EXPECT().SetEnabled(true).Times(1) - h.onUpdate(map[string]state.APMSamplingConfig{"datadog/2/APM_SAMPLING/samplerconfig/config": config}) + h.onUpdate(map[string]state.RawConfig{"datadog/2/APM_SAMPLING/samplerconfig/config": config}) ctrl.Finish() } @@ -87,7 +87,7 @@ func TestErrorsSampler(t *testing.T) { } raw, _ := json.Marshal(payload) - config := state.APMSamplingConfig{ + config := state.RawConfig{ Config: raw, } @@ -95,7 +95,7 @@ func TestErrorsSampler(t *testing.T) { errorsSampler.EXPECT().UpdateTargetTPS(float64(42)).Times(1) rareSampler.EXPECT().SetEnabled(true).Times(1) - h.onUpdate(map[string]state.APMSamplingConfig{"datadog/2/APM_SAMPLING/samplerconfig/config": config}) + h.onUpdate(map[string]state.RawConfig{"datadog/2/APM_SAMPLING/samplerconfig/config": config}) ctrl.Finish() } @@ -117,7 +117,7 @@ func TestRareSampler(t *testing.T) { } raw, _ := json.Marshal(payload) - config := state.APMSamplingConfig{ + config := state.RawConfig{ Config: raw, } @@ -125,7 +125,7 @@ func TestRareSampler(t *testing.T) { errorsSampler.EXPECT().UpdateTargetTPS(float64(41)).Times(1) rareSampler.EXPECT().SetEnabled(false).Times(1) - h.onUpdate(map[string]state.APMSamplingConfig{"datadog/2/APM_SAMPLING/samplerconfig/config": config}) + h.onUpdate(map[string]state.RawConfig{"datadog/2/APM_SAMPLING/samplerconfig/config": config}) ctrl.Finish() } @@ -157,7 +157,7 @@ func TestEnvPrecedence(t *testing.T) { } raw, _ := json.Marshal(payload) - config := state.APMSamplingConfig{ + config := state.RawConfig{ Config: raw, } @@ -165,7 +165,7 @@ func TestEnvPrecedence(t *testing.T) { errorsSampler.EXPECT().UpdateTargetTPS(float64(43)).Times(1) rareSampler.EXPECT().SetEnabled(false).Times(1) - h.onUpdate(map[string]state.APMSamplingConfig{"datadog/2/APM_SAMPLING/samplerconfig/config": config}) + h.onUpdate(map[string]state.RawConfig{"datadog/2/APM_SAMPLING/samplerconfig/config": config}) ctrl.Finish() } From 46ab12a6c39f19d405a4ba034b69ed1350b605a0 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 9 Jun 2023 08:43:32 -0400 Subject: [PATCH 70/76] CWS: sync BTFhub constants (#17550) Co-authored-by: paulcacheux --- .../probe/constantfetch/btfhub/constants.json | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/pkg/security/probe/constantfetch/btfhub/constants.json b/pkg/security/probe/constantfetch/btfhub/constants.json index 0a4e1de7b00d0..47bc9fd3310bf 100644 --- a/pkg/security/probe/constantfetch/btfhub/constants.json +++ b/pkg/security/probe/constantfetch/btfhub/constants.json @@ -1,5 +1,5 @@ { - "commit": "836f43887cabdfc30549a1cd49c2ee2ca08e46f5", + "commit": "913e6fe1ebe04a479e7ba352a324092d6bf63405", "constants": [ { "binprm_file_offset": 168, @@ -13216,6 +13216,20 @@ "uname_release": "3.10.0-1160.90.1.0.2.el7.x86_64", "cindex": 81 }, + { + "distrib": "ol", + "version": "7", + "arch": "x86_64", + "uname_release": "3.10.0-1160.92.1.0.1.el7.x86_64", + "cindex": 81 + }, + { + "distrib": "ol", + "version": "7", + "arch": "x86_64", + "uname_release": "3.10.0-1160.92.1.0.2.el7.x86_64", + "cindex": 81 + }, { "distrib": "ol", "version": "7", @@ -14441,6 +14455,13 @@ "uname_release": "4.1.12-124.74.2.el7uek.x86_64", "cindex": 82 }, + { + "distrib": "ol", + "version": "7", + "arch": "x86_64", + "uname_release": "4.1.12-124.75.3.el7uek.x86_64", + "cindex": 82 + }, { "distrib": "ol", "version": "7", From d71aaa4e8d3538ad75de3e95330e5494b298890a Mon Sep 17 00:00:00 2001 From: Nicolas PLANEL Date: Fri, 9 Jun 2023 14:59:11 +0200 Subject: [PATCH 71/76] https java tests use local https server (#17067) https java tests use local https server --- pkg/network/java/testdata/Wget$1.class | Bin 430 -> 693 bytes pkg/network/java/testdata/Wget$2.class | Bin 0 -> 430 bytes .../Wget$InvalidCertificateHostVerifier.class | Bin 477 -> 0 bytes pkg/network/java/testdata/Wget.class | Bin 1805 -> 2750 bytes pkg/network/java/testdata/Wget.java | 60 ++++++++++++++---- pkg/network/java/testdata/docker-compose.yml | 2 + pkg/network/java/testutil/inject.go | 3 + .../protocols/http/testutil/testutil.go | 6 +- pkg/network/tracer/tracer_usm_linux_test.go | 25 ++++++-- 9 files changed, 80 insertions(+), 16 deletions(-) create mode 100644 pkg/network/java/testdata/Wget$2.class delete mode 100644 pkg/network/java/testdata/Wget$InvalidCertificateHostVerifier.class diff --git a/pkg/network/java/testdata/Wget$1.class b/pkg/network/java/testdata/Wget$1.class index 43b10c24bbc595fac31dfdd1985445c251ca1a38..c557237a1e50057bdce3546563f04a6e2cd101a0 100644 GIT binary patch literal 693 zcma)3!A=xG5PiK146LglDiIXCn7BY>AclitOw0xo641jEHR06TTPzJj59#h9_*Z%| z@!$veQO4I})~v=v4_#GV{i^D{>Tln_d!tB0v^13?ji$B!;f|>cD#Fxg%MU=r_2$lGt@TjwTw128Ebsof2-o_8P5g+sS z+nZ0j4D7KrI?4{q&54+^Zehj6Lth1UQFzw*uj-!@3hjn@FM8{SJBev)_bRcmr3)GE zjVAQOUy}1^LaSF+-pDJPB+R^{hK)p*0(YG$%D`p^5>LuOhWl+SW2KErOmQm-`fy7D z3hh1T#CHoFf>85Zt+!_Lrhh6XDy*c`RqiC_Ar!Uxn!$l~dMKWI`pb^S_VY^#_n!vS zoonk97DfyDT|73?;5QP+KTU_6dCM3r(~~tO*FHmiVxTZho1TGn+8MNH6Lg6_WgF@v z?Kti+Z`aV~kc3<0X(q&$Fm>C4v83frGMA#WbCrW5pvX!M4Wu{d!GU#jgWF?j* z>gOcprRxWm6lLb6TZ2U^^z%|n^oxsg^n-(af>Vo&GxPJTHKQhe(`6ImVGw7Kn5@a@ zBH)o*NWN+|CD diff --git a/pkg/network/java/testdata/Wget$2.class b/pkg/network/java/testdata/Wget$2.class new file mode 100644 index 0000000000000000000000000000000000000000..79408f81719448a414204b066a7062ba37f3d2a0 GIT binary patch literal 430 zcmZWlJxc>Y5Pg%cOX6uFYWx7LED{S(w2asUMIlDvB!X6(IK~Z^J-FQj{ZBSlf`vc8 zA0^J(M6lTRX5Y@vyqT}>k52$c*sLOtdVu8ss{z&srDJWhJ0awotv;d9NgtR{>uSTj z>14p!jT$7PlxCdi#}`7>?2gq;MTs(_D0Z1PqxP@z92s_zwMi7m-I%S_scE;Q;h*WTww$nN#oj_(<^q<_g5W$5X z;75sfs!(v_;=ay3oO`&RU+*6P&QNnvMBu?f)xm~?Z3jCHwtf(*eo9SrH|Dxc&AE_5 zUog0hAE?=5usYe0GgKlW`Sont=lN~YPYJQ-JQt%UhOiM$l6exQi5!Qq&V?Me7sz8M zxek>|!#Iv&u9V1RyLr#x#n~($@JnHITyy=zDEP49_$Xo5!5+hrS=767o}^;f;kgzg zF-SDO%9QSz+k)o|`~MOAu9Q6Qq=`~oF$7DmH~k48Xp%6{(yY;!$&@c|6dQ|A7(Y0m zUs_;T0Sf|Sm|k3= diff --git a/pkg/network/java/testdata/Wget.class b/pkg/network/java/testdata/Wget.class index 648c47671b2394706ac1da874ec38c92f7c96d6c..3fbe3875d0b31b67009fdf2c0738618cd97af686 100644 GIT binary patch literal 2750 zcmaJ@S#(oH82*MPop8NSESo8dK?=5o5{t{x77!^Qh0_kI@x^oWfd{pIbJHd%RFiY&&iwPQ-~azJ^W#6?oC9z* zzA|tfx@Th#Zi%4BKmxr67keYv7bXLLP3H~l#{r2x0|pLC9FjO}U=F$s+=|=uaJwGv zh`=(?kEBG(zyi&w3@p-Y{TPrKG!Vr>y*OeZhP1>{1Iuts4;hK9gl%AjW{<&<$Qh_d zcLaCpud9ikp80ynOB|Otp@~BV)?(Pe8r-FayEW||iF*yK*B;y_aZ=)b0SK5KwyoUu zjOBUC6R6&hw$uJ5fvSeaeFC9&C#3{xI@7l5%4hqP+iUe_NC{=Fv@Nix;ZWyM>$nxq zSoUB%;k#*juuTijN%&Us*lsHq@DnD92P7Vpcu3-5V!_B6Y7iiueuTc!Ede9pMZ;%Pi1P#X#Iq)z!}9{m%bs@FzH;4s&R3~zLrInM(~fQ81+)s(X|AETt^By>W#YYV-t%`` zwl%0+!lNzMw=fJ7FXEJmm+-QQSMaKU?Cne(Z&|mV@oDmF0;>aibR+Mk{o#0*lgKBJ z+>{w~xIB_A*_|{QFEJ*xgzB;El#?~_I!+7JPgk`|4HsR?D%&q9GVuo9H1QVRW?BOQ z9mL+AP7NOsdI#?c#HNS0!}oI@S=t?zK~lpo736vo@8Nxc#et@Z{BFsoGbs(mydLG{ z9NSZ|B&#I0F=pZed}!h$oYAup6CdLgYa~#RcH&#|0|UxcsUBqo^3kb{4m+3kSv<xhG@ia1nr^(<9@G3u412!HvfG?Ic^4LYiBRofBTXVg zyQP>b$Sk;=X38*O3max`!jKwDQ*EfBL$_oF482E)bxI)YWt7Tkj-8sLCeRpkZm(-4 z8Q5F`xK#~U`HbH?oFidDL*vD^1TG<8hwb^6t)L#TaenmmF z9ctIEt@}@vGr_Kv>T^tB|KtHx<|_4$+xEZdzQEtgrVLKFc?>z>B#$Y7yOm@a3=3Q_ z2~ODS2d0~eWRG0=o&-K80NKxq9Gv)xKy-;Yiq|azcoAp zqqRCp9Sfsj(L9btFCWhHuDG+e-vF)SU&vc9IO^`ltcxu$^2zeh|9j$;KSt|(w7 zeHlkR7prPl7jUK4*-$`Z0Znvp9BcZ0_>&5v z5%P{q{HobnMzBDKbF~g<1d*;0gu2cWqWMI%o=>DM?8N~-fNnjj*DlVwn2f!+ ziPmn!L2RbQcG}!dt6Sk>8&2S6oWxGP8ai=`-0$#t_bnxU;)CvIO8tU9{D#ByD@hM; z!=Kb}9(Uj`t|wrz5R&w?UxbjN1wdiW-*iswk=PuWpflBy)`i3tiFQe&oNlY;?)K^l zs*Z41;^y+c#14rLP=8cn=LF-e3KVF$UArhtC7rq?chlG`I($99wVbWs7l`oD8GQc* Dj_}b? delta 919 zcmaizJ5y6Z6vuxz4>sJnA|_%8Ac6svV2psMJVX>9pfM^67<@*(U@!(v0zN3PvT%m# zjs-JVSg2!(MdFwlM++_d4mOUBy@iDu&y63zy>riF_kYg$@7djVHA_{CpZ~ml2XwKZ z(?U-rz4UqL*V)H_F3x@rgKh!H2>sMKz(K{3j?N*)VI6}bwm7O7R*dLW)1$MNV~XQC zK6*SvZGFO?jM>&nTbxpyR*cHzBxiK$Ijd90m@UR_j!PP1Jju9#Gu*JvC`&nHsJ z>qBNHmz+voOXSSq*=%my%!p@ZG>nmS+RO~464|Vo)xgrUN#Bs-f)Fj!lad!DvGq`^ zZ*3!_xMXmdD;oO5w3%z_pUb2M6bXZ?Tr;?iX}#C{6;lS&+_1iA!GV z>Ip9vG2$U-XMr`*_B>VZSsM!%sg4&|m&f}WM-iVm>%BF3HiYx|^VH@E)2~P4Qm$C%g^Ir5_R=a0~Qh>ARqsUSh;VZ+5-Gy(;W{G%w1IbRoCQ zitNKtCVrJ#q30K`7DYfVQ=LE?<&HH8rbWJHTG=ce2ukEu_OgvZ>Bey)a?Twr$WwU4 zE*{g(6IorBhp-~=;3<7Pqo3yt2oiRqeve6JP44nePl*$_6&;FBP0^(!0lx?+x=Ye7 gr>xj*R_yi&u{{#*kkng6d&O!MDqF;^mLEKS0mNOYDF6Tf diff --git a/pkg/network/java/testdata/Wget.java b/pkg/network/java/testdata/Wget.java index e2b2d078ff95e..4baebef2d2cd8 100644 --- a/pkg/network/java/testdata/Wget.java +++ b/pkg/network/java/testdata/Wget.java @@ -8,16 +8,18 @@ import javax.net.ssl.HostnameVerifier; import javax.net.ssl.SSLSession; +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; +import java.security.cert.X509Certificate; +import java.security.cert.CertificateException; +import java.security.NoSuchAlgorithmException; +import java.security.KeyManagementException; +import java.security.KeyStore; +import java.security.KeyStoreException; public class Wget { - class InvalidCertificateHostVerifier implements HostnameVerifier { - @Override - public boolean verify(String host, SSLSession session) { - return true; - } - } - public static void main(String[] args) { URL url; boolean dumpContent = false; @@ -36,14 +38,47 @@ public static void main(String[] args) { } try { + TrustManager[] trustAllCerts = new TrustManager[] { + new X509TrustManager() { + public java.security.cert.X509Certificate[] getAcceptedIssuers() { + return null; + } + @Override + public void checkClientTrusted(X509Certificate[] arg0, String arg1) + throws CertificateException {} + + @Override + public void checkServerTrusted(X509Certificate[] arg0, String arg1) + throws CertificateException {} + } + }; + + KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType()); + trustStore.load(null, null); + + SSLContext sc=null; + try { + sc = SSLContext.getInstance("TLSv1.2"); + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + } + try { + sc.init(null, trustAllCerts, new java.security.SecureRandom()); + } catch (KeyManagementException e) { + e.printStackTrace(); + } + HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); + + url = new URL(args[0]); + HttpsURLConnection connection = (HttpsURLConnection) url.openConnection(); // skip certificate validation connection.setHostnameVerifier(new HostnameVerifier() { - public boolean verify(String s, SSLSession sslSession) { - return true; - } - });//(new InvalidCertificateHostVerifier()); + public boolean verify(String s, SSLSession sslSession) { + return true; + } + }); System.out.println("Response code = " + connection.getResponseCode()); BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream())); @@ -58,6 +93,9 @@ public boolean verify(String s, SSLSession sslSession) { } catch (IOException urlException) { urlException.printStackTrace(); System.exit(1); + } catch (Exception e) { + e.printStackTrace(); + System.exit(1); } } diff --git a/pkg/network/java/testdata/docker-compose.yml b/pkg/network/java/testdata/docker-compose.yml index a1d7ed01c08de..6af3b7fc38470 100644 --- a/pkg/network/java/testdata/docker-compose.yml +++ b/pkg/network/java/testdata/docker-compose.yml @@ -3,6 +3,8 @@ services: java: image: ${IMAGE_VERSION} entrypoint: java -cp /v ${ENTRYCLASS} + extra_hosts: + - ${EXTRA_HOSTS} # setting the limits here as new os confuse (abort()) old glibc with default big numbers # https://datadoghq.atlassian.net/browse/USMO-295 # numbers here are default from /etc/systemd/system.conf diff --git a/pkg/network/java/testutil/inject.go b/pkg/network/java/testutil/inject.go index 80e07223bab9e..3096a588f3d68 100644 --- a/pkg/network/java/testutil/inject.go +++ b/pkg/network/java/testutil/inject.go @@ -27,9 +27,12 @@ func RunJavaVersion(t testing.TB, version string, class string, waitForParam ... } dir, _ := testutil.CurDir() + addr := "172.17.0.1" // for some reason docker network inspect bridge --format='{{(index .IPAM.Config 0).Gateway}}' is not reliable and doesn't report Gateway ip sometime env := []string{ "IMAGE_VERSION=" + version, "ENTRYCLASS=" + class, + "EXTRA_HOSTS=host.docker.internal:" + addr, } + return protocolsUtils.RunDockerServer(t, version, dir+"/../testdata/docker-compose.yml", env, waitFor, protocolsUtils.DefaultTimeout) } diff --git a/pkg/network/protocols/http/testutil/testutil.go b/pkg/network/protocols/http/testutil/testutil.go index c5b1d1525ebd3..8fb7933b9ae0e 100644 --- a/pkg/network/protocols/http/testutil/testutil.go +++ b/pkg/network/protocols/http/testutil/testutil.go @@ -45,7 +45,11 @@ func HTTPServer(t *testing.T, addr string, options Options) func() { time.Sleep(options.SlowResponse) } statusCode := StatusFromPath(req.URL.Path) - w.WriteHeader(int(statusCode)) + if statusCode == 0 { + t.Logf("wrong request format %s", req.URL.Path) + } else { + w.WriteHeader(int(statusCode)) + } defer req.Body.Close() io.Copy(w, req.Body) diff --git a/pkg/network/tracer/tracer_usm_linux_test.go b/pkg/network/tracer/tracer_usm_linux_test.go index a9da4f0e8b207..0f9442d48eaec 100644 --- a/pkg/network/tracer/tracer_usm_linux_test.go +++ b/pkg/network/tracer/tracer_usm_linux_test.go @@ -870,16 +870,21 @@ func (s *USMSuite) TestJavaInjection() { cfg.ProtocolClassificationEnabled = true cfg.CollectTCPv4Conns = true cfg.CollectTCPv6Conns = true + + serverDoneFn := testutil.HTTPServer(t, "0.0.0.0:5443", testutil.Options{ + EnableTLS: true, + }) + t.Cleanup(serverDoneFn) }, postTracerSetup: func(t *testing.T, ctx testContext) { - require.NoError(t, javatestutil.RunJavaVersion(t, "openjdk:15-oraclelinux8", "Wget https://httpbin.org/anything/java-tls-request", regexp.MustCompile("Response code = .*")), "Failed running Java version") + require.NoError(t, javatestutil.RunJavaVersion(t, "openjdk:15-oraclelinux8", "Wget https://host.docker.internal:5443/200/anything/java-tls-request", regexp.MustCompile("Response code = .*")), "Failed running Java version") }, validation: func(t *testing.T, ctx testContext, tr *Tracer) { // Iterate through active connections until we find connection created above require.Eventuallyf(t, func() bool { payload := getConnections(t, tr) - for key := range payload.HTTP { - if key.Path.Content == "/anything/java-tls-request" { + for key, stats := range payload.HTTP { + if key.Path.Content == "/200/anything/java-tls-request" { t.Log("path content found") // socket filter is not supported on fentry tracer if tr.ebpfTracer.Type() == connection.TracerTypeFentry { @@ -887,16 +892,28 @@ func (s *USMSuite) TestJavaInjection() { return true } + req, exists := stats.Data[200] + if !exists { + t.Logf("wrong response, not 200 : %#+v", key) + continue + } + + if req.StaticTags != network.ConnTagJava { + t.Logf("tag not java : %#+v", key) + continue + } + for _, c := range payload.Conns { if c.SPort == key.SrcPort && c.DPort == key.DstPort && c.ProtocolStack.Contains(protocols.TLS) { return true } } + t.Logf("TLS connection tag not found : %#+v", key) } } return false - }, 4*time.Second, time.Second, "couldn't find http connection matching: %s", "https://httpbin.org/anything/java-tls-request") + }, 4*time.Second, time.Second, "couldn't find http connection matching: %s", "https://host.docker.internal:5443/200/anything/java-tls-request") }, }, } From 334192ceac66f24d9e70d252ed130f03434f1795 Mon Sep 17 00:00:00 2001 From: Paul Cacheux Date: Fri, 9 Jun 2023 09:03:03 -0400 Subject: [PATCH 72/76] [CWS] revert snapshot event playing (#17553) * [CWS] do not play snapshot for now * remove test --- pkg/eventmonitor/eventmonitor.go | 2 -- pkg/security/tests/snapshot_replay_test.go | 41 ---------------------- 2 files changed, 43 deletions(-) delete mode 100644 pkg/security/tests/snapshot_replay_test.go diff --git a/pkg/eventmonitor/eventmonitor.go b/pkg/eventmonitor/eventmonitor.go index f1c2c5c9e2f3b..1f6d2d514fa45 100644 --- a/pkg/eventmonitor/eventmonitor.go +++ b/pkg/eventmonitor/eventmonitor.go @@ -149,8 +149,6 @@ func (m *EventMonitor) Start() error { log.Errorf("unable to start %s event consumer: %v", em.ID(), err) } } - // Apply rules to the snapshotted data - m.Probe.PlaySnapshot() m.wg.Add(1) go m.statsSender() diff --git a/pkg/security/tests/snapshot_replay_test.go b/pkg/security/tests/snapshot_replay_test.go deleted file mode 100644 index 68bcd77a257fa..0000000000000 --- a/pkg/security/tests/snapshot_replay_test.go +++ /dev/null @@ -1,41 +0,0 @@ -// Unless explicitly stated otherwise all files in this repository are licensed -// under the Apache License Version 2.0. -// This product includes software developed at Datadog (https://www.datadoghq.com/). -// Copyright 2016-present Datadog, Inc. - -//go:build functionaltests - -package tests - -import ( - "fmt" - "github.com/DataDog/datadog-agent/pkg/security/secl/model" - "github.com/DataDog/datadog-agent/pkg/security/secl/rules" - "testing" -) - -func TestSnapshotReplay(t *testing.T) { - ruleDef := &rules.RuleDefinition{ - ID: "test_rule_snapshot_replay", - Expression: fmt.Sprintf(`exec.comm in ["testsuite"] `), - } - - test, err := newTestModule(t, nil, []*rules.RuleDefinition{ruleDef}, testOpts{}) - - if err != nil { - t.Fatal(err) - } - defer test.Close() - - t.Run("snapshot-replay", func(t *testing.T) { - // Check that the process is present in the process resolver's entrycache - test.WaitSignal(t, func() error { - go test.probe.PlaySnapshot() - return nil - }, func(event *model.Event, rule *rules.Rule) { - assertTriggeredRule(t, rule, "test_rule_snapshot_replay") - test.validateExecSchema(t, event) - }) - }) - -} From 3419bc6a31606d7b36a46e4d1d19411ab03d3c25 Mon Sep 17 00:00:00 2001 From: Guy Arbitman Date: Fri, 9 Jun 2023 20:20:05 +0300 Subject: [PATCH 73/76] deprecate more usm values (#17342) * Fixed bug in configuration * usm: Deprecated system_probe_config.http_map_cleaner_interval_in_s in favor of service_monitoring_config.http_map_cleaner_interval_in_s * usm: Deprecated system_probe_config.http_idle_connection_ttl_in_s in favor of service_monitoring_config.http_idle_connection_ttl_in_s * usm: Deprecated network_config.http_notification_threshold in favor of service_monitoring_config.http_notification_threshold * usm: Deprecated network_config.http_max_request_fragment in favor of service_monitoring_config.http_max_request_fragment * usm: Added releasenotes * Fixed file name linter * Addressed CR comments * usm: Use apply default * Fixed test * added missing import * Fixed imports --- cmd/system-probe/config/adjust_usm.go | 16 +- pkg/config/system_probe.go | 24 +- pkg/config/test_helpers.go | 11 + pkg/network/config/config.go | 8 +- pkg/network/config/config_linux_test.go | 4 +- pkg/network/config/config_test.go | 569 +++++++++++++++--- ...ProbeConfig-HTTPNotificationThreshold.yaml | 2 - ...ig-HTTPNotificationThresholdOverLimit.yaml | 2 - pkg/network/usm/monitor_test.go | 10 +- ...configuration-values-0e331d18c41c3f87.yaml | 6 + 10 files changed, 537 insertions(+), 115 deletions(-) delete mode 100644 pkg/network/config/testdata/TestDDSystemProbeConfig-HTTPNotificationThreshold.yaml delete mode 100644 pkg/network/config/testdata/TestDDSystemProbeConfig-HTTPNotificationThresholdOverLimit.yaml create mode 100644 releasenotes/notes/deprecating-usm-configuration-values-0e331d18c41c3f87.yaml diff --git a/cmd/system-probe/config/adjust_usm.go b/cmd/system-probe/config/adjust_usm.go index bd0d3c7caa281..255a28d5d4481 100644 --- a/cmd/system-probe/config/adjust_usm.go +++ b/cmd/system-probe/config/adjust_usm.go @@ -20,7 +20,17 @@ func adjustUSM(cfg config.Config) { deprecateBool(cfg, netNS("enable_http_monitoring"), smNS("enable_http_monitoring")) deprecateGeneric(cfg, netNS("http_replace_rules"), smNS("http_replace_rules")) deprecateInt64(cfg, netNS("max_tracked_http_connections"), smNS("max_tracked_http_connections")) + applyDefault(cfg, smNS("max_tracked_http_connections"), 1024) deprecateInt(cfg, netNS("max_http_stats_buffered"), smNS("max_http_stats_buffered")) + applyDefault(cfg, smNS("max_http_stats_buffered"), 100000) + deprecateInt(cfg, spNS("http_map_cleaner_interval_in_s"), smNS("http_map_cleaner_interval_in_s")) + applyDefault(cfg, smNS("http_map_cleaner_interval_in_s"), 300) + deprecateInt(cfg, spNS("http_idle_connection_ttl_in_s"), smNS("http_idle_connection_ttl_in_s")) + applyDefault(cfg, smNS("http_idle_connection_ttl_in_s"), 30) + deprecateInt64(cfg, netNS("http_notification_threshold"), smNS("http_notification_threshold")) + applyDefault(cfg, smNS("http_notification_threshold"), 512) + deprecateInt64(cfg, netNS("http_max_request_fragment"), smNS("http_max_request_fragment")) + applyDefault(cfg, smNS("http_max_request_fragment"), 160) if cfg.GetBool(dsmNS("enabled")) { // DSM infers USM @@ -42,13 +52,13 @@ func adjustUSM(cfg config.Config) { cfg.Set(smNS("process_service_inference", "enabled"), false) } - validateInt(cfg, netNS("http_notification_threshold"), cfg.GetInt(netNS("max_tracked_http_connections"))/2, func(v int) error { - limit := cfg.GetInt(netNS("max_tracked_http_connections")) + validateInt(cfg, smNS("http_notification_threshold"), cfg.GetInt(smNS("max_tracked_http_connections"))/2, func(v int) error { + limit := cfg.GetInt(smNS("max_tracked_http_connections")) if v >= limit { return fmt.Errorf("notification threshold %d set higher than tracked connections %d", v, limit) } return nil }) - limitMaxInt64(cfg, netNS("http_max_request_fragment"), maxHTTPFrag) + limitMaxInt64(cfg, smNS("http_max_request_fragment"), maxHTTPFrag) } diff --git a/pkg/config/system_probe.go b/pkg/config/system_probe.go index 3870221e2f94e..7dce57ac7a937 100644 --- a/pkg/config/system_probe.go +++ b/pkg/config/system_probe.go @@ -176,8 +176,6 @@ func InitSystemProbeConfig(cfg Config) { cfg.BindEnvAndSetDefault(join(spNS, "collect_dns_domains"), true, "DD_COLLECT_DNS_DOMAINS") cfg.BindEnvAndSetDefault(join(spNS, "max_dns_stats"), 20000) cfg.BindEnvAndSetDefault(join(spNS, "dns_timeout_in_s"), 15) - cfg.BindEnvAndSetDefault(join(spNS, "http_map_cleaner_interval_in_s"), 300) - cfg.BindEnvAndSetDefault(join(spNS, "http_idle_connection_ttl_in_s"), 30) cfg.BindEnvAndSetDefault(join(spNS, "enable_conntrack"), true) cfg.BindEnvAndSetDefault(join(spNS, "conntrack_max_state_size"), 65536*2) @@ -210,7 +208,8 @@ func InitSystemProbeConfig(cfg Config) { cfg.BindEnvAndSetDefault(join(smNS, "enable_http_stats_by_status_code"), false) cfg.BindEnvAndSetDefault(join(netNS, "enable_gateway_lookup"), true, "DD_SYSTEM_PROBE_NETWORK_ENABLE_GATEWAY_LOOKUP") - cfg.BindEnvAndSetDefault(join(netNS, "max_http_stats_buffered"), 100000, "DD_SYSTEM_PROBE_NETWORK_MAX_HTTP_STATS_BUFFERED") + // Default value (100000) is set in `adjustUSM`, to avoid having "deprecation warning", due to the default value. + cfg.BindEnv(join(netNS, "max_http_stats_buffered"), "DD_SYSTEM_PROBE_NETWORK_MAX_HTTP_STATS_BUFFERED") cfg.BindEnv(join(smNS, "max_http_stats_buffered")) cfg.BindEnvAndSetDefault(join(smNS, "max_kafka_stats_buffered"), 100000) @@ -230,10 +229,15 @@ func InitSystemProbeConfig(cfg Config) { cfg.SetEnvKeyTransformer(oldHTTPRules, httpRulesTransformer(oldHTTPRules)) cfg.SetEnvKeyTransformer(newHTTPRules, httpRulesTransformer(newHTTPRules)) - cfg.BindEnvAndSetDefault(join(netNS, "max_tracked_http_connections"), 1024) + // Default value (1024) is set in `adjustUSM`, to avoid having "deprecation warning", due to the default value. + cfg.BindEnv(join(netNS, "max_tracked_http_connections")) cfg.BindEnv(join(smNS, "max_tracked_http_connections")) - cfg.BindEnvAndSetDefault(join(netNS, "http_notification_threshold"), 512) - cfg.BindEnvAndSetDefault(join(netNS, "http_max_request_fragment"), 160) + // Default value (512) is set in `adjustUSM`, to avoid having "deprecation warning", due to the default value. + cfg.BindEnv(join(netNS, "http_notification_threshold")) + cfg.BindEnv(join(smNS, "http_notification_threshold")) + // Default value (160) is set in `adjustUSM`, to avoid having "deprecation warning", due to the default value. + cfg.BindEnv(join(netNS, "http_max_request_fragment")) + cfg.BindEnv(join(smNS, "http_max_request_fragment")) // list of DNS query types to be recorded cfg.BindEnvAndSetDefault(join(netNS, "dns_recorded_query_types"), []string{}) @@ -256,6 +260,14 @@ func InitSystemProbeConfig(cfg Config) { cfg.BindEnvAndSetDefault(join(smNS, "process_service_inference", "enabled"), false, "DD_SYSTEM_PROBE_PROCESS_SERVICE_INFERENCE_ENABLED") cfg.BindEnvAndSetDefault(join(smNS, "process_service_inference", "use_windows_service_name"), true, "DD_SYSTEM_PROBE_PROCESS_SERVICE_INFERENCE_USE_WINDOWS_SERVICE_NAME") + // Default value (300) is set in `adjustUSM`, to avoid having "deprecation warning", due to the default value. + cfg.BindEnv(join(spNS, "http_map_cleaner_interval_in_s")) + cfg.BindEnv(join(smNS, "http_map_cleaner_interval_in_s")) + + // Default value (30) is set in `adjustUSM`, to avoid having "deprecation warning", due to the default value. + cfg.BindEnv(join(spNS, "http_idle_connection_ttl_in_s")) + cfg.BindEnv(join(smNS, "http_idle_connection_ttl_in_s")) + // data streams cfg.BindEnvAndSetDefault(join(dsNS, "enabled"), false, "DD_SYSTEM_PROBE_DATA_STREAMS_ENABLED") diff --git a/pkg/config/test_helpers.go b/pkg/config/test_helpers.go index 87cacef05f2e2..152a00a9e9c2f 100644 --- a/pkg/config/test_helpers.go +++ b/pkg/config/test_helpers.go @@ -11,6 +11,7 @@ import ( "bytes" "log" "strings" + "testing" ) func SetupConf() Config { @@ -28,3 +29,13 @@ func SetupConfFromYAML(yamlConfig string) Config { } return conf } + +// ResetSystemProbeConfig resets the configuration. +func ResetSystemProbeConfig(t *testing.T) { + originalConfig := SystemProbe + t.Cleanup(func() { + SystemProbe = originalConfig + }) + SystemProbe = NewConfig("system-probe", "DD", strings.NewReplacer(".", "_")) + InitSystemProbeConfig(SystemProbe) +} diff --git a/pkg/network/config/config.go b/pkg/network/config/config.go index 2590b65102810..999bb4f4e9ee2 100644 --- a/pkg/network/config/config.go +++ b/pkg/network/config/config.go @@ -303,8 +303,8 @@ func New() *Config { MaxKafkaStatsBuffered: cfg.GetInt(join(smNS, "max_kafka_stats_buffered")), MaxTrackedHTTPConnections: cfg.GetInt64(join(smNS, "max_tracked_http_connections")), - HTTPNotificationThreshold: cfg.GetInt64(join(netNS, "http_notification_threshold")), - HTTPMaxRequestFragment: cfg.GetInt64(join(netNS, "http_max_request_fragment")), + HTTPNotificationThreshold: cfg.GetInt64(join(smNS, "http_notification_threshold")), + HTTPMaxRequestFragment: cfg.GetInt64(join(smNS, "http_max_request_fragment")), EnableConntrack: cfg.GetBool(join(spNS, "enable_conntrack")), ConntrackMaxStateSize: cfg.GetInt(join(spNS, "conntrack_max_state_size")), @@ -327,8 +327,8 @@ func New() *Config { EnableRootNetNs: cfg.GetBool(join(netNS, "enable_root_netns")), - HTTPMapCleanerInterval: time.Duration(cfg.GetInt(join(spNS, "http_map_cleaner_interval_in_s"))) * time.Second, - HTTPIdleConnectionTTL: time.Duration(cfg.GetInt(join(spNS, "http_idle_connection_ttl_in_s"))) * time.Second, + HTTPMapCleanerInterval: time.Duration(cfg.GetInt(join(smNS, "http_map_cleaner_interval_in_s"))) * time.Second, + HTTPIdleConnectionTTL: time.Duration(cfg.GetInt(join(smNS, "http_idle_connection_ttl_in_s"))) * time.Second, // Service Monitoring EnableJavaTLSSupport: cfg.GetBool(join(smjtNS, "enabled")), diff --git a/pkg/network/config/config_linux_test.go b/pkg/network/config/config_linux_test.go index c6ba2ff4b8d9e..74244d3d06916 100644 --- a/pkg/network/config/config_linux_test.go +++ b/pkg/network/config/config_linux_test.go @@ -11,10 +11,12 @@ import ( "github.com/stretchr/testify/require" "github.com/vishvananda/netns" + + aconfig "github.com/DataDog/datadog-agent/pkg/config" ) func TestDisableRootNetNamespace(t *testing.T) { - newConfig(t) + aconfig.ResetSystemProbeConfig(t) t.Setenv("DD_NETWORK_CONFIG_ENABLE_ROOT_NETNS", "false") cfg := New() diff --git a/pkg/network/config/config_test.go b/pkg/network/config/config_test.go index b2f7bf9fa2e89..79ad034bc0154 100644 --- a/pkg/network/config/config_test.go +++ b/pkg/network/config/config_test.go @@ -12,28 +12,19 @@ import ( "os" "regexp" "strconv" - "strings" "testing" + "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" sysconfig "github.com/DataDog/datadog-agent/cmd/system-probe/config" - "github.com/DataDog/datadog-agent/pkg/config" + aconfig "github.com/DataDog/datadog-agent/pkg/config" ) -func newConfig(t *testing.T) { - originalConfig := config.SystemProbe - t.Cleanup(func() { - config.SystemProbe = originalConfig - }) - config.SystemProbe = config.NewConfig("system-probe", "DD", strings.NewReplacer(".", "_")) - config.InitSystemProbeConfig(config.SystemProbe) -} - func TestDisablingDNSInspection(t *testing.T) { t.Run("via YAML", func(t *testing.T) { - newConfig(t) + aconfig.ResetSystemProbeConfig(t) _, err := sysconfig.New("./testdata/TestDDAgentConfigYamlAndSystemProbeConfig-DisableDNS.yaml") require.NoError(t, err) cfg := New() @@ -42,7 +33,7 @@ func TestDisablingDNSInspection(t *testing.T) { }) t.Run("via ENV variable", func(t *testing.T) { - newConfig(t) + aconfig.ResetSystemProbeConfig(t) t.Setenv("DD_DISABLE_DNS_INSPECTION", "true") _, err := sysconfig.New("") require.NoError(t, err) @@ -54,7 +45,7 @@ func TestDisablingDNSInspection(t *testing.T) { func TestDisablingProtocolClassification(t *testing.T) { t.Run("via YAML", func(t *testing.T) { - newConfig(t) + aconfig.ResetSystemProbeConfig(t) _, err := sysconfig.New("./testdata/TestDDAgentConfigYamlAndSystemProbeConfig-NoPRTCLClassifying.yaml") require.NoError(t, err) cfg := New() @@ -63,7 +54,7 @@ func TestDisablingProtocolClassification(t *testing.T) { }) t.Run("via ENV variable", func(t *testing.T) { - newConfig(t) + aconfig.ResetSystemProbeConfig(t) t.Setenv("DD_ENABLE_PROTOCOL_CLASSIFICATION", "false") _, err := sysconfig.New("") require.NoError(t, err) @@ -75,7 +66,7 @@ func TestDisablingProtocolClassification(t *testing.T) { func TestEnableGoTLSSupport(t *testing.T) { t.Run("via YAML", func(t *testing.T) { - newConfig(t) + aconfig.ResetSystemProbeConfig(t) _, err := sysconfig.New("./testdata/TestDDAgentConfigYamlAndSystemProbeConfig-EnableGoTLS.yaml") require.NoError(t, err) cfg := New() @@ -84,7 +75,7 @@ func TestEnableGoTLSSupport(t *testing.T) { }) t.Run("via ENV variable", func(t *testing.T) { - newConfig(t) + aconfig.ResetSystemProbeConfig(t) t.Setenv("DD_SERVICE_MONITORING_CONFIG_ENABLE_GO_TLS_SUPPORT", "true") _, err := sysconfig.New("") require.NoError(t, err) @@ -96,7 +87,7 @@ func TestEnableGoTLSSupport(t *testing.T) { func TestEnableHTTPStatsByStatusCode(t *testing.T) { t.Run("via YAML", func(t *testing.T) { - newConfig(t) + aconfig.ResetSystemProbeConfig(t) _, err := sysconfig.New("./testdata/TestDDSystemProbeConfig-EnableHTTPStatusCodeAggr.yaml") require.NoError(t, err) cfg := New() @@ -105,7 +96,7 @@ func TestEnableHTTPStatsByStatusCode(t *testing.T) { }) t.Run("via ENV variable", func(t *testing.T) { - newConfig(t) + aconfig.ResetSystemProbeConfig(t) t.Setenv("DD_SERVICE_MONITORING_CONFIG_ENABLE_HTTP_STATS_BY_STATUS_CODE", "true") _, err := sysconfig.New("") require.NoError(t, err) @@ -117,7 +108,7 @@ func TestEnableHTTPStatsByStatusCode(t *testing.T) { func TestEnableHTTPMonitoring(t *testing.T) { t.Run("via deprecated YAML", func(t *testing.T) { - newConfig(t) + aconfig.ResetSystemProbeConfig(t) _, err := sysconfig.New("./testdata/TestDDAgentConfigYamlAndSystemProbeConfig-DeprecatedEnableHTTP.yaml") require.NoError(t, err) cfg := New() @@ -126,7 +117,7 @@ func TestEnableHTTPMonitoring(t *testing.T) { }) t.Run("via deprecated ENV variable", func(t *testing.T) { - newConfig(t) + aconfig.ResetSystemProbeConfig(t) t.Setenv("DD_SYSTEM_PROBE_NETWORK_ENABLE_HTTP_MONITORING", "true") _, err := sysconfig.New("") @@ -137,7 +128,7 @@ func TestEnableHTTPMonitoring(t *testing.T) { }) t.Run("via YAML", func(t *testing.T) { - newConfig(t) + aconfig.ResetSystemProbeConfig(t) _, err := sysconfig.New("./testdata/TestDDAgentConfigYamlAndSystemProbeConfig-EnableHTTP.yaml") require.NoError(t, err) cfg := New() @@ -146,7 +137,7 @@ func TestEnableHTTPMonitoring(t *testing.T) { }) t.Run("via ENV variable", func(t *testing.T) { - newConfig(t) + aconfig.ResetSystemProbeConfig(t) t.Setenv("DD_SERVICE_MONITORING_CONFIG_ENABLE_HTTP_MONITORING", "true") _, err := sysconfig.New("") @@ -157,7 +148,7 @@ func TestEnableHTTPMonitoring(t *testing.T) { }) t.Run("Deprecated is enabled, new is disabled", func(t *testing.T) { - newConfig(t) + aconfig.ResetSystemProbeConfig(t) t.Setenv("DD_SYSTEM_PROBE_NETWORK_ENABLE_HTTP_MONITORING", "true") t.Setenv("DD_SERVICE_MONITORING_CONFIG_ENABLE_HTTP_MONITORING", "false") @@ -169,7 +160,7 @@ func TestEnableHTTPMonitoring(t *testing.T) { }) t.Run("Deprecated is disabled, new is enabled", func(t *testing.T) { - newConfig(t) + aconfig.ResetSystemProbeConfig(t) t.Setenv("DD_SYSTEM_PROBE_NETWORK_ENABLE_HTTP_MONITORING", "false") t.Setenv("DD_SERVICE_MONITORING_CONFIG_ENABLE_HTTP_MONITORING", "true") @@ -181,7 +172,7 @@ func TestEnableHTTPMonitoring(t *testing.T) { }) t.Run("Both enabled", func(t *testing.T) { - newConfig(t) + aconfig.ResetSystemProbeConfig(t) t.Setenv("DD_SYSTEM_PROBE_NETWORK_ENABLE_HTTP_MONITORING", "true") t.Setenv("DD_SERVICE_MONITORING_CONFIG_ENABLE_HTTP_MONITORING", "true") @@ -193,7 +184,7 @@ func TestEnableHTTPMonitoring(t *testing.T) { }) t.Run("Not enabled", func(t *testing.T) { - newConfig(t) + aconfig.ResetSystemProbeConfig(t) cfg := New() assert.False(t, cfg.EnableHTTPMonitoring) @@ -202,7 +193,7 @@ func TestEnableHTTPMonitoring(t *testing.T) { func TestEnableDataStreams(t *testing.T) { t.Run("via YAML", func(t *testing.T) { - newConfig(t) + aconfig.ResetSystemProbeConfig(t) _, err := sysconfig.New("./testdata/TestDDAgentConfigYamlAndSystemProbeConfig-EnableDataStreams.yaml") require.NoError(t, err) cfg := New() @@ -211,7 +202,7 @@ func TestEnableDataStreams(t *testing.T) { }) t.Run("via ENV variable", func(t *testing.T) { - newConfig(t) + aconfig.ResetSystemProbeConfig(t) t.Setenv("DD_SYSTEM_PROBE_DATA_STREAMS_ENABLED", "true") _, err := sysconfig.New("") @@ -224,7 +215,7 @@ func TestEnableDataStreams(t *testing.T) { func TestEnableJavaTLSSupport(t *testing.T) { t.Run("via YAML", func(t *testing.T) { - newConfig(t) + aconfig.ResetSystemProbeConfig(t) _, err := sysconfig.New("./testdata/TestDDAgentConfigYamlAndSystemProbeConfig-EnableJavaTLS.yaml") require.NoError(t, err) @@ -234,7 +225,7 @@ func TestEnableJavaTLSSupport(t *testing.T) { }) t.Run("via ENV variable", func(t *testing.T) { - newConfig(t) + aconfig.ResetSystemProbeConfig(t) t.Setenv("DD_SERVICE_MONITORING_CONFIG_JAVA_TLS_ENABLED", "true") _, err := sysconfig.New("") @@ -247,8 +238,7 @@ func TestEnableJavaTLSSupport(t *testing.T) { func TestEnableHTTP2Monitoring(t *testing.T) { t.Run("via YAML", func(t *testing.T) { - newConfig(t) - + aconfig.ResetSystemProbeConfig(t) _, err := sysconfig.New("./testdata/TestDDAgentConfigYamlAndSystemProbeConfig-EnableHTTP2.yaml") require.NoError(t, err) cfg := New() @@ -257,8 +247,7 @@ func TestEnableHTTP2Monitoring(t *testing.T) { }) t.Run("via ENV variable", func(t *testing.T) { - newConfig(t) - + aconfig.ResetSystemProbeConfig(t) t.Setenv("DD_SERVICE_MONITORING_CONFIG_ENABLE_HTTP2_MONITORING", "true") _, err := sysconfig.New("") require.NoError(t, err) @@ -269,7 +258,7 @@ func TestEnableHTTP2Monitoring(t *testing.T) { } func TestDefaultDisabledJavaTLSSupport(t *testing.T) { - newConfig(t) + aconfig.ResetSystemProbeConfig(t) _, err := sysconfig.New("") require.NoError(t, err) @@ -279,7 +268,7 @@ func TestDefaultDisabledJavaTLSSupport(t *testing.T) { } func TestDefaultDisabledHTTP2Support(t *testing.T) { - newConfig(t) + aconfig.ResetSystemProbeConfig(t) _, err := sysconfig.New("") require.NoError(t, err) @@ -290,7 +279,7 @@ func TestDefaultDisabledHTTP2Support(t *testing.T) { func TestDisableGatewayLookup(t *testing.T) { t.Run("via YAML", func(t *testing.T) { - newConfig(t) + aconfig.ResetSystemProbeConfig(t) // default config _, err := sysconfig.New("") require.NoError(t, err) @@ -298,7 +287,7 @@ func TestDisableGatewayLookup(t *testing.T) { assert.True(t, cfg.EnableGatewayLookup) - newConfig(t) + aconfig.ResetSystemProbeConfig(t) _, err = sysconfig.New("./testdata/TestDDAgentConfigYamlAndSystemProbeConfig-DisableGwLookup.yaml") require.NoError(t, err) cfg = New() @@ -307,7 +296,7 @@ func TestDisableGatewayLookup(t *testing.T) { }) t.Run("via ENV variable", func(t *testing.T) { - newConfig(t) + aconfig.ResetSystemProbeConfig(t) t.Setenv("DD_SYSTEM_PROBE_NETWORK_ENABLE_GATEWAY_LOOKUP", "false") _, err := sysconfig.New("") require.NoError(t, err) @@ -319,7 +308,7 @@ func TestDisableGatewayLookup(t *testing.T) { func TestIgnoreConntrackInitFailure(t *testing.T) { t.Run("via YAML", func(t *testing.T) { - newConfig(t) + aconfig.ResetSystemProbeConfig(t) _, err := sysconfig.New("./testdata/TestDDAgentConfigYamlAndSystemProbeConfig-IgnoreCTInitFailure.yaml") require.NoError(t, err) cfg := New() @@ -328,7 +317,7 @@ func TestIgnoreConntrackInitFailure(t *testing.T) { }) t.Run("via ENV variable", func(t *testing.T) { - newConfig(t) + aconfig.ResetSystemProbeConfig(t) t.Setenv("DD_SYSTEM_PROBE_NETWORK_IGNORE_CONNTRACK_INIT_FAILURE", "true") _, err := sysconfig.New("") require.NoError(t, err) @@ -341,7 +330,7 @@ func TestIgnoreConntrackInitFailure(t *testing.T) { func TestEnablingDNSStatsCollection(t *testing.T) { t.Run("via YAML", func(t *testing.T) { - newConfig(t) + aconfig.ResetSystemProbeConfig(t) _, err := sysconfig.New("./testdata/TestDDAgentConfigYamlAndSystemProbeConfig-EnableDNSStats.yaml") require.NoError(t, err) cfg := New() @@ -350,7 +339,7 @@ func TestEnablingDNSStatsCollection(t *testing.T) { }) t.Run("via ENV variable", func(t *testing.T) { - newConfig(t) + aconfig.ResetSystemProbeConfig(t) t.Setenv("DD_COLLECT_DNS_STATS", "false") _, err := sysconfig.New("") require.NoError(t, err) @@ -358,7 +347,7 @@ func TestEnablingDNSStatsCollection(t *testing.T) { assert.False(t, cfg.CollectDNSStats) - newConfig(t) + aconfig.ResetSystemProbeConfig(t) t.Setenv("DD_COLLECT_DNS_STATS", "true") _, err = sysconfig.New("") require.NoError(t, err) @@ -370,7 +359,7 @@ func TestEnablingDNSStatsCollection(t *testing.T) { func TestDisablingDNSDomainCollection(t *testing.T) { t.Run("via YAML", func(t *testing.T) { - newConfig(t) + aconfig.ResetSystemProbeConfig(t) _, err := sysconfig.New("./testdata/TestDDAgentConfigYamlAndSystemProbeConfig-DisableDNSDomains.yaml") require.NoError(t, err) cfg := New() @@ -379,7 +368,7 @@ func TestDisablingDNSDomainCollection(t *testing.T) { }) t.Run("via ENV variable", func(t *testing.T) { - newConfig(t) + aconfig.ResetSystemProbeConfig(t) t.Setenv("DD_COLLECT_DNS_DOMAINS", "false") _, err := sysconfig.New("") require.NoError(t, err) @@ -387,7 +376,7 @@ func TestDisablingDNSDomainCollection(t *testing.T) { assert.False(t, cfg.CollectDNSDomains) - newConfig(t) + aconfig.ResetSystemProbeConfig(t) t.Setenv("DD_COLLECT_DNS_DOMAINS", "true") _, err = sysconfig.New("") require.NoError(t, err) @@ -399,7 +388,7 @@ func TestDisablingDNSDomainCollection(t *testing.T) { func TestSettingMaxDNSStats(t *testing.T) { t.Run("via YAML", func(t *testing.T) { - newConfig(t) + aconfig.ResetSystemProbeConfig(t) _, err := sysconfig.New("./testdata/TestDDAgentConfigYamlAndSystemProbeConfig-DisableDNSDomains.yaml") require.NoError(t, err) cfg := New() @@ -408,7 +397,7 @@ func TestSettingMaxDNSStats(t *testing.T) { }) t.Run("via ENV variable", func(t *testing.T) { - newConfig(t) + aconfig.ResetSystemProbeConfig(t) os.Unsetenv("DD_SYSTEM_PROBE_CONFIG_MAX_DNS_STATS") _, err := sysconfig.New("") require.NoError(t, err) @@ -416,7 +405,7 @@ func TestSettingMaxDNSStats(t *testing.T) { assert.Equal(t, 20000, cfg.MaxDNSStats) // default value - newConfig(t) + aconfig.ResetSystemProbeConfig(t) t.Setenv("DD_SYSTEM_PROBE_CONFIG_MAX_DNS_STATS", "10000") _, err = sysconfig.New("") require.NoError(t, err) @@ -461,7 +450,7 @@ func TestHTTPReplaceRules(t *testing.T) { ` t.Run("via deprecated YAML", func(t *testing.T) { - newConfig(t) + aconfig.ResetSystemProbeConfig(t) _, err := sysconfig.New("./testdata/TestDDSystemProbeConfig-HTTPReplaceRulesDeprecated.yaml") require.NoError(t, err) cfg := New() @@ -473,7 +462,7 @@ func TestHTTPReplaceRules(t *testing.T) { }) t.Run("via deprecated ENV variable", func(t *testing.T) { - newConfig(t) + aconfig.ResetSystemProbeConfig(t) t.Setenv("DD_SYSTEM_PROBE_NETWORK_HTTP_REPLACE_RULES", envContent) cfg := New() @@ -485,7 +474,7 @@ func TestHTTPReplaceRules(t *testing.T) { }) t.Run("via YAML", func(t *testing.T) { - newConfig(t) + aconfig.ResetSystemProbeConfig(t) _, err := sysconfig.New("./testdata/TestDDSystemProbeConfig-HTTPReplaceRules.yaml") require.NoError(t, err) cfg := New() @@ -497,7 +486,7 @@ func TestHTTPReplaceRules(t *testing.T) { }) t.Run("via ENV variable", func(t *testing.T) { - newConfig(t) + aconfig.ResetSystemProbeConfig(t) t.Setenv("DD_SERVICE_MONITORING_CONFIG_HTTP_REPLACE_RULES", envContent) cfg := New() @@ -509,7 +498,7 @@ func TestHTTPReplaceRules(t *testing.T) { }) t.Run("Deprecated is enabled, new is disabled", func(t *testing.T) { - newConfig(t) + aconfig.ResetSystemProbeConfig(t) t.Setenv("DD_SYSTEM_PROBE_NETWORK_HTTP_REPLACE_RULES", envContent) cfg := New() @@ -521,7 +510,7 @@ func TestHTTPReplaceRules(t *testing.T) { }) t.Run("Deprecated is disabled, new is enabled", func(t *testing.T) { - newConfig(t) + aconfig.ResetSystemProbeConfig(t) t.Setenv("DD_SERVICE_MONITORING_CONFIG_HTTP_REPLACE_RULES", envContent) cfg := New() @@ -533,7 +522,7 @@ func TestHTTPReplaceRules(t *testing.T) { }) t.Run("Both enabled", func(t *testing.T) { - newConfig(t) + aconfig.ResetSystemProbeConfig(t) t.Setenv("DD_SERVICE_MONITORING_CONFIG_HTTP_REPLACE_RULES", envContent) // Setting a different value for the old value, as we should override. t.Setenv("DD_SYSTEM_PROBE_NETWORK_HTTP_REPLACE_RULES", ` @@ -553,7 +542,7 @@ func TestHTTPReplaceRules(t *testing.T) { }) t.Run("Not enabled", func(t *testing.T) { - newConfig(t) + aconfig.ResetSystemProbeConfig(t) cfg := New() assert.Empty(t, cfg.HTTPReplaceRules) @@ -562,7 +551,7 @@ func TestHTTPReplaceRules(t *testing.T) { func TestMaxTrackedHTTPConnections(t *testing.T) { t.Run("via deprecated YAML", func(t *testing.T) { - newConfig(t) + aconfig.ResetSystemProbeConfig(t) _, err := sysconfig.New("./testdata/TestDDSystemProbeConfig-MaxTrackedHTTPConnectionsDeprecated.yaml") require.NoError(t, err) cfg := New() @@ -571,7 +560,7 @@ func TestMaxTrackedHTTPConnections(t *testing.T) { }) t.Run("via deprecated ENV variable", func(t *testing.T) { - newConfig(t) + aconfig.ResetSystemProbeConfig(t) t.Setenv("DD_NETWORK_CONFIG_MAX_TRACKED_HTTP_CONNECTIONS", "1025") cfg := New() @@ -580,7 +569,7 @@ func TestMaxTrackedHTTPConnections(t *testing.T) { }) t.Run("via YAML", func(t *testing.T) { - newConfig(t) + aconfig.ResetSystemProbeConfig(t) _, err := sysconfig.New("./testdata/TestDDSystemProbeConfig-MaxTrackedHTTPConnections.yaml") require.NoError(t, err) cfg := New() @@ -589,7 +578,7 @@ func TestMaxTrackedHTTPConnections(t *testing.T) { }) t.Run("via ENV variable", func(t *testing.T) { - newConfig(t) + aconfig.ResetSystemProbeConfig(t) t.Setenv("DD_SERVICE_MONITORING_CONFIG_MAX_TRACKED_HTTP_CONNECTIONS", "1025") cfg := New() @@ -598,7 +587,7 @@ func TestMaxTrackedHTTPConnections(t *testing.T) { }) t.Run("Deprecated is enabled, new is disabled", func(t *testing.T) { - newConfig(t) + aconfig.ResetSystemProbeConfig(t) t.Setenv("DD_NETWORK_CONFIG_MAX_TRACKED_HTTP_CONNECTIONS", "1025") cfg := New() @@ -607,7 +596,7 @@ func TestMaxTrackedHTTPConnections(t *testing.T) { }) t.Run("Deprecated is disabled, new is enabled", func(t *testing.T) { - newConfig(t) + aconfig.ResetSystemProbeConfig(t) t.Setenv("DD_SERVICE_MONITORING_CONFIG_MAX_TRACKED_HTTP_CONNECTIONS", "1025") cfg := New() @@ -616,7 +605,7 @@ func TestMaxTrackedHTTPConnections(t *testing.T) { }) t.Run("Both enabled", func(t *testing.T) { - newConfig(t) + aconfig.ResetSystemProbeConfig(t) // Setting a different value t.Setenv("DD_NETWORK_CONFIG_MAX_TRACKED_HTTP_CONNECTIONS", "1026") t.Setenv("DD_SERVICE_MONITORING_CONFIG_MAX_TRACKED_HTTP_CONNECTIONS", "1025") @@ -627,25 +616,203 @@ func TestMaxTrackedHTTPConnections(t *testing.T) { }) t.Run("Not enabled", func(t *testing.T) { - newConfig(t) + aconfig.ResetSystemProbeConfig(t) cfg := New() // Default value. require.Equal(t, cfg.MaxTrackedHTTPConnections, int64(1024)) }) } -func TestHTTPNotificationThreshold(t *testing.T) { +func TestHTTPMapCleanerInterval(t *testing.T) { + t.Run("via deprecated YAML", func(t *testing.T) { + aconfig.ResetSystemProbeConfig(t) + cfg := configurationFromYAML(t, ` +system_probe_config: + http_map_cleaner_interval_in_s: 1025 +`) + + require.Equal(t, cfg.HTTPMapCleanerInterval, 1025*time.Second) + }) + + t.Run("via deprecated ENV variable", func(t *testing.T) { + aconfig.ResetSystemProbeConfig(t) + t.Setenv("DD_SYSTEM_PROBE_CONFIG_HTTP_MAP_CLEANER_INTERVAL_IN_S", "1025") + + cfg := New() + + require.Equal(t, cfg.HTTPMapCleanerInterval, 1025*time.Second) + }) + t.Run("via YAML", func(t *testing.T) { - newConfig(t) - _, err := sysconfig.New("./testdata/TestDDSystemProbeConfig-HTTPNotificationThreshold.yaml") - require.NoError(t, err) + aconfig.ResetSystemProbeConfig(t) + cfg := configurationFromYAML(t, ` +service_monitoring_config: + http_map_cleaner_interval_in_s: 1025 +`) + + require.Equal(t, cfg.HTTPMapCleanerInterval, 1025*time.Second) + }) + + t.Run("via ENV variable", func(t *testing.T) { + aconfig.ResetSystemProbeConfig(t) + t.Setenv("DD_SERVICE_MONITORING_CONFIG_HTTP_MAP_CLEANER_INTERVAL_IN_S", "1025") + + cfg := New() + + require.Equal(t, cfg.HTTPMapCleanerInterval, 1025*time.Second) + }) + + t.Run("Deprecated is enabled, new is disabled", func(t *testing.T) { + aconfig.ResetSystemProbeConfig(t) + t.Setenv("DD_SYSTEM_PROBE_CONFIG_HTTP_MAP_CLEANER_INTERVAL_IN_S", "1025") + + cfg := New() + + require.Equal(t, cfg.HTTPMapCleanerInterval, 1025*time.Second) + }) + + t.Run("Deprecated is disabled, new is enabled", func(t *testing.T) { + aconfig.ResetSystemProbeConfig(t) + t.Setenv("DD_SERVICE_MONITORING_CONFIG_HTTP_MAP_CLEANER_INTERVAL_IN_S", "1025") + + cfg := New() + + require.Equal(t, cfg.HTTPMapCleanerInterval, 1025*time.Second) + }) + + t.Run("Both enabled", func(t *testing.T) { + aconfig.ResetSystemProbeConfig(t) + // Setting a different value + t.Setenv("DD_SYSTEM_PROBE_CONFIG_HTTP_MAP_CLEANER_INTERVAL_IN_S", "1026") + t.Setenv("DD_SERVICE_MONITORING_CONFIG_HTTP_MAP_CLEANER_INTERVAL_IN_S", "1025") + + cfg := New() + + require.Equal(t, cfg.HTTPMapCleanerInterval, 1025*time.Second) + }) + + t.Run("Not enabled", func(t *testing.T) { + aconfig.ResetSystemProbeConfig(t) + cfg := New() + // Default value. + require.Equal(t, cfg.HTTPMapCleanerInterval, 300*time.Second) + }) +} + +func TestHTTPIdleConnectionTTL(t *testing.T) { + t.Run("via deprecated YAML", func(t *testing.T) { + aconfig.ResetSystemProbeConfig(t) + cfg := configurationFromYAML(t, ` +system_probe_config: + http_idle_connection_ttl_in_s: 1025 +`) + + require.Equal(t, cfg.HTTPIdleConnectionTTL, 1025*time.Second) + }) + + t.Run("via deprecated ENV variable", func(t *testing.T) { + aconfig.ResetSystemProbeConfig(t) + t.Setenv("DD_SYSTEM_PROBE_CONFIG_HTTP_IDLE_CONNECTION_TTL_IN_S", "1025") + + cfg := New() + + require.Equal(t, cfg.HTTPIdleConnectionTTL, 1025*time.Second) + }) + + t.Run("via YAML", func(t *testing.T) { + aconfig.ResetSystemProbeConfig(t) + cfg := configurationFromYAML(t, ` +service_monitoring_config: + http_idle_connection_ttl_in_s: 1025 +`) + require.Equal(t, cfg.HTTPIdleConnectionTTL, 1025*time.Second) + }) + + t.Run("via ENV variable", func(t *testing.T) { + aconfig.ResetSystemProbeConfig(t) + t.Setenv("DD_SERVICE_MONITORING_CONFIG_HTTP_IDLE_CONNECTION_TTL_IN_S", "1025") + + cfg := New() + + require.Equal(t, cfg.HTTPIdleConnectionTTL, 1025*time.Second) + }) + + t.Run("Deprecated is enabled, new is disabled", func(t *testing.T) { + aconfig.ResetSystemProbeConfig(t) + t.Setenv("DD_SYSTEM_PROBE_CONFIG_HTTP_IDLE_CONNECTION_TTL_IN_S", "1025") + + cfg := New() + + require.Equal(t, cfg.HTTPIdleConnectionTTL, 1025*time.Second) + }) + + t.Run("Deprecated is disabled, new is enabled", func(t *testing.T) { + aconfig.ResetSystemProbeConfig(t) + t.Setenv("DD_SERVICE_MONITORING_CONFIG_HTTP_IDLE_CONNECTION_TTL_IN_S", "1025") + + cfg := New() + + require.Equal(t, cfg.HTTPIdleConnectionTTL, 1025*time.Second) + }) + + t.Run("Both enabled", func(t *testing.T) { + aconfig.ResetSystemProbeConfig(t) + // Setting a different value + t.Setenv("DD_SYSTEM_PROBE_CONFIG_HTTP_IDLE_CONNECTION_TTL_IN_S", "1026") + t.Setenv("DD_SERVICE_MONITORING_CONFIG_HTTP_IDLE_CONNECTION_TTL_IN_S", "1025") + + cfg := New() + + require.Equal(t, cfg.HTTPIdleConnectionTTL, 1025*time.Second) + }) + + t.Run("Not enabled", func(t *testing.T) { + aconfig.ResetSystemProbeConfig(t) + cfg := New() + // Default value. + require.Equal(t, cfg.HTTPIdleConnectionTTL, 30*time.Second) + }) +} + +func TestHTTPNotificationThreshold(t *testing.T) { + t.Run("via deprecated YAML", func(t *testing.T) { + aconfig.ResetSystemProbeConfig(t) + cfg := configurationFromYAML(t, ` +network_config: + http_notification_threshold: 100 +`) + require.Equal(t, cfg.HTTPNotificationThreshold, int64(100)) + }) + + t.Run("via deprecated ENV variable", func(t *testing.T) { + aconfig.ResetSystemProbeConfig(t) + t.Setenv("DD_NETWORK_CONFIG_HTTP_NOTIFICATION_THRESHOLD", "100") + cfg := New() require.Equal(t, cfg.HTTPNotificationThreshold, int64(100)) }) + t.Run("via YAML", func(t *testing.T) { + aconfig.ResetSystemProbeConfig(t) + cfg := configurationFromYAML(t, ` +service_monitoring_config: + http_notification_threshold: 100 +`) + require.Equal(t, cfg.HTTPNotificationThreshold, int64(100)) + }) + t.Run("via ENV variable", func(t *testing.T) { - newConfig(t) + aconfig.ResetSystemProbeConfig(t) + t.Setenv("DD_SERVICE_MONITORING_CONFIG_HTTP_NOTIFICATION_THRESHOLD", "100") + + cfg := New() + + require.Equal(t, cfg.HTTPNotificationThreshold, int64(100)) + }) + + t.Run("Deprecated is enabled, new is disabled", func(t *testing.T) { + aconfig.ResetSystemProbeConfig(t) t.Setenv("DD_NETWORK_CONFIG_HTTP_NOTIFICATION_THRESHOLD", "100") cfg := New() @@ -653,8 +820,28 @@ func TestHTTPNotificationThreshold(t *testing.T) { require.Equal(t, cfg.HTTPNotificationThreshold, int64(100)) }) + t.Run("Deprecated is disabled, new is enabled", func(t *testing.T) { + aconfig.ResetSystemProbeConfig(t) + t.Setenv("DD_SERVICE_MONITORING_CONFIG_HTTP_NOTIFICATION_THRESHOLD", "100") + + cfg := New() + + require.Equal(t, cfg.HTTPNotificationThreshold, int64(100)) + }) + + t.Run("Both enabled", func(t *testing.T) { + aconfig.ResetSystemProbeConfig(t) + // Setting a different value + t.Setenv("DD_NETWORK_CONFIG_HTTP_NOTIFICATION_THRESHOLD", "101") + t.Setenv("DD_SERVICE_MONITORING_CONFIG_HTTP_NOTIFICATION_THRESHOLD", "100") + + cfg := New() + + require.Equal(t, cfg.HTTPNotificationThreshold, int64(100)) + }) + t.Run("Not enabled", func(t *testing.T) { - newConfig(t) + aconfig.ResetSystemProbeConfig(t) cfg := New() // Default value. require.Equal(t, cfg.HTTPNotificationThreshold, int64(512)) @@ -663,18 +850,65 @@ func TestHTTPNotificationThreshold(t *testing.T) { // Testing we're not exceeding the limit for http_notification_threshold. func TestHTTPNotificationThresholdOverLimit(t *testing.T) { - t.Run("via YAML", func(t *testing.T) { - newConfig(t) - _, err := sysconfig.New("./testdata/TestDDSystemProbeConfig-HTTPNotificationThresholdOverLimit.yaml") - require.NoError(t, err) + t.Run("via deprecated YAML", func(t *testing.T) { + aconfig.ResetSystemProbeConfig(t) + cfg := configurationFromYAML(t, ` +network_config: + http_notification_threshold: 1025 +`) + require.Equal(t, cfg.HTTPNotificationThreshold, int64(512)) + }) + + t.Run("via deprecated ENV variable", func(t *testing.T) { + aconfig.ResetSystemProbeConfig(t) + t.Setenv("DD_NETWORK_CONFIG_HTTP_NOTIFICATION_THRESHOLD", "1025") + cfg := New() require.Equal(t, cfg.HTTPNotificationThreshold, int64(512)) }) + t.Run("via YAML", func(t *testing.T) { + aconfig.ResetSystemProbeConfig(t) + cfg := configurationFromYAML(t, ` +service_monitoring_config: + http_notification_threshold: 1025 +`) + require.Equal(t, cfg.HTTPNotificationThreshold, int64(512)) + }) + t.Run("via ENV variable", func(t *testing.T) { - newConfig(t) - t.Setenv("DD_NETWORK_CONFIG_HTTP_NOTIFICATION_THRESHOLD", "2000") + aconfig.ResetSystemProbeConfig(t) + t.Setenv("DD_SERVICE_MONITORING_CONFIG_HTTP_NOTIFICATION_THRESHOLD", "1025") + + cfg := New() + + require.Equal(t, cfg.HTTPNotificationThreshold, int64(512)) + }) + + t.Run("Deprecated is enabled, new is disabled", func(t *testing.T) { + aconfig.ResetSystemProbeConfig(t) + t.Setenv("DD_NETWORK_CONFIG_HTTP_NOTIFICATION_THRESHOLD", "1025") + + cfg := New() + + require.Equal(t, cfg.HTTPNotificationThreshold, int64(512)) + }) + + t.Run("Deprecated is disabled, new is enabled", func(t *testing.T) { + aconfig.ResetSystemProbeConfig(t) + t.Setenv("DD_SERVICE_MONITORING_CONFIG_HTTP_NOTIFICATION_THRESHOLD", "1025") + + cfg := New() + + require.Equal(t, cfg.HTTPNotificationThreshold, int64(512)) + }) + + t.Run("Both enabled", func(t *testing.T) { + aconfig.ResetSystemProbeConfig(t) + // Setting a different value + t.Setenv("DD_NETWORK_CONFIG_HTTP_NOTIFICATION_THRESHOLD", "1026") + t.Setenv("DD_SERVICE_MONITORING_CONFIG_HTTP_NOTIFICATION_THRESHOLD", "1025") cfg := New() @@ -682,25 +916,174 @@ func TestHTTPNotificationThresholdOverLimit(t *testing.T) { }) t.Run("Not enabled", func(t *testing.T) { - newConfig(t) + aconfig.ResetSystemProbeConfig(t) cfg := New() // Default value. require.Equal(t, cfg.HTTPNotificationThreshold, int64(512)) }) } +func TestHTTPMaxRequestFragment(t *testing.T) { + t.Run("via deprecated YAML", func(t *testing.T) { + aconfig.ResetSystemProbeConfig(t) + cfg := configurationFromYAML(t, ` +network_config: + http_max_request_fragment: 155 +`) + require.Equal(t, cfg.HTTPMaxRequestFragment, int64(155)) + }) + + t.Run("via deprecated ENV variable", func(t *testing.T) { + aconfig.ResetSystemProbeConfig(t) + t.Setenv("DD_NETWORK_CONFIG_HTTP_MAX_REQUEST_FRAGMENT", "155") + + cfg := New() + + require.Equal(t, cfg.HTTPMaxRequestFragment, int64(155)) + }) + + t.Run("via YAML", func(t *testing.T) { + aconfig.ResetSystemProbeConfig(t) + cfg := configurationFromYAML(t, ` +service_monitoring_config: + http_max_request_fragment: 155 +`) + require.Equal(t, cfg.HTTPMaxRequestFragment, int64(155)) + }) + + t.Run("via ENV variable", func(t *testing.T) { + aconfig.ResetSystemProbeConfig(t) + t.Setenv("DD_SERVICE_MONITORING_CONFIG_HTTP_MAX_REQUEST_FRAGMENT", "155") + + cfg := New() + + require.Equal(t, cfg.HTTPMaxRequestFragment, int64(155)) + }) + + t.Run("Deprecated is enabled, new is disabled", func(t *testing.T) { + aconfig.ResetSystemProbeConfig(t) + t.Setenv("DD_NETWORK_CONFIG_HTTP_MAX_REQUEST_FRAGMENT", "155") + + cfg := New() + + require.Equal(t, cfg.HTTPMaxRequestFragment, int64(155)) + }) + + t.Run("Deprecated is disabled, new is enabled", func(t *testing.T) { + aconfig.ResetSystemProbeConfig(t) + t.Setenv("DD_SERVICE_MONITORING_CONFIG_HTTP_MAX_REQUEST_FRAGMENT", "155") + + cfg := New() + + require.Equal(t, cfg.HTTPMaxRequestFragment, int64(155)) + }) + + t.Run("Both enabled", func(t *testing.T) { + aconfig.ResetSystemProbeConfig(t) + // Setting a different value + t.Setenv("DD_NETWORK_CONFIG_HTTP_MAX_REQUEST_FRAGMENT", "151") + t.Setenv("DD_SERVICE_MONITORING_CONFIG_HTTP_MAX_REQUEST_FRAGMENT", "155") + + cfg := New() + + require.Equal(t, cfg.HTTPMaxRequestFragment, int64(155)) + }) + + t.Run("Not enabled", func(t *testing.T) { + aconfig.ResetSystemProbeConfig(t) + cfg := New() + // Default value. + require.Equal(t, cfg.HTTPMaxRequestFragment, int64(160)) + }) +} + +// Testing we're not exceeding the hard coded limit of http_max_request_fragment. +func TestHTTPMaxRequestFragmentLimit(t *testing.T) { + t.Run("via deprecated YAML", func(t *testing.T) { + aconfig.ResetSystemProbeConfig(t) + cfg := configurationFromYAML(t, ` +network_config: + http_max_request_fragment: 175 +`) + require.Equal(t, cfg.HTTPMaxRequestFragment, int64(160)) + }) + + t.Run("via deprecated ENV variable", func(t *testing.T) { + aconfig.ResetSystemProbeConfig(t) + t.Setenv("DD_NETWORK_CONFIG_HTTP_MAX_REQUEST_FRAGMENT", "175") + + cfg := New() + + require.Equal(t, cfg.HTTPMaxRequestFragment, int64(160)) + }) + + t.Run("via YAML", func(t *testing.T) { + aconfig.ResetSystemProbeConfig(t) + cfg := configurationFromYAML(t, ` +service_monitoring_config: + http_max_request_fragment: 175 +`) + require.Equal(t, cfg.HTTPMaxRequestFragment, int64(160)) + }) + + t.Run("via ENV variable", func(t *testing.T) { + aconfig.ResetSystemProbeConfig(t) + t.Setenv("DD_SERVICE_MONITORING_CONFIG_HTTP_MAX_REQUEST_FRAGMENT", "175") + + cfg := New() + + require.Equal(t, cfg.HTTPMaxRequestFragment, int64(160)) + }) + + t.Run("Deprecated is enabled, new is disabled", func(t *testing.T) { + aconfig.ResetSystemProbeConfig(t) + t.Setenv("DD_NETWORK_CONFIG_HTTP_MAX_REQUEST_FRAGMENT", "175") + + cfg := New() + + require.Equal(t, cfg.HTTPMaxRequestFragment, int64(160)) + }) + + t.Run("Deprecated is disabled, new is enabled", func(t *testing.T) { + aconfig.ResetSystemProbeConfig(t) + t.Setenv("DD_SERVICE_MONITORING_CONFIG_HTTP_MAX_REQUEST_FRAGMENT", "175") + + cfg := New() + + require.Equal(t, cfg.HTTPMaxRequestFragment, int64(160)) + }) + + t.Run("Both enabled", func(t *testing.T) { + aconfig.ResetSystemProbeConfig(t) + // Setting a different value + t.Setenv("DD_NETWORK_CONFIG_HTTP_MAX_REQUEST_FRAGMENT", "176") + t.Setenv("DD_SERVICE_MONITORING_CONFIG_HTTP_MAX_REQUEST_FRAGMENT", "175") + + cfg := New() + + require.Equal(t, cfg.HTTPMaxRequestFragment, int64(160)) + }) + + t.Run("Not enabled", func(t *testing.T) { + aconfig.ResetSystemProbeConfig(t) + cfg := New() + // Default value. + require.Equal(t, cfg.HTTPMaxRequestFragment, int64(160)) + }) +} + func TestMaxClosedConnectionsBuffered(t *testing.T) { maxTrackedConnections := New().MaxTrackedConnections t.Run("value set", func(t *testing.T) { - newConfig(t) + aconfig.ResetSystemProbeConfig(t) t.Setenv("DD_SYSTEM_PROBE_CONFIG_MAX_CLOSED_CONNECTIONS_BUFFERED", fmt.Sprintf("%d", maxTrackedConnections-1)) cfg := New() require.Equal(t, maxTrackedConnections-1, cfg.MaxClosedConnectionsBuffered) }) t.Run("value not set", func(t *testing.T) { - newConfig(t) + aconfig.ResetSystemProbeConfig(t) cfg := New() require.Equal(t, cfg.MaxTrackedConnections, cfg.MaxClosedConnectionsBuffered) }) @@ -708,7 +1091,7 @@ func TestMaxClosedConnectionsBuffered(t *testing.T) { func TestMaxHTTPStatsBuffered(t *testing.T) { t.Run("via deprecated YAML", func(t *testing.T) { - newConfig(t) + aconfig.ResetSystemProbeConfig(t) _, err := sysconfig.New("./testdata/TestDDSystemProbeConfig-MaxHTTPStatsBufferedDeprecated.yaml") require.NoError(t, err) cfg := New() @@ -717,7 +1100,7 @@ func TestMaxHTTPStatsBuffered(t *testing.T) { }) t.Run("via deprecated ENV variable", func(t *testing.T) { - newConfig(t) + aconfig.ResetSystemProbeConfig(t) t.Setenv("DD_SYSTEM_PROBE_NETWORK_MAX_HTTP_STATS_BUFFERED", "513") cfg := New() @@ -726,7 +1109,7 @@ func TestMaxHTTPStatsBuffered(t *testing.T) { }) t.Run("via YAML", func(t *testing.T) { - newConfig(t) + aconfig.ResetSystemProbeConfig(t) _, err := sysconfig.New("./testdata/TestDDSystemProbeConfig-MaxHTTPStatsBuffered.yaml") require.NoError(t, err) cfg := New() @@ -735,7 +1118,7 @@ func TestMaxHTTPStatsBuffered(t *testing.T) { }) t.Run("via ENV variable", func(t *testing.T) { - newConfig(t) + aconfig.ResetSystemProbeConfig(t) t.Setenv("DD_SERVICE_MONITORING_CONFIG_MAX_HTTP_STATS_BUFFERED", "513") cfg := New() @@ -744,7 +1127,7 @@ func TestMaxHTTPStatsBuffered(t *testing.T) { }) t.Run("Deprecated is enabled, new is disabled", func(t *testing.T) { - newConfig(t) + aconfig.ResetSystemProbeConfig(t) t.Setenv("DD_SYSTEM_PROBE_NETWORK_MAX_HTTP_STATS_BUFFERED", "513") cfg := New() @@ -753,7 +1136,7 @@ func TestMaxHTTPStatsBuffered(t *testing.T) { }) t.Run("Deprecated is disabled, new is enabled", func(t *testing.T) { - newConfig(t) + aconfig.ResetSystemProbeConfig(t) t.Setenv("DD_SERVICE_MONITORING_CONFIG_MAX_HTTP_STATS_BUFFERED", "513") cfg := New() @@ -762,7 +1145,7 @@ func TestMaxHTTPStatsBuffered(t *testing.T) { }) t.Run("Both enabled", func(t *testing.T) { - newConfig(t) + aconfig.ResetSystemProbeConfig(t) t.Setenv("DD_SYSTEM_PROBE_NETWORK_MAX_HTTP_STATS_BUFFERED", "514") t.Setenv("DD_SERVICE_MONITORING_CONFIG_MAX_HTTP_STATS_BUFFERED", "513") @@ -772,7 +1155,7 @@ func TestMaxHTTPStatsBuffered(t *testing.T) { }) t.Run("Not enabled", func(t *testing.T) { - newConfig(t) + aconfig.ResetSystemProbeConfig(t) cfg := New() // Default value. require.Equal(t, cfg.MaxHTTPStatsBuffered, 100000) @@ -781,7 +1164,7 @@ func TestMaxHTTPStatsBuffered(t *testing.T) { func TestMaxKafkaStatsBuffered(t *testing.T) { t.Run("value set through env var", func(t *testing.T) { - newConfig(t) + aconfig.ResetSystemProbeConfig(t) t.Setenv("DD_SERVICE_MONITORING_CONFIG_MAX_KAFKA_STATS_BUFFERED", "50000") cfg := New() @@ -789,7 +1172,7 @@ func TestMaxKafkaStatsBuffered(t *testing.T) { }) t.Run("value set through yaml", func(t *testing.T) { - newConfig(t) + aconfig.ResetSystemProbeConfig(t) cfg := configurationFromYAML(t, ` service_monitoring_config: max_kafka_stats_buffered: 30000 @@ -837,7 +1220,7 @@ func TestNetworkConfigEnabled(t *testing.T) { t.Setenv("DD_SYSTEM_PROBE_DATA_STREAMS_ENABLED", strconv.FormatBool(*tc.dsmIn)) } - newConfig(t) + aconfig.ResetSystemProbeConfig(t) _, err = sysconfig.New(f.Name()) require.NoError(t, err) cfg := New() diff --git a/pkg/network/config/testdata/TestDDSystemProbeConfig-HTTPNotificationThreshold.yaml b/pkg/network/config/testdata/TestDDSystemProbeConfig-HTTPNotificationThreshold.yaml deleted file mode 100644 index e4bbb12a1cac7..0000000000000 --- a/pkg/network/config/testdata/TestDDSystemProbeConfig-HTTPNotificationThreshold.yaml +++ /dev/null @@ -1,2 +0,0 @@ -network_config: - http_notification_threshold: 100 diff --git a/pkg/network/config/testdata/TestDDSystemProbeConfig-HTTPNotificationThresholdOverLimit.yaml b/pkg/network/config/testdata/TestDDSystemProbeConfig-HTTPNotificationThresholdOverLimit.yaml deleted file mode 100644 index c31177ae4a1f3..0000000000000 --- a/pkg/network/config/testdata/TestDDSystemProbeConfig-HTTPNotificationThresholdOverLimit.yaml +++ /dev/null @@ -1,2 +0,0 @@ -network_config: - http_notification_threshold: 2000 diff --git a/pkg/network/usm/monitor_test.go b/pkg/network/usm/monitor_test.go index f2ef7bb051375..1d84630aa0c18 100644 --- a/pkg/network/usm/monitor_test.go +++ b/pkg/network/usm/monitor_test.go @@ -27,8 +27,9 @@ import ( "github.com/stretchr/testify/require" "github.com/stretchr/testify/suite" + "github.com/DataDog/datadog-agent/pkg/config" "github.com/DataDog/datadog-agent/pkg/ebpf/ebpftest" - "github.com/DataDog/datadog-agent/pkg/network/config" + networkconfig "github.com/DataDog/datadog-agent/pkg/network/config" netlink "github.com/DataDog/datadog-agent/pkg/network/netlink/testutil" "github.com/DataDog/datadog-agent/pkg/network/protocols/http" "github.com/DataDog/datadog-agent/pkg/network/protocols/http/testutil" @@ -229,8 +230,9 @@ func (s *HTTPTestSuite) TestHTTPMonitorIntegrationSlowResponse() { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - t.Setenv("DD_SYSTEM_PROBE_CONFIG_HTTP_MAP_CLEANER_INTERVAL_IN_S", strconv.Itoa(tt.mapCleanerIntervalSeconds)) - t.Setenv("DD_SYSTEM_PROBE_CONFIG_HTTP_IDLE_CONNECTION_TTL_IN_S", strconv.Itoa(tt.httpIdleConnectionTTLSeconds)) + config.ResetSystemProbeConfig(t) + t.Setenv("DD_SERVICE_MONITORING_CONFIG_HTTP_MAP_CLEANER_INTERVAL_IN_S", strconv.Itoa(tt.mapCleanerIntervalSeconds)) + t.Setenv("DD_SERVICE_MONITORING_CONFIG_HTTP_IDLE_CONNECTION_TTL_IN_S", strconv.Itoa(tt.httpIdleConnectionTTLSeconds)) monitor := newHTTPMonitor(t) slowResponseTimeout := time.Duration(tt.slowResponseTime) * time.Second @@ -590,7 +592,7 @@ func countRequestOccurrences(allStats map[http.Key]*http.RequestStats, req *neth } func newHTTPMonitor(t *testing.T) *Monitor { - cfg := config.New() + cfg := networkconfig.New() cfg.EnableHTTPMonitoring = true monitor, err := NewMonitor(cfg, nil, nil, nil) skipIfNotSupported(t, err) diff --git a/releasenotes/notes/deprecating-usm-configuration-values-0e331d18c41c3f87.yaml b/releasenotes/notes/deprecating-usm-configuration-values-0e331d18c41c3f87.yaml new file mode 100644 index 0000000000000..a721f54d3b267 --- /dev/null +++ b/releasenotes/notes/deprecating-usm-configuration-values-0e331d18c41c3f87.yaml @@ -0,0 +1,6 @@ +--- +deprecations: + - The `system_probe_config.http_map_cleaner_interval_in_s` configuration has been deprecated. Use `service_monitoring_config.http_map_cleaner_interval_in_s` instead. + - The `system_probe_config.http_idle_connection_ttl_in_s` configuration has been deprecated. Use `service_monitoring_config.http_idle_connection_ttl_in_s` instead. + - The `network_config.http_notification_threshold` configuration has been deprecated. Use `service_monitoring_config.http_notification_threshold` instead. + - The `network_config.http_max_request_fragment` configuration has been deprecated. Use `service_monitoring_config.http_max_request_fragment` instead. From 09f72d2f1d8b6fe4ca9f2fef6131f3f20d5897bc Mon Sep 17 00:00:00 2001 From: Ivan Topolcic Date: Fri, 9 Jun 2023 15:13:22 -0400 Subject: [PATCH 74/76] Adds DD_RESOURCE_GROUP and DD_SUBSCRIPTION_ID to env vars (#17558) --- .../cloudservice/appservice.go | 5 ++ cmd/serverless-init/cloudservice/cloudrun.go | 5 ++ .../cloudservice/containerapp.go | 50 ++++++++++++++++++- .../cloudservice/containerapp_test.go | 47 +++++++++++++++++ cmd/serverless-init/cloudservice/service.go | 10 +++- .../cloudservice/service_test.go | 6 +-- cmd/serverless-init/main.go | 5 ++ 7 files changed, 122 insertions(+), 6 deletions(-) diff --git a/cmd/serverless-init/cloudservice/appservice.go b/cmd/serverless-init/cloudservice/appservice.go index 432d1bf3ae6cd..2511dfece3a7b 100644 --- a/cmd/serverless-init/cloudservice/appservice.go +++ b/cmd/serverless-init/cloudservice/appservice.go @@ -43,6 +43,11 @@ func (a *AppService) GetPrefix() string { return "azure.appservice" } +// Init is empty for AppService +func (a *AppService) Init() error { + return nil +} + func isAppService() bool { _, exists := os.LookupEnv(RunZip) return exists diff --git a/cmd/serverless-init/cloudservice/cloudrun.go b/cmd/serverless-init/cloudservice/cloudrun.go index 999d9b1dea103..af2a552a6e339 100644 --- a/cmd/serverless-init/cloudservice/cloudrun.go +++ b/cmd/serverless-init/cloudservice/cloudrun.go @@ -54,6 +54,11 @@ func (c *CloudRun) GetPrefix() string { return "gcp.run" } +// Init is empty for CloudRun +func (c *CloudRun) Init() error { + return nil +} + func isCloudRunService() bool { _, exists := os.LookupEnv(serviceNameEnvVar) return exists diff --git a/cmd/serverless-init/cloudservice/containerapp.go b/cmd/serverless-init/cloudservice/containerapp.go index ca33df1bf495d..1decc15ae477d 100644 --- a/cmd/serverless-init/cloudservice/containerapp.go +++ b/cmd/serverless-init/cloudservice/containerapp.go @@ -6,17 +6,24 @@ package cloudservice import ( + "fmt" "os" "strings" ) // ContainerApp has helper functions for getting specific Azure Container App data -type ContainerApp struct{} +type ContainerApp struct { + SubscriptionId string + ResourceGroup string +} const ( ContainerAppNameEnvVar = "CONTAINER_APP_NAME" ContainerAppDNSSuffix = "CONTAINER_APP_ENV_DNS_SUFFIX" ContainerAppRevision = "CONTAINER_APP_REVISION" + + AzureSubscriptionIdEnvVar = "DD_AZURE_SUBSCRIPTION_ID" + AzureResourceGroupEnvVar = "DD_AZURE_RESOURCE_GROUP" ) // GetTags returns a map of Azure-related tags @@ -29,13 +36,23 @@ func (c *ContainerApp) GetTags() map[string]string { revision := os.Getenv(ContainerAppRevision) - return map[string]string{ + tags := map[string]string{ "app_name": appName, "region": region, "revision": revision, "origin": c.GetOrigin(), "_dd.origin": c.GetOrigin(), } + + if c.SubscriptionId != "" { + tags["subscription_id"] = c.SubscriptionId + } + + if c.ResourceGroup != "" { + tags["resource_group"] = c.ResourceGroup + } + + return tags } // GetOrigin returns the `origin` attribute type for the given @@ -50,6 +67,35 @@ func (c *ContainerApp) GetPrefix() string { return "azure.containerapp" } +// NewContainerApp returns a new ContainerApp instance +func NewContainerApp() *ContainerApp { + return &ContainerApp{ + SubscriptionId: "", + ResourceGroup: "", + } +} + +// Init initializes ContainerApp specific code +func (c *ContainerApp) Init() error { + // For ContainerApp, the customers must set DD_AZURE_SUBSCRIPTION_ID + // and DD_AZURE_RESOURCE_GROUP. + // These environment variables are optional for now. Once we go GA, + // return `false` if these are not set. + if subscriptionId, exists := os.LookupEnv(AzureSubscriptionIdEnvVar); exists { + c.SubscriptionId = subscriptionId + } else { + return fmt.Errorf("must set %v", AzureSubscriptionIdEnvVar) + } + + if resourceGroup, exists := os.LookupEnv(AzureResourceGroupEnvVar); exists { + c.ResourceGroup = resourceGroup + } else { + return fmt.Errorf("must set %v", AzureResourceGroupEnvVar) + } + + return nil +} + func isContainerAppService() bool { _, exists := os.LookupEnv(ContainerAppNameEnvVar) return exists diff --git a/cmd/serverless-init/cloudservice/containerapp_test.go b/cmd/serverless-init/cloudservice/containerapp_test.go index 8856391480e3a..2003757de2923 100644 --- a/cmd/serverless-init/cloudservice/containerapp_test.go +++ b/cmd/serverless-init/cloudservice/containerapp_test.go @@ -6,6 +6,7 @@ package cloudservice import ( + "fmt" "testing" "github.com/stretchr/testify/assert" @@ -28,3 +29,49 @@ func TestGetContainerAppTags(t *testing.T) { "_dd.origin": "containerapp", }, tags) } + +func TestGetContainerAppTagsWithOptionalEnvVars(t *testing.T) { + service := NewContainerApp() + + t.Setenv("CONTAINER_APP_NAME", "test_app_name") + t.Setenv("CONTAINER_APP_ENV_DNS_SUFFIX", "test.bluebeach.eastus.azurecontainerapps.io") + t.Setenv("CONTAINER_APP_REVISION", "test_revision") + + t.Setenv("DD_AZURE_SUBSCRIPTION_ID", "test_subscription_id") + t.Setenv("DD_AZURE_RESOURCE_GROUP", "test_resource_group") + + err := service.Init() + assert.NoError(t, err) + + tags := service.GetTags() + + assert.Equal(t, map[string]string{ + "app_name": "test_app_name", + "origin": "containerapp", + "region": "eastus", + "revision": "test_revision", + "_dd.origin": "containerapp", + "subscription_id": "test_subscription_id", + "resource_group": "test_resource_group", + }, tags) + + assert.Nil(t, err) +} + +func TestInitHasErrorsWhenMissingEnvVars(t *testing.T) { + service := NewContainerApp() + + t.Setenv("CONTAINER_APP_NAME", "test_app_name") + t.Setenv("CONTAINER_APP_ENV_DNS_SUFFIX", "test.bluebeach.eastus.azurecontainerapps.io") + t.Setenv("CONTAINER_APP_REVISION", "test_revision") + + err := service.Init() + assert.Equal(t, fmt.Errorf("must set %v", AzureSubscriptionIdEnvVar), err) + + // Set the missing environment variable. We also need to set DD_AZURE_RESOURCE_GROUP, + // so we should still error when we call Init() again. + t.Setenv("DD_AZURE_SUBSCRIPTION_ID", "test_subscription_id") + + err = service.Init() + assert.Equal(t, fmt.Errorf("must set %v", AzureResourceGroupEnvVar), err) +} diff --git a/cmd/serverless-init/cloudservice/service.go b/cmd/serverless-init/cloudservice/service.go index 6ad1988434594..6f8785ba4bc56 100644 --- a/cmd/serverless-init/cloudservice/service.go +++ b/cmd/serverless-init/cloudservice/service.go @@ -20,6 +20,9 @@ type CloudService interface { // gcp.run.{metric_name}. In this example, `gcp.run` is the // prefix. GetPrefix() string + + // Init bootstraps the CloudService. + Init() error } type LocalService struct{} @@ -39,13 +42,18 @@ func (l *LocalService) GetPrefix() string { return "local" } +// Init is not necessary for LocalService +func (l *LocalService) Init() error { + return nil +} + func GetCloudServiceType() CloudService { if isCloudRunService() { return &CloudRun{} } if isContainerAppService() { - return &ContainerApp{} + return NewContainerApp() } if isAppService() { diff --git a/cmd/serverless-init/cloudservice/service_test.go b/cmd/serverless-init/cloudservice/service_test.go index 90c8b4a69c2a4..33757bd2b731a 100644 --- a/cmd/serverless-init/cloudservice/service_test.go +++ b/cmd/serverless-init/cloudservice/service_test.go @@ -12,11 +12,11 @@ import ( ) func TestGetCloudServiceType(t *testing.T) { - assert.Equal(t, &LocalService{}, GetCloudServiceType()) + assert.Equal(t, "local", GetCloudServiceType().GetOrigin()) t.Setenv(ContainerAppNameEnvVar, "test-name") - assert.Equal(t, &ContainerApp{}, GetCloudServiceType()) + assert.Equal(t, "containerapp", GetCloudServiceType().GetOrigin()) t.Setenv(serviceNameEnvVar, "test-name") - assert.Equal(t, &CloudRun{}, GetCloudServiceType()) + assert.Equal(t, "cloudrun", GetCloudServiceType().GetOrigin()) } diff --git a/cmd/serverless-init/main.go b/cmd/serverless-init/main.go index b11b6681a6d6a..7d2aa3292ee24 100644 --- a/cmd/serverless-init/main.go +++ b/cmd/serverless-init/main.go @@ -43,6 +43,11 @@ func setup() (cloudservice.CloudService, *log.Config, *trace.ServerlessTraceAgen setupProxy() cloudService := cloudservice.GetCloudServiceType() + + // Ignore errors for now. Once we go GA, check for errors + // and exit right away. + _ = cloudService.Init() + tags := tags.MergeWithOverwrite(tags.ArrayToMap(config.GetGlobalConfiguredTags(false)), cloudService.GetTags()) origin := cloudService.GetOrigin() prefix := cloudService.GetPrefix() From 2d93fc1092bfc7df858c211546ac5f8cd40eab6f Mon Sep 17 00:00:00 2001 From: Atsushi Watanabe Date: Sat, 10 Jun 2023 04:20:47 +0900 Subject: [PATCH 75/76] rtloader: Use execinfo only on glibc (#15256) Use execinfo only on glibc. Functions in execinfo.h are GNU extensions and not available on other C libraries like musl. We used to use libexecinfo package (A quick-n-dirty BSD licensed clone of the GNU libc backtrace facility.) of Alpine Linux to build datadog-agent on Alpine, but it has been removed since Alpine 3.17. This PR allow to build datadog-agent on Alpine Linux and other non-glibc environments. --- ...use-execinfo-only-on-glibc-5b734df32fc1555a.yaml | 13 +++++++++++++ rtloader/rtloader/CMakeLists.txt | 2 ++ rtloader/rtloader/api.cpp | 6 ++++++ 3 files changed, 21 insertions(+) create mode 100644 releasenotes/notes/rtloader-use-execinfo-only-on-glibc-5b734df32fc1555a.yaml diff --git a/releasenotes/notes/rtloader-use-execinfo-only-on-glibc-5b734df32fc1555a.yaml b/releasenotes/notes/rtloader-use-execinfo-only-on-glibc-5b734df32fc1555a.yaml new file mode 100644 index 0000000000000..a7337ddc044d9 --- /dev/null +++ b/releasenotes/notes/rtloader-use-execinfo-only-on-glibc-5b734df32fc1555a.yaml @@ -0,0 +1,13 @@ +# Each section from every release note are combined when the +# CHANGELOG.rst is rendered. So the text needs to be worded so that +# it does not depend on any information only available in another +# section. This may mean repeating some details, but each section +# must be readable independently of the other. +# +# Each section note must be formatted as reStructuredText. +--- +fixes: + - | + rtloader: Use `execinfo` only if provided to fix builds on + C libraries like `musl`. + diff --git a/rtloader/rtloader/CMakeLists.txt b/rtloader/rtloader/CMakeLists.txt index 8cb06c7e799d1..a830f18c995c3 100644 --- a/rtloader/rtloader/CMakeLists.txt +++ b/rtloader/rtloader/CMakeLists.txt @@ -32,6 +32,7 @@ add_library(datadog-agent-rtloader SHARED find_library(EXECINFO execinfo) if(EXECINFO) target_link_libraries(datadog-agent-rtloader execinfo) + add_compile_definitions(HAS_BACKTRACE_LIB) endif() endif() @@ -39,6 +40,7 @@ endif() if(${CMAKE_SYSTEM_NAME} STREQUAL FreeBSD) find_package(Backtrace REQUIRED) target_link_libraries(datadog-agent-rtloader ${Backtrace_LIBRARIES}) + add_compile_definitions(HAS_BACKTRACE_LIB) endif() set_target_properties(datadog-agent-rtloader PROPERTIES diff --git a/rtloader/rtloader/api.cpp b/rtloader/rtloader/api.cpp index af5fe74b5972b..f150be80d06fd 100644 --- a/rtloader/rtloader/api.cpp +++ b/rtloader/rtloader/api.cpp @@ -12,7 +12,9 @@ #ifndef _WIN32 // clang-format off // handler stuff +#ifdef HAS_BACKTRACE_LIB #include +#endif #include #include #include @@ -371,11 +373,14 @@ static inline void core(int sig) # define STACKTRACE_SIZE 500 void signalHandler(int sig, siginfo_t *, void *) { +# ifdef HAS_BACKTRACE_LIB void *buffer[STACKTRACE_SIZE]; char **symbols; size_t nptrs = backtrace(buffer, STACKTRACE_SIZE); +# endif std::cerr << "HANDLER CAUGHT signal Error: signal " << sig << std::endl; +# ifdef HAS_BACKTRACE_LIB symbols = backtrace_symbols(buffer, nptrs); if (symbols == NULL) { std::cerr << "Error getting backtrace symbols" << std::endl; @@ -387,6 +392,7 @@ void signalHandler(int sig, siginfo_t *, void *) _free(symbols); } +# endif // dump core if so configured __sync_synchronize(); From 5c8ef804d8e6407d6126cb7fa64dda72129dd039 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9na=C3=AFc=20Huard?= Date: Sat, 10 Jun 2023 14:04:10 +0200 Subject: [PATCH 76/76] Remove a no more used SBOM check config parameter (#17405) --- pkg/collector/corechecks/sbom/check.go | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/pkg/collector/corechecks/sbom/check.go b/pkg/collector/corechecks/sbom/check.go index afb0ad3649a58..aa649095c99dd 100644 --- a/pkg/collector/corechecks/sbom/check.go +++ b/pkg/collector/corechecks/sbom/check.go @@ -31,11 +31,10 @@ func init() { // Config holds the container_image check configuration type Config struct { - ChunkSize int `yaml:"chunk_size"` - NewSBOMMaxLatencySeconds int `yaml:"new_sbom_max_latency_seconds"` - ContainerPeriodicRefreshSeconds int `yaml:"periodic_refresh_seconds"` - HostSBOM bool `yaml:"host_sbom"` - HostPeriodicRefreshSeconds int `yaml:"host_periodic_refresh_seconds"` + ChunkSize int `yaml:"chunk_size"` + NewSBOMMaxLatencySeconds int `yaml:"new_sbom_max_latency_seconds"` + ContainerPeriodicRefreshSeconds int `yaml:"periodic_refresh_seconds"` + HostPeriodicRefreshSeconds int `yaml:"host_periodic_refresh_seconds"` } type configValueRange struct {