diff --git a/internal/agentdeployer/_static/docker-agent-base.yml b/internal/agentdeployer/_static/docker-agent-base.yml.tmpl similarity index 67% rename from internal/agentdeployer/_static/docker-agent-base.yml rename to internal/agentdeployer/_static/docker-agent-base.yml.tmpl index c16f94c3ed..16171de842 100644 --- a/internal/agentdeployer/_static/docker-agent-base.yml +++ b/internal/agentdeployer/_static/docker-agent-base.yml.tmpl @@ -7,6 +7,18 @@ services: test: "elastic-agent status" retries: 180 interval: 1s + {{ if ne .pidMode "" }} + pid: {{ .pidMode }} + {{ end }} + {{ if ne .user "" }} + user: {{ .user }} + {{ end }} + {{ if .capabilities }} + cap_add: + {{- range .capabilities }} + - {{ . }} + {{- end }} + {{ end }} environment: - FLEET_ENROLL=1 - FLEET_URL=https://fleet-server:8220 @@ -15,4 +27,3 @@ services: volumes: - ${SERVICE_LOGS_DIR}:/tmp/service_logs/ - ${LOCAL_CA_CERT}:/etc/ssl/certs/elastic-package.pem - diff --git a/internal/agentdeployer/agent.go b/internal/agentdeployer/agent.go index 3bac4f6959..0927333dcf 100644 --- a/internal/agentdeployer/agent.go +++ b/internal/agentdeployer/agent.go @@ -10,6 +10,7 @@ import ( "fmt" "os" "path/filepath" + "text/template" "time" "github.com/elastic/elastic-package/internal/compose" @@ -24,13 +25,12 @@ import ( const ( dockerTestAgentNamePrefix = "elastic-agent" - dockerTestgentDir = "docker_test_agent" dockerTestAgentDockerCompose = "docker-agent-base.yml" defaultAgentPolicyName = "Elastic-Agent (elastic-package)" ) -//go:embed _static/docker-agent-base.yml -var dockerAgentDockerComposeContent []byte +//go:embed _static/docker-agent-base.yml.tmpl +var dockerTestAgentDockerComposeTemplate string // CustomAgentDeployer knows how to deploy a custom elastic-agent defined via // a Docker Compose file. @@ -112,7 +112,7 @@ func (d *DockerComposeAgentDeployer) SetUp(ctx context.Context, agentInfo AgentI fmt.Sprintf("%s=%s", agentHostnameEnv, d.agentHostname()), ) - configDir, err := d.installDockerfile() + configDir, err := d.installDockerfile(agentInfo) if err != nil { return nil, fmt.Errorf("could not create resources for custom agent: %w", err) } @@ -236,7 +236,7 @@ func (d *DockerComposeAgentDeployer) agentName() string { // installDockerfile creates the files needed to run the custom elastic agent and returns // the directory with these files. -func (d *DockerComposeAgentDeployer) installDockerfile() (string, error) { +func (d *DockerComposeAgentDeployer) installDockerfile(agentInfo AgentInfo) (string, error) { customAgentDir := filepath.Join(d.profile.ProfilePath, fmt.Sprintf("agent-%s", d.agentName())) err := os.MkdirAll(customAgentDir, 0755) if err != nil { @@ -244,9 +244,21 @@ func (d *DockerComposeAgentDeployer) installDockerfile() (string, error) { } customAgentDockerfile := filepath.Join(customAgentDir, dockerTestAgentDockerCompose) - err = os.WriteFile(customAgentDockerfile, dockerAgentDockerComposeContent, 0644) + file, err := os.Create(customAgentDockerfile) if err != nil { - return "", fmt.Errorf("failed to create docker compose file for custom agent: %w", err) + return "", fmt.Errorf("failed to create file (name %s): %w", customAgentDockerfile, err) + } + defer file.Close() + + tmpl := template.Must(template.New(dockerTestAgentDockerCompose).Parse(dockerTestAgentDockerComposeTemplate)) + err = tmpl.Execute(file, map[string]any{ + "user": agentInfo.Agent.User, + "capabilities": agentInfo.Agent.LinuxCapabilities, + "runtime": agentInfo.Agent.Runtime, + "pidMode": agentInfo.Agent.PidMode, + }) + if err != nil { + return "", fmt.Errorf("failed to create contents of the docker-compose file %q: %w", customAgentDockerfile, err) } return customAgentDir, nil diff --git a/internal/agentdeployer/info.go b/internal/agentdeployer/info.go index 4529286338..3da8ea4efb 100644 --- a/internal/agentdeployer/info.go +++ b/internal/agentdeployer/info.go @@ -71,6 +71,17 @@ type AgentInfo struct { // Name prefix for the host's name NamePrefix string } + + // User user to run Elastic Agent process + User string + // PidMode selects the host PID mode + // (From docker-compose docs) Turns on sharing between container and the host + // operating system the PID address space + PidMode string + // Runtime is the selected runtime to run the Elastic Agent process + Runtime string + // LinuxCapabilities is a list of the capabilities needed to run the Elastic Agent process + LinuxCapabilities []string } // CustomProperties store additional data used to boot up the service, e.g. AWS credentials. diff --git a/internal/testrunner/runners/system/runner.go b/internal/testrunner/runners/system/runner.go index 1c5a0813db..2492d4f0fb 100644 --- a/internal/testrunner/runners/system/runner.go +++ b/internal/testrunner/runners/system/runner.go @@ -299,7 +299,7 @@ func (r *runner) createServiceOptions(variantName string) servicedeployer.Factor } } -func (r *runner) createAgentInfo(policy *kibana.Policy) (agentdeployer.AgentInfo, error) { +func (r *runner) createAgentInfo(policy *kibana.Policy, config *testConfig) (agentdeployer.AgentInfo, error) { var info agentdeployer.AgentInfo info.Name = r.options.TestFolder.Package @@ -320,6 +320,11 @@ func (r *runner) createAgentInfo(policy *kibana.Policy) (agentdeployer.AgentInfo info.Policy.Name = policy.Name info.Policy.ID = policy.ID + info.Agent.User = config.Agent.User + info.Agent.LinuxCapabilities = config.Agent.LinuxCapabilities + info.Agent.Runtime = config.Agent.Runtime + info.Agent.PidMode = config.Agent.PidMode + return info, nil } @@ -716,7 +721,7 @@ type scenarioTest struct { syntheticEnabled bool docs []common.MapStr agent agentdeployer.DeployedAgent - enrollingTime time.Time + startTestTime time.Time } func (r *runner) prepareScenario(ctx context.Context, config *testConfig, svcInfo servicedeployer.ServiceInfo, serviceOptions servicedeployer.FactoryOptions) (*scenarioTest, error) { @@ -792,17 +797,11 @@ func (r *runner) prepareScenario(ctx context.Context, config *testConfig, svcInf return nil } - enrollingTime := time.Now() - if r.options.RunTearDown || r.options.RunTestsOnly { - enrollingTime = serviceStateData.EnrollingAgentTime - } - - agentDeployed, agentInfo, err := r.setupAgent(ctx, serviceStateData, policy) + agentDeployed, agentInfo, err := r.setupAgent(ctx, config, serviceStateData, policy) if err != nil { return nil, err } - scenario.enrollingTime = enrollingTime scenario.agent = agentDeployed service, svcInfo, err := r.setupService(ctx, config, serviceOptions, svcInfo, agentInfo, agentDeployed, policy, serviceStateData) @@ -873,6 +872,10 @@ func (r *runner) prepareScenario(ctx context.Context, config *testConfig, svcInf } r.deletePackageHandler = deletePackageHandler + // store the time just before adding the Test Policy, this time will be used to check + // the agent logs from that time onwards to avoid possible previous errors present in logs + scenario.startTestTime = time.Now() + logger.Debug("adding package data stream to test policy...") ds := createPackageDatastream(*policy, *scenario.pkgManifest, policyTemplate, *scenario.dataStreamManifest, *config) if r.options.RunTearDown || r.options.RunTestsOnly { @@ -1083,7 +1086,6 @@ func (r *runner) prepareScenario(ctx context.Context, config *testConfig, svcInf currentPolicy: policy, config: config, agent: origAgent, - enrollingTime: enrollingTime, agentInfo: agentInfo, svcInfo: svcInfo, } @@ -1143,12 +1145,12 @@ func (r *runner) setupService(ctx context.Context, config *testConfig, serviceOp return service, service.Info(), nil } -func (r *runner) setupAgent(ctx context.Context, state ServiceState, policy *kibana.Policy) (agentdeployer.DeployedAgent, agentdeployer.AgentInfo, error) { +func (r *runner) setupAgent(ctx context.Context, config *testConfig, state ServiceState, policy *kibana.Policy) (agentdeployer.DeployedAgent, agentdeployer.AgentInfo, error) { if !r.options.RunIndependentElasticAgent { return nil, agentdeployer.AgentInfo{}, nil } logger.Warn("setting up agent (technical preview)...") - agentInfo, err := r.createAgentInfo(policy) + agentInfo, err := r.createAgentInfo(policy, config) if err != nil { return nil, agentdeployer.AgentInfo{}, err } @@ -1162,6 +1164,7 @@ func (r *runner) setupAgent(ctx context.Context, state ServiceState, policy *kib return nil, agentInfo, fmt.Errorf("could not create agent runner: %w", err) } if agentDeployer == nil { + logger.Debug("Not found agent deployer. Agent will be created along with the service.") return nil, agentInfo, nil } @@ -1215,15 +1218,14 @@ func (r *runner) readServiceStateData() (ServiceState, error) { } type ServiceState struct { - OrigPolicy kibana.Policy `json:"orig_policy"` - CurrentPolicy kibana.Policy `json:"current_policy"` - Agent kibana.Agent `json:"agent"` - ConfigFilePath string `json:"config_file_path"` - VariantName string `json:"variant_name"` - EnrollingAgentTime time.Time `json:"enrolling_agent_time"` - ServiceRunID string `json:"service_info_run_id"` - AgentRunID string `json:"agent_info_run_id"` - ServiceOutputDir string `json:"service_output_dir"` + OrigPolicy kibana.Policy `json:"orig_policy"` + CurrentPolicy kibana.Policy `json:"current_policy"` + Agent kibana.Agent `json:"agent"` + ConfigFilePath string `json:"config_file_path"` + VariantName string `json:"variant_name"` + ServiceRunID string `json:"service_info_run_id"` + AgentRunID string `json:"agent_info_run_id"` + ServiceOutputDir string `json:"service_output_dir"` } type scenarioStateOpts struct { @@ -1231,22 +1233,20 @@ type scenarioStateOpts struct { origPolicy *kibana.Policy config *testConfig agent kibana.Agent - enrollingTime time.Time agentInfo agentdeployer.AgentInfo svcInfo servicedeployer.ServiceInfo } func (r *runner) writeScenarioState(opts scenarioStateOpts) error { data := ServiceState{ - OrigPolicy: *opts.origPolicy, - CurrentPolicy: *opts.currentPolicy, - Agent: opts.agent, - ConfigFilePath: opts.config.Path, - VariantName: opts.config.ServiceVariantName, - EnrollingAgentTime: opts.enrollingTime, - ServiceRunID: opts.svcInfo.Test.RunID, - AgentRunID: opts.agentInfo.Test.RunID, - ServiceOutputDir: opts.svcInfo.OutputDir, + OrigPolicy: *opts.origPolicy, + CurrentPolicy: *opts.currentPolicy, + Agent: opts.agent, + ConfigFilePath: opts.config.Path, + VariantName: opts.config.ServiceVariantName, + ServiceRunID: opts.svcInfo.Test.RunID, + AgentRunID: opts.agentInfo.Test.RunID, + ServiceOutputDir: opts.svcInfo.OutputDir, } dataBytes, err := json.Marshal(data) if err != nil { @@ -1366,7 +1366,7 @@ func (r *runner) validateTestScenario(ctx context.Context, result *testrunner.Re } if scenario.agent != nil { - logResults, err := r.checkNewAgentLogs(ctx, scenario.agent, scenario.enrollingTime, errorPatterns) + logResults, err := r.checkNewAgentLogs(ctx, scenario.agent, scenario.startTestTime, errorPatterns) if err != nil { return result.WithError(err) } diff --git a/internal/testrunner/runners/system/test_config.go b/internal/testrunner/runners/system/test_config.go index 2a319777df..662ceb7ddf 100644 --- a/internal/testrunner/runners/system/test_config.go +++ b/internal/testrunner/runners/system/test_config.go @@ -51,6 +51,14 @@ type testConfig struct { Path string `config:",ignore"` // Path of config file. ServiceVariantName string `config:",ignore"` // Name of test variant when using variants.yml. + + // Agent related properties + Agent struct { + User string `config:"user"` + PidMode string `config:"pid_mode"` + LinuxCapabilities []string `config:"linux_capabilities"` + Runtime string `config:"runtime"` + } `config:"agent"` } func (t testConfig) Name() string { diff --git a/scripts/test-check-packages.sh b/scripts/test-check-packages.sh index f5aaa84f75..0bbbfa75bf 100755 --- a/scripts/test-check-packages.sh +++ b/scripts/test-check-packages.sh @@ -85,10 +85,10 @@ fi for d in test/packages/${PACKAGE_TEST_TYPE:-other}/${PACKAGE_UNDER_TEST:-*}/; do ( cd "$d" + package_to_test=$(basename "${d}") if [ "${PACKAGE_TEST_TYPE:-other}" == "benchmarks" ]; then # It is not used PACKAGE_UNDER_TEST, so all benchmark packages are run in the same loop - package_to_test=$(basename "${d}") if [ "${package_to_test}" == "pipeline_benchmark" ]; then rm -rf "${OLDPWD}/build/benchmark-results" elastic-package benchmark pipeline -v --report-format xUnit --report-output file --fail-on-missing @@ -109,6 +109,10 @@ for d in test/packages/${PACKAGE_TEST_TYPE:-other}/${PACKAGE_UNDER_TEST:-*}/; do elif [ "${PACKAGE_TEST_TYPE:-other}" == "with-logstash" ] && [ "${PACKAGE_UNDER_TEST:-*}" == "system_benchmark" ]; then elastic-package benchmark system --benchmark logs-benchmark -v --defer-cleanup 1s else + if [[ "${ELASTIC_PACKAGE_TEST_ENABLE_INDEPENDENT_AGENT}" == "false" && "${package_to_test}" == "auditd_manager_independent_agent" ]]; then + echo "Package \"${package_to_test}\" skipped: not supported with Elastic Agent running in the stack (missing capabilities)." + exit # as it is run in a subshell, it cannot be used "continue" + fi # defer-cleanup is set to a short period to verify that the option is available elastic-package test -v \ --report-format xUnit \ diff --git a/test/packages/with-custom-agent/auditd_manager_independent_agent/_dev/build/build.yml b/test/packages/with-custom-agent/auditd_manager_independent_agent/_dev/build/build.yml new file mode 100644 index 0000000000..d61527283e --- /dev/null +++ b/test/packages/with-custom-agent/auditd_manager_independent_agent/_dev/build/build.yml @@ -0,0 +1,3 @@ +dependencies: + ecs: + reference: git@8.2 diff --git a/test/packages/with-custom-agent/auditd_manager_independent_agent/changelog.yml b/test/packages/with-custom-agent/auditd_manager_independent_agent/changelog.yml new file mode 100644 index 0000000000..fbfe014a86 --- /dev/null +++ b/test/packages/with-custom-agent/auditd_manager_independent_agent/changelog.yml @@ -0,0 +1,6 @@ +# newer versions go on top +- version: "999.999.999" + changes: + - description: Initial draft of the package + type: enhancement + link: https://github.com/elastic/integrations/pull/1 diff --git a/test/packages/with-custom-agent/auditd_manager_independent_agent/data_stream/auditd/_dev/test/system/test-default-config.yml b/test/packages/with-custom-agent/auditd_manager_independent_agent/data_stream/auditd/_dev/test/system/test-default-config.yml new file mode 100644 index 0000000000..75d196b392 --- /dev/null +++ b/test/packages/with-custom-agent/auditd_manager_independent_agent/data_stream/auditd/_dev/test/system/test-default-config.yml @@ -0,0 +1,12 @@ +data_stream: + vars: + audit_rules: + - "-a always,exit -F arch=b64 -S execve,execveat -k exec" + preserve_original_event: true +agent: + runtime: docker + user: "root" + pid_mode: "host" + linux_capabilities: + - AUDIT_CONTROL + - AUDIT_READ diff --git a/test/packages/with-custom-agent/auditd_manager_independent_agent/data_stream/auditd/agent/stream/auditd.yml.hbs b/test/packages/with-custom-agent/auditd_manager_independent_agent/data_stream/auditd/agent/stream/auditd.yml.hbs new file mode 100644 index 0000000000..626b5973ec --- /dev/null +++ b/test/packages/with-custom-agent/auditd_manager_independent_agent/data_stream/auditd/agent/stream/auditd.yml.hbs @@ -0,0 +1,34 @@ +# EQL expression evaluated by Elastic Agent to limit input to Linux. +condition: ${host.platform} == 'linux' + +type: audit/auditd +include_raw_message: true +{{#if multicast}} +socket_type: multicast +{{else}} +socket_type: unicast +{{/if}} +resolve_ids: {{resolve_ids}} +failure_mode: {{failure_mode}} +audit_rules: | +{{#each audit_rules as |rule i|}} + {{rule}} +{{/each}} +backlog_limit: {{backlog_limit}} +rate_limit: {{rate_limit}} +include_warnings: {{include_warnings}} +backpressure_strategy: {{backpressure_strategy}} +tags: +{{#if preserve_original_event}} + - preserve_original_event +{{/if}} +{{#each tags as |tag i|}} + - {{tag}} +{{/each}} +{{#contains "forwarded" tags}} +publisher_pipeline.disable_host: true +{{/contains}} +{{#if processors}} +processors: +{{processors}} +{{/if}} \ No newline at end of file diff --git a/test/packages/with-custom-agent/auditd_manager_independent_agent/data_stream/auditd/elasticsearch/ingest_pipeline/default.yml b/test/packages/with-custom-agent/auditd_manager_independent_agent/data_stream/auditd/elasticsearch/ingest_pipeline/default.yml new file mode 100644 index 0000000000..99afeed506 --- /dev/null +++ b/test/packages/with-custom-agent/auditd_manager_independent_agent/data_stream/auditd/elasticsearch/ingest_pipeline/default.yml @@ -0,0 +1,333 @@ +--- +description: Pipeline for parsing Linux auditd logs +processors: + - set: + field: ecs.version + value: '8.2.0' + - rename: + field: event.original + target_field: auditd.messages + ignore_missing: true + - join: + field: auditd.messages + separator: "\n" + target_field: event.original + if: ctx?.auditd?.messages != null && ctx.auditd.messages instanceof List + - rename: + field: error.message + target_field: auditd.warnings + ignore_missing: true + - join: + field: auditd.warnings + separator: "\n" + target_field: error.message + if: ctx?.auditd?.warnings != null && ctx.auditd.warnings instanceof List + # if it is not a list, rename it back to error.message + - set: + field: error.message + copy_from: auditd.warnings + ignore_empty_value: true + if: ctx?.auditd?.warnings != null && !(ctx.auditd.warnings instanceof List) + - rename: + field: source.path + target_field: source.address + ignore_missing: true + ignore_failure: true + - rename: + field: destination.path + target_field: destination.address + ignore_missing: true + ignore_failure: true + - rename: + field: user.audit + target_field: auditd.user.audit + ignore_missing: true + ignore_failure: true + - rename: + field: file.selinux + target_field: auditd.file.selinux + ignore_missing: true + ignore_failure: true + - rename: + field: user.selinux + target_field: auditd.user.selinux + ignore_missing: true + ignore_failure: true + - rename: + field: user.saved + target_field: auditd.user.saved + ignore_missing: true + ignore_failure: true + - rename: + field: user.filesystem + target_field: auditd.user.filesystem + ignore_missing: true + ignore_failure: true + - rename: + field: user.new_auid + target_field: auditd.user.new_auid + ignore_missing: true + ignore_failure: true + - rename: + field: user.new-auid + target_field: auditd.user.new_auid + ignore_missing: true + ignore_failure: true + - rename: + field: user.old_auid + target_field: auditd.user.old_auid + ignore_missing: true + ignore_failure: true + - rename: + field: user.old-auid + target_field: auditd.user.old_auid + ignore_missing: true + ignore_failure: true + - rename: + field: auditd.data.new-ses + target_field: auditd.data.new_ses + ignore_missing: true + ignore_failure: true + - rename: + field: auditd.data.old-ses + target_field: auditd.data.old_ses + ignore_missing: true + ignore_failure: true + - rename: + field: auditd.data.new-enabled + target_field: auditd.data.new_enabled + ignore_missing: true + ignore_failure: true + - rename: + field: auditd.data.old-enabled + target_field: auditd.data.old_enabled + ignore_missing: true + ignore_failure: true + - rename: + field: auditd.data.vm-ctx + target_field: auditd.data.vm_ctx + ignore_missing: true + ignore_failure: true + - rename: + field: auditd.data.new-rng + target_field: auditd.data.new_rng + ignore_missing: true + ignore_failure: true + - rename: + field: auditd.data.new-net + target_field: auditd.data.new_net + ignore_missing: true + ignore_failure: true + - rename: + field: auditd.data.new-seuser + target_field: auditd.data.new_seuser + ignore_missing: true + ignore_failure: true + - rename: + field: auditd.data.old-net + target_field: auditd.data.old_net + ignore_missing: true + ignore_failure: true + - rename: + field: auditd.data.nlnk-pid + target_field: auditd.data.nlnk_pid + ignore_missing: true + ignore_failure: true + - rename: + field: auditd.data.ipx-net + target_field: auditd.data.ipx_net + ignore_missing: true + ignore_failure: true + - rename: + field: auditd.data.old-vpcu + target_field: auditd.data.old_vpcu + ignore_missing: true + ignore_failure: true + - rename: + field: auditd.data.new-fs + target_field: auditd.data.new_fs + ignore_missing: true + ignore_failure: true + - rename: + field: auditd.data.vm-pid + target_field: auditd.data.vm_pid + ignore_missing: true + ignore_failure: true + - rename: + field: auditd.data.old-auid + target_field: auditd.data.old_auid + ignore_missing: true + ignore_failure: true + - rename: + field: auditd.data.new-disk + target_field: auditd.data.new_disk + ignore_missing: true + ignore_failure: true + - rename: + field: auditd.data.nlnk-grp + target_field: auditd.data.nlnk_grp + ignore_missing: true + ignore_failure: true + - rename: + field: auditd.data.new-mem + target_field: auditd.data.new_mem + ignore_missing: true + ignore_failure: true + - rename: + field: auditd.data.new-chardev + target_field: auditd.data.new_chardev + ignore_missing: true + ignore_failure: true + - rename: + field: auditd.data.old-rng + target_field: auditd.data.old_rng + ignore_missing: true + ignore_failure: true + - rename: + field: auditd.data.new-level + target_field: auditd.data.new_level + ignore_missing: true + ignore_failure: true + - rename: + field: auditd.data.old-mem + target_field: auditd.data.old_mem + ignore_missing: true + ignore_failure: true + - rename: + field: auditd.data.default-context + target_field: auditd.data.default_context + ignore_missing: true + ignore_failure: true + - rename: + field: auditd.data.new-log_passwd + target_field: auditd.data.new_log_passwd + ignore_missing: true + ignore_failure: true + - rename: + field: auditd.data.selected-context + target_field: auditd.data.selected_context + ignore_missing: true + ignore_failure: true + - rename: + field: auditd.data.old-range + target_field: auditd.data.old_range + ignore_missing: true + ignore_failure: true + - rename: + field: auditd.data.new-range + target_field: auditd.data.new_range + ignore_missing: true + ignore_failure: true + - rename: + field: auditd.data.old-disk + target_field: auditd.data.old_disk + ignore_missing: true + ignore_failure: true + - rename: + field: auditd.data.nlnk-fam + target_field: auditd.data.nlnk_fam + ignore_missing: true + ignore_failure: true + - rename: + field: auditd.data.old-fs + target_field: auditd.data.old_fs + ignore_missing: true + ignore_failure: true + - rename: + field: auditd.data.old-ses + target_field: auditd.data.old_ses + ignore_missing: true + ignore_failure: true + - rename: + field: auditd.data.new-vcpu + target_field: auditd.data.new_vcpu + ignore_missing: true + ignore_failure: true + - rename: + field: auditd.data.old-level + target_field: auditd.data.old_level + ignore_missing: true + ignore_failure: true + - rename: + field: auditd.data.old-role + target_field: auditd.data.old_role + ignore_missing: true + ignore_failure: true + - rename: + field: auditd.data.new-role + target_field: auditd.data.new_role + ignore_missing: true + ignore_failure: true + - rename: + field: auditd.data.old-log_passwd + target_field: auditd.data.old_log_passwd + ignore_missing: true + ignore_failure: true + - rename: + field: auditd.data.old-seuser + target_field: auditd.data.old_seuser + ignore_missing: true + ignore_failure: true + - rename: + field: auditd.data.img-ctx + target_field: auditd.data.img_ctx + ignore_missing: true + ignore_failure: true + - rename: + field: auditd.data.old-chardev + target_field: auditd.data.old_chardev + ignore_missing: true + ignore_failure: true + - set: + field: event.outcome + value: failure + if: ctx?.event?.outcome == "fail" + - rename: + field: auditd.sequence + target_field: event.sequence + ignore_missing: true + ignore_failure: true + - rename: + field: auditd.data.id + target_field: event.id + ignore_missing: true + ignore_failure: true + - remove: + field: event.original + if: "ctx?.tags == null || !(ctx.tags.contains('preserve_original_event'))" + ignore_failure: true + ignore_missing: true + - remove: + field: auditd.messages + if: "ctx?.tags == null || !(ctx.tags.contains('preserve_original_event'))" + ignore_failure: true + ignore_missing: true + - script: + lang: painless + description: This script processor iterates over the whole document to remove fields with null values. + source: | + void handleMap(Map map) { + for (def x : map.values()) { + if (x instanceof Map) { + handleMap(x); + } else if (x instanceof List) { + handleList(x); + } + } + map.values().removeIf(v -> v == null || v == '' || (v instanceof Map && v.size() == 0) || (v instanceof List && v.size() == 0)); + } + void handleList(List list) { + for (def x : list) { + if (x instanceof Map) { + handleMap(x); + } else if (x instanceof List) { + handleList(x); + } + } + list.removeIf(v -> v == null || v == '' || (v instanceof Map && v.size() == 0) || (v instanceof List && v.size() == 0)); + } + handleMap(ctx); +on_failure: + - set: + field: error.message + value: "{{ _ingest.on_failure_message }}" diff --git a/test/packages/with-custom-agent/auditd_manager_independent_agent/data_stream/auditd/fields/base-fields.yml b/test/packages/with-custom-agent/auditd_manager_independent_agent/data_stream/auditd/fields/base-fields.yml new file mode 100644 index 0000000000..db43ca3cde --- /dev/null +++ b/test/packages/with-custom-agent/auditd_manager_independent_agent/data_stream/auditd/fields/base-fields.yml @@ -0,0 +1,21 @@ +- name: data_stream.type + type: constant_keyword + description: Data stream type. +- name: data_stream.dataset + type: constant_keyword + description: Data stream dataset. +- name: data_stream.namespace + type: constant_keyword + description: Data stream namespace. +- name: event.module + type: constant_keyword + description: Event module + value: auditd +- name: event.dataset + type: constant_keyword + description: Event dataset + value: auditd_manager_independent_agent.auditd +- name: '@timestamp' + external: ecs +- name: tags + external: ecs diff --git a/test/packages/with-custom-agent/auditd_manager_independent_agent/data_stream/auditd/fields/ecs.yml b/test/packages/with-custom-agent/auditd_manager_independent_agent/data_stream/auditd/fields/ecs.yml new file mode 100644 index 0000000000..d2aeb018d6 --- /dev/null +++ b/test/packages/with-custom-agent/auditd_manager_independent_agent/data_stream/auditd/fields/ecs.yml @@ -0,0 +1,76 @@ +- name: ecs.version + external: ecs +- name: event.outcome + external: ecs +- name: process.pid + external: ecs +- name: process.executable + external: ecs +- name: process.name + external: ecs +- name: process.parent.pid + external: ecs +- name: process.title + external: ecs +- name: process.working_directory + external: ecs +- name: process.args + external: ecs +- name: related.user + external: ecs +- name: service.type + external: ecs +- name: event.id + external: ecs +- name: file.device + external: ecs +- name: file.gid + external: ecs +- name: file.group + external: ecs +- name: file.inode + external: ecs +- name: file.mode + external: ecs +- name: file.owner + external: ecs +- name: file.path + external: ecs +- name: file.uid + external: ecs +- name: source.ip + external: ecs +- name: source.address + external: ecs +- name: destination.address + external: ecs +- name: network.direction + external: ecs +- name: group.id + external: ecs +- name: group.name + external: ecs +- name: user.group.id + external: ecs +- name: user.group.name + external: ecs +- name: user.id + external: ecs +- name: user.name + external: ecs +- name: user.effective.id + external: ecs +- name: user.effective.name + external: ecs +- name: user.target.id + external: ecs +- name: user.target.name + external: ecs +- name: user.effective.group.id + external: ecs +- name: user.effective.group.name + external: ecs +- name: user.target.group.id + external: ecs +- name: user.target.group.name + external: ecs diff --git a/test/packages/with-custom-agent/auditd_manager_independent_agent/data_stream/auditd/fields/fields.yml b/test/packages/with-custom-agent/auditd_manager_independent_agent/data_stream/auditd/fields/fields.yml new file mode 100644 index 0000000000..e27a9a2331 --- /dev/null +++ b/test/packages/with-custom-agent/auditd_manager_independent_agent/data_stream/auditd/fields/fields.yml @@ -0,0 +1,2 @@ +- name: auditd + type: flattened diff --git a/test/packages/with-custom-agent/auditd_manager_independent_agent/data_stream/auditd/manifest.yml b/test/packages/with-custom-agent/auditd_manager_independent_agent/data_stream/auditd/manifest.yml new file mode 100644 index 0000000000..a8e01480f9 --- /dev/null +++ b/test/packages/with-custom-agent/auditd_manager_independent_agent/data_stream/auditd/manifest.yml @@ -0,0 +1,128 @@ +title: "Auditd Manager Agent" +type: logs +streams: + - input: audit/auditd + title: Auditd events + template_path: auditd.yml.hbs + description: Collect auditd events + vars: + - name: multicast + type: bool + title: Multicast socket type + show_user: true + multi: false + default: false + description: "This setting controls if the socket type used to receive events is multicast.\nThis setting should be disabled when `elastic-agent` is the primary userspace\ndaemon for receiving audit events and managing the rules. Only a single process\ncan receive audit events if this is disabled, so any other daemons should be \nstopped (e.g. stop `auditd`).\n\nThis setting can be enabled with kernel versions 3.16 and newer. By setting it\n`elastic-agent` will receive an audit event broadcast that is not exclusive\nto a single process. This is ideal for situations where `auditd` is running and\nmanaging the rules.\n\nIf it is set to `true`, but the kernel version is less than 3.16 it will be\nautomatically disabled.\\n\"\n" + - name: resolve_ids + type: bool + title: Resolve IDs + show_user: true + multi: false + default: true + description: Enables the resolution of UIDs and GIDs to their associated names. + - name: failure_mode + type: text + title: Failure mode + required: true + multi: false + show_user: false + default: silent + description: | + This determines the kernel's behavior on critical + failures such as errors sending events to `elastic-agent`, the backlog limit was + exceeded, the kernel ran out of memory, or the rate limit was exceeded. The + options are `silent`, `log`, or `panic`. `silent` makes the kernel + ignore the errors, `log` makes the kernel write the audit messages using + `printk` so they show up in system's syslog, and `panic` causes the kernel to + panic to prevent use of the machine. + - name: audit_rules + type: text + title: Audit rules + required: true + multi: true + show_user: true + description: "List of the audit rules that should be\ninstalled to the kernel. There should be one rule per line. Comments can be\nembedded in the string using `#` as a prefix. The format for rules is the same\nused by the Linux `auditctl` utility. `elastic-agent` supports adding file watches\n(`-w`) and syscall rules (`-a` or `-A`). For more information, \nsee the integration detail page.\n" + - name: preserve_original_event + required: true + show_user: true + title: Preserve original event + description: Preserves a raw copy of the original event, added to the field `event.original` + type: bool + default: false + multi: false + - name: backlog_limit + type: text + title: Backlog limit + required: true + show_user: false + default: 8192 + description: This controls the maximum number of audit messages that will be buffered by the kernel. + multi: false + - name: rate_limit + type: text + title: Rate limit + required: true + show_user: false + default: 0 + multi: false + description: | + This sets a rate limit on the number of messages/sec + delivered by the kernel. The default is `0`, which disables rate limiting. + Changing this value to anything other than zero can cause messages to be lost. + The preferred approach to reduce the messaging rate is be more selective in the + audit ruleset. + - name: include_warnings + required: true + show_user: false + multi: false + title: Include warnings + description: | + Causes to include as warnings any issues that were encountered while parsing the raw + messages. The messages are written to the `error.message` field. + When this setting is enabled the raw messages will be included + in the event regardless of the `Preserve original event` config setting. This + setting is primarily used for debugging purposes. + type: bool + default: false + - name: backpressure_strategy + type: text + title: Backpressure strategy + required: true + show_user: false + multi: false + default: auto + description: | + Specifies the strategy that used to + prevent backpressure from propagating to the kernel and impacting audited + processes. + + The possible values are: + + * `auto`: uses the `kernel` strategy, if supported, or + falls back to the `userspace` strategy. + * `kernel`: sets the `backlog_wait_time` in the kernel's + audit framework to 0. This causes events to be discarded in the kernel if + the audit backlog queue fills to capacity. Requires a 3.14 kernel or + newer. + * `userspace`: drops events when there is backpressure + from the publishing pipeline. If no `Rate limit` is set, sets a rate + limit of `5000``. Users should test their setup and adjust the `Rate limit` + option accordingly. + * `both`: uses the `kernel` and `userspace` strategies at the same + time. + * `none`: No backpressure mitigation measures are enabled. + - name: tags + type: text + title: Tags + multi: true + required: true + show_user: false + default: + - auditd_manager-auditd + - name: processors + type: yaml + title: Processors + required: false + show_user: false + multi: false + description: "Processors are used to reduce the number of fields in the exported event or to enhance the event with metadata. \nThis executes in the agent before the logs are parsed. See [Processors](https://www.elastic.co/guide/en/beats/filebeat/current/filtering-and-enhancing-data.html) for details.\n" diff --git a/test/packages/with-custom-agent/auditd_manager_independent_agent/docs/README.md b/test/packages/with-custom-agent/auditd_manager_independent_agent/docs/README.md new file mode 100644 index 0000000000..4381ae615e --- /dev/null +++ b/test/packages/with-custom-agent/auditd_manager_independent_agent/docs/README.md @@ -0,0 +1 @@ +# TEST PACKAGE \ No newline at end of file diff --git a/test/packages/with-custom-agent/auditd_manager_independent_agent/img/linux.svg b/test/packages/with-custom-agent/auditd_manager_independent_agent/img/linux.svg new file mode 100644 index 0000000000..c0a92e0c0f --- /dev/null +++ b/test/packages/with-custom-agent/auditd_manager_independent_agent/img/linux.svg @@ -0,0 +1,1532 @@ + + + + Tux + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + Tux + 20 June 2012 + + + Garrett LeSage + + + + + + Larry Ewing, the creator of the original Tux graphic + + + + + tux + Linux + penguin + logo + + + + + Larry Ewing, Garrett LeSage + + + https://github.com/garrett/Tux + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/packages/with-custom-agent/auditd_manager_independent_agent/img/sample-screenshot.png b/test/packages/with-custom-agent/auditd_manager_independent_agent/img/sample-screenshot.png new file mode 100644 index 0000000000..d7a56a3ecc Binary files /dev/null and b/test/packages/with-custom-agent/auditd_manager_independent_agent/img/sample-screenshot.png differ diff --git a/test/packages/with-custom-agent/auditd_manager_independent_agent/manifest.yml b/test/packages/with-custom-agent/auditd_manager_independent_agent/manifest.yml new file mode 100644 index 0000000000..9e97507435 --- /dev/null +++ b/test/packages/with-custom-agent/auditd_manager_independent_agent/manifest.yml @@ -0,0 +1,32 @@ +format_version: 1.0.0 +name: auditd_manager_independent_agent +title: "Auditd Manager" +version: 999.999.999 +license: basic +description: "The Auditd Manager Integration receives audit events from the Linux Audit Framework that is a part of the Linux kernel." +type: integration +categories: + - os_system + - security +conditions: + kibana.version: "^8.2.0" +screenshots: + - src: /img/sample-screenshot.png + title: Sample screenshot + size: 600x600 + type: image/png +icons: + - src: /img/linux.svg + title: linux + size: 299x354 + type: image/svg+xml +policy_templates: + - name: auditd + title: Auditd + description: Collect auditd events + inputs: + - type: audit/auditd + title: Collect auditd events + description: Collecting auditd events +owner: + github: elastic/security-external-integrations